Basic CI/CD workflow with Gitlab CI¶
This section provides a short introduction to the CI/CD workflow.
What is CI / CD?¶
- CI stands for Continuous Integration
- CI is a practice
- code is integrated with other developers
- most commonly the way to integrate code is to check if the build step is still working
- a common practice is to also check if unit tests still work
- coding guidelines should also be considered (can be mostly automated)
- work is integrated all the time, multiple times per day
- most of the time the goal of the CI pipeline is to build a package that can be deployed
- CD can stand for Continuous Delivery
- CD is done after CI
- you cannot do CD without first doing CI
- the goal of CD is to take the package created by the CI pipeline and to test it further
- making sure it can be installed (by actually installing the package on a system similar to production)
- run additional tests to check if the package integrates with other systems
- after a manual check/decision, the package can be installed on a production system as well
- CD can also stand for Continuous Deployment
- CD goes a step further and automatically installs every package to production
- the package must first go through all previous stages successfully
- no manual intervention is required
YOUR NOTES
- the advantages of CI
- detecting errors early in the development process
- reduces integration errors
- allow developers to work faster
- the advantages of CD
- ensure that every change is releasable
- reduces the risk of a new deployment
- delivers value much faster (changes are released more often)
Short introduction to Node.js and npm¶
- Node.js is a runtime environment for executing JavaScript
- initially, JavaScript was only executed within a browser
- Node.js opened the possibility of running JavaScript without a browser.
- we will need Node.js for running some tools
- npm is the Node Package Manager
- npm is used to install new tools/libraries
YOUR NOTES¶
Creating a new project¶
- to build a simple static website we will use a tool called Gatsby
- Gatsby runs on Node.js and we need to use npm to install it
- first, check that Node.js / npm are installed.
- open a terminal and run node –version and npm –version
- in order to install simply gatsby, run npm install -g gatsby-cli
- -g instructs npm to globally install the tool on your computer (so that you can use it from any folder)
- to create a new website run gatsby new static-website
- instead of static-website you can use any name you like
- inspect the website by starting the local development server: gatsby develop
- open the website from the address http://localhost:8000
Building the project locally¶
- gatsby develop can only be used for local development
- we need to create a production-ready version of the website
- to create a build from gatsby we use: gatsby build
- the output is inside the public folder
YOUR NOTES¶
Short introduction to images and Docker¶
- Docker is a tool that allows virtualization
- there is a large collection of images that have many software configurations “pre-installed”
- docker works with images
- an image is a file with a set of instructions on how to package code or tools and all the dependencies
- once an image is executed, it becomes a container
- a container has some similarities with a virtual machine (but it isn’t one)
- traditional CI server require to install all the tools/dependencies on the server
- Gitlab breaks this pattern (see the architecture lecture as well) and works with Docker images which contain all the dependencies
- the Gitlab CI Runner with be using the specified Docker images
YOUR NOTES¶
Building the project using Gitlab CI¶
- I recommend you use a code editor to edit the project files
- I am using Visual Studio Code which is free to use and can be downloaded from https://code.visualstudio.com/
- we now need to replicate the steps that we have done on our computer in Gitlab
- we first need to create a new file for defining the pipeline: .gitlab-ci.yml
- we use npm install to install all the project dependencies
- we also need to install Gatsby: npm install -g gatsby-cli
- with gatsby build we will build the website on Gitlab
- we prefer to use a Docker image instead of manually installing node & npm
- the reason for using a Docker image with pre-installed node & npm is speed and a simpler pipeline configuration file
- use Docker Hub (https://hub.docker.com/) to search for images
- make sure you are using official images
- make sure the image that you plan to use is updated regularly
- usually a large number of downloads in a good indication that the image is popular and up-to-date
- we will use the “node” image without specifying a version
- if the job fails, try using node in a specific version:
- due to the architecture of Gitlab, executing the jobs may seem very slow (compared to other CI servers)
- we will improve the speed of the jobs during the course
- the output from the job is not saved anywhere, so we need to define an artifact
- the artifact contains only the public folder (no other files)
Adding a test stage¶
- why do jobs fail?
- all command have an exit code (between 0 and 255) that is returned
- 0 means successfully executed
- >0 means that is failed
- we will add a simple test
- the test will check if a string is found inside the index.html file (the start page of the website)
- we use the command grep like this: grep “Gatsby” index.html
- use echo $? will give you the last exit code (on Unix-like machines)
- it is essential to find a way to test your assertions, to make sure that the pipeline fails
Running jobs in parallel¶
- we can use the alpine Docker image to optimize our build speed
- alpine images are only 5MB in size and are faster to download and start
- we can use Gatsby to start a server from the production build (the public folder)
- when we start a server with the website, we can run other kinds of tests
- we use gatsby server to start a local server
- we want to start a server with our website and check if it works
- we can use curl to download a copy of the website using HTTP (similar to what a standard browser does)
- pipes (|) are used to use the output from one command as the input for another
- assigning two jobs to the same stage makes them run in parallel
- when planning to run parallel jobs, you need to make sure there are no dependencies between them
YOUR NOTES
Running jobs in the background¶
- gatsby serve is a never-ending process; it will run forever
- such commands will block the pipeline as the runner will wait for them to complete (which they don’t)
- all jobs have a default timeout (most commonly 1h)
- if a job is not done in 1 hour, Gitlab will terminate it and the pipeline will be marked as failed
- adding & after a command will release the terminal and run the command in the background
- with the sleep command, you can add a delay between commands
- using sleep is considered rather a bad practice, but in some cases, it is acceptable (especially if we are talking about a few seconds)
- if you are adding sleeps that exceed 30 seconds, it might be a sign that you are doing something working
- pipelines can run in parallel (if the previous pipeline did not finish before the next pipeline is triggered)
- if you want to stop a running job, you can simply open the job and click on Cancel
- we have used the tac command to fix an error that has occurred as a result of using curl
YOUR NOTES
Deployment using surge.sh¶
- surge is a cloud platform for hosting static websites
- surge is easy to use & configure
- install surge on your computer using npm install –global surge
- to create an account/project simply run surge and follow the instructions
YOUR NOTES
Using environment variables for managing secrets¶
- do not store any credentials (username, passwords, tokens) in your pipeline OR project files
- with Gitlab you can define environment variables that contain secrets
- environment variables will be available when running the pipeline
- in order to deploy with surge from Gitlab, we need to generate a token: surge token
- we do not want to give Gitlab our username (email) and password, so a token is a better alternative
- to create an environment variable from your project to Settings > CI/CD
- the variables that we will use are SURGE_LOGIN and SURGE_TOKEN
- the name of the variables is given by Surge, as Surge will automatically detect them
YOUR NOTES
Deploying the project using Gitlab CI¶
- every time you want to use a tool, you need to make sure it is installed
- the node Docker image that we use does not include surge, so we use npm to install surge
- alternatively, we could use a Docker image that already has surge installed
- to deploy a project run: surge –project ./public –domain SOMENAME.surge.sh
YOUR NOTES
How does Surge use environment variables?¶
- if you use a predefined name for the variable, Surge will automatically look for the variables and use them
- this makes the configuration much easier
- it also reduces the temptation of including credentails in the pipeline