{"id":418880,"date":"2022-03-20T14:00:11","date_gmt":"2022-03-20T11:00:11","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/how-to-manage-gitlab-runner-concurrency-for-parallel-ci-jobs-cloudsavvy-it\/"},"modified":"2022-03-20T14:00:11","modified_gmt":"2022-03-20T11:00:11","slug":"how-to-manage-gitlab-runner-concurrency-for-parallel-ci-jobs-cloudsavvy-it","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/how-to-manage-gitlab-runner-concurrency-for-parallel-ci-jobs-cloudsavvy-it\/","title":{"rendered":"#How to Manage GitLab Runner Concurrency For Parallel CI Jobs \u2013 CloudSavvy IT"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a23fb7e5d478\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #dd3333;color:#dd3333\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #dd3333;color:#dd3333\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a23fb7e5d478\" checked aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-manage-gitlab-runner-concurrency-for-parallel-ci-jobs-cloudsavvy-it\/#%E2%80%9CHow_to_Manage_GitLab_Runner_Concurrency_For_Parallel_CI_Jobs_%E2%80%93_CloudSavvy_IT%E2%80%9D\" >&#8220;How to Manage GitLab Runner Concurrency For Parallel CI Jobs \u2013 CloudSavvy IT&#8221;<\/a><ul class='ez-toc-list-level-2' ><li class='ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-manage-gitlab-runner-concurrency-for-parallel-ci-jobs-cloudsavvy-it\/#Increasing_the_Runner_Count\" >Increasing the Runner Count<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-manage-gitlab-runner-concurrency-for-parallel-ci-jobs-cloudsavvy-it\/#Raising_the_Concurrency_Limit\" >Raising the Concurrency Limit<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-manage-gitlab-runner-concurrency-for-parallel-ci-jobs-cloudsavvy-it\/#Handling_%E2%80%9CRequest_Concurrency%E2%80%9D\" >Handling \u201cRequest Concurrency\u201d<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-manage-gitlab-runner-concurrency-for-parallel-ci-jobs-cloudsavvy-it\/#The_Global_Concurrency_Level\" >The Global Concurrency Level<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-manage-gitlab-runner-concurrency-for-parallel-ci-jobs-cloudsavvy-it\/#Applying_Changes\" >Applying Changes<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-manage-gitlab-runner-concurrency-for-parallel-ci-jobs-cloudsavvy-it\/#Arranging_Your_Pipelines_for_Parallel_Jobs\" >Arranging Your Pipelines for Parallel Jobs<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-manage-gitlab-runner-concurrency-for-parallel-ci-jobs-cloudsavvy-it\/#What_About_Caching\" >What About Caching?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-manage-gitlab-runner-concurrency-for-parallel-ci-jobs-cloudsavvy-it\/#Summary\" >Summary<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<h1><span class=\"ez-toc-section\" id=\"%E2%80%9CHow_to_Manage_GitLab_Runner_Concurrency_For_Parallel_CI_Jobs_%E2%80%93_CloudSavvy_IT%E2%80%9D\"><\/span>&#8220;How to Manage GitLab Runner Concurrency For Parallel CI Jobs \u2013 CloudSavvy IT&#8221;<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<div id=\"article-content-area\">\n<img loading=\"lazy\" decoding=\"async\" class=\"type:primaryImage aligncenter size-full wp-image-9546\" data-pagespeed-lazy-srcset=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/02\/266bb4cf.jpg?width=398&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1 400w, https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/02\/266bb4cf.jpg?width=1198&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1 1200w\" sizes=\"auto, 400w, 1200w\" data-pagespeed-lazy-src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/02\/266bb4cf.jpg?width=1198&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"Graphic showing the GitLab logo, a stylised fox head\" width=\"1602\" height=\"902\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>GitLab\u2019s Continuous Integration (CI) pipelines are a popular way to automate builds, tests, and releases each time you push code to your repository. Pipelines run concurrently and consist of sequential stages; each stage can include multiple jobs that run in parallel during the stage. The maximum concurrency of both parallel jobs and cross-instance pipelines depends on your server configuration.<\/p>\n<p>Jobs are run by GitLab Runner instances. <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.gitlab.com\/ee\/ci\/runners\">Runners operate as<\/a> isolated processes that receive new jobs from their controlling GitLab server. When a job is issued, the runner will create a sub-process that executes the CI <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/download-scripts-themes-apps\/\" data-internallinksmanager029f6b8e52c=\"9\" title=\"Download Scripts &amp; Themes &amp; Apps\" target=\"_blank\" rel=\"noopener\">script<\/a>. There are multiple variables that control when a runner will accept a job and start executing it. In this guide we\u2019ll look at the ways you can configure parallel jobs and pipelines.<\/p>\n<h2 id=\"increasing-the-runner-count\"><span class=\"ez-toc-section\" id=\"Increasing_the_Runner_Count\"><\/span>Increasing the Runner Count<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>One way to allow more jobs to run simultaneously is to simply register more runners. Each installation of GitLab Runner can register multiple distinct runner instances. They operate independently of each other and don\u2019t all need to refer to the same coordinating server.<\/p>\n<p>Use the <code>gitlab-runner register<\/code> command to add a new runner:<\/p>\n<pre>sudo gitlab-runner register<\/pre>\n<p>You\u2019ll be prompted to supply the registration information from your GitLab server. You can find this on the Settings &gt; CI\/CD page of a GitLab project or group, or head to Overview &gt; Runners in the Admin Centre for an instance-level runner. Runners will only execute jobs originating within the scope they\u2019re registered to.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-15627\" data-pagespeed-lazy-src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2022\/02\/14880839.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"1268\" height=\"648\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Each registered runner gets its own section in your <code>\/etc\/gitlab-runner\/config.toml<\/code> file:<\/p>\n<pre># Runner 1&#13;\n[[runners]]&#13;\n    executor = \"shell\"&#13;\n    ...&#13;\n&#13;\n# Runner 2&#13;\n[[runners]]&#13;\n    executor = \"shell\"&#13;\n    ...&#13;\n&#13;\n# Runner 3&#13;\n[[runners]]&#13;\n    executor = \"shell\"&#13;\n    ...<\/pre>\n<p>If all three runners were registered to the same server, you\u2019d now see up to three jobs running in parallel.<\/p>\n<h2 id=\"raising-the-concurrency-limit\"><span class=\"ez-toc-section\" id=\"Raising_the_Concurrency_Limit\"><\/span>Raising the Concurrency Limit<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>You can set the permitted concurrency of a specific runner registration using the <code>limit<\/code> field within its config block:<\/p>\n<pre># Runner 1&#13;\n[[runners]]&#13;\n    executor = \"shell\"&#13;\n    limit = 4<\/pre>\n<p>This change allows the first runner to execute up to four simultaneous jobs in sub-processes. Registering another runner with <code>limit = 2<\/code> would raise the concurrency level to a total of six jobs, assuming both runners referenced the same controlling GitLab server.<\/p>\n<h2 id=\"handling-request-concurrency\"><span class=\"ez-toc-section\" id=\"Handling_%E2%80%9CRequest_Concurrency%E2%80%9D\"><\/span>Handling \u201cRequest Concurrency\u201d<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The number of live jobs under execution isn\u2019t the only variable that impacts concurrency. GitLab Runner manages the number of <em>job requests<\/em> it can accept via the separate <code>request_concurrency<\/code> variable.<\/p>\n<p>This value controls the number of queued requests the runner will take from GitLab. When the server needs to schedule a new CI job, runners have to indicate whether they\u2019ve got sufficient capacity to receive it. The runner won\u2019t accept the job if it\u2019s already got more queued requests than <code>request_concurrency<\/code> permits.<\/p>\n<p>Consider this example:<\/p>\n<pre># Runner 1&#13;\n[[runners]]&#13;\n    executor = \"shell\"&#13;\n    limit = 2&#13;\n    request_concurrency = 4<\/pre>\n<p>This runner will accept up to four concurrent job requests and execute up to two simultaneously. Additional jobs won\u2019t be taken until the initial two have completed.<\/p>\n<h2 id=\"the-global-concurrency-level\"><span class=\"ez-toc-section\" id=\"The_Global_Concurrency_Level\"><\/span>The Global Concurrency Level<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>GitLab Runner also maintains a global concurrency factor that places an overall cap on the <code>limit<\/code> values exposed by individual registrations. You can control this value with the <code>concurrency<\/code> setting at the top of your <code>config.toml<\/code>:<\/p>\n<pre>concurrency = 4&#13;\n&#13;\n# Runner 1&#13;\n[[runners]]&#13;\n    executor = \"shell\"&#13;\n    limit = 4&#13;\n&#13;\n# Runner 2&#13;\n[[runners]]&#13;\n    executor = \"shell\"&#13;\n    limit = 2<\/pre>\n<p>Here the configuration of the two runners suggests a total job concurrency of six. However the presence of the global <code>concurrency<\/code> setting means no more than four jobs will actually run simultaneously. This value limits the total number of sub-processes that can be created by the entire GitLab Runner installation.<\/p>\n<h2 id=\"applying-changes\"><span class=\"ez-toc-section\" id=\"Applying_Changes\"><\/span>Applying Changes<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Once you\u2019ve made the changes you need, you can save your <code>config.toml<\/code> and return to running your pipelines. Modifications to the file are automatically detected by GitLab Runner and should apply almost im<a href=\"https:\/\/buradabiliyorum.com\/en\/category\/social-mediaa\/\" data-internallinksmanager029f6b8e52c=\"1\" title=\"Social Media\" target=\"_blank\" rel=\"noopener\">media<\/a>tely.<\/p>\n<p>You can try restarting the GitLab Runner process if the new concurrency level doesn\u2019t seem to have applied:<\/p>\n<pre>sudo gitlab-runner restart<\/pre>\n<p>This stops and starts the GitLab Runner service, reloading the config file.<\/p>\n<h2 id=\"arranging-your-pipelines-for-parallel-jobs\"><span class=\"ez-toc-section\" id=\"Arranging_Your_Pipelines_for_Parallel_Jobs\"><\/span>Arranging Your Pipelines for Parallel Jobs<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>If your jobs in a single pipeline aren\u2019t being parallelized, it\u2019s worth checking the basics of your <code>.gitlab-ci.yml<\/code> configuration. It\u2019s only <em>jobs<\/em> that run concurrently by default, not the pipeline stages:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><span class=\"co4\">stages<\/span>:<span class=\"co4\">\n  test<\/span>:<span class=\"co4\">\n  build<\/span>:<span class=\"co4\">\n  deploy<\/span><span class=\"sy2\">:\n<\/span><span class=\"co4\">\ntest<\/span>:<span class=\"co3\">\n  stage<\/span><span class=\"sy2\">: <\/span>test\n  <span class=\"co1\"># ...<\/span>\n<span class=\"co4\">\nbuild_ios<\/span>:<span class=\"co3\">\n  stage<\/span><span class=\"sy2\">: <\/span>build\n  <span class=\"co1\"># ...<\/span>\n<span class=\"co4\">\nbuild_android<\/span>:<span class=\"co3\">\n  stage<\/span><span class=\"sy2\">: <\/span>build\n  <span class=\"co1\"># ...<\/span>\n<span class=\"co4\">\ndeploy_ios<\/span>:<span class=\"co3\">\n  stage<\/span><span class=\"sy2\">: <\/span>deploy\n  <span class=\"co1\"># ...<\/span>\n<span class=\"co4\">\ndeploy_android<\/span>:<span class=\"co3\">\n  stage<\/span><span class=\"sy2\">: <\/span>deploy\n  <span class=\"co1\"># ...<\/span><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>This pipeline defines three stages that are shown horizontally in the GitLab UI. Each stage must complete before the next can begin. The <code>build<\/code> and <code>deploy<\/code> stages have two jobs each. These jobs run in parallel if your runners have enough capacity to stay within their configured concurrency limits.<\/p>\n<p>It is possible to break the \u201cstages execute sequentially\u201d rule by using the <code>needs<\/code> keyword to build a <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/about.gitlab.com\/blog\/2020\/05\/12\/directed-acyclic-graph\">Directed Acyclic Graph<\/a>:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><span class=\"co4\">stages<\/span>:<span class=\"co4\">\n  test<\/span>:<span class=\"co4\">\n  build<\/span>:<span class=\"co4\">\n  deploy<\/span><span class=\"sy2\">:\n<\/span><span class=\"co4\">\ntest<\/span>:<span class=\"co3\">\n  stage<\/span><span class=\"sy2\">: <\/span>test\n  <span class=\"co1\"># ...<\/span>\n<span class=\"co4\">\nbuild_ios<\/span>:<span class=\"co3\">\n  stage<\/span><span class=\"sy2\">: <\/span>build\n  <span class=\"co1\"># ...<\/span>\n<span class=\"co4\">\nbuild_android<\/span>:<span class=\"co3\">\n  stage<\/span><span class=\"sy2\">: <\/span>build\n  <span class=\"co1\"># ...<\/span>\n<span class=\"co4\">\ndeploy_ios<\/span>:<span class=\"co3\">\n  stage<\/span><span class=\"sy2\">: <\/span>deploy<span class=\"co3\">\n  needs<\/span><span class=\"sy2\">: <\/span><span class=\"br0\">[<\/span><span class=\"st0\">\"test\"<\/span>, <span class=\"st0\">\"build_ios\"<\/span><span class=\"br0\">]<\/span>\n  <span class=\"co1\"># ...<\/span>\n<span class=\"co4\">\ndeploy_android<\/span>:<span class=\"co3\">\n  stage<\/span><span class=\"sy2\">: <\/span>deploy<span class=\"co3\">\n  needs<\/span><span class=\"sy2\">: <\/span><span class=\"br0\">[<\/span><span class=\"st0\">\"test\"<\/span>, <span class=\"st0\">\"build_android\"<\/span><span class=\"br0\">]<\/span>\n  <span class=\"co1\"># ...<\/span><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Here the iOS deployment is allowed to proceed as soon as the <code>build_ios<\/code> job has finished, even if the remainder of the <code>build<\/code> stage has not completed. Using <code>needs<\/code> makes your pipelines more flexible by adding new opportunities for parallelization. However it also brings along complexity which can be harder to maintain over time as you add more jobs to your pipeline.<\/p>\n<h2 id=\"what-about-caching\"><span class=\"ez-toc-section\" id=\"What_About_Caching\"><\/span>What About Caching?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Use of concurrency means your jobs may be picked up by different runners on each pass through a particular pipeline. Runners maintain their own cache instances so a job\u2019s not guaranteed to hit a cache even if a previous run through the pipeline populated one. The cache might reside on a different runner to that executing the second job.<\/p>\n<p>You can address this by setting up a shared cache provider using an S3-compatible object storage system. This will cause caches to be uploaded to that provider after the job completes, storing the content independently of any specific runner. Other runner instances will be able to retrieve the cache from the object storage server even if they didn\u2019t create it.<\/p>\n<p>Shared caching can improve performance by increasing the probability of a cache hit, reducing the work your jobs need to complete. Your pipelines shouldn\u2019t <em>require<\/em> successful cache resolution though: caches <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.gitlab.com\/ee\/ci\/caching\">are used on<\/a> a best-effort basis so CI scripts are meant to be resilient to misses.<\/p>\n<h2 id=\"summary\"><span class=\"ez-toc-section\" id=\"Summary\"><\/span>Summary<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>GitLab Runner gives you three primary controls for managing concurrency: the <code>limit<\/code> and <code>request_concurrency<\/code> fields on individual runners, and the <code>concurrency<\/code> value of the overall installation. A particular Runner installation won\u2019t execute more than <code>&lt;concurrency&gt;<\/code> jobs simultaneously, even if the sum of its registrations\u2019 <code>limit<\/code> values suggests it could take more.<\/p>\n<p>Adding more runners is another way to impact overall concurrency. In <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/general\/\" data-internallinksmanager029f6b8e52c=\"3\" title=\"General\" target=\"_blank\" rel=\"noopener\">general<\/a> it\u2019s best to raise the concurrency on an existing runner if you simply want to run more jobs with the same configuration. Add a new runner and set its <code>limit<\/code> value when you need to execute jobs with a <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.gitlab.com\/runner\/executors\">new executor<\/a> or settings that differ from your existing fleet.\n<\/div>\n<blockquote><p><strong><span style=\"color: #ff6600;\">If you liked the article, do not forget to share it with your friends. Follow us on\u00a0<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/news.google.com\/publications\/CAAqBwgKMLG0nwswvr63Aw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google News<\/a><\/span>\u00a0too, click on the star and choose us from your favorites.<\/span><\/strong><\/p><\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\">For forums sites go to <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/forum.buradabiliyorum.com\/\" target=\"_blank\" rel=\"noopener\">Forum.BuradaBiliyorum.Com<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\"><strong>If you want to read more like this article, you can visit our <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/en.buradabiliyorum.com\/technology\/\" target=\"_blank\" rel=\"noopener\">Technology category.<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<p><span style=\"color: black;\"><a style=\"color: #ff9900;\" href=\"https:\/\/www.cloudsavvyit.com\/15602\/how-to-manage-gitlab-runner-concurrency-for-parallel-ci-jobs\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;How to Manage GitLab Runner Concurrency For Parallel CI Jobs \u2013 CloudSavvy IT&#8221; GitLab\u2019s Continuous Integration (CI) pipelines are a popular way to automate builds, tests, and releases each time you push code to your repository. Pipelines run concurrently and consist of sequential stages; each stage can include multiple jobs that run in parallel during&#8230;<\/p>\n","protected":false},"author":1,"featured_media":418881,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/02\/266bb4cf.jpg","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[],"class_list":["post-418880","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology"],"_links":{"self":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/418880","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/comments?post=418880"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/418880\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media\/418881"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=418880"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=418880"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=418880"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}