DEV Community

Cover image for GitLab - Define and write jobs’ specifications
Jean-Phi Baconnais for Zenika

Posted on • Edited on

GitLab - Define and write jobs’ specifications

The “specs” attribute?

The “specs” attribute has been introduced in GitLab CI since the release 15.11 of GitLab (as mentioned in this blog post).

This attribute allows you to invalidate CI when one field typed as “important” is missing.

When should I use the specs attribute?

To illustrate one benefit of using this attribute, let me explain with an example. This simple command allows you to deploy a Cloud Run service based on a Docker image called my-image.

gcloud run deploy my-service --image my-image
Enter fullscreen mode Exit fullscreen mode

This works, but if I want to optimize this script and use it for other services, I can replace the names of my service and my image by variables, like this:

gcloud run deploy $MY_SERVICE --image $MY_IMAGE

Enter fullscreen mode Exit fullscreen mode

To integrate this command into a GitLab CI job, I can simply include it in a script attribute within a job:

deploy-cloud-run-services:
[...]
script: 
gcloud run deploy $MY_SERVICE --image $MY_IMAGE
Enter fullscreen mode Exit fullscreen mode

Before GitLab 15.11 release or without the specs attribute, how can I call this script?

If all jobs are defined in the same .gitlab-ci.yml file, I can add a variables attribute:

variables: 
  MY_SERVICE: my-service-1
  MY_IMAGE: my-image-1

deploy-cloud-run-services:
[...]
script: 
gcloud run deploy $MY_SERVICE --image $MY_IMAGE

Enter fullscreen mode Exit fullscreen mode

In most “real life” cases, not all your jobs are in the same file. Well, I hope so 😅. By using the include attribute, you can link files and your variables will automatically be sent to the included jobs.

.gitlab-ci.yml file :

stages:
  - deploy 

variables: 
  MY_SERVICE: my-service-2
  MY_IMAGE: my-image-2

include:
  - local: jobs-deploy.yml

Enter fullscreen mode Exit fullscreen mode

jobs-deploy.yml

deploy-cloud-run-services:
  stage: deploy
  script: 
    - echo $MY_SERVICE " - " $MY_IMAGE

Enter fullscreen mode Exit fullscreen mode

By using an included file, you can quickly see that knowing which parameters I should send to each job I call can be complicated. Of course every job included in your pipeline needs to be checked. But when a job adds a variable, all the impacts may be hard to find.

The only way to verify the impacts in your pipelines is to execute them. However you will be informed a bit late if something goes wrong.

This is why the specs attribute can save your life time.

Within the specs attribute, a yaml invalid error will appear immediately in your pipeline if a variable is missing.

The specsattribute allows you to create reusable jobs, avoiding you to duplicate jobs and most important, to catch errors earlier. With this attribute, you can easily have a description of all the parameters for a job and identify which ones are essential.

To sum up our example, with the specs attribute you start by defining all your parameters in a spec.inputsstructure:

spec:
  inputs:
    my-service:
    my-image: 
---
Enter fullscreen mode Exit fullscreen mode

With this specification, written at the beginning of your yaml file, users can easily see all parameters. In this case, these two parameters have to be set, or an error will appear in your pipeline.

You can specify a default value for your parameters. Jobs that call your job can not define my-imagevariable.

spec:
  inputs:
    my-service:
    my-image: 
      default: "my-image:latest"
---
Enter fullscreen mode Exit fullscreen mode

In jobs, a new way to use your variable is to enclose it within two square brackets like $[[ inputs.my-service ]].

deploy-cloud-run-services:
[...]
script: 
gcloud run deploy $[[ inputs.my-service ]]" --image $[[ inputs.my-image ]]"
Enter fullscreen mode Exit fullscreen mode

Pipelines including this example job can use it and customize with their own variables with this syntax:

include:
  - local: jobs-deploy.yml
    inputs:
       MY_SERVICE: my-service-2
       MY_IMAGE: my-image-2
Enter fullscreen mode Exit fullscreen mode

Edit 2023-12-18

💡 You can have rules on your jobs containing variables from spec attribute, you have to wrap the input block by a quote

rules:
    - if: '"$[[ inputs.my-image ]]" == "a type of image"'
Enter fullscreen mode Exit fullscreen mode

A CI/CD Catalog

This new feature is the first step of a significant epic, the CI/CD Catalog. You can find all the information and thoughts in this epic. This feature is in its early stages but the primary goal is to provide templates that can be easily used in many projects without too much effort. Every component has to be isolated, reusable, versioned, resolvable and focused on a single objective while being as small as possible.

This feature has already been explored. I am thinking in particular of R2DevOps (who is a partner with GitLab) and Orange with this project to-be-continuous.

GitLab is working on its own catalog but some challenges exist and are hard to resolve: how do you document templates? How do you version them? How do you maintain these templates? For further informations, you can refer to this page: https://docs.gitlab.com/ee/architecture/blueprints/ci_pipeline_components/

Top comments (2)

Collapse
 
bcouetil profile image
Benoit COUETIL 💫

Excited to test this 😁

It took me some time to understand the usage, but it seems pretty straitghforward.

I would declare it this way :

spec:
  inputs:
    stage:
      default: test
---
component-job:
  script: echo job 1
  stage: $[[ inputs.stage ]]
Enter fullscreen mode Exit fullscreen mode

And use it this way :

include:
  - component: gitlab.example.com/my-namespace/my-component@1.0
    inputs:
      stage: build
Enter fullscreen mode Exit fullscreen mode
Collapse
 
jphi_baconnais profile image
Jean-Phi Baconnais

Yes the syntax is a little bit different but it’a a great feature and very good to create commons jobs