# Gitlab-CI

![](https://cdn-images-1.medium.com/max/2400/1*ezikvlWu0UAwFfh3ko8LXQ.png)

To enable CI/CD Gitlab requires us to follow two steps. They are

1. Add .gitlab-ci.yml to project’s root folder.
2. Setup a Runner.

**Add .gitlab-ci.yml:-**

In the root folder of your Gitlab project add a file with the name `.gitlab-ci.yml` . Gitlab uses this file for CI/CD. All your configurations for CI/CD should be added here. Since it is under git project is also part of the version control system. As you change the configurations in this file and push it to Gitlab, It automatically runs the jobs as per your configurations using your Runner configuration.

**Setup a Runner:-**

In GitLab, Runners run the jobs that you define in `.gitlab-ci.yml`. A Runner can be a virtual machine, a VPS, a bare-metal machine, a docker container or even a cluster of containers. Here I use the default Gitlab runner. If you want to configure your own runner Please check [gitlab ci/cd documentation.](https://docs.gitlab.com/ee/ci/quick_start/README.html#configuring-a-runner)

Now let's try different configurations.

1. **A Basic Job:-**

Let’s start in a traditional way. I mean let us create a basic job that says “Hello world” 😃

The syntax for declaring a job in .gitlab-ci.yml is as follows.

```
job name:
    script:
        - your shell script.
        - more script.....
Ex:-
sayhello:
    script:
      - echo "Hello world"        
```

Tips:-

* `.gitlab-ci.yml` should contain at least one job. If there are no jobs defined in it when you push the code to Gitlab, Gitlab runner will throw an error saying `invalid yaml configuration.` the job running fails.
* Make sure you validate .gitlab-ci.yml before you commit and Gitlab. If there is any validation error you can get it during the validation process. I use [Gitlab Workflow](https://about.gitlab.com/2018/03/01/gitlab-vscode-extension/) ❣️, A great plugin for git operations with visual studio code.
* You can see all the pipelines of a project under the Pipelines section of Gitlab repository.
* You can see the logs of the job by clicking on it. ✅ button indicates your job ran successfully. `Yellow` indicates your job is paused. ❌ indicates that your job failed. `Blue` represents that the job is running.
* Any `.gitlab-ci.yml` supported keywords can't be used as a job name.

Once you commit the above code and push it to Gitlab, it should run a job with the specified name and execute the script you mentioned under script tag.gitlab pipelines section which shows all the jobs running and ran with respective status.

![](https://cdn-images-1.medium.com/max/2400/1*gWmgcl8eN0boYK1SA3D6HQ.png)

**2. Multiple jobs:-**

Okay now we know how to write a single job, Can we write multiple jobs in .gitlab-ci.yml?

The answer is **Yes**. You can write as many as jobs you want. The Only condition is that Jobs should have different names. Let’s write 2 jobs in which one says **hi** and the other says **Bye**.

```
#A job with sayHello name
sayHello:
   script: 
      - echo "hi"
#A job with sayBye name
sayBye:
   script:
      - echo "Bye"      
```

Tips:-

* Make sure you don’t have multiple jobs with the same name If your config has multiple jobs with the same name, beginning jobs will be skipped and the last job will be executed.
* The default stage for a given job is **test.**

The output should look like this if you click on the pipeline id which starts with `#`.Multiple job configurations.

![](https://cdn-images-1.medium.com/max/2400/1*_rMyCFdq9Xj0taA1UuiEJQ.png)

**3. Jobs with stages:-**

Generally, every project will have stages before deploying like clean, build, test and deploy. Each stage will have a set of commands to execute. How do we configure jobs in with `stages in .gitlab-ci.yml` ?

```
#stages can be declared using a keyword stages. You can add any number of stages as you require.
```

```
stages:
   - clean
   - build
   - test
   - deploy
#Lets define a job with for every stage.
jobCleaning:
   stage: clean # This tag tells gitlab to run this job only for clean stage
   script:
      - echo "Cleaning the code"
jobBuilding:
   stage: build # This tag tells gitlab to run this job only for build stage
   script:
      - echo "Building the code"
jobTesting:
   stage: test # This tag tells gitlab to run this job only for test stage
   script:
      - echo "Testing the code"
jobDeploying:
   stage: deploy # This tag tells gitlab to run this job only for deploy stage
   script:
      - echo "Deploying the code"   
   
```

image showing stages, respective job configurations.

![](https://cdn-images-1.medium.com/max/2400/1*2DDPuuSMRuZiUrXdY85lBw.png)

Tips:-

* Every stage need not have a job declared.
* Order of the job execution is based on the order of stage declaration. If a stage doesn’t have at least one job defined, Then that stage will be skipped and goes to next stage job.
* A stage can have multiple jobs defined.

Image showing multiple jobs under a stage.

![](https://cdn-images-1.medium.com/max/2400/1*7z3FEoRJyw-TqidV8cs0Nw.png)

* if you have defined a stage called “test”, and define a job without stage added in it, Then the job will run under test stage since the default stage is **test**.
* If you haven’t defined the **test stage** and create a job without stage defined in it, Then Gitlab pipeline will throw an error like `yaml invalid`and will ask you to specify the stage for the job as shown below.

pipeline failure caused by not specifying stage parameter to the job named commonJob.

![](https://cdn-images-1.medium.com/max/2400/1*W7al7dW5rmlMUTrv6hv_Fw.png)

**4. Branch-specific jobs:-**

By default with the previous configurations we had, Whenever you make a push to any other branch the pipeline will get triggered on the branch. This setup is good if you have common functionality to implement. But let’s try to add a config which runs only when you push the code to **dev** branch.

This can be done very simply by adding `only` tag to a job.

```
stages:
   - clean
   - build
   - test
   - deploy
```

```
jobCleaning:
   stage: clean 
   script:
      - echo "Cleaning the code"
   only:
      -dev
jobBuilding:
   stage: build 
   script:
      - echo "Building the code"
   only:
      -dev
jobTesting:
   stage: test
   script:
      - echo "Testing the code"
   only:
      -dev
jobDeploying:
   stage: deploy
   script:
      - echo "Deploying the code"
   only:
      -dev      
```

As discussed above snippet will run on all operation you perform on dev branch i.e for merge requests, issues, pushes.

Tips:-

* `only` will accept regular expressions. If your commit matches with regular expression, pipeline gets activated and jobs will executed as per configuration.
* allowed values to `only` tag are as follows.

allowed values to

![](https://cdn-images-1.medium.com/max/1600/1*tFb--yl5pbkb7OXcUne-6Q.png)

But what if you want to run your job only for issue commits or new merge requests only?

**5. Excepting a job from pipeline:-**

What if your requirement is not to run your pipeline for a certain case?

We can achieve this by providing `except`to the job configuration. See the following example

```
stages:
   - clean
   - build
   - test
   - deploy
jobCleaning:
   stage: clean clean stage
   script:
      - echo "Cleaning the code"
   only:
      - dev
   except:
      - merge_requests # this job will not run for all merge requests on dev branch
jobBuilding:
   stage: build 
   script:
      - echo "Building the code"
   only:
      - dev
jobTesting:
   stage: test
   script:
      - echo "Testing the code"
   only:
      -dev
jobDeploying:
   stage: deploy
   script:
      - echo "Deploying the code"
   only:
      -dev   
```

If your job has both `only, except` configurations, The flow of execution as follows

* `only` and `except` are inclusive. If both `only` and `except` are defined in a job specification, the ref is filtered by `only` and `except`.
* `only` and `except` allow the use of regular expressions (using [Ruby regexp syntax](https://ruby-doc.org/core/Regexp.html)).
* `only` and `except` allow to specify a repository path to filter jobs for forks.

**6. Fail-safe jobs:-**

By default If a pipeline contains multiple jobs in multiple stages, If an error occurs at any job, Next jobs will be skipped with a pipeline status as `failed`.Image showing job failure and skipping remaining jobs in the pipeline.

![](https://cdn-images-1.medium.com/max/2400/1*qOE3AMVTR8iS7nbtIMkoNQ.png)

But If we still want to proceed and continue the pipeline, we can achieve this by adding a config param called `allow_failure`. It accepts either `true` or `false` . The default value is false. That is the reason if any error occurs in pipeline remaining jobs will be skipped.

See the below example configuration.

```
stages:
   - clean
   - build
   - test
   - deploy
jobCleaning:
   stage: clean clean stage
   allow_failure: true #this tells gitlab to not skip other jobs in the pipeline if any error occurs in the current job.
   script:
      - echo "Cleaning the code"
   only:
      - dev
   except:
      - merge_requests # this job will not run for all merge requests on dev branch
jobBuilding:
   stage: build 
   script:
      - echo "Building the code"
   only:
      - dev
jobTesting:
   stage: test
   script:
      - echo "Testing the code"
   only:
      -dev
jobDeploying:
   stage: deploy
   script:
      - echo "Deploying the code"
   only:
      -dev   
```

Image showing job failure but still continuing remaining jobs in the pipeline.

![](https://cdn-images-1.medium.com/max/2400/1*Rx-7Ee9DF2O3kOAwbb64Kg.png)

Tips:-

* If you want to retry the job in case of failure again for a certain number of times can be configured using `retry` in the job configuration.
* If `retry` is set to 2, and a job succeeds in a second run (first retry), it won’t be retried again.
* `retry` value has to be a positive integer, equal to or larger than 0, but lower or equal to 2 (two retries maximum, three runs in total).

**7. Running Jobs at a certain job status:-**

Okay, We have tried faile safe jobs and retrying them too. But What if we need to implement a job which runs if a job fails or a job runs successfully or even always despite the job status?

This can be achieved by using the `when` tag of the job configuration.

Allows values for the when tag are

* `on_success` - execute job only when all jobs from prior stages succeed (or are considered succeeding because they are marked `allow_failure`). This is the default.
* `on_failure` - execute job only when at least one job from prior stages fails.
* `always` - execute job regardless of the status of jobs from prior stages.
* `manual` - execute job manually (added in GitLab 8.10). Read about [manual actions](https://docs.gitlab.com/ee/ci/yaml/README.html#whenmanual) below.

Let's see an example which runs a job called `jobSuccess` for the successful running of the job, `jobFailure` which runs on job failure, `runAlways` which runs always.

```
stages:
   - clean
   - build
   - test
   - deploy
jobCleaning:
   stage: clean clean stage
   script:
      - echo "Cleaning the code"
   only:
      - dev
   except:
      - merge_requests # this job will not run for all merge requests on dev branch
jobBuilding:
   stage: build 
   script:
      - echo "Building the code"
   only:
      - dev
jobTesting:
   stage: test
   script:
      - echo "Testing the code"
   only:
      -dev
jobDeploying:
   stage: deploy
   script:
      - echo "Deploying the code"
   only:
      -dev
jobSuccess:
   script:
      - echo "Running on successful running of the job."
   when: on_success
   stage: test
jobFailure:
   script:
      - echo "Running on failure of the job."
   when: on_failure 
   stage: test
jobAlways:
   script:
      - echo "Running always job"
   when: always
   stage: test   
```

Image showing pipeline which has jobSuccess, jobFailure, jobAlways which are configured with when field.

![](https://cdn-images-1.medium.com/max/2400/1*4YqLxvMGmqe3MYxRWGSPUA.png)

Note:-

* Observe that `jobFailure` is skipped because `jobTesting` is not Failed. It will run if `jobTesting`fails.

**8. Defining variables in jobs:-**

Gitlab allows you to create variables in the `gitlab-ci.yml` .These variables can be later used in the job configurations. A variable declaration should follow`key:value` format.

There are two types of variables in Gitlab CI/CD.

* Global variables.
* Job specific variables.

Both types of variables can be defined by using a tag called `variables` .

If you define `variables` in Job configuration, variables under it become job specific variables and will override the global variables with the same name are defined.

If you define `variables` as root tag, Values under it will become global variables. These can be accessed in any job under the pipeline.

Once you define the variables, They can be accessed using

```
# Global variables. These variables can be accessed in any job.
variables:
   BRANCH_NAME: "dev"
   CLEAN_COMMAND: "mvn clean"
   OVERRIDE_VARIABLE: "OVERIDE BEFORE"
stages:
   - clean
   - build
   - test
   - deploy
jobCleaning:
   stage: clean clean stage
   variables: #Job specific variables. 
      SECRET_KEY: "This is secret key"
      OVERRIDE_VARIABLE: "OVERIDED AFTER" #Varibale name is same as gloabl variable. SO this variable should be overriden.
   retry: 1
   script:
      - echo "Cleaning the code"
      - echo "${OVERRIDE_VARIABLE}" # should print  OVERIDED AFTER.
      - echo "${CLEAN_COMMAND}"
only:
      - dev
   except:
      - merge_requests # this job will not run for all merge requests on dev branch
jobBuilding:
   stage: build 
   script:
      - echo "Building the code"
   only:
      - dev
jobTesting:
   stage: test
   script:
      - echo "Testing the code"
   only:
      -dev
jobDeploying:
   stage: deploy
   script:
      - echo "Deploying the code"
   only:
      -dev   
   
```

Job log which shows job specific and global variables.

![](https://cdn-images-1.medium.com/max/2400/1*OxHWzeiE3LJ0KbiM8Ecpzw.png)

These are some of the cases I have tried. There are more advanced topics like `cache, artifacts, environments, include` etc. I will write about them in another blog. If you want to read more about Gitlab CI/CD refer below document.

Copied From - <https://medium.com/faun/ci-cd-essentials-from-scratch-with-gitlab-61502acf318e>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tkssharma-devops.gitbook.io/devops-training/devops-01-continuous-integration/continuous-integration-and-continuous-delivery/ci-cd-using-gitlab-ci-s3.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
