Gitlab CI in multiple platforms simultaneously - gitlab

I have a C++ project that is compiled and packaged for multiple OS (Linux, Windows, MacOS) as well as multiple CPU architectures (i386, x86_64, arm, Aarch64)
For this I'm using Jenkins to grab the source code and run the build script in parallel on each system. It's a simple working solution, since my build script deals with the system differences.
Now I'm looking into Gitlab CI/CD, and it has many things I find appealing ( being able to keep the build script as part of the repository, very well integrated with the git repo and ticketing system, natural use of Docker containers, etc), but I cannot find any way to run the same pipeline in multiple architectures/systems parallel to each other.
So, say that my build script is:
build:
stage: build
script:
- uname -m > arch.txt
artifacts:
paths:
- arch.txt
How can I tell Gitlab that I want to run this job in multiple runners/Docker containers/systems at the same time? All the documentation I've read so far deals with running multiple tests on one build, integrating multiple projects or deploying in different environments depending on branches. Nothing I've read so far tries to do many separate builds, test and package them individually and report on their independent results. Is this feasible on Gitlab CI/CD?

GitLab uses "runners" to execute CI jobs. Runners are installed wherever you want to run a CI job, so if you want to run on multiple architectures then you will need to install runners on systems for each architecture. Runner install documentation can be found here:
https://docs.gitlab.com/runner/install/index.html
For Linux-based jobs it is common to use Docker for job execution - this doesn't give architectural flexibility, but it does allow you to test on different flavors and with different software using containerisation. For other architectures you may need to install runners yourself, or use other peoples shared runners.
While you are installing the runner software there are some keys steps:
you have the opportunity to link each runner to your GitLab project, which means it will show up in the runners list under Project > Settings > CI/CD.
you will have the opportunity to assign "tags" to the runners. Tags can be used to help identify a runner or group of runners by an arbitrary name (e.g. you could add "Windows x86_64" as a tag, or "Windows" and "x86_64" tags). These tags can be used in jobs to select a runner.
Once you have your runners installed you can get editing your .gitlab-ci.yml file.
GitLab CI files are broken up into "stages". Jobs in each stage can run in parallel. Stage names are defined at the top of the file.
stages:
- build
- deploy
Each CI job can be attached to a stage by using the stage: entry:
build job:
stage: build
script:
- echo "I am a build stage job"
In your case you will need to create multiple jobs for each architecture you want to build for. Attaching these to the same stage will allow them to run in parallel.
To control where each job runs you have two main mechanisms:
Tags - tags allow you to pin a job to a runner tag. You can specify multiple tags using the tags: entry which forms an AND list (e.g. win tag AND x86_64 tag). When that job runs GitLab will find a runner that has all the required tags, and run the job there.
Image - When running on Docker / Kubernetes you can specify a docker image to use for the runner. To use a docker image you first need to specify a runner that can run docker images (e.g. a docker-in-docker or kubernetes runner), which might, for example, be tagged with docker or kubernetes. Then you use the image: entry to specify the docker image.
Here's an example showing both tags and images:
build win x86_64:
stage: build
tags:
- win
- x86_64
script:
- echo "I am a build stage job for win x86_64"
build win 32:
stage: build
tags:
- win
- 32-bit
script:
- echo "I am a build stage job for win 32"
build debian:
stage: build
tags:
- docker
image: debian:stretch
script:
- echo "I am a build stage job for debian, running on docker using debian:stretch image"
There is currently no support for dynamic jobs, or running one job on multiple runners / architectures, so this involves a bit of manual effort. On the positive side it makes GitLab CI files easy to read, and easy to see what will run during CI execution.

Check out the latest GitLab release 11.5 (Nov. 2018) with:
Parallel attribute for faster pipelines
The speed of pipelines is an important factor for any team, and running tests or other parallelizable tasks tends to take a big chunk of the time for any build.
Adding this new keyword gives teams the ability to simply parallelize tests, allowing everyone to accelerate their software delivery process.
To use this feature, simply set the parallel attribute to how many copies of the task you’d like to split it into, and GitLab will handle the work of automatically creating the appropriate number of jobs running your task.
As commented by March, this is not an exact fit for the OP (which is about running the same pipeline in multiple architectures/systems parallel to each other).
See documentation and issue.
parallel allows you to configure how many instances of a job to run in parallel.
This value has to be greater than or equal to two (2) and less or equal than 50.
This creates N instances of the same job that run in parallel.
They’re named sequentially from job_name 1/N to job_name N/N.
test:
script: rspec
parallel: 5

Related

In Gitlab why we are using the particular image if we already have gitlab runner to run the code

I am new to Gitlab, and bit confuse with the Gitlab Image keyword..
If we already have gitlab runners specified to run the commands they why are we separately use Image keywords in the gitlab-ci.yml (in Any stage or Jobs)enter image description here
One important concept to be aware of is that there are a few different executors that a gitlab-runner may use. On gitlab.com, a docker+machine executor is used. The docker/kubernetes executors are the only context where the image: keyword is relevant.
When jobs run in these executor types, they do not run directly in the host context of the runner. Instead, a docker container is created to run each job. For this, a Docker image must be used. The default image works for general use cases, but you may want to choose a different ready-made image for your use. This can make your environment more repeatable as well as reduce job times by avoiding time that would otherwise need to be spent installing software requirements.
For example, if I have a job that builds python software, I may choose to use image: "python:3.10.2" because it will contain the Python runtime and tools I need for building Python software.
By contrast, if you are using a shell executor, your jobs execute directly in the host -- you can simply use software available on the runner host itself and there is no image: to choose.

Run jobs in parallel in .gitlab.ci.yml

Basically I currently have 5 test licenses on a server. I have a pipeline that runs test scripts when I trigger it manually. It connects to the license server and acquires a floating license . This approach is good for now but soon I will be wanting to expand this so that when the application needs testing, I can run multiple pipelines in parallel to have multiple tests running. Here's the thing, I'm wanting to only sometimes run them in parallel based on what I need to test and I would want to manually trigger each pipeline. For example, one day I might only want to run the tests scripts on one job so this requires one pipeline running. Another day I might want to run 3 jobs at the same time or another day I may want to run 5 jobs throughout the day but may overlap with a running pipeline so it needs to run its own pipeline.
My question is, how do I go about setting this up in a gitlab yml file.
If anyone could also provide a basic example that would be helpful!
As a general rule, any job within the same stage is run in parallel. Within those jobs, you can define rules that specify when a given job runs. Note that needing to manually kick off jobs will cause your overall pipeline to be listed as "blocked" when the manual jobs are reached. Similarly, you'll need to set some jobs as allow_failure: true or they will block the next stage from executing. Example pipeline:
stages:
- build
- test
build_job:
image: alpine:latest
stage: build
script:
- echo "hello world"
test_job_1:
image: alpine:latest
stage: test
rules:
- when: manual
script:
- echo "test 1"
test_job_2:
image: alpine:latest
stage: test
rules:
- when: manual
script:
- echo "test 2"
When you run the above pipeline, you will have to manually click "play" on both jobs to start them.
I will note though, that this feels like an anti-pattern. It sounds like you want to conserve your 5 test licenses to make sure that you don't, for example, have 6 jobs running and have a job fail due to no free licenses. If so, this is one of the exact use-cases that the resource_group keyword is meant to address. Jobs added to the same resource group do not run concurrently (even if they are in different pipelines), so you could have a test_1 resource group, test_2 resource group, etc, and those jobs would always run in parallel automatically, but would never run more than one instance of that job at once even across different pipelines. This allows you ensure you only use 5 licenses, but your tests still run automatically and you don't need to manually trigger them, which also allows you to more easily define downstream jobs to run when your tests pass.

Gitlab CI how to deploy to different environments using different runners?

I use gitflow for my branching feature-branches, develop, master + release. On top, I have multiple environments dev and multiple tests in one account and stage and prod in another. Now I want to have one "runner" in each account and want to deploy to each of these environments with Gitlab CI.
Branches
feature/*
develop
master
release
Environments
Account test - one runner here
dev
test
Account prod - one runner here
stage
prod
I came across environments ... but do not know what benefit they bring beyond visibility, I tinker with tags and could link runners to jobs by tags ... which is quite inflexible.
Can you help me out how to do this without having one job for each environment, resulting in a lot of jobs and a loooong .gitlab-ci.yml?
Here, do we need to have one job for each environment? Since you have 2 account groups, one test (feature, develop, etc.) and the other one as prod (master, release), are you ok with having 2 jobs for each of these?

gitlab cloud CI: how to increase memory for shared runner

My Gitlab CI jobs fail because of RAM limitations.
Page https://docs.gitlab.com/ee/user/gitlab_com/index.html says:
All your CI/CD jobs run on n1-standard-1 instances with 3.75GB of RAM, CoreOS and the latest Docker Engine installed.
Below it says:
The gitlab-shared-runners-manager-X.gitlab.com fleet of runners are dedicated for GitLab projects as well as community forks of them. They use a slightly larger machine type (n1-standard-2) and have a bigger SSD disk size. They don’t run untagged jobs and unlike the general fleet of shared runners, the instances are re-used up to 40 times.
So, how do I enable these n1-standard-2 runners (which have 7.5 GB RAM)? I've read the docs over and over but can't seem to find any instructions.
Disclaimer: I did not check if you can use them with a project and if they picked up for your gitlab CI/CD - but that is the way, of how you can check for available Runners and their tags, and how to use them. The terminology GitLab projects as well as community forks of them reads like that this is only for Official GitLab projects and their forks - and not for random projects on GitLab.
You can check all the available runners in your projects CI/CD Settings under Runners, and you will see a list of runners there like:
As you can see there are Runners tagged with gitlab-org. Base on the description you can not run them, without using a tag. Hence that you need to adapt your .gitlab-ci.yml file with those appropriate tags.
EG:
job:
tags:
- gitlab-org
see GitLab documentation for tags

Gitlab CI: running the same set of tests on several machines

In high performance computing is crucial to have a code tested against many different architectures/compilers: from a laptop to a supercomputer.
Assuming that we have
N testing machines/workers (each one running gitlab-ci-runner);
M tests,
what shall be the correct layout of .gitlab-ci.yml to ensure that each of the N machines runs all the tests?
Looks to me that adding just more workers ends up in a round-robin like assignment of the jobs.
Thanks for your help.
You could use tags in your .gitlab-ci.yml and on the runners to distribute your tests to all mashines you want. Gitlab CI is very open to those use cases. I assume that you don't use docker for testing.
To accomplish your goal, do following steps:
Install your gitlab-ci-multi-runners on your N mashines BUT if the runner ask you for tags, tag the mashine with a specifc name e.g. "MashineWithManyCPUsWhatever". Please use the gitlab-ci-multi-runner register command to do so. You can alternatively change the tags in Gitlab on the administration view after registration.
The type of the runners should be "shared" not "specific".
When you installed and tagged every runner on your mashines, tag you jobs.
Example:
Every job will now be excecuted on the specific mashine with the specific tag.
For more Information see Gitlab CI Documentation

Resources