[{"data":1,"prerenderedAt":721},["ShallowReactive",2],{"/en-us/blog/basics-of-gitlab-ci-updated/":3,"navigation-en-us":37,"banner-en-us":466,"footer-en-us":483,"Itzik Gan Baruch":693,"next-steps-en-us":706},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":27,"_id":30,"_type":31,"title":32,"_source":33,"_file":34,"_stem":35,"_extension":36},"/en-us/blog/basics-of-gitlab-ci-updated","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Running CI jobs in sequential, parallel, and custom orders","New to continuous integration? Learn how to build your first CI pipeline with GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662061/Blog/Hero%20Images/cicdcover.png","https://about.gitlab.com/blog/basics-of-gitlab-ci-updated","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The basics of CI: How to run jobs sequentially, in parallel, or out of order\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2020-12-10\",\n      }",{"title":17,"description":10,"authors":18,"heroImage":11,"date":20,"body":21,"category":22,"tags":23,"updatedDate":26},"The basics of CI: How to run jobs sequentially, in parallel, or out of order",[19],"Itzik Gan Baruch","2020-12-10","Let's assume that you don't know anything about [continuous integration\n(CI)](/topics/ci-cd/) and [why it's\nneeded](/blog/how-to-keep-up-with-ci-cd-best-practices/) in the software\ndevelopment lifecycle.\n\n\nImagine that you work on a project, where all the code consists of two text\nfiles. Moreover, it is super critical that the concatenation of these two\nfiles contains the phrase \"Hello, world.\"\n\n\nIf it's not there, the whole development team won't get paid that month.\nYeah, it is that serious!\n\n\nThe most responsible software developer wrote a small script to run every\ntime we are about to send our code to customers.\n\n\nThe code is pretty sophisticated:\n\n\n```bash\n\ncat file1.txt file2.txt | grep -q \"Hello world\"\n\n```\n\n\nThe problem is that there are 10 developers on the team, and, you know,\nhuman factors can hit hard.\n\n\nA week ago, a new guy forgot to run the script and three clients got broken\nbuilds. So you decided to solve the problem once and for all. Luckily, your\ncode is already on GitLab, and you remember that there is [built-in\nCI](/solutions/continuous-integration/). Moreover, you heard at a conference\nthat people use CI to run tests...\n\n\n## Let's run our first test inside CI\n\n\nAfter taking a couple of minutes to find and read the docs, it seems like\nall we need is these two lines of code in a file called `.gitlab-ci.yml`:\n\n\n```yaml\n\ntest:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n```\n\n\nWe commit it, and hooray! Our build is successful:\n\n\n![build\nsucceeded](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/build_succeeded.png)\n\n\nLet's change \"world\" to \"Africa\" in the second file and check what happens:\n\n\n![build\nfailed](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/build_failed.png)\n\n\nThe build fails as expected!\n\n\nOK, we now have automated tests here! GitLab CI will run our test script\nevery time we push new code to the source code repository in the DevOps\nenvironment.\n\n\n**Note:** In the above example, we assume that file1.txt and file2.txt exist\nin the runner host.\n\n\nTo run this example in GitLab, use the below code that first will create the\nfiles and then run the script.\n\n\n```yaml\n\ntest:\n\nbefore_script:\n      - echo \"Hello \" > | tr -d \"\\n\" | > file1.txt\n      - echo \"world\" > file2.txt\nscript: cat file1.txt file2.txt | grep -q 'Hello world'\n\n```\n\n\nFor the sake of compactness, we will assume that these files exist in the\nhost, and will not create them in the following examples.\n\n\n## Make results of builds downloadable\n\n\nThe next business requirement is to package the code before sending it to\nour customers. Let's automate that part of the software development process\nas well!\n\n\nAll we need to do is define another job for CI. Let's name the job\n\"package\":\n\n\n```yaml\n\ntest:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  script: cat file1.txt file2.txt | gzip > package.gz\n```\n\n\nWe have two tabs now:\n\n\n![Two tabs - generated from two\njobs](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/two_tabs.png)\n\n\nHowever, we forgot to specify that the new file is a build _artifact_, so\nthat it could be downloaded. We can fix it by adding an `artifacts` section:\n\n\n```yaml\n\ntest:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  script: cat file1.txt file2.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n```\n\n\nChecking... it is there:\n\n\n![Checking the download\nbutton](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/artifacts.png)\n\n\nPerfect, it is! However, we have a problem to fix: The jobs are running in\nparallel, but we do not want to package our application if our tests fail.\n\n\n## Run jobs sequentially\n\n\nWe only want to run the 'package' job if the tests are successful. Let's\ndefine the order by specifying `stages`:\n\n\n```yaml\n\nstages:\n  - test\n  - package\n\ntest:\n  stage: test\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  stage: package\n  script: cat file1.txt file2.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n```\n\n\nThat should be good!\n\n\nAlso, we forgot to mention, that compilation (which is represented by\nconcatenation in our case) takes a while, so we don't want to run it twice.\nLet's define a separate step for it:\n\n\n```yaml\n\nstages:\n  - compile\n  - test\n  - package\n\ncompile:\n  stage: compile\n  script: cat file1.txt file2.txt > compiled.txt\n  artifacts:\n    paths:\n    - compiled.txt\n\ntest:\n  stage: test\n  script: cat compiled.txt | grep -q 'Hello world'\n\npackage:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n```\n\n\nLet's take a look at our artifacts:\n\n\n![Unnecessary\nartifact](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/clean-artifacts.png)\n\n\nHmm, we do not need that \"compile\" file to be downloadable. Let's make our\ntemporary artifacts expire by setting `expire_in` to '20 minutes':\n\n\n```yaml\n\ncompile:\n  stage: compile\n  script: cat file1.txt file2.txt > compiled.txt\n  artifacts:\n    paths:\n    - compiled.txt\n    expire_in: 20 minutes\n```\n\n\nNow our config looks pretty impressive:\n\n\n- We have three sequential stages to compile, test, and package our\napplication.\n\n- We pass the compiled app to the next stages so that there's no need to run\ncompilation twice (so it will run faster).\n\n- We store a packaged version of our app in build artifacts for further\nusage.\n\n\n## Learning which Docker image to use\n\n\nSo far, so good. However, it appears our builds are still slow. Let's take a\nlook at the logs.\n\n\n![ruby3.1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/ruby-31.png)\n\n\nWait, what is this? Ruby 3.1?\n\n\nWhy do we need Ruby at all? Oh, GitLab.com uses Docker images to [run our\nbuilds](/blog/shared-runners/), and [by\ndefault](https://docs.gitlab.com/ee/user/gitlab_com/#shared-runners) it uses\nthe [`ruby:3.1`](https://hub.docker.com/_/ruby/) image. For sure, this image\ncontains many packages we don't need. After a minute of Googling, we figure\nout that there's an image called\n[`alpine`](https://hub.docker.com/_/alpine/), which is an almost blank Linux\nimage.\n\n\nOK, let's explicitly specify that we want to use this image by adding\n`image: alpine` to `.gitlab-ci.yml`.\n\n\nNow we're talking! We shaved nearly three minutes off:\n\n\n![Build speed\nimproved](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/speed.png)\n\n\nIt looks like there are a lot of public images around:\n\n- [mysql](https://hub.docker.com/_/mysql/)\n\n- [Python](https://hub.docker.com/_/python/)\n\n- [Java](https://hub.docker.com/_/java/)\n\n- [php](https://hub.docker.com/_/php/)\n\n\nSo we can just grab one for our technology stack. It makes sense to specify\nan image that contains no extra software because it minimizes download time.\n\n\n## Dealing with complex scenarios\n\n\nSo far, so good. However, let's suppose we have a new client who wants us to\npackage our app into `.iso` image instead of `.gz`. Since CI does all the\nwork, we can just add one more job to it. ISO images can be created using\nthe [mkisofs](http://www.w3big.com/linux/linux-comm-mkisofs.html) command.\nHere's how our config should look:\n\n\n```yaml\n\nimage: alpine\n\n\nstages:\n  - compile\n  - test\n  - package\n\n# ... \"compile\" and \"test\" jobs are skipped here for the sake of compactness\n\n\npack-gz:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n\npack-iso:\n  stage: package\n  script:\n  - mkisofs -o ./packaged.iso ./compiled.txt\n  artifacts:\n    paths:\n    - packaged.iso\n```\n\n\nNote that job names shouldn't necessarily be the same. In fact, if they were\nthe same, it wouldn't be possible to make the jobs run in parallel inside\nthe same stage of the software development process. Hence, think of same\nnames of jobs and stages as coincidence.\n\n\nAnyhow, the build is failing:\n\n\n![Failed build because of missing\nmkisofs](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/mkisofs.png)\n\n\nThe problem is that `mkisofs` is not included in the `alpine` image, so we\nneed to install it first.\n\n\n## Dealing with missing software/packages\n\n\nAccording to the [Alpine Linux\nwebsite](https://pkgs.alpinelinux.org/contents?file=mkisofs&path=&name=&branch=edge&repo=&arch=)\n`mkisofs` is a part of the `xorriso` and `cdrkit` packages. These are the\nmagic commands that we need to run to install a package:\n\n\n```bash\n\necho \"ipv6\" >> /etc/modules  # enable networking\n\napk update                   # update packages list\n\napk add xorriso              # install package\n\n```\n\n\nFor CI, these are just like any other commands. The full list of commands we\nneed to pass to `script` section should look like this:\n\n\n```yml\n\nscript:\n\n- echo \"ipv6\" >> /etc/modules\n\n- apk update\n\n- apk add xorriso\n\n- mkisofs -o ./packaged.iso ./compiled.txt\n\n```\n\n\nHowever, to make it semantically correct, let's put commands related to\npackage installation in `before_script`. Note that if you use\n`before_script` at the top level of a configuration, then the commands will\nrun before all jobs. In our case, we just want it to run before one specific\njob.\n\n\n## Directed Acyclic Graphs: Get faster and more flexible pipelines\n\n\nWe defined stages so that the package jobs will run only if the tests\npassed. What if we want to break the stage sequencing a bit, and run a few\njobs earlier, even if they are defined in a later stage? In some cases, the\ntraditional stage sequencing might slow down the overall pipeline execution\ntime.\n\n\nImagine that our test stage includes a few more heavy tests that take a lot\nof time to execute, and that those tests are not necessarily related to the\npackage jobs. In this case, it would be more efficient if the package jobs\ndon't have to wait for those tests to complete before they can start. This\nis where Directed Acyclic Graphs (DAG) come in: To break the stage order for\nspecific jobs, you can define job dependencies which will skip the regular\nstage order.\n\n\nGitLab has a special keyword `needs`, which creates dependencies between\njobs, and allows jobs to run earlier, as soon as their dependent jobs\ncomplete.\n\n\nIn the below example, the pack jobs will start running as soon as the test\njob completes, so if, in future, someone adds more tests in the test stage,\nthe package jobs will start to run before the new test jobs complete:\n\n\n```yaml\n\npack-gz:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.gz\n\npack-iso:\n  stage: package\n  before_script:\n  - echo \"ipv6\" >> /etc/modules\n  - apk update\n  - apk add xorriso\n  script:\n  - mkisofs -o ./packaged.iso ./compiled.txt\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.iso\n```\n\n\nOur final version of `.gitlab-ci.yml`:\n\n\n```yaml\n\nimage: alpine\n\n\nstages:\n  - compile\n  - test\n  - package\n\ncompile:\n  stage: compile\n  before_script:\n      - echo \"Hello  \" | tr -d \"\\n\" > file1.txt\n      - echo \"world\" > file2.txt\n  script: cat file1.txt file2.txt > compiled.txt\n  artifacts:\n    paths:\n    - compiled.txt\n    expire_in: 20 minutes\n\ntest:\n  stage: test\n  script: cat compiled.txt | grep -q 'Hello world'\n\npack-gz:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.gz\n\npack-iso:\n  stage: package\n  before_script:\n  - echo \"ipv6\" >> /etc/modules\n  - apk update\n  - apk add xorriso\n  script:\n  - mkisofs -o ./packaged.iso ./compiled.txt\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.iso\n```\n\n\nWow, it looks like we have just created a pipeline! We have three sequential\nstages, the jobs `pack-gz` and `pack-iso`, inside the `package` stage, are\nrunning in parallel:\n\n\n![Pipelines\nillustration](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/pipeline.png)\n\n\n## Elevating your pipeline\n\n\nHere is how to elevate your pipeline.\n\n\n### Incorporating automated testing into CI pipelines\n\n\nIn DevOps, a key software development strategy rule is making really great\napps with amazing user experience. So, let's add some tests in our CI\npipeline to catch bugs early in the entire process. This way, we fix issues\nbefore they get big and before we move on to work on a new project.\n\n\nGitLab makes our lives easier by offering out-of-the-box templates for\nvarious [tests](https://docs.gitlab.com/ee/ci/testing/). All we need to do\nis include these templates in our CI configuration.\n\n\nIn this example, we will include [accessibility\ntesting](https://docs.gitlab.com/ee/ci/testing/accessibility_testing.html):\n\n\n```yaml\n\nstages:\n  - accessibility\n\nvariables:\n  a11y_urls: \"https://about.gitlab.com https://www.example.com\"\n\ninclude:\n  - template: \"Verify/Accessibility.gitlab-ci.yml\"\n```\n\n\nCustomize the `a11y_urls` variable to list the URLs of the web pages to test\nwith [Pa11y](https://pa11y.org/) and [code\nquality](https://docs.gitlab.com/ee/ci/testing/code_quality.html).\n\n\n```yaml\n   include:\n   - template: Jobs/Code-Quality.gitlab-ci.yml\n```\n\n\nGitLab makes it easy to see the test report right in the merge request\nwidget area. Having the code review, pipeline status, and test results in\none spot makes everything smoother and more efficient.\n\n\n![Accessibility\nreport](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_10.56.41.png)\n\n\u003Ccenter>\u003Ci>Accessibility merge request widget\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\n\n![Code quality widget in\nMR](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_11.00.25.png)\n\n\u003Ccenter>\u003Ci>Code quality merge request widget\u003C/i>\u003C/center>\n\n\n### Matrix builds\n\n\nIn some cases, we will need to test our app in different configurations, OS\nversions, programming language versions, etc. For those cases, we'll use the\n[parallel:matrix](https://docs.gitlab.com/ee/ci/yaml/#parallelmatrix) build\nto test our application across various combinations in parallel using one\njob configuration. In this blog, we'll test our code with different Python\nversions using the matrix keyword.\n\n\n```yaml\n\npython-req:\n  image: python:$VERSION\n  stage: lint\n  script:\n    - pip install -r requirements_dev.txt\n    - chmod +x ./build_cpp.sh\n    - ./build_cpp.sh\n  parallel:\n    matrix:\n      - VERSION: ['3.8', '3.9', '3.10', '3.11']   # https://hub.docker.com/_/python\n```\n\n\nDuring pipeline execution, this job will run in parallel four times, each\ntime using different Python image as shown below:\n\n\n![Matrix job\nrunning](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_11.12.48.png)\n\n\n### Unit testing\n\n\n#### What are unit tests?\n\n\nUnit tests are small, targeted tests that check individual components or\nfunctions of software to ensure they work as expected. They are essential\nfor catching bugs early in the software development process and verifying\nthat each part of the code performs correctly in isolation.\n\n\nExample: Imagine you're developing a calculator app. A unit test for the\naddition function would check if 2 + 2 equals 4. If this test passes, it\nconfirms that the addition function is working correctly.\n\n\n#### Unit testing best practices\n\n\nIf the tests fail, the pipeline fails and users get notified. The developer\nneeds to check the job logs, which usually contain thousands of lines, and\nsee where the tests failed so that they can fix them. This check is\ntime-consuming and inefficient.\n\n\nYou can configure your job to use [unit test\nreports](https://docs.gitlab.com/ee/ci/testing/unit_test_reports.html).\nGitLab displays reports on the merge request and on the pipelines details\npage, making it easier and faster to identify the failure without having to\ncheck the entire log.\n\n\n##### JUnit test report\n\n\nThis is a sample JUnit test report:\n\n\n![pipelines JUnit test report v13\n10](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674097/Blog/Content%20Images/pipelines_junit_test_report_v13_10.png){:\n.shadow.center}\n\n\n### Integration and end-to-end testing strategies\n\n\nIn addition to our regular development routine, it's super important to set\nup a special pipeline just for integration and end-to-end testing. This\nchecks that all the different parts of our code work together smoothly,\nincluding those\n[microservices](https://about.gitlab.com/topics/microservices/), UI testing,\nand any other components.\n\n\nWe run these tests\n[nightly](https://docs.gitlab.com/ee/ci/pipelines/schedules.html). We can\nset it up so that the [results automatically get sent to a special Slack\nchannel](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html#notification-events).\nThis way, when developers come in the next day, they can quickly spot any\nissues. It's all about catching and fixing problems early on!\n\n\n### Test environment\n\n\nFor some of the tests, we may need a test environment to properly test our\napps. With GitLab CI/CD, we can automate the deployment of testing\nenvironments and save a ton of time. Since this blog mostly focuses on CI, I\nwon't elaborate on this, but you can refer to this section in the [GitLab\ndocumentation](https://docs.gitlab.com/ee/topics/release_your_application.html).\n\n\n## Implementing security scans in CI pipelines\n\n\nHere are the ways to implement security scans in CI pipelines.\n\n\n### SAST and DAST integration\n\n\nWe're all about keeping our code safe. If there are any vulnerabilities in\nour latest changes, we want to know ASAP. That's why it's a good idea to add\nsecurity scans to your pipeline. They'll check the code with every commit\nand give you a heads up about any risks. We've put together a product tour\nto walk you through adding scans, including static application security\ntesting ([SAST](https://docs.gitlab.com/ee/user/application_security/sast/))\nand dynamic application security testing\n([DAST](https://docs.gitlab.com/ee/user/application_security/dast/)), to\nyour CI pipeline.\n\n\n__Click__ the image below to start the tour.\n\n\n[![Scans product\ntour](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-14_at_13.44.42.png)](https://gitlab.navattic.com/gitlab-scans)\n\n\nPlus, with AI, we can dig even deeper into vulnerabilities and get\nsuggestions on how to fix them. Check out this demo for more info.\n\n\n__Click__ the image below to start the tour.\n\n\n[![product tour explain vulnerability\n](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-14_at_13.50.24.png)](https://tech-marketing.gitlab.io/static-demos/pt-explain-vulnerability.html)\n\n\n## Recap\n\n\nThere's much more to cover but let's stop here for now. All examples were\nmade intentionally trivial so that you could learn the concepts of GitLab CI\nwithout being distracted by an unfamiliar technology stack. Let's wrap up\nwhat we have learned:\n\n\n1. To delegate some work to GitLab CI you should define one or more\n[jobs](https://docs.gitlab.com/ee/ci/jobs/) in `.gitlab-ci.yml`.\n\n2. Jobs should have names and it's your responsibility to come up with good\nones.\n\n3. Every job contains a set of rules and instructions for GitLab CI, defined\nby [special keywords](#keywords).\n\n4. Jobs can run sequentially, in parallel, or out of order using\n[DAG](https://docs.gitlab.com/ee/ci/directed_acyclic_graph/index.html).\n\n5. You can pass files between jobs and store them in build artifacts so that\nthey can be downloaded from the interface.\n\n6. Add [tests and security\nscans](https://docs.gitlab.com/ee/development/integrations/secure.html) to\nthe CI pipeline to ensure the quality and security of your app.\n\n\nBelow are more formal descriptions of the terms and keywords we used, as\nwell as links to the relevant documentation.\n\n\n### Keyword descriptions and documentation\n\n\n{: #keywords}\n\n\n| Keyword/term       | Description |\n\n|---------------|--------------------|\n\n| [.gitlab-ci.yml](https://docs.gitlab.com/ee/ci/yaml/) | File containing\nall definitions of how your project should be built |\n\n| [script](https://docs.gitlab.com/ee/ci/yaml/#script)        | Defines a\nshell script to be executed |\n\n| [before_script](https://docs.gitlab.com/ee/ci/yaml/#before_script) | Used\nto define the command that should be run before (all) jobs |\n\n|\n[image](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-image)\n| Defines what Docker image to use |\n\n| [stages](https://docs.gitlab.com/ee/ci/yaml/#stages)         | Defines a\npipeline stage (default: `test`) |\n\n| [artifacts](https://docs.gitlab.com/ee/ci/yaml/#artifacts)     | Defines a\nlist of build artifacts |\n\n|\n[artifacts:expire_in](https://docs.gitlab.com/ee/ci/yaml/#artifactsexpire_in)\n| Used to delete uploaded artifacts after the specified time |\n\n| [needs](https://docs.gitlab.com/ee/ci/yaml/#needs) | Used to define\ndependencies between jobs and allows to run jobs out of order |\n\n| [pipelines](https://about.gitlab.com/topics/ci-cd/cicd-pipeline/) | A\npipeline is a group of builds that get executed in stages (batches) |\n\n\n## More on CI/CD\n\n\n- [GitLab’s guide to CI/CD for beginners](/blog/beginner-guide-ci-cd/)\n\n- [Get faster and more flexible pipelines with a Directed Acyclic\nGraph](/blog/directed-acyclic-graph/)\n\n- [Decrease build time with custom Docker\nimage](http://beenje.github.io/blog/posts/gitlab-ci-and-conda/)\n\n- [Introducing the GitLab CI/CD Catalog\nBeta](https://about.gitlab.com/blog/introducing-the-gitlab-ci-cd-catalog-beta/)\n\n\n## FAQ\n\n\n### How do you choose between running CI jobs sequentially vs. in parallel?\n\n\nConsiderations for choosing between running CI jobs sequentially or in\nparallel include job dependencies, resource availability, execution times,\npotential interference, test suite structure, and cost considerations. For\nexample, if you have a build job that must finish before a deployment job\ncan start, you would run these jobs sequentially to ensure the correct order\nof execution. On the other hand, tasks such as unit testing and integration\ntesting can typically run in parallel since they are independent and don't\nrely on each other's completion.\n\n\n### What are directed Acyclic Graphs in GitLab CI, and how do they improve\npipeline flexibility?\n\n\nA Directed Acyclic Graph (DAG) in GitLab CI breaks the linear order of\npipeline stages. It lets you set dependencies between jobs, so jobs in later\nstages start as soon as earlier stage jobs finish. This reduces overall\npipeline execution time, improves efficiency, and lets some jobs complete\nearlier than in a regular order.\n\n\n### What is the importance of choosing the right Docker image for CI jobs in\nGitLab?\n\n\nGitLab utilizes Docker images to execute jobs. The default image is\nruby:3.1. Depending on your job's requirements, it's crucial to choose the\nappropriate image. Note that jobs first download the specified Docker image,\nand if the image contains additional packages beyond what's necessary, it\nwill increase download and execution times. Therefore, it's important to\nensure that the chosen image contains only the packages essential for your\njob to avoid unnecessary delays in execution.\n\n\n## Next steps\n\n\nAs a next step and to further modernize your software development practice,\ncheck out the [GitLab CI/CD\nCatalog](https://docs.gitlab.com/ee/architecture/blueprints/ci_pipeline_components/)\nto learn how to standardize and reuse CI/CD components.\n","engineering",[24,25],"CI","tutorial","2024-04-24",{"slug":28,"featured":6,"template":29},"basics-of-gitlab-ci-updated","BlogPost","content:en-us:blog:basics-of-gitlab-ci-updated.yml","yaml","Basics Of Gitlab Ci Updated","content","en-us/blog/basics-of-gitlab-ci-updated.yml","en-us/blog/basics-of-gitlab-ci-updated","yml",{"_path":38,"_dir":39,"_draft":6,"_partial":6,"_locale":7,"data":40,"_id":462,"_type":31,"title":463,"_source":33,"_file":464,"_stem":465,"_extension":36},"/shared/en-us/main-navigation","en-us",{"logo":41,"freeTrial":46,"sales":51,"login":56,"items":61,"search":393,"minimal":424,"duo":443,"pricingDeployment":452},{"config":42},{"href":43,"dataGaName":44,"dataGaLocation":45},"/","gitlab logo","header",{"text":47,"config":48},"Get free trial",{"href":49,"dataGaName":50,"dataGaLocation":45},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":52,"config":53},"Talk to sales",{"href":54,"dataGaName":55,"dataGaLocation":45},"/sales/","sales",{"text":57,"config":58},"Sign in",{"href":59,"dataGaName":60,"dataGaLocation":45},"https://gitlab.com/users/sign_in/","sign in",[62,106,204,209,314,374],{"text":63,"config":64,"cards":66,"footer":89},"Platform",{"dataNavLevelOne":65},"platform",[67,73,81],{"title":63,"description":68,"link":69},"The most comprehensive AI-powered DevSecOps Platform",{"text":70,"config":71},"Explore our Platform",{"href":72,"dataGaName":65,"dataGaLocation":45},"/platform/",{"title":74,"description":75,"link":76},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":77,"config":78},"Meet GitLab Duo",{"href":79,"dataGaName":80,"dataGaLocation":45},"/gitlab-duo/","gitlab duo ai",{"title":82,"description":83,"link":84},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":85,"config":86},"Learn more",{"href":87,"dataGaName":88,"dataGaLocation":45},"/why-gitlab/","why gitlab",{"title":90,"items":91},"Get started with",[92,97,102],{"text":93,"config":94},"Platform Engineering",{"href":95,"dataGaName":96,"dataGaLocation":45},"/solutions/platform-engineering/","platform engineering",{"text":98,"config":99},"Developer Experience",{"href":100,"dataGaName":101,"dataGaLocation":45},"/developer-experience/","Developer experience",{"text":103,"config":104},"MLOps",{"href":105,"dataGaName":103,"dataGaLocation":45},"/topics/devops/the-role-of-ai-in-devops/",{"text":107,"left":108,"config":109,"link":111,"lists":115,"footer":186},"Product",true,{"dataNavLevelOne":110},"solutions",{"text":112,"config":113},"View all Solutions",{"href":114,"dataGaName":110,"dataGaLocation":45},"/solutions/",[116,141,165],{"title":117,"description":118,"link":119,"items":124},"Automation","CI/CD and automation to accelerate deployment",{"config":120},{"icon":121,"href":122,"dataGaName":123,"dataGaLocation":45},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[125,129,133,137],{"text":126,"config":127},"CI/CD",{"href":128,"dataGaLocation":45,"dataGaName":126},"/solutions/continuous-integration/",{"text":130,"config":131},"AI-Assisted Development",{"href":79,"dataGaLocation":45,"dataGaName":132},"AI assisted development",{"text":134,"config":135},"Source Code Management",{"href":136,"dataGaLocation":45,"dataGaName":134},"/solutions/source-code-management/",{"text":138,"config":139},"Automated Software Delivery",{"href":122,"dataGaLocation":45,"dataGaName":140},"Automated software delivery",{"title":142,"description":143,"link":144,"items":149},"Security","Deliver code faster without compromising security",{"config":145},{"href":146,"dataGaName":147,"dataGaLocation":45,"icon":148},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[150,155,160],{"text":151,"config":152},"Application Security Testing",{"href":153,"dataGaName":154,"dataGaLocation":45},"/solutions/application-security-testing/","Application security testing",{"text":156,"config":157},"Software Supply Chain Security",{"href":158,"dataGaLocation":45,"dataGaName":159},"/solutions/supply-chain/","Software supply chain security",{"text":161,"config":162},"Software Compliance",{"href":163,"dataGaName":164,"dataGaLocation":45},"/solutions/software-compliance/","software compliance",{"title":166,"link":167,"items":172},"Measurement",{"config":168},{"icon":169,"href":170,"dataGaName":171,"dataGaLocation":45},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[173,177,181],{"text":174,"config":175},"Visibility & Measurement",{"href":170,"dataGaLocation":45,"dataGaName":176},"Visibility and Measurement",{"text":178,"config":179},"Value Stream Management",{"href":180,"dataGaLocation":45,"dataGaName":178},"/solutions/value-stream-management/",{"text":182,"config":183},"Analytics & Insights",{"href":184,"dataGaLocation":45,"dataGaName":185},"/solutions/analytics-and-insights/","Analytics and insights",{"title":187,"items":188},"GitLab for",[189,194,199],{"text":190,"config":191},"Enterprise",{"href":192,"dataGaLocation":45,"dataGaName":193},"/enterprise/","enterprise",{"text":195,"config":196},"Small Business",{"href":197,"dataGaLocation":45,"dataGaName":198},"/small-business/","small business",{"text":200,"config":201},"Public Sector",{"href":202,"dataGaLocation":45,"dataGaName":203},"/solutions/public-sector/","public sector",{"text":205,"config":206},"Pricing",{"href":207,"dataGaName":208,"dataGaLocation":45,"dataNavLevelOne":208},"/pricing/","pricing",{"text":210,"config":211,"link":213,"lists":217,"feature":301},"Resources",{"dataNavLevelOne":212},"resources",{"text":214,"config":215},"View all resources",{"href":216,"dataGaName":212,"dataGaLocation":45},"/resources/",[218,251,273],{"title":219,"items":220},"Getting started",[221,226,231,236,241,246],{"text":222,"config":223},"Install",{"href":224,"dataGaName":225,"dataGaLocation":45},"/install/","install",{"text":227,"config":228},"Quick start guides",{"href":229,"dataGaName":230,"dataGaLocation":45},"/get-started/","quick setup checklists",{"text":232,"config":233},"Learn",{"href":234,"dataGaLocation":45,"dataGaName":235},"https://university.gitlab.com/","learn",{"text":237,"config":238},"Product documentation",{"href":239,"dataGaName":240,"dataGaLocation":45},"https://docs.gitlab.com/","product documentation",{"text":242,"config":243},"Best practice videos",{"href":244,"dataGaName":245,"dataGaLocation":45},"/getting-started-videos/","best practice videos",{"text":247,"config":248},"Integrations",{"href":249,"dataGaName":250,"dataGaLocation":45},"/integrations/","integrations",{"title":252,"items":253},"Discover",[254,259,263,268],{"text":255,"config":256},"Customer success stories",{"href":257,"dataGaName":258,"dataGaLocation":45},"/customers/","customer success stories",{"text":260,"config":261},"Blog",{"href":262,"dataGaName":5,"dataGaLocation":45},"/blog/",{"text":264,"config":265},"Remote",{"href":266,"dataGaName":267,"dataGaLocation":45},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":269,"config":270},"TeamOps",{"href":271,"dataGaName":272,"dataGaLocation":45},"/teamops/","teamops",{"title":274,"items":275},"Connect",[276,281,286,291,296],{"text":277,"config":278},"GitLab Services",{"href":279,"dataGaName":280,"dataGaLocation":45},"/services/","services",{"text":282,"config":283},"Community",{"href":284,"dataGaName":285,"dataGaLocation":45},"/community/","community",{"text":287,"config":288},"Forum",{"href":289,"dataGaName":290,"dataGaLocation":45},"https://forum.gitlab.com/","forum",{"text":292,"config":293},"Events",{"href":294,"dataGaName":295,"dataGaLocation":45},"/events/","events",{"text":297,"config":298},"Partners",{"href":299,"dataGaName":300,"dataGaLocation":45},"/partners/","partners",{"backgroundColor":302,"textColor":303,"text":304,"image":305,"link":309},"#2f2a6b","#fff","Insights for the future of software development",{"altText":306,"config":307},"the source promo card",{"src":308},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":310,"config":311},"Read the latest",{"href":312,"dataGaName":313,"dataGaLocation":45},"/the-source/","the source",{"text":315,"config":316,"lists":318},"Company",{"dataNavLevelOne":317},"company",[319],{"items":320},[321,326,332,334,339,344,349,354,359,364,369],{"text":322,"config":323},"About",{"href":324,"dataGaName":325,"dataGaLocation":45},"/company/","about",{"text":327,"config":328,"footerGa":331},"Jobs",{"href":329,"dataGaName":330,"dataGaLocation":45},"/jobs/","jobs",{"dataGaName":330},{"text":292,"config":333},{"href":294,"dataGaName":295,"dataGaLocation":45},{"text":335,"config":336},"Leadership",{"href":337,"dataGaName":338,"dataGaLocation":45},"/company/team/e-group/","leadership",{"text":340,"config":341},"Team",{"href":342,"dataGaName":343,"dataGaLocation":45},"/company/team/","team",{"text":345,"config":346},"Handbook",{"href":347,"dataGaName":348,"dataGaLocation":45},"https://handbook.gitlab.com/","handbook",{"text":350,"config":351},"Investor relations",{"href":352,"dataGaName":353,"dataGaLocation":45},"https://ir.gitlab.com/","investor relations",{"text":355,"config":356},"Trust Center",{"href":357,"dataGaName":358,"dataGaLocation":45},"/security/","trust center",{"text":360,"config":361},"AI Transparency Center",{"href":362,"dataGaName":363,"dataGaLocation":45},"/ai-transparency-center/","ai transparency center",{"text":365,"config":366},"Newsletter",{"href":367,"dataGaName":368,"dataGaLocation":45},"/company/contact/","newsletter",{"text":370,"config":371},"Press",{"href":372,"dataGaName":373,"dataGaLocation":45},"/press/","press",{"text":375,"config":376,"lists":377},"Contact us",{"dataNavLevelOne":317},[378],{"items":379},[380,383,388],{"text":52,"config":381},{"href":54,"dataGaName":382,"dataGaLocation":45},"talk to sales",{"text":384,"config":385},"Get help",{"href":386,"dataGaName":387,"dataGaLocation":45},"/support/","get help",{"text":389,"config":390},"Customer portal",{"href":391,"dataGaName":392,"dataGaLocation":45},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":394,"login":395,"suggestions":402},"Close",{"text":396,"link":397},"To search repositories and projects, login to",{"text":398,"config":399},"gitlab.com",{"href":59,"dataGaName":400,"dataGaLocation":401},"search login","search",{"text":403,"default":404},"Suggestions",[405,407,411,413,417,421],{"text":74,"config":406},{"href":79,"dataGaName":74,"dataGaLocation":401},{"text":408,"config":409},"Code Suggestions (AI)",{"href":410,"dataGaName":408,"dataGaLocation":401},"/solutions/code-suggestions/",{"text":126,"config":412},{"href":128,"dataGaName":126,"dataGaLocation":401},{"text":414,"config":415},"GitLab on AWS",{"href":416,"dataGaName":414,"dataGaLocation":401},"/partners/technology-partners/aws/",{"text":418,"config":419},"GitLab on Google Cloud",{"href":420,"dataGaName":418,"dataGaLocation":401},"/partners/technology-partners/google-cloud-platform/",{"text":422,"config":423},"Why GitLab?",{"href":87,"dataGaName":422,"dataGaLocation":401},{"freeTrial":425,"mobileIcon":430,"desktopIcon":435,"secondaryButton":438},{"text":426,"config":427},"Start free trial",{"href":428,"dataGaName":50,"dataGaLocation":429},"https://gitlab.com/-/trials/new/","nav",{"altText":431,"config":432},"Gitlab Icon",{"src":433,"dataGaName":434,"dataGaLocation":429},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":431,"config":436},{"src":437,"dataGaName":434,"dataGaLocation":429},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":439,"config":440},"Get Started",{"href":441,"dataGaName":442,"dataGaLocation":429},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":444,"mobileIcon":448,"desktopIcon":450},{"text":445,"config":446},"Learn more about GitLab Duo",{"href":79,"dataGaName":447,"dataGaLocation":429},"gitlab duo",{"altText":431,"config":449},{"src":433,"dataGaName":434,"dataGaLocation":429},{"altText":431,"config":451},{"src":437,"dataGaName":434,"dataGaLocation":429},{"freeTrial":453,"mobileIcon":458,"desktopIcon":460},{"text":454,"config":455},"Back to pricing",{"href":207,"dataGaName":456,"dataGaLocation":429,"icon":457},"back to pricing","GoBack",{"altText":431,"config":459},{"src":433,"dataGaName":434,"dataGaLocation":429},{"altText":431,"config":461},{"src":437,"dataGaName":434,"dataGaLocation":429},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":467,"_dir":39,"_draft":6,"_partial":6,"_locale":7,"title":468,"button":469,"image":474,"config":478,"_id":480,"_type":31,"_source":33,"_file":481,"_stem":482,"_extension":36},"/shared/en-us/banner","is now in public beta!",{"text":470,"config":471},"Try the Beta",{"href":472,"dataGaName":473,"dataGaLocation":45},"/gitlab-duo/agent-platform/","duo banner",{"altText":475,"config":476},"GitLab Duo Agent Platform",{"src":477},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":479},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":484,"_dir":39,"_draft":6,"_partial":6,"_locale":7,"data":485,"_id":689,"_type":31,"title":690,"_source":33,"_file":691,"_stem":692,"_extension":36},"/shared/en-us/main-footer",{"text":486,"source":487,"edit":493,"contribute":498,"config":503,"items":508,"minimal":681},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":488,"config":489},"View page source",{"href":490,"dataGaName":491,"dataGaLocation":492},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":494,"config":495},"Edit this page",{"href":496,"dataGaName":497,"dataGaLocation":492},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":499,"config":500},"Please contribute",{"href":501,"dataGaName":502,"dataGaLocation":492},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":504,"facebook":505,"youtube":506,"linkedin":507},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[509,532,588,617,651],{"title":63,"links":510,"subMenu":515},[511],{"text":512,"config":513},"DevSecOps platform",{"href":72,"dataGaName":514,"dataGaLocation":492},"devsecops platform",[516],{"title":205,"links":517},[518,522,527],{"text":519,"config":520},"View plans",{"href":207,"dataGaName":521,"dataGaLocation":492},"view plans",{"text":523,"config":524},"Why Premium?",{"href":525,"dataGaName":526,"dataGaLocation":492},"/pricing/premium/","why premium",{"text":528,"config":529},"Why Ultimate?",{"href":530,"dataGaName":531,"dataGaLocation":492},"/pricing/ultimate/","why ultimate",{"title":533,"links":534},"Solutions",[535,540,542,544,549,554,558,561,565,570,572,575,578,583],{"text":536,"config":537},"Digital transformation",{"href":538,"dataGaName":539,"dataGaLocation":492},"/topics/digital-transformation/","digital transformation",{"text":151,"config":541},{"href":153,"dataGaName":151,"dataGaLocation":492},{"text":140,"config":543},{"href":122,"dataGaName":123,"dataGaLocation":492},{"text":545,"config":546},"Agile development",{"href":547,"dataGaName":548,"dataGaLocation":492},"/solutions/agile-delivery/","agile delivery",{"text":550,"config":551},"Cloud transformation",{"href":552,"dataGaName":553,"dataGaLocation":492},"/topics/cloud-native/","cloud transformation",{"text":555,"config":556},"SCM",{"href":136,"dataGaName":557,"dataGaLocation":492},"source code management",{"text":126,"config":559},{"href":128,"dataGaName":560,"dataGaLocation":492},"continuous integration & delivery",{"text":562,"config":563},"Value stream management",{"href":180,"dataGaName":564,"dataGaLocation":492},"value stream management",{"text":566,"config":567},"GitOps",{"href":568,"dataGaName":569,"dataGaLocation":492},"/solutions/gitops/","gitops",{"text":190,"config":571},{"href":192,"dataGaName":193,"dataGaLocation":492},{"text":573,"config":574},"Small business",{"href":197,"dataGaName":198,"dataGaLocation":492},{"text":576,"config":577},"Public sector",{"href":202,"dataGaName":203,"dataGaLocation":492},{"text":579,"config":580},"Education",{"href":581,"dataGaName":582,"dataGaLocation":492},"/solutions/education/","education",{"text":584,"config":585},"Financial services",{"href":586,"dataGaName":587,"dataGaLocation":492},"/solutions/finance/","financial services",{"title":210,"links":589},[590,592,594,596,599,601,603,605,607,609,611,613,615],{"text":222,"config":591},{"href":224,"dataGaName":225,"dataGaLocation":492},{"text":227,"config":593},{"href":229,"dataGaName":230,"dataGaLocation":492},{"text":232,"config":595},{"href":234,"dataGaName":235,"dataGaLocation":492},{"text":237,"config":597},{"href":239,"dataGaName":598,"dataGaLocation":492},"docs",{"text":260,"config":600},{"href":262,"dataGaName":5,"dataGaLocation":492},{"text":255,"config":602},{"href":257,"dataGaName":258,"dataGaLocation":492},{"text":264,"config":604},{"href":266,"dataGaName":267,"dataGaLocation":492},{"text":277,"config":606},{"href":279,"dataGaName":280,"dataGaLocation":492},{"text":269,"config":608},{"href":271,"dataGaName":272,"dataGaLocation":492},{"text":282,"config":610},{"href":284,"dataGaName":285,"dataGaLocation":492},{"text":287,"config":612},{"href":289,"dataGaName":290,"dataGaLocation":492},{"text":292,"config":614},{"href":294,"dataGaName":295,"dataGaLocation":492},{"text":297,"config":616},{"href":299,"dataGaName":300,"dataGaLocation":492},{"title":315,"links":618},[619,621,623,625,627,629,631,635,640,642,644,646],{"text":322,"config":620},{"href":324,"dataGaName":317,"dataGaLocation":492},{"text":327,"config":622},{"href":329,"dataGaName":330,"dataGaLocation":492},{"text":335,"config":624},{"href":337,"dataGaName":338,"dataGaLocation":492},{"text":340,"config":626},{"href":342,"dataGaName":343,"dataGaLocation":492},{"text":345,"config":628},{"href":347,"dataGaName":348,"dataGaLocation":492},{"text":350,"config":630},{"href":352,"dataGaName":353,"dataGaLocation":492},{"text":632,"config":633},"Sustainability",{"href":634,"dataGaName":632,"dataGaLocation":492},"/sustainability/",{"text":636,"config":637},"Diversity, inclusion and belonging (DIB)",{"href":638,"dataGaName":639,"dataGaLocation":492},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":355,"config":641},{"href":357,"dataGaName":358,"dataGaLocation":492},{"text":365,"config":643},{"href":367,"dataGaName":368,"dataGaLocation":492},{"text":370,"config":645},{"href":372,"dataGaName":373,"dataGaLocation":492},{"text":647,"config":648},"Modern Slavery Transparency Statement",{"href":649,"dataGaName":650,"dataGaLocation":492},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":652,"links":653},"Contact Us",[654,657,659,661,666,671,676],{"text":655,"config":656},"Contact an expert",{"href":54,"dataGaName":55,"dataGaLocation":492},{"text":384,"config":658},{"href":386,"dataGaName":387,"dataGaLocation":492},{"text":389,"config":660},{"href":391,"dataGaName":392,"dataGaLocation":492},{"text":662,"config":663},"Status",{"href":664,"dataGaName":665,"dataGaLocation":492},"https://status.gitlab.com/","status",{"text":667,"config":668},"Terms of use",{"href":669,"dataGaName":670,"dataGaLocation":492},"/terms/","terms of use",{"text":672,"config":673},"Privacy statement",{"href":674,"dataGaName":675,"dataGaLocation":492},"/privacy/","privacy statement",{"text":677,"config":678},"Cookie preferences",{"dataGaName":679,"dataGaLocation":492,"id":680,"isOneTrustButton":108},"cookie preferences","ot-sdk-btn",{"items":682},[683,685,687],{"text":667,"config":684},{"href":669,"dataGaName":670,"dataGaLocation":492},{"text":672,"config":686},{"href":674,"dataGaName":675,"dataGaLocation":492},{"text":677,"config":688},{"dataGaName":679,"dataGaLocation":492,"id":680,"isOneTrustButton":108},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[694],{"_path":695,"_dir":696,"_draft":6,"_partial":6,"_locale":7,"content":697,"config":701,"_id":703,"_type":31,"title":19,"_source":33,"_file":704,"_stem":705,"_extension":36},"/en-us/blog/authors/itzik-gan-baruch","authors",{"name":19,"config":698},{"headshot":699,"ctfId":700},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749658921/Blog/Author%20Headshots/iganbaruch-headshot.jpg","iganbaruch",{"template":702},"BlogAuthor","content:en-us:blog:authors:itzik-gan-baruch.yml","en-us/blog/authors/itzik-gan-baruch.yml","en-us/blog/authors/itzik-gan-baruch",{"_path":707,"_dir":39,"_draft":6,"_partial":6,"_locale":7,"header":708,"eyebrow":709,"blurb":710,"button":711,"secondaryButton":715,"_id":717,"_type":31,"title":718,"_source":33,"_file":719,"_stem":720,"_extension":36},"/shared/en-us/next-steps","Start shipping better software faster","50%+ of the Fortune 100 trust GitLab","See what your team can do with the intelligent\n\n\nDevSecOps platform.\n",{"text":47,"config":712},{"href":713,"dataGaName":50,"dataGaLocation":714},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":52,"config":716},{"href":54,"dataGaName":55,"dataGaLocation":714},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1758326248310]