[{"data":1,"prerenderedAt":706},["ShallowReactive",2],{"/en-us/blog/tutorial-advanced-use-case-for-gitlab-pipeline-execution-policies/":3,"navigation-en-us":38,"banner-en-us":453,"footer-en-us":468,"Dan Rabinovitz":678,"next-steps-en-us":691},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":28,"_id":31,"_type":32,"title":33,"_source":34,"_file":35,"_stem":36,"_extension":37},"/en-us/blog/tutorial-advanced-use-case-for-gitlab-pipeline-execution-policies","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Tutorial: Advanced use case for GitLab Pipeline Execution Policies","Learn how new GitLab Ultimate functionality can enforce a standardized pipeline across an organization for improved compliance.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098083/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_397632156_3Ldy1urjMStQCl4qnOBvE0_1750098083312.jpg","https://about.gitlab.com/blog/tutorial-advanced-use-case-for-gitlab-pipeline-execution-policies","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: Advanced use case for GitLab Pipeline Execution Policies\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dan Rabinovitz\"}],\n        \"datePublished\": \"2025-01-22\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22},[18],"Dan Rabinovitz","2025-01-22","[Pipeline execution policies](https://docs.gitlab.com/ee/user/application_security/policies/pipeline_execution_policies.html) are a newer addition to the GitLab DevSecOps platform and a powerful mechanism to enforce CI/CD jobs across applicable projects. They enable platform engineering or security teams to inject jobs into developers’ YAML pipeline definition files, guaranteeing that certain CI/CD jobs will execute no matter what a developer defines in their \\`.gitlab-ci.yml\\` file. \n\nThis article will explain how to utilize pipeline execution policies to create guardrails around the stages or jobs that a developer can use in their pipeline definition. In regulated environments, this may be necessary to ensure developers adhere to a standard set of jobs or stages in their GitLab pipeline. Any job or stage that a developer adds to their pipeline that does not adhere to a corporate standard will cause the pipeline to fail. \n\nOne example use case for pipeline execution policies is ensuring a security scanner job runs. Let’s say an organization has made an investment in a third-party security scanner and they have a requirement that the external scan runs before any merge is made into the main branch. Without a pipeline execution policy, a developer could easily skip this step by not including the required code in their `.gitlab-ci.yml` file.  With a pipeline execution policy in place, a security team can guarantee the external security scanning job executes regardless of how a developer defines their pipeline.\n\nTo use pipeline execution policies to enforce these restrictions requires two parts: a shell script to make calls to the GitLab API and the policy itself. This tutorial uses a bash script; if your runner uses a different scripting language, it is easy to adapt to other languages.\n\nHere is the example shell script I will use for this exercise:\n\n``` \n#!/bin/bash\n\necho \"Checking pipeline stages and jobs...\"\n\n# Pull the group access token from the environment variable\nGROUP_ACCESS_TOKEN=\"$PIPELINE_TOKEN\"\n\necho \"PROJECT_ID: $PROJECT_ID\"\necho \"PIPELINE_ID: $PIPELINE_ID\"\n\nif [ -z \"$GROUP_ACCESS_TOKEN\" ]; then  \n  echo \"GROUP_ACCESS_TOKEN (MR_GENERATOR) is not set\"\n  exit 1\nfi\n\nif [ -z \"$PROJECT_ID\" ]; then\n  echo \"PROJECT_ID is not set\"\n  exit 1\nfi\n\nif [ -z \"$PIPELINE_ID\" ]; then\n  echo \"PIPELINE_ID is not set\"\n  exit 1\nfi\n\n# Use the group access token for the API request\napi_url=\"$GITLAB_API_URL/projects/$PROJECT_ID/pipelines/$PIPELINE_ID/jobs\"\necho \"API URL: $api_url\"\n\n# Fetch pipeline jobs using the group access token\njobs=$(curl --silent --header \"PRIVATE-TOKEN: $GROUP_ACCESS_TOKEN\" \"$api_url\")\necho \"Fetched Jobs: $jobs\"\n\nif [[ \"$jobs\" == *\"404 Project Not Found\"* ]]; then\n  echo \"Failed to authenticate with GitLab API: Project not found\"\n  exit 1\nfi\n\n# Extract stages and jobs\npipeline_stages=$(echo \"$jobs\" | grep -o '\"stage\":\"[^\"]*\"' | cut -d '\"' -f 4 | sort | uniq | tr '\\n' ',')\npipeline_jobs=$(echo \"$jobs\" | grep -o '\"name\":\"[^\"]*\"' | cut -d '\"' -f 4 | sort | uniq | tr '\\n' ',')\n\necho \"Pipeline Stages: $pipeline_stages\"  \necho \"Pipeline Jobs: $pipeline_jobs\"\n\n# Check if pipeline stages are approved\nfor stage in $(echo $pipeline_stages | tr ',' ' '); do \n  echo \"Checking stage: $stage\"\n  if ! [[ \",$APPROVED_STAGES,\" =~ \",$stage,\" ]]; then\n    echo \"Stage $stage is not approved.\"\n    exit 1\n  fi\ndone\n\n# Check if pipeline jobs are approved \nfor job in $(echo $pipeline_jobs | tr ',' ' '); do\n  echo \"Checking job: $job\"\n  if ! [[ \",$APPROVED_JOBS,\" =~ \",$job,\" ]]; then\n    echo \"Job $job is not approve\n```\n\nLet’s break this down a bit. \n\nThe first few lines of this code perform some sanity checks, ensuring that a pipeline ID, project ID, and group access token exist.\n\n* A GitLab pipeline ID is a unique numerical identifier that GitLab automatically assigns to each pipeline run.\n* A GitLab project ID is a unique numerical identifier assigned to each project in GitLab.\n* A GitLab group access token is a token that authenticates and authorizes access to resources at the group level in GitLab. This is in contrast to a GitLab personal access token (PAT), which is unique to each user.  \n\nThe bulk of the work comes from the [GitLab Projects API](https://docs.gitlab.com/ee/api/projects.html) call where the script requests the jobs for the specified pipeline. Once you have job information for the currently running pipeline, you can use a simple grep command to parse out stage and job names, and store them in variables for comparison. The last portion of the script checks to see if pipeline stages and jobs are on the approved list. Where do these parameters come from?\n\nThis is where [GitLab Pipeline Execution Policies](https://docs.gitlab.com/ee/user/application_security/policies/pipeline_execution_policies.html) come into play. They enable injection of YAML code into a pipeline. How can we leverage injected YAML to execute this shell script?  Here’s a code snippet showing how to do this.\n\n```\n## With this config, the goal is to create a pre-check job that evaluates the pipeline and fails the job/pipeline if any checks do not pass\n\nvariables:\n  GITLAB_API_URL: \"https://gitlab.com/api/v4\"\n  PROJECT_ID: $CI_PROJECT_ID\n  PIPELINE_ID: $CI_PIPELINE_ID\n  APPROVED_STAGES: \".pipeline-policy-pre,pre_check,build,test,deploy\"\n  APPROVED_JOBS: \"pre_check,build_job,test_job,deploy_job\"\n\npre_check:\n  stage: .pipeline-policy-pre\n  script:\n    - curl -H \"PRIVATE-TOKEN:${REPO_ACCESS_TOKEN}\" --url \"https://\u003Cgitlab_URL>/api/v4/projects/\u003Cproject_id>/repository/files/check_settings.sh/raw\" -o pre-check.sh\n    - ls -l\n    - chmod +x pre-check.sh\n    - DEBUG_MODE=false ./pre-check.sh  # Set DEBUG_MODE to true or false\n  allow_failure: true\n```\n\nIn this YAML snippet, we set a few variables used in the shell script. Most importantly, this is where approved stages and approved jobs are defined. After the `variables` section, we then add a new job to the `.pipeline-policy-pre` stage. This is a reserved stage for pipeline execution policies and is guaranteed to execute before any stages defined in a `.gitlab-ci.yml` file.  There is a corresponding `.pipeline-policy-post` stage as well, though we will not be using it in this scenario.  \n\nThe script portion of the job does the actual work. Here, we leverage a curl command to execute the shell script defined above. This example includes authentication if it’s located in a private repository. However, if it’s publicly accessible, you can forgo this authentication. The last line controls whether or not the pipeline will fail. In this example, the pipeline will continue. This is useful for testing – in practice, you would likely set `allow_failure: false` to cause the pipeline to fail. This is desired as the goal of this exercise is to not allow pipelines to continue execution if a developer adds a rogue job or stage.\n\nTo utilize this YAML, save it to a `.yml` file in a repository of your choice. We’ll see how to connect it to a policy shortly.\n\nNow, we have our script and our YAML to inject into a developer’s pipeline. Next, let’s see how to put this together using a pipeline execution policy.\n\nLike creating other policies in GitLab, start by creating a new Pipeline Execution Policy by navigating to **Secure > Policies** in the left hand navigation menu. Then, choose **New Policy** at the top right, and select **Pipeline Execution Policy** from the policy creation options.  \n\nFor this exercise, you can leave the **Policy Scope** set to the default options. In the **Actions** section, be sure to choose **Inject** and select the project and file where you’ve saved your YAML code snippet. Click on **Update via Merge Request** at the very bottom to create an MR that you can then merge into your project.\n\nIf this is your first security policy, clicking on **Merge** in the MR will create a [Security Policy Project](https://docs.gitlab.com/ee/user/application_security/policies/vulnerability_management_policy.html), which is a project to store all security policies. When implementing any type of security policy in a production environment, [access to this project should be restricted](https://docs.gitlab.com/ee/user/project/members/) so developers cannot make changes to security policies. In fact, you may also want to consider storing YAML code that’s used by pipeline execution policies in this project to restrict access as well, though this is not a requirement.  \nExecuting a pipeline where this pipeline execution policy is enabled should result in the following output when you attempt to add an invalid stage to the project `.gitlab-ci.yml` file.\n\n![Output of attempting an invalid stage to project gitlab-ci.yml file](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098102/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098102394.png)\n\nWhile this use case is very focused on one aspect of security and compliance in your organization, this opens the door to other use cases. For example, you may want to make group-level variables accessible to every project within a group; this is possible with pipeline execution policies. Or, you may want to create a golden pipeline and have developers add to it. The possibilities are endless. GitLab customers are finding new and exciting ways to use this new functionality every day.\n\nIf you’re a GitLab Ultimate customer, try this out today and let us know how you’re using pipeline execution policies. Not a GitLab Ultimate customer? [Sign up for a free 60-day trial](https://about.gitlab.com/free-trial/devsecops/) to get started.\n\n## Read more\n- [How to integrate custom security scanners into GitLab](https://about.gitlab.com/blog/how-to-integrate-custom-security-scanners-into-gitlab/)\n- [Integrate external security scanners into your DevSecOps workflow](https://about.gitlab.com/blog/integrate-external-security-scanners-into-your-devsecops-workflow/)\n- [Why GitLab is deprecating compliance pipelines in favor of security policies](https://about.gitlab.com/blog/why-gitlab-is-deprecating-compliance-pipelines-in-favor-of-security-policies/)\n","security",[21,23,24,25,26,27],"tutorial","public sector","DevSecOps platform","CI/CD","features",{"slug":29,"featured":6,"template":30},"tutorial-advanced-use-case-for-gitlab-pipeline-execution-policies","BlogPost","content:en-us:blog:tutorial-advanced-use-case-for-gitlab-pipeline-execution-policies.yml","yaml","Tutorial Advanced Use Case For Gitlab Pipeline Execution Policies","content","en-us/blog/tutorial-advanced-use-case-for-gitlab-pipeline-execution-policies.yml","en-us/blog/tutorial-advanced-use-case-for-gitlab-pipeline-execution-policies","yml",{"_path":39,"_dir":40,"_draft":6,"_partial":6,"_locale":7,"data":41,"_id":449,"_type":32,"title":450,"_source":34,"_file":451,"_stem":452,"_extension":37},"/shared/en-us/main-navigation","en-us",{"logo":42,"freeTrial":47,"sales":52,"login":57,"items":62,"search":390,"minimal":421,"duo":440},{"config":43},{"href":44,"dataGaName":45,"dataGaLocation":46},"/","gitlab logo","header",{"text":48,"config":49},"Get free trial",{"href":50,"dataGaName":51,"dataGaLocation":46},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":53,"config":54},"Talk to sales",{"href":55,"dataGaName":56,"dataGaLocation":46},"/sales/","sales",{"text":58,"config":59},"Sign in",{"href":60,"dataGaName":61,"dataGaLocation":46},"https://gitlab.com/users/sign_in/","sign in",[63,107,201,206,311,371],{"text":64,"config":65,"cards":67,"footer":90},"Platform",{"dataNavLevelOne":66},"platform",[68,74,82],{"title":64,"description":69,"link":70},"The most comprehensive AI-powered DevSecOps Platform",{"text":71,"config":72},"Explore our Platform",{"href":73,"dataGaName":66,"dataGaLocation":46},"/platform/",{"title":75,"description":76,"link":77},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":78,"config":79},"Meet GitLab Duo",{"href":80,"dataGaName":81,"dataGaLocation":46},"/gitlab-duo/","gitlab duo ai",{"title":83,"description":84,"link":85},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":86,"config":87},"Learn more",{"href":88,"dataGaName":89,"dataGaLocation":46},"/why-gitlab/","why gitlab",{"title":91,"items":92},"Get started with",[93,98,103],{"text":94,"config":95},"Platform Engineering",{"href":96,"dataGaName":97,"dataGaLocation":46},"/solutions/platform-engineering/","platform engineering",{"text":99,"config":100},"Developer Experience",{"href":101,"dataGaName":102,"dataGaLocation":46},"/developer-experience/","Developer experience",{"text":104,"config":105},"MLOps",{"href":106,"dataGaName":104,"dataGaLocation":46},"/topics/devops/the-role-of-ai-in-devops/",{"text":108,"left":109,"config":110,"link":112,"lists":116,"footer":184},"Product",true,{"dataNavLevelOne":111},"solutions",{"text":113,"config":114},"View all Solutions",{"href":115,"dataGaName":111,"dataGaLocation":46},"/solutions/",[117,141,163],{"title":118,"description":119,"link":120,"items":125},"Automation","CI/CD and automation to accelerate deployment",{"config":121},{"icon":122,"href":123,"dataGaName":124,"dataGaLocation":46},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[126,129,133,137],{"text":26,"config":127},{"href":128,"dataGaLocation":46,"dataGaName":26},"/solutions/continuous-integration/",{"text":130,"config":131},"AI-Assisted Development",{"href":80,"dataGaLocation":46,"dataGaName":132},"AI assisted development",{"text":134,"config":135},"Source Code Management",{"href":136,"dataGaLocation":46,"dataGaName":134},"/solutions/source-code-management/",{"text":138,"config":139},"Automated Software Delivery",{"href":123,"dataGaLocation":46,"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":46,"icon":148},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[150,153,158],{"text":151,"config":152},"Security & Compliance",{"href":146,"dataGaLocation":46,"dataGaName":151},{"text":154,"config":155},"Software Supply Chain Security",{"href":156,"dataGaLocation":46,"dataGaName":157},"/solutions/supply-chain/","Software supply chain security",{"text":159,"config":160},"Compliance & Governance",{"href":161,"dataGaLocation":46,"dataGaName":162},"/solutions/continuous-software-compliance/","Compliance and governance",{"title":164,"link":165,"items":170},"Measurement",{"config":166},{"icon":167,"href":168,"dataGaName":169,"dataGaLocation":46},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[171,175,179],{"text":172,"config":173},"Visibility & Measurement",{"href":168,"dataGaLocation":46,"dataGaName":174},"Visibility and Measurement",{"text":176,"config":177},"Value Stream Management",{"href":178,"dataGaLocation":46,"dataGaName":176},"/solutions/value-stream-management/",{"text":180,"config":181},"Analytics & Insights",{"href":182,"dataGaLocation":46,"dataGaName":183},"/solutions/analytics-and-insights/","Analytics and insights",{"title":185,"items":186},"GitLab for",[187,192,197],{"text":188,"config":189},"Enterprise",{"href":190,"dataGaLocation":46,"dataGaName":191},"/enterprise/","enterprise",{"text":193,"config":194},"Small Business",{"href":195,"dataGaLocation":46,"dataGaName":196},"/small-business/","small business",{"text":198,"config":199},"Public Sector",{"href":200,"dataGaLocation":46,"dataGaName":24},"/solutions/public-sector/",{"text":202,"config":203},"Pricing",{"href":204,"dataGaName":205,"dataGaLocation":46,"dataNavLevelOne":205},"/pricing/","pricing",{"text":207,"config":208,"link":210,"lists":214,"feature":298},"Resources",{"dataNavLevelOne":209},"resources",{"text":211,"config":212},"View all resources",{"href":213,"dataGaName":209,"dataGaLocation":46},"/resources/",[215,248,270],{"title":216,"items":217},"Getting started",[218,223,228,233,238,243],{"text":219,"config":220},"Install",{"href":221,"dataGaName":222,"dataGaLocation":46},"/install/","install",{"text":224,"config":225},"Quick start guides",{"href":226,"dataGaName":227,"dataGaLocation":46},"/get-started/","quick setup checklists",{"text":229,"config":230},"Learn",{"href":231,"dataGaLocation":46,"dataGaName":232},"https://university.gitlab.com/","learn",{"text":234,"config":235},"Product documentation",{"href":236,"dataGaName":237,"dataGaLocation":46},"https://docs.gitlab.com/","product documentation",{"text":239,"config":240},"Best practice videos",{"href":241,"dataGaName":242,"dataGaLocation":46},"/getting-started-videos/","best practice videos",{"text":244,"config":245},"Integrations",{"href":246,"dataGaName":247,"dataGaLocation":46},"/integrations/","integrations",{"title":249,"items":250},"Discover",[251,256,260,265],{"text":252,"config":253},"Customer success stories",{"href":254,"dataGaName":255,"dataGaLocation":46},"/customers/","customer success stories",{"text":257,"config":258},"Blog",{"href":259,"dataGaName":5,"dataGaLocation":46},"/blog/",{"text":261,"config":262},"Remote",{"href":263,"dataGaName":264,"dataGaLocation":46},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":266,"config":267},"TeamOps",{"href":268,"dataGaName":269,"dataGaLocation":46},"/teamops/","teamops",{"title":271,"items":272},"Connect",[273,278,283,288,293],{"text":274,"config":275},"GitLab Services",{"href":276,"dataGaName":277,"dataGaLocation":46},"/services/","services",{"text":279,"config":280},"Community",{"href":281,"dataGaName":282,"dataGaLocation":46},"/community/","community",{"text":284,"config":285},"Forum",{"href":286,"dataGaName":287,"dataGaLocation":46},"https://forum.gitlab.com/","forum",{"text":289,"config":290},"Events",{"href":291,"dataGaName":292,"dataGaLocation":46},"/events/","events",{"text":294,"config":295},"Partners",{"href":296,"dataGaName":297,"dataGaLocation":46},"/partners/","partners",{"backgroundColor":299,"textColor":300,"text":301,"image":302,"link":306},"#2f2a6b","#fff","Insights for the future of software development",{"altText":303,"config":304},"the source promo card",{"src":305},"/images/navigation/the-source-promo-card.svg",{"text":307,"config":308},"Read the latest",{"href":309,"dataGaName":310,"dataGaLocation":46},"/the-source/","the source",{"text":312,"config":313,"lists":315},"Company",{"dataNavLevelOne":314},"company",[316],{"items":317},[318,323,329,331,336,341,346,351,356,361,366],{"text":319,"config":320},"About",{"href":321,"dataGaName":322,"dataGaLocation":46},"/company/","about",{"text":324,"config":325,"footerGa":328},"Jobs",{"href":326,"dataGaName":327,"dataGaLocation":46},"/jobs/","jobs",{"dataGaName":327},{"text":289,"config":330},{"href":291,"dataGaName":292,"dataGaLocation":46},{"text":332,"config":333},"Leadership",{"href":334,"dataGaName":335,"dataGaLocation":46},"/company/team/e-group/","leadership",{"text":337,"config":338},"Team",{"href":339,"dataGaName":340,"dataGaLocation":46},"/company/team/","team",{"text":342,"config":343},"Handbook",{"href":344,"dataGaName":345,"dataGaLocation":46},"https://handbook.gitlab.com/","handbook",{"text":347,"config":348},"Investor relations",{"href":349,"dataGaName":350,"dataGaLocation":46},"https://ir.gitlab.com/","investor relations",{"text":352,"config":353},"Trust Center",{"href":354,"dataGaName":355,"dataGaLocation":46},"/security/","trust center",{"text":357,"config":358},"AI Transparency Center",{"href":359,"dataGaName":360,"dataGaLocation":46},"/ai-transparency-center/","ai transparency center",{"text":362,"config":363},"Newsletter",{"href":364,"dataGaName":365,"dataGaLocation":46},"/company/contact/","newsletter",{"text":367,"config":368},"Press",{"href":369,"dataGaName":370,"dataGaLocation":46},"/press/","press",{"text":372,"config":373,"lists":374},"Contact us",{"dataNavLevelOne":314},[375],{"items":376},[377,380,385],{"text":53,"config":378},{"href":55,"dataGaName":379,"dataGaLocation":46},"talk to sales",{"text":381,"config":382},"Get help",{"href":383,"dataGaName":384,"dataGaLocation":46},"/support/","get help",{"text":386,"config":387},"Customer portal",{"href":388,"dataGaName":389,"dataGaLocation":46},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":391,"login":392,"suggestions":399},"Close",{"text":393,"link":394},"To search repositories and projects, login to",{"text":395,"config":396},"gitlab.com",{"href":60,"dataGaName":397,"dataGaLocation":398},"search login","search",{"text":400,"default":401},"Suggestions",[402,404,408,410,414,418],{"text":75,"config":403},{"href":80,"dataGaName":75,"dataGaLocation":398},{"text":405,"config":406},"Code Suggestions (AI)",{"href":407,"dataGaName":405,"dataGaLocation":398},"/solutions/code-suggestions/",{"text":26,"config":409},{"href":128,"dataGaName":26,"dataGaLocation":398},{"text":411,"config":412},"GitLab on AWS",{"href":413,"dataGaName":411,"dataGaLocation":398},"/partners/technology-partners/aws/",{"text":415,"config":416},"GitLab on Google Cloud",{"href":417,"dataGaName":415,"dataGaLocation":398},"/partners/technology-partners/google-cloud-platform/",{"text":419,"config":420},"Why GitLab?",{"href":88,"dataGaName":419,"dataGaLocation":398},{"freeTrial":422,"mobileIcon":427,"desktopIcon":432,"secondaryButton":435},{"text":423,"config":424},"Start free trial",{"href":425,"dataGaName":51,"dataGaLocation":426},"https://gitlab.com/-/trials/new/","nav",{"altText":428,"config":429},"Gitlab Icon",{"src":430,"dataGaName":431,"dataGaLocation":426},"/images/brand/gitlab-logo-tanuki.svg","gitlab icon",{"altText":428,"config":433},{"src":434,"dataGaName":431,"dataGaLocation":426},"/images/brand/gitlab-logo-type.svg",{"text":436,"config":437},"Get Started",{"href":438,"dataGaName":439,"dataGaLocation":426},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":441,"mobileIcon":445,"desktopIcon":447},{"text":442,"config":443},"Learn more about GitLab Duo",{"href":80,"dataGaName":444,"dataGaLocation":426},"gitlab duo",{"altText":428,"config":446},{"src":430,"dataGaName":431,"dataGaLocation":426},{"altText":428,"config":448},{"src":434,"dataGaName":431,"dataGaLocation":426},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":454,"_dir":40,"_draft":6,"_partial":6,"_locale":7,"title":455,"button":456,"image":460,"config":463,"_id":465,"_type":32,"_source":34,"_file":466,"_stem":467,"_extension":37},"/shared/en-us/banner","is now in public beta!",{"text":86,"config":457},{"href":458,"dataGaName":459,"dataGaLocation":46},"/gitlab-duo/agent-platform/","duo banner",{"config":461},{"src":462},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":464},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":469,"_dir":40,"_draft":6,"_partial":6,"_locale":7,"data":470,"_id":674,"_type":32,"title":675,"_source":34,"_file":676,"_stem":677,"_extension":37},"/shared/en-us/main-footer",{"text":471,"source":472,"edit":478,"contribute":483,"config":488,"items":493,"minimal":666},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":473,"config":474},"View page source",{"href":475,"dataGaName":476,"dataGaLocation":477},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":479,"config":480},"Edit this page",{"href":481,"dataGaName":482,"dataGaLocation":477},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":484,"config":485},"Please contribute",{"href":486,"dataGaName":487,"dataGaLocation":477},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":489,"facebook":490,"youtube":491,"linkedin":492},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[494,516,573,602,636],{"title":64,"links":495,"subMenu":499},[496],{"text":25,"config":497},{"href":73,"dataGaName":498,"dataGaLocation":477},"devsecops platform",[500],{"title":202,"links":501},[502,506,511],{"text":503,"config":504},"View plans",{"href":204,"dataGaName":505,"dataGaLocation":477},"view plans",{"text":507,"config":508},"Why Premium?",{"href":509,"dataGaName":510,"dataGaLocation":477},"/pricing/premium/","why premium",{"text":512,"config":513},"Why Ultimate?",{"href":514,"dataGaName":515,"dataGaLocation":477},"/pricing/ultimate/","why ultimate",{"title":517,"links":518},"Solutions",[519,524,527,529,534,539,543,546,550,555,557,560,563,568],{"text":520,"config":521},"Digital transformation",{"href":522,"dataGaName":523,"dataGaLocation":477},"/topics/digital-transformation/","digital transformation",{"text":151,"config":525},{"href":146,"dataGaName":526,"dataGaLocation":477},"security & compliance",{"text":140,"config":528},{"href":123,"dataGaName":124,"dataGaLocation":477},{"text":530,"config":531},"Agile development",{"href":532,"dataGaName":533,"dataGaLocation":477},"/solutions/agile-delivery/","agile delivery",{"text":535,"config":536},"Cloud transformation",{"href":537,"dataGaName":538,"dataGaLocation":477},"/topics/cloud-native/","cloud transformation",{"text":540,"config":541},"SCM",{"href":136,"dataGaName":542,"dataGaLocation":477},"source code management",{"text":26,"config":544},{"href":128,"dataGaName":545,"dataGaLocation":477},"continuous integration & delivery",{"text":547,"config":548},"Value stream management",{"href":178,"dataGaName":549,"dataGaLocation":477},"value stream management",{"text":551,"config":552},"GitOps",{"href":553,"dataGaName":554,"dataGaLocation":477},"/solutions/gitops/","gitops",{"text":188,"config":556},{"href":190,"dataGaName":191,"dataGaLocation":477},{"text":558,"config":559},"Small business",{"href":195,"dataGaName":196,"dataGaLocation":477},{"text":561,"config":562},"Public sector",{"href":200,"dataGaName":24,"dataGaLocation":477},{"text":564,"config":565},"Education",{"href":566,"dataGaName":567,"dataGaLocation":477},"/solutions/education/","education",{"text":569,"config":570},"Financial services",{"href":571,"dataGaName":572,"dataGaLocation":477},"/solutions/finance/","financial services",{"title":207,"links":574},[575,577,579,581,584,586,588,590,592,594,596,598,600],{"text":219,"config":576},{"href":221,"dataGaName":222,"dataGaLocation":477},{"text":224,"config":578},{"href":226,"dataGaName":227,"dataGaLocation":477},{"text":229,"config":580},{"href":231,"dataGaName":232,"dataGaLocation":477},{"text":234,"config":582},{"href":236,"dataGaName":583,"dataGaLocation":477},"docs",{"text":257,"config":585},{"href":259,"dataGaName":5,"dataGaLocation":477},{"text":252,"config":587},{"href":254,"dataGaName":255,"dataGaLocation":477},{"text":261,"config":589},{"href":263,"dataGaName":264,"dataGaLocation":477},{"text":274,"config":591},{"href":276,"dataGaName":277,"dataGaLocation":477},{"text":266,"config":593},{"href":268,"dataGaName":269,"dataGaLocation":477},{"text":279,"config":595},{"href":281,"dataGaName":282,"dataGaLocation":477},{"text":284,"config":597},{"href":286,"dataGaName":287,"dataGaLocation":477},{"text":289,"config":599},{"href":291,"dataGaName":292,"dataGaLocation":477},{"text":294,"config":601},{"href":296,"dataGaName":297,"dataGaLocation":477},{"title":312,"links":603},[604,606,608,610,612,614,616,620,625,627,629,631],{"text":319,"config":605},{"href":321,"dataGaName":314,"dataGaLocation":477},{"text":324,"config":607},{"href":326,"dataGaName":327,"dataGaLocation":477},{"text":332,"config":609},{"href":334,"dataGaName":335,"dataGaLocation":477},{"text":337,"config":611},{"href":339,"dataGaName":340,"dataGaLocation":477},{"text":342,"config":613},{"href":344,"dataGaName":345,"dataGaLocation":477},{"text":347,"config":615},{"href":349,"dataGaName":350,"dataGaLocation":477},{"text":617,"config":618},"Sustainability",{"href":619,"dataGaName":617,"dataGaLocation":477},"/sustainability/",{"text":621,"config":622},"Diversity, inclusion and belonging (DIB)",{"href":623,"dataGaName":624,"dataGaLocation":477},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":352,"config":626},{"href":354,"dataGaName":355,"dataGaLocation":477},{"text":362,"config":628},{"href":364,"dataGaName":365,"dataGaLocation":477},{"text":367,"config":630},{"href":369,"dataGaName":370,"dataGaLocation":477},{"text":632,"config":633},"Modern Slavery Transparency Statement",{"href":634,"dataGaName":635,"dataGaLocation":477},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":637,"links":638},"Contact Us",[639,642,644,646,651,656,661],{"text":640,"config":641},"Contact an expert",{"href":55,"dataGaName":56,"dataGaLocation":477},{"text":381,"config":643},{"href":383,"dataGaName":384,"dataGaLocation":477},{"text":386,"config":645},{"href":388,"dataGaName":389,"dataGaLocation":477},{"text":647,"config":648},"Status",{"href":649,"dataGaName":650,"dataGaLocation":477},"https://status.gitlab.com/","status",{"text":652,"config":653},"Terms of use",{"href":654,"dataGaName":655,"dataGaLocation":477},"/terms/","terms of use",{"text":657,"config":658},"Privacy statement",{"href":659,"dataGaName":660,"dataGaLocation":477},"/privacy/","privacy statement",{"text":662,"config":663},"Cookie preferences",{"dataGaName":664,"dataGaLocation":477,"id":665,"isOneTrustButton":109},"cookie preferences","ot-sdk-btn",{"items":667},[668,670,672],{"text":652,"config":669},{"href":654,"dataGaName":655,"dataGaLocation":477},{"text":657,"config":671},{"href":659,"dataGaName":660,"dataGaLocation":477},{"text":662,"config":673},{"dataGaName":664,"dataGaLocation":477,"id":665,"isOneTrustButton":109},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[679],{"_path":680,"_dir":681,"_draft":6,"_partial":6,"_locale":7,"content":682,"config":686,"_id":688,"_type":32,"title":18,"_source":34,"_file":689,"_stem":690,"_extension":37},"/en-us/blog/authors/dan-rabinovitz","authors",{"name":18,"config":683},{"headshot":684,"ctfId":685},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664796/Blog/Author%20Headshots/dan_rabinovitz_headshot.png","31AXb267jy94budCWQZQyr",{"template":687},"BlogAuthor","content:en-us:blog:authors:dan-rabinovitz.yml","en-us/blog/authors/dan-rabinovitz.yml","en-us/blog/authors/dan-rabinovitz",{"_path":692,"_dir":40,"_draft":6,"_partial":6,"_locale":7,"header":693,"eyebrow":694,"blurb":695,"button":696,"secondaryButton":700,"_id":702,"_type":32,"title":703,"_source":34,"_file":704,"_stem":705,"_extension":37},"/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":48,"config":697},{"href":698,"dataGaName":51,"dataGaLocation":699},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":53,"config":701},{"href":55,"dataGaName":56,"dataGaLocation":699},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1754424517322]