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
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
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
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
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
jobs-deploy.yml
deploy-cloud-run-services:
stage: deploy
script:
- echo $MY_SERVICE " - " $MY_IMAGE
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 specs
attribute 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.inputs
structure:
spec:
inputs:
my-service:
my-image:
---
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-image
variable.
spec:
inputs:
my-service:
my-image:
default: "my-image:latest"
---
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 ]]"
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
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"'
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)
Excited to test this 😁
It took me some time to understand the usage, but it seems pretty straitghforward.
I would declare it this way :
And use it this way :
Yes the syntax is a little bit different but it’a a great feature and very good to create commons jobs