[{"data":1,"prerenderedAt":1838},["ShallowReactive",2],{"/blog/how-to-provision-reviewops":3,"navigation-en-us":1041,"banner-en-us":1469,"footer-en-us":1479,"blog-post-authors-en-us-Joe Randazzo|Madou Coulibaly":1721,"blog-related-posts-en-us-how-to-provision-reviewops":1748,"blog-promotions-en-us":1774,"next-steps-en-us":1828},{"id":4,"title":5,"authors":6,"body":9,"category":1019,"date":1020,"description":1021,"extension":1022,"externalUrl":1023,"faq":1023,"featured":1024,"heroImage":1025,"meta":1026,"navigation":1027,"path":1028,"seo":1029,"slug":1034,"stem":1035,"tags":1036,"template":1039,"updatedDate":1023,"__hash__":1040},"blogPosts/en-us/blog/how-to-provision-reviewops.md","How to provision dynamic review environments using merge requests and Argo CD",[7,8],"Joe Randazzo","Madou Coulibaly",{"type":10,"value":11,"toc":1009},"minimark",[12,34,37,40,43,62,67,76,457,462,499,502,511,514,518,521,549,553,562,565,579,586,590,616,643,651,662,668,725,729,842,846,882,886,994,999,1002,1005],[13,14,15,16,22,23,28,29,33],"p",{},"We recently learned of a new contribution to the ApplicationSet in the Argo CD project, specifically the ",[17,18,21],"a",{"href":19,"rel":20},"https://github.com/argoproj/argo-cd/blob/master/docs/operator-manual/applicationset/Generators-Pull-Request.md#gitlab",[],"Pull Request generator for GitLab"," and decided to take it for a spin. What makes this interesting is now dynamic ",[17,24,27],{"href":25,"rel":26},"https://docs.gitlab.com/ci/review_apps/",[],"review environments"," can be provisioned intuitively from the merge request (MR) using a ",[17,30,32],{"href":31},"/topics/gitops/","GitOps"," workflow. The benefit is code reviewers or designers can quickly review any app changes to your Kubernetes cluster all from within the merge request.",[13,35,36],{},"In traditional testing workflows, you may have pushed your changes into a development environment, waiting for the QA and UX team to pull those changes into their environment for further review, and then received feedback based on your small change. At this point, time was wasted between various teams with environment coordination or adding bugs to the backlog of the new changes.",[13,38,39],{},"With the combination of a merge request and review environments, you can quickly spin up a test environment based on the changes of your feature branch. This means the QA or UX team can suggest improvements or changes during the code review process without wasting cycles.",[13,41,42],{},"The introduction of the ApplicationSet has given greater flexibility to Argo CD workflows such as:",[44,45,46,50,53,56],"ul",{},[47,48,49],"li",{},"Allowing unprivileged cluster users to deploy applications (without namespace access)",[47,51,52],{},"Deploying applications to multiple clusters at once",[47,54,55],{},"Deploying many applications from a single monorepo",[47,57,58],{},[59,60,61],"strong",{},"And triggering review environments based on a pull request",[63,64,66],"h3",{"id":65},"lets-review-the-applicationset-and-the-gitlab-pull-request-generator","Let's review the ApplicationSet and the GitLab Pull Request Generator",[13,68,69,70,75],{},"The ",[17,71,74],{"href":72,"rel":73},"https://argo-cd.readthedocs.io/en/latest/operator-manual/applicationset/Generators-Pull-Request",[],"Pull Request Generator"," will use the GitLab API to automatically discover new merge requests within a repository. Depending on the filter match of the MR, a review environment will then be generated.",[77,78,83],"pre",{"className":79,"code":80,"language":81,"meta":82,"style":82},"language-yaml shiki shiki-themes github-light","apiVersion: argoproj.io/v1alpha1\nkind: ApplicationSet\nmetadata:\n  name: review-the-application\n  namespace: argocd\nspec:\n  generators:\n  - pullRequest:\n      gitlab:\n        project: \u003Cproject-id>\n        api: https://gitlab.com/\n        tokenRef:\n          secretName: \u003Cgitlab-token>\n          key: token\n        pullRequestState: opened\n      requeueAfterSeconds: 60\n  template:\n    metadata:\n      name: 'review-the-application-{{number}}'\n    spec:\n      source:\n        repoURL: \u003Crepository-with-manifest-files>\n        path: chart/\n        targetRevision: 'HEAD'\n        helm:\n          parameters:\n          - name: \"image.repository\"\n            value: \"registry.gitlab.com/\u003Cgroup-and-project-path>/{{branch}}\"\n          - name: \"image.tag\"\n            value: \"{{head_sha}}\"\n          - name: \"service.url\"\n            value: \"the-application-{{number}}.\u003Cip>.nip.io\"\n      project: default\n      destination:\n        server: https://kubernetes.default.svc\n        namespace: dynamic-environments-with-argo-cd\n\n","yaml","",[84,85,86,103,114,123,134,145,153,161,172,180,191,202,210,221,232,243,255,263,271,282,290,298,309,320,331,339,347,361,372,384,394,406,416,427,435,446],"code",{"__ignoreMap":82},[87,88,91,95,99],"span",{"class":89,"line":90},"line",1,[87,92,94],{"class":93},"shJU0","apiVersion",[87,96,98],{"class":97},"sgsFI",": ",[87,100,102],{"class":101},"sYBdl","argoproj.io/v1alpha1\n",[87,104,106,109,111],{"class":89,"line":105},2,[87,107,108],{"class":93},"kind",[87,110,98],{"class":97},[87,112,113],{"class":101},"ApplicationSet\n",[87,115,117,120],{"class":89,"line":116},3,[87,118,119],{"class":93},"metadata",[87,121,122],{"class":97},":\n",[87,124,126,129,131],{"class":89,"line":125},4,[87,127,128],{"class":93},"  name",[87,130,98],{"class":97},[87,132,133],{"class":101},"review-the-application\n",[87,135,137,140,142],{"class":89,"line":136},5,[87,138,139],{"class":93},"  namespace",[87,141,98],{"class":97},[87,143,144],{"class":101},"argocd\n",[87,146,148,151],{"class":89,"line":147},6,[87,149,150],{"class":93},"spec",[87,152,122],{"class":97},[87,154,156,159],{"class":89,"line":155},7,[87,157,158],{"class":93},"  generators",[87,160,122],{"class":97},[87,162,164,167,170],{"class":89,"line":163},8,[87,165,166],{"class":97},"  - ",[87,168,169],{"class":93},"pullRequest",[87,171,122],{"class":97},[87,173,175,178],{"class":89,"line":174},9,[87,176,177],{"class":93},"      gitlab",[87,179,122],{"class":97},[87,181,183,186,188],{"class":89,"line":182},10,[87,184,185],{"class":93},"        project",[87,187,98],{"class":97},[87,189,190],{"class":101},"\u003Cproject-id>\n",[87,192,194,197,199],{"class":89,"line":193},11,[87,195,196],{"class":93},"        api",[87,198,98],{"class":97},[87,200,201],{"class":101},"https://gitlab.com/\n",[87,203,205,208],{"class":89,"line":204},12,[87,206,207],{"class":93},"        tokenRef",[87,209,122],{"class":97},[87,211,213,216,218],{"class":89,"line":212},13,[87,214,215],{"class":93},"          secretName",[87,217,98],{"class":97},[87,219,220],{"class":101},"\u003Cgitlab-token>\n",[87,222,224,227,229],{"class":89,"line":223},14,[87,225,226],{"class":93},"          key",[87,228,98],{"class":97},[87,230,231],{"class":101},"token\n",[87,233,235,238,240],{"class":89,"line":234},15,[87,236,237],{"class":93},"        pullRequestState",[87,239,98],{"class":97},[87,241,242],{"class":101},"opened\n",[87,244,246,249,251],{"class":89,"line":245},16,[87,247,248],{"class":93},"      requeueAfterSeconds",[87,250,98],{"class":97},[87,252,254],{"class":253},"sYu0t","60\n",[87,256,258,261],{"class":89,"line":257},17,[87,259,260],{"class":93},"  template",[87,262,122],{"class":97},[87,264,266,269],{"class":89,"line":265},18,[87,267,268],{"class":93},"    metadata",[87,270,122],{"class":97},[87,272,274,277,279],{"class":89,"line":273},19,[87,275,276],{"class":93},"      name",[87,278,98],{"class":97},[87,280,281],{"class":101},"'review-the-application-{{number}}'\n",[87,283,285,288],{"class":89,"line":284},20,[87,286,287],{"class":93},"    spec",[87,289,122],{"class":97},[87,291,293,296],{"class":89,"line":292},21,[87,294,295],{"class":93},"      source",[87,297,122],{"class":97},[87,299,301,304,306],{"class":89,"line":300},22,[87,302,303],{"class":93},"        repoURL",[87,305,98],{"class":97},[87,307,308],{"class":101},"\u003Crepository-with-manifest-files>\n",[87,310,312,315,317],{"class":89,"line":311},23,[87,313,314],{"class":93},"        path",[87,316,98],{"class":97},[87,318,319],{"class":101},"chart/\n",[87,321,323,326,328],{"class":89,"line":322},24,[87,324,325],{"class":93},"        targetRevision",[87,327,98],{"class":97},[87,329,330],{"class":101},"'HEAD'\n",[87,332,334,337],{"class":89,"line":333},25,[87,335,336],{"class":93},"        helm",[87,338,122],{"class":97},[87,340,342,345],{"class":89,"line":341},26,[87,343,344],{"class":93},"          parameters",[87,346,122],{"class":97},[87,348,350,353,356,358],{"class":89,"line":349},27,[87,351,352],{"class":97},"          - ",[87,354,355],{"class":93},"name",[87,357,98],{"class":97},[87,359,360],{"class":101},"\"image.repository\"\n",[87,362,364,367,369],{"class":89,"line":363},28,[87,365,366],{"class":93},"            value",[87,368,98],{"class":97},[87,370,371],{"class":101},"\"registry.gitlab.com/\u003Cgroup-and-project-path>/{{branch}}\"\n",[87,373,375,377,379,381],{"class":89,"line":374},29,[87,376,352],{"class":97},[87,378,355],{"class":93},[87,380,98],{"class":97},[87,382,383],{"class":101},"\"image.tag\"\n",[87,385,387,389,391],{"class":89,"line":386},30,[87,388,366],{"class":93},[87,390,98],{"class":97},[87,392,393],{"class":101},"\"{{head_sha}}\"\n",[87,395,397,399,401,403],{"class":89,"line":396},31,[87,398,352],{"class":97},[87,400,355],{"class":93},[87,402,98],{"class":97},[87,404,405],{"class":101},"\"service.url\"\n",[87,407,409,411,413],{"class":89,"line":408},32,[87,410,366],{"class":93},[87,412,98],{"class":97},[87,414,415],{"class":101},"\"the-application-{{number}}.\u003Cip>.nip.io\"\n",[87,417,419,422,424],{"class":89,"line":418},33,[87,420,421],{"class":93},"      project",[87,423,98],{"class":97},[87,425,426],{"class":101},"default\n",[87,428,430,433],{"class":89,"line":429},34,[87,431,432],{"class":93},"      destination",[87,434,122],{"class":97},[87,436,438,441,443],{"class":89,"line":437},35,[87,439,440],{"class":93},"        server",[87,442,98],{"class":97},[87,444,445],{"class":101},"https://kubernetes.default.svc\n",[87,447,449,452,454],{"class":89,"line":448},36,[87,450,451],{"class":93},"        namespace",[87,453,98],{"class":97},[87,455,456],{"class":101},"dynamic-environments-with-argo-cd\n",[458,459,461],"h4",{"id":460},"fields","Fields",[44,463,464,470,476,482,488],{},[47,465,466,469],{},[84,467,468],{},"project",": The GitLab Project ID",[47,471,472,475],{},[84,473,474],{},"api",": URL of GitLab instance",[47,477,478,481],{},[84,479,480],{},"tokenRef",": The secret to monitor merge request changes",[47,483,484,487],{},[84,485,486],{},"labels",": Provision review environments based on a GitLab label",[47,489,490,493,494],{},[84,491,492],{},"pullRequestState",": Provision review environments based on ",[17,495,498],{"href":496,"rel":497},"https://docs.gitlab.com/api/merge_requests/",[],"MR states",[13,500,501],{},"Filter options include GitLab labels, merge request state (open, closed, merged), and branch match. Templating options include merge request ID, branch name, branch slug, head sha, and head short sha.",[13,503,504,505,510],{},"See the latest ",[17,506,509],{"href":507,"rel":508},"https://argo-cd.readthedocs.io/en/latest/operator-manual/applicationset/Generators-Pull-Request/#gitlab",[],"ApplicationSet documentation"," for additional details.",[13,512,513],{},"For this blog post, we explore using the Argo CD ApplicationSet to provision a “ReviewOps” environment based on merge request changes.",[63,515,517],{"id":516},"prerequisites","Prerequisites",[13,519,520],{},"The following tools are required for running this tutorial. Please install and/or configure them before getting started.",[44,522,523,539],{},[47,524,525,528],{},[59,526,527],{},"Tools",[44,529,530,533,536],{},[47,531,532],{},"GitLab v15.0+",[47,534,535],{},"Kubernetes cluster v1.21+",[47,537,538],{},"Argo CD 2.5.0+",[47,540,541,544],{},[59,542,543],{},"CLI",[44,545,546],{},[47,547,548],{},"kubectl v1.21+",[63,550,552],{"id":551},"explore-the-source-code","Explore the Source Code",[13,554,555,556,561],{},"First, let’s explore the ",[17,557,560],{"href":558,"rel":559},"https://gitlab.com/madou-stories/dynamic-environments-with-argo-cd",[],"source code"," for the tutorial.",[13,563,564],{},"This GitLab group is composed of the 2 following projects:",[44,566,567,573],{},[47,568,569,572],{},[84,570,571],{},"The Application",": contains the source code of a containerized application and its CI/CD pipeline",[47,574,575,578],{},[84,576,577],{},"The Application Configuration",": contains the application configuration (Kubernetes Manifests) managed by Helm",[13,580,581],{},[582,583],"img",{"alt":584,"src":585},"git-repository","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397718/blog/Content%20Images/2022-08-01-how-to-provision-reviewops/git-repository.png",[63,587,589],{"id":588},"setting-up-gitlab","Setting up GitLab",[591,592,593,606],"ol",{},[47,594,595,596,600,601,605],{},"Create your GitLab Group and fork the ",[17,597,571],{"href":598,"rel":599},"https://gitlab.com/madou-stories/dynamic-environments-with-argo-cd/the-application",[]," and ",[17,602,577],{"href":603,"rel":604},"https://gitlab.com/madou-stories/dynamic-environments-with-argo-cd/the-application-configuration",[]," projects into it.",[47,607,608,609,611,612,615],{},"In ",[84,610,577],{}," project, edit the ",[84,613,614],{},"**manifests/applicationset.yml**"," as follows:",[44,617,618,626,634],{},[47,619,620,623,624],{},[84,621,622],{},".spec.generators.pullRequest.gitlab.project",": The Project ID of ",[84,625,571],{},[47,627,628,631,632],{},[84,629,630],{},".spec.template.spec.source.repoURL",": Git URL of ",[84,633,577],{},[47,635,636,639,640],{},[84,637,638],{},".spec.template.spec.source.helm.parameters.\"image.repository\"",": Point to image repository, for example ",[84,641,642],{},"registry.gitlab.com/\u003CYour_GitLab_Group>/the-application/{{branch}}",[13,644,645,646,650],{},"Note: keep the ",[647,648],"binding",{"value":649},"branch"," string as is and replace \u003CYour_GitLab_Group> with the name of the group you created in step 1.",[44,652,653],{},[47,654,655,658,659],{},[84,656,657],{},".spec.template.spec.source.helm.parameters.\"service.url\"",": Templated with ",[84,660,661],{},"the-application-{{number}}.\u003CYour_Kube_Ingress_Base_Domain>",[13,663,645,664,667],{},[647,665],{"value":666},"number"," string as is and replace \u003CYour_Kube_Ingress_Base_Domain> with the base domain of your Kubernetes Cluster.",[591,669,670,706],{"start":116},[47,671,672,673,699,702],{},"Define the following CI/CD variables at the group level:",[44,674,675,681,687,693],{},[47,676,677,680],{},[84,678,679],{},"ARGOCD_SERVER_URL",", the Argo CD server address",[47,682,683,686],{},[84,684,685],{},"ARGOCD_USERNAME",", the username of your Argo CD account",[47,688,689,692],{},[84,690,691],{},"ARGOCD_PASSWORD",", the password of your Argo CD account",[47,694,695,698],{},[84,696,697],{},"KUBE_INGRESS_BASE_DOMAIN",", the base domain of your Kubernetes Cluster",[700,701],"br",{},[582,703],{"alt":704,"src":705},"cicd-variables","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397716/blog/Content%20Images/2022-08-01-how-to-provision-reviewops/cicd-variables.png",[47,707,708,709,600,712,715,716,718,722,724],{},"Generate a Group access token to grant ",[84,710,711],{},"read_api",[84,713,714],{},"read_registry"," access to this group and its sub-projects.",[700,717],{},[582,719],{"alt":720,"src":721},"group-access-token","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397719/blog/Content%20Images/2022-08-01-how-to-provision-reviewops/group-access-token.png",[700,723],{},"Save the group access token somewhere safe. We will use it later.",[63,726,728],{"id":727},"setting-up-kubernetes","Setting up Kubernetes",[591,730,731,760,806],{},[47,732,733,734,737,738],{},"Create a namespace called ",[84,735,736],{},"dynamic-environments-with-argo-cd",".\n",[77,739,743],{"className":740,"code":741,"language":742,"meta":82,"style":82},"language-shell shiki shiki-themes github-light","kubectl create namespace dynamic-environments-with-argo-cd\n","shell",[84,744,745],{"__ignoreMap":82},[87,746,747,751,754,757],{"class":89,"line":90},[87,748,750],{"class":749},"s7eDp","kubectl",[87,752,753],{"class":101}," create",[87,755,756],{"class":101}," namespace",[87,758,759],{"class":101}," dynamic-environments-with-argo-cd\n",[47,761,762,763,766,767],{},"Create a Kubernetes secret called ",[84,764,765],{},"gitlab-token-dewac"," to allow Argo CD to use the GitLab API.\n",[77,768,770],{"className":740,"code":769,"language":742,"meta":82,"style":82},"kubectl create secret generic gitlab-token-dewac -n argocd --from-literal=token=\u003CYour_Access_Token>\n",[84,771,772],{"__ignoreMap":82},[87,773,774,776,778,781,784,787,790,793,796,800,803],{"class":89,"line":90},[87,775,750],{"class":749},[87,777,753],{"class":101},[87,779,780],{"class":101}," secret",[87,782,783],{"class":101}," generic",[87,785,786],{"class":101}," gitlab-token-dewac",[87,788,789],{"class":253}," -n",[87,791,792],{"class":101}," argocd",[87,794,795],{"class":253}," --from-literal=token=",[87,797,799],{"class":798},"sD7c4","\u003C",[87,801,802],{"class":253},"Your_Access_Token",[87,804,805],{"class":798},">\n",[47,807,808,809,811,812],{},"Create another Kubernetes secret called ",[84,810,765],{}," to allow Kubernetes to pull images from the GitLab Container Registry.\n",[77,813,815],{"className":740,"code":814,"language":742,"meta":82,"style":82},"kubectl create secret generic gitlab-token-dewac -n dynamic-environments-with-argo-cd --from-literal=token=\u003CYour_Access_Token>\n",[84,816,817],{"__ignoreMap":82},[87,818,819,821,823,825,827,829,831,834,836,838,840],{"class":89,"line":90},[87,820,750],{"class":749},[87,822,753],{"class":101},[87,824,780],{"class":101},[87,826,783],{"class":101},[87,828,786],{"class":101},[87,830,789],{"class":253},[87,832,833],{"class":101}," dynamic-environments-with-argo-cd",[87,835,795],{"class":253},[87,837,799],{"class":798},[87,839,802],{"class":253},[87,841,805],{"class":798},[63,843,845],{"id":844},"setting-up-argo-cd","Setting up Argo CD",[591,847,848],{},[47,849,850,851],{},"Create the Argo CD ApplicationSet to generate an Argo CD Application associated with a merge request.\n",[77,852,854],{"className":740,"code":853,"language":742,"meta":82,"style":82},"kubectl apply -f https://gitlab.com/\u003CYour_GitLab_Group>/the-application-configuration/-/raw/main/manifests/applicationset.yaml\n",[84,855,856],{"__ignoreMap":82},[87,857,858,860,863,866,869,871,874,876,879],{"class":89,"line":90},[87,859,750],{"class":749},[87,861,862],{"class":101}," apply",[87,864,865],{"class":253}," -f",[87,867,868],{"class":101}," https://gitlab.com/",[87,870,799],{"class":798},[87,872,873],{"class":101},"Your_GitLab_Grou",[87,875,13],{"class":97},[87,877,878],{"class":798},">",[87,880,881],{"class":101},"/the-application-configuration/-/raw/main/manifests/applicationset.yaml\n",[63,883,885],{"id":884},"update-the-source-code","Update the source code",[591,887,888,893,906,922,925,957,969,991],{},[47,889,608,890,892],{},[84,891,571],{}," project, create a GitLab issue, then an associated branch and merge request.",[47,894,895,896,899,900,902],{},"In Argo CD, a new application is provisioned called ",[84,897,898],{},"review-the-application"," based on the new merge request event.",[700,901],{},[582,903],{"alt":904,"src":905},"review-the-application-argocd","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397720/blog/Content%20Images/2022-08-01-how-to-provision-reviewops/review-the-application-argocd.png",[47,907,608,908,611,910,913,914,917,918,921],{},[84,909,571],{},[84,911,912],{},"index.pug"," and replace ",[84,915,916],{},"p Welcome to #{title}","  with ",[84,919,920],{},"p Bienvenue à #{title}",".",[47,923,924],{},"Commit into your recent branch which is going to trigger a pipeline run.",[47,926,927,928,930,934,936,937],{},"In the CI/CD > Pipelines, you will find the following pipeline running on your merge request:",[700,929],{},[582,931],{"alt":932,"src":933},"feature-branch-pipeline","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397718/blog/Content%20Images/2022-08-01-how-to-provision-reviewops/feature-branch-pipeline.png",[700,935],{},"where,",[44,938,939,945,951],{},[47,940,941,944],{},[84,942,943],{},"docker-build",": builds the container image",[47,946,947,950],{},[84,948,949],{},"reviewops",": configures and deploys the container into the review environment using Argo CD",[47,952,953,956],{},[84,954,955],{},"stop-reviewops",": deletes the review environment",[47,958,959,960,962,963,965],{},"Once completed, the ",[84,961,898],{}," application in Argo CD is now synced.",[700,964],{},[582,966],{"alt":967,"src":968},"review-the-application-synced","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397720/blog/Content%20Images/2022-08-01-how-to-provision-reviewops/review-the-application-synced.png",[47,970,971,972,975,976,978,982,984,985,987],{},"From the merge request, click on the ",[84,973,974],{},"View app"," button to access to your application.",[700,977],{},[582,979],{"alt":980,"src":981},"view-app-button","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397720/blog/Content%20Images/2022-08-01-how-to-provision-reviewops/view-app-button.png",[700,983],{},"The outcome should be as follows:",[700,986],{},[582,988],{"alt":989,"src":990},"express-app","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397717/blog/Content%20Images/2022-08-01-how-to-provision-reviewops/express-app.png",[47,992,993],{},"You have succesfully provisioned a dynamic review environment based on your merge request! Once the merge request is closed, the environment will be automatically cleaned up.",[995,996,998],"h2",{"id":997},"to-sum-up","To sum up",[13,1000,1001],{},"Hopefully this tutorial has been helpful and has inspired your GitLab + Argo CD workflows with review environments.",[13,1003,1004],{},"We'd love to hear in the comments on how this is working for you, as well as your ideas on how we can make GitLab a better place for GitOps workflows.",[1006,1007,1008],"style",{},"html pre.shiki code .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}",{"title":82,"searchDepth":105,"depth":105,"links":1010},[1011,1012,1013,1014,1015,1016,1017,1018],{"id":65,"depth":116,"text":66},{"id":516,"depth":116,"text":517},{"id":551,"depth":116,"text":552},{"id":588,"depth":116,"text":589},{"id":727,"depth":116,"text":728},{"id":844,"depth":116,"text":845},{"id":884,"depth":116,"text":885},{"id":997,"depth":105,"text":998},"engineering","2022-08-02","Here's how to use the Argo CD ApplicationSet to provision a ‘ReviewOps’ environment based on merge request changes.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681920/Blog/Hero%20Images/kubernetes.png",{},true,"/en-us/blog/how-to-provision-reviewops",{"title":1030,"description":1021,"ogTitle":1030,"ogDescription":1021,"noIndex":1024,"ogImage":1025,"ogUrl":1031,"ogSiteName":1032,"ogType":1033,"canonicalUrls":1031},"Deploying dynamic review environments with MRs and Argo CD","https://about.gitlab.com/blog/how-to-provision-reviewops","https://about.gitlab.com","article","how-to-provision-reviewops","en-us/blog/how-to-provision-reviewops",[1037,32,1038],"code review","DevOps","BlogPost","7IpfYbBcbOzbRKa7otyQZLdeag-wZSc6lWwiCmqIB-U",{"logo":1042,"freeTrial":1047,"sales":1052,"login":1057,"items":1062,"search":1389,"minimal":1420,"duo":1439,"switchNav":1448,"pricingDeployment":1459},{"config":1043},{"href":1044,"dataGaName":1045,"dataGaLocation":1046},"/","gitlab logo","header",{"text":1048,"config":1049},"Get free trial",{"href":1050,"dataGaName":1051,"dataGaLocation":1046},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":1053,"config":1054},"Request a demo",{"href":1055,"dataGaName":1056,"dataGaLocation":1046},"/sales/?contact-topic=request-demo","sales",{"text":1058,"config":1059},"Sign in",{"href":1060,"dataGaName":1061,"dataGaLocation":1046},"https://gitlab.com/users/sign_in/","sign in",[1063,1092,1192,1197,1311,1367],{"text":1064,"config":1065,"menu":1067},"Platform",{"dataNavLevelOne":1066},"platform",{"type":1068,"columns":1069},"cards",[1070,1076,1084],{"title":1064,"description":1071,"link":1072},"The intelligent orchestration platform for DevSecOps",{"text":1073,"config":1074},"Explore our Platform",{"href":1075,"dataGaName":1066,"dataGaLocation":1046},"/platform/",{"title":1077,"description":1078,"link":1079},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":1080,"config":1081},"Meet GitLab Duo",{"href":1082,"dataGaName":1083,"dataGaLocation":1046},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":1085,"description":1086,"link":1087},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":1088,"config":1089},"Learn more",{"href":1090,"dataGaName":1091,"dataGaLocation":1046},"/why-gitlab/","why gitlab",{"text":1093,"left":1027,"config":1094,"menu":1096},"Product",{"dataNavLevelOne":1095},"solutions",{"type":1097,"link":1098,"columns":1102,"feature":1171},"lists",{"text":1099,"config":1100},"View all Solutions",{"href":1101,"dataGaName":1095,"dataGaLocation":1046},"/solutions/",[1103,1127,1150],{"title":1104,"description":1105,"link":1106,"items":1111},"Automation","CI/CD and automation to accelerate deployment",{"config":1107},{"icon":1108,"href":1109,"dataGaName":1110,"dataGaLocation":1046},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[1112,1116,1119,1123],{"text":1113,"config":1114},"CI/CD",{"href":1115,"dataGaLocation":1046,"dataGaName":1113},"/solutions/continuous-integration/",{"text":1077,"config":1117},{"href":1082,"dataGaLocation":1046,"dataGaName":1118},"gitlab duo agent platform - product menu",{"text":1120,"config":1121},"Source Code Management",{"href":1122,"dataGaLocation":1046,"dataGaName":1120},"/solutions/source-code-management/",{"text":1124,"config":1125},"Automated Software Delivery",{"href":1109,"dataGaLocation":1046,"dataGaName":1126},"Automated software delivery",{"title":1128,"description":1129,"link":1130,"items":1135},"Security","Deliver code faster without compromising security",{"config":1131},{"href":1132,"dataGaName":1133,"dataGaLocation":1046,"icon":1134},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[1136,1140,1145],{"text":1137,"config":1138},"Application Security Testing",{"href":1132,"dataGaName":1139,"dataGaLocation":1046},"Application security testing",{"text":1141,"config":1142},"Software Supply Chain Security",{"href":1143,"dataGaLocation":1046,"dataGaName":1144},"/solutions/supply-chain/","Software supply chain security",{"text":1146,"config":1147},"Software Compliance",{"href":1148,"dataGaName":1149,"dataGaLocation":1046},"/solutions/software-compliance/","software compliance",{"title":1151,"link":1152,"items":1157},"Measurement",{"config":1153},{"icon":1154,"href":1155,"dataGaName":1156,"dataGaLocation":1046},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[1158,1162,1166],{"text":1159,"config":1160},"Visibility & Measurement",{"href":1155,"dataGaLocation":1046,"dataGaName":1161},"Visibility and Measurement",{"text":1163,"config":1164},"Value Stream Management",{"href":1165,"dataGaLocation":1046,"dataGaName":1163},"/solutions/value-stream-management/",{"text":1167,"config":1168},"Analytics & Insights",{"href":1169,"dataGaLocation":1046,"dataGaName":1170},"/solutions/analytics-and-insights/","Analytics and insights",{"title":1172,"type":1097,"items":1173},"GitLab for",[1174,1180,1186],{"text":1175,"config":1176},"Enterprise",{"icon":1177,"href":1178,"dataGaLocation":1046,"dataGaName":1179},"Building","/enterprise/","enterprise",{"text":1181,"config":1182},"Small Business",{"icon":1183,"href":1184,"dataGaLocation":1046,"dataGaName":1185},"Work","/small-business/","small business",{"text":1187,"config":1188},"Public Sector",{"icon":1189,"href":1190,"dataGaLocation":1046,"dataGaName":1191},"Organization","/solutions/public-sector/","public sector",{"text":1193,"config":1194},"Pricing",{"href":1195,"dataGaName":1196,"dataGaLocation":1046,"dataNavLevelOne":1196},"/pricing/","pricing",{"text":1198,"config":1199,"menu":1201},"Resources",{"dataNavLevelOne":1200},"resources",{"type":1097,"link":1202,"columns":1206,"feature":1300},{"text":1203,"config":1204},"View all resources",{"href":1205,"dataGaName":1200,"dataGaLocation":1046},"/resources/",[1207,1240,1267],{"title":1208,"items":1209},"Getting started",[1210,1215,1220,1225,1230,1235],{"text":1211,"config":1212},"Install",{"href":1213,"dataGaName":1214,"dataGaLocation":1046},"/install/","install",{"text":1216,"config":1217},"Quick start guides",{"href":1218,"dataGaName":1219,"dataGaLocation":1046},"/get-started/","quick setup checklists",{"text":1221,"config":1222},"Learn",{"href":1223,"dataGaLocation":1046,"dataGaName":1224},"https://university.gitlab.com/","learn",{"text":1226,"config":1227},"Product documentation",{"href":1228,"dataGaName":1229,"dataGaLocation":1046},"https://docs.gitlab.com/","product documentation",{"text":1231,"config":1232},"Best practice videos",{"href":1233,"dataGaName":1234,"dataGaLocation":1046},"/getting-started-videos/","best practice videos",{"text":1236,"config":1237},"Integrations",{"href":1238,"dataGaName":1239,"dataGaLocation":1046},"/integrations/","integrations",{"title":1241,"items":1242},"Discover",[1243,1248,1253,1258,1262],{"text":1244,"config":1245},"Customer success stories",{"href":1246,"dataGaName":1247,"dataGaLocation":1046},"/customers/","customer success stories",{"text":1249,"config":1250},"Blog",{"href":1251,"dataGaName":1252,"dataGaLocation":1046},"/blog/","blog",{"text":1254,"config":1255},"Demo Hub",{"href":1256,"dataGaName":1257,"dataGaLocation":1046},"/demo-hub/","demo hub",{"text":1259,"config":1260},"The Source",{"href":1261,"dataGaName":1252,"dataGaLocation":1046},"/the-source/",{"text":1263,"config":1264},"Remote",{"href":1265,"dataGaName":1266,"dataGaLocation":1046},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":1268,"items":1269},"Connect",[1270,1275,1280,1285,1290,1295],{"text":1271,"config":1272},"GitLab Services",{"href":1273,"dataGaName":1274,"dataGaLocation":1046},"/services/","services",{"text":1276,"config":1277},"Contribute",{"href":1278,"dataGaName":1279,"dataGaLocation":1046},"https://contributors.gitlab.com","contribute",{"text":1281,"config":1282},"Community",{"href":1283,"dataGaName":1284,"dataGaLocation":1046},"/community/","community",{"text":1286,"config":1287},"Forum",{"href":1288,"dataGaName":1289,"dataGaLocation":1046},"https://forum.gitlab.com/","forum",{"text":1291,"config":1292},"Events",{"href":1293,"dataGaName":1294,"dataGaLocation":1046},"/events/","events",{"text":1296,"config":1297},"Partners",{"href":1298,"dataGaName":1299,"dataGaLocation":1046},"/partners/","partners",{"config":1301,"title":1304,"text":1305,"link":1306},{"background":1302,"textColor":1303},"url('https://res.cloudinary.com/about-gitlab-com/image/upload/v1777322348/qpq8yrgn8knii57omj0c.png')","#000","What’s new in GitLab","Stay updated with our latest features and improvements.",{"text":1307,"config":1308},"Read the latest",{"href":1309,"dataGaName":1310,"dataGaLocation":1046},"/whats-new/","whats new",{"text":1312,"config":1313,"menu":1315},"Company",{"dataNavLevelOne":1314},"company",{"type":1097,"columns":1316},[1317],{"items":1318},[1319,1324,1330,1332,1337,1342,1347,1352,1357,1362],{"text":1320,"config":1321},"About",{"href":1322,"dataGaName":1323,"dataGaLocation":1046},"/company/","about",{"text":1325,"config":1326,"footerGa":1329},"Jobs",{"href":1327,"dataGaName":1328,"dataGaLocation":1046},"/jobs/","jobs",{"dataGaName":1328},{"text":1291,"config":1331},{"href":1293,"dataGaName":1294,"dataGaLocation":1046},{"text":1333,"config":1334},"Leadership",{"href":1335,"dataGaName":1336,"dataGaLocation":1046},"/company/team/e-group/","leadership",{"text":1338,"config":1339},"Handbook",{"href":1340,"dataGaName":1341,"dataGaLocation":1046},"https://handbook.gitlab.com/","handbook",{"text":1343,"config":1344},"Investor relations",{"href":1345,"dataGaName":1346,"dataGaLocation":1046},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1348,"config":1349},"Trust Center",{"href":1350,"dataGaName":1351,"dataGaLocation":1046},"/security/","trust center",{"text":1353,"config":1354},"AI Transparency Center",{"href":1355,"dataGaName":1356,"dataGaLocation":1046},"/ai-transparency-center/","ai transparency center",{"text":1358,"config":1359},"Newsletter",{"href":1360,"dataGaName":1361,"dataGaLocation":1046},"/company/contact/#contact-forms","newsletter",{"text":1363,"config":1364},"Press",{"href":1365,"dataGaName":1366,"dataGaLocation":1046},"/press/","press",{"text":1368,"config":1369,"menu":1370},"Contact us",{"dataNavLevelOne":1314},{"type":1097,"columns":1371},[1372],{"items":1373},[1374,1379,1384],{"text":1375,"config":1376},"Talk to sales",{"href":1377,"dataGaName":1378,"dataGaLocation":1046},"/sales/","talk to sales",{"text":1380,"config":1381},"Support portal",{"href":1382,"dataGaName":1383,"dataGaLocation":1046},"https://support.gitlab.com/hc/en-us","support portal",{"text":1385,"config":1386},"Customer portal",{"href":1387,"dataGaName":1388,"dataGaLocation":1046},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1390,"login":1391,"suggestions":1398},"Close",{"text":1392,"link":1393},"To search repositories and projects, login to",{"text":1394,"config":1395},"gitlab.com",{"href":1060,"dataGaName":1396,"dataGaLocation":1397},"search login","search",{"text":1399,"default":1400},"Suggestions",[1401,1403,1407,1409,1413,1417],{"text":1077,"config":1402},{"href":1082,"dataGaName":1077,"dataGaLocation":1397},{"text":1404,"config":1405},"Code Suggestions (AI)",{"href":1406,"dataGaName":1404,"dataGaLocation":1397},"/solutions/code-suggestions/",{"text":1113,"config":1408},{"href":1115,"dataGaName":1113,"dataGaLocation":1397},{"text":1410,"config":1411},"GitLab on AWS",{"href":1412,"dataGaName":1410,"dataGaLocation":1397},"/partners/technology-partners/aws/",{"text":1414,"config":1415},"GitLab on Google Cloud",{"href":1416,"dataGaName":1414,"dataGaLocation":1397},"/partners/technology-partners/google-cloud-platform/",{"text":1418,"config":1419},"Why GitLab?",{"href":1090,"dataGaName":1418,"dataGaLocation":1397},{"freeTrial":1421,"mobileIcon":1426,"desktopIcon":1431,"secondaryButton":1434},{"text":1422,"config":1423},"Start free trial",{"href":1424,"dataGaName":1051,"dataGaLocation":1425},"https://gitlab.com/-/trials/new/","nav",{"altText":1427,"config":1428},"Gitlab Icon",{"src":1429,"dataGaName":1430,"dataGaLocation":1425},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1427,"config":1432},{"src":1433,"dataGaName":1430,"dataGaLocation":1425},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1435,"config":1436},"Get Started",{"href":1437,"dataGaName":1438,"dataGaLocation":1425},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1440,"mobileIcon":1444,"desktopIcon":1446},{"text":1441,"config":1442},"Learn more about GitLab Duo",{"href":1082,"dataGaName":1443,"dataGaLocation":1425},"gitlab duo",{"altText":1427,"config":1445},{"src":1429,"dataGaName":1430,"dataGaLocation":1425},{"altText":1427,"config":1447},{"src":1433,"dataGaName":1430,"dataGaLocation":1425},{"button":1449,"mobileIcon":1454,"desktopIcon":1456},{"text":1450,"config":1451},"/switch",{"href":1452,"dataGaName":1453,"dataGaLocation":1425},"#contact","switch",{"altText":1427,"config":1455},{"src":1429,"dataGaName":1430,"dataGaLocation":1425},{"altText":1427,"config":1457},{"src":1458,"dataGaName":1430,"dataGaLocation":1425},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1460,"mobileIcon":1465,"desktopIcon":1467},{"text":1461,"config":1462},"Back to pricing",{"href":1195,"dataGaName":1463,"dataGaLocation":1425,"icon":1464},"back to pricing","GoBack",{"altText":1427,"config":1466},{"src":1429,"dataGaName":1430,"dataGaLocation":1425},{"altText":1427,"config":1468},{"src":1433,"dataGaName":1430,"dataGaLocation":1425},{"title":1470,"titleMobile":1471,"button":1472,"config":1477},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":1088,"config":1473},{"href":1474,"dataGaName":1475,"dataGaLocation":1476},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":1478,"disabled":1024},"release",{"data":1480},{"text":1481,"source":1482,"edit":1488,"contribute":1493,"config":1498,"items":1503,"minimal":1710},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1483,"config":1484},"View page source",{"href":1485,"dataGaName":1486,"dataGaLocation":1487},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1489,"config":1490},"Edit this page",{"href":1491,"dataGaName":1492,"dataGaLocation":1487},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1494,"config":1495},"Please contribute",{"href":1496,"dataGaName":1497,"dataGaLocation":1487},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1499,"facebook":1500,"youtube":1501,"linkedin":1502},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1504,1551,1602,1646,1678],{"title":1193,"links":1505,"subMenu":1520},[1506,1510,1515],{"text":1507,"config":1508},"View plans",{"href":1195,"dataGaName":1509,"dataGaLocation":1487},"view plans",{"text":1511,"config":1512},"Why Premium?",{"href":1513,"dataGaName":1514,"dataGaLocation":1487},"/pricing/premium/","why premium",{"text":1516,"config":1517},"Why Ultimate?",{"href":1518,"dataGaName":1519,"dataGaLocation":1487},"/pricing/ultimate/","why ultimate",[1521],{"title":1522,"links":1523},"Contact Us",[1524,1527,1529,1531,1536,1541,1546],{"text":1525,"config":1526},"Contact sales",{"href":1377,"dataGaName":1056,"dataGaLocation":1487},{"text":1380,"config":1528},{"href":1382,"dataGaName":1383,"dataGaLocation":1487},{"text":1385,"config":1530},{"href":1387,"dataGaName":1388,"dataGaLocation":1487},{"text":1532,"config":1533},"Status",{"href":1534,"dataGaName":1535,"dataGaLocation":1487},"https://status.gitlab.com/","status",{"text":1537,"config":1538},"Terms of use",{"href":1539,"dataGaName":1540,"dataGaLocation":1487},"/terms/","terms of use",{"text":1542,"config":1543},"Privacy statement",{"href":1544,"dataGaName":1545,"dataGaLocation":1487},"/privacy/","privacy statement",{"text":1547,"config":1548},"Cookie preferences",{"dataGaName":1549,"dataGaLocation":1487,"id":1550,"isOneTrustButton":1027},"cookie preferences","ot-sdk-btn",{"title":1093,"links":1552,"subMenu":1561},[1553,1557],{"text":1554,"config":1555},"DevSecOps platform",{"href":1075,"dataGaName":1556,"dataGaLocation":1487},"devsecops platform",{"text":1558,"config":1559},"AI-Assisted Development",{"href":1082,"dataGaName":1560,"dataGaLocation":1487},"ai-assisted development",[1562],{"title":1563,"links":1564},"Topics",[1565,1570,1573,1577,1582,1587,1592,1597],{"text":1566,"config":1567},"CICD",{"href":1568,"dataGaName":1569,"dataGaLocation":1487},"/topics/ci-cd/","cicd",{"text":32,"config":1571},{"href":31,"dataGaName":1572,"dataGaLocation":1487},"gitops",{"text":1038,"config":1574},{"href":1575,"dataGaName":1576,"dataGaLocation":1487},"/topics/devops/","devops",{"text":1578,"config":1579},"Version Control",{"href":1580,"dataGaName":1581,"dataGaLocation":1487},"/topics/version-control/","version control",{"text":1583,"config":1584},"DevSecOps",{"href":1585,"dataGaName":1586,"dataGaLocation":1487},"/topics/devsecops/","devsecops",{"text":1588,"config":1589},"Cloud Native",{"href":1590,"dataGaName":1591,"dataGaLocation":1487},"/topics/cloud-native/","cloud native",{"text":1593,"config":1594},"AI for Coding",{"href":1595,"dataGaName":1596,"dataGaLocation":1487},"/topics/devops/ai-for-coding/","ai for coding",{"text":1598,"config":1599},"Agentic AI",{"href":1600,"dataGaName":1601,"dataGaLocation":1487},"/topics/agentic-ai/","agentic ai",{"title":1603,"links":1604},"Solutions",[1605,1607,1609,1614,1618,1621,1625,1628,1630,1633,1636,1641],{"text":1137,"config":1606},{"href":1132,"dataGaName":1137,"dataGaLocation":1487},{"text":1126,"config":1608},{"href":1109,"dataGaName":1110,"dataGaLocation":1487},{"text":1610,"config":1611},"Agile development",{"href":1612,"dataGaName":1613,"dataGaLocation":1487},"/solutions/agile-delivery/","agile delivery",{"text":1615,"config":1616},"SCM",{"href":1122,"dataGaName":1617,"dataGaLocation":1487},"source code management",{"text":1566,"config":1619},{"href":1115,"dataGaName":1620,"dataGaLocation":1487},"continuous integration & delivery",{"text":1622,"config":1623},"Value stream management",{"href":1165,"dataGaName":1624,"dataGaLocation":1487},"value stream management",{"text":32,"config":1626},{"href":1627,"dataGaName":1572,"dataGaLocation":1487},"/solutions/gitops/",{"text":1175,"config":1629},{"href":1178,"dataGaName":1179,"dataGaLocation":1487},{"text":1631,"config":1632},"Small business",{"href":1184,"dataGaName":1185,"dataGaLocation":1487},{"text":1634,"config":1635},"Public sector",{"href":1190,"dataGaName":1191,"dataGaLocation":1487},{"text":1637,"config":1638},"Education",{"href":1639,"dataGaName":1640,"dataGaLocation":1487},"/solutions/education/","education",{"text":1642,"config":1643},"Financial services",{"href":1644,"dataGaName":1645,"dataGaLocation":1487},"/solutions/finance/","financial services",{"title":1198,"links":1647},[1648,1650,1652,1654,1657,1659,1662,1664,1666,1668,1670,1672,1674,1676],{"text":1211,"config":1649},{"href":1213,"dataGaName":1214,"dataGaLocation":1487},{"text":1216,"config":1651},{"href":1218,"dataGaName":1219,"dataGaLocation":1487},{"text":1221,"config":1653},{"href":1223,"dataGaName":1224,"dataGaLocation":1487},{"text":1226,"config":1655},{"href":1228,"dataGaName":1656,"dataGaLocation":1487},"docs",{"text":1249,"config":1658},{"href":1251,"dataGaName":1252,"dataGaLocation":1487},{"text":1660,"config":1661},"What's new",{"href":1309,"dataGaName":1310,"dataGaLocation":1487},{"text":1244,"config":1663},{"href":1246,"dataGaName":1247,"dataGaLocation":1487},{"text":1263,"config":1665},{"href":1265,"dataGaName":1266,"dataGaLocation":1487},{"text":1271,"config":1667},{"href":1273,"dataGaName":1274,"dataGaLocation":1487},{"text":1276,"config":1669},{"href":1278,"dataGaName":1279,"dataGaLocation":1487},{"text":1281,"config":1671},{"href":1283,"dataGaName":1284,"dataGaLocation":1487},{"text":1286,"config":1673},{"href":1288,"dataGaName":1289,"dataGaLocation":1487},{"text":1291,"config":1675},{"href":1293,"dataGaName":1294,"dataGaLocation":1487},{"text":1296,"config":1677},{"href":1298,"dataGaName":1299,"dataGaLocation":1487},{"title":1312,"links":1679},[1680,1682,1684,1686,1688,1690,1694,1699,1701,1703,1705],{"text":1320,"config":1681},{"href":1322,"dataGaName":1314,"dataGaLocation":1487},{"text":1325,"config":1683},{"href":1327,"dataGaName":1328,"dataGaLocation":1487},{"text":1333,"config":1685},{"href":1335,"dataGaName":1336,"dataGaLocation":1487},{"text":1338,"config":1687},{"href":1340,"dataGaName":1341,"dataGaLocation":1487},{"text":1343,"config":1689},{"href":1345,"dataGaName":1346,"dataGaLocation":1487},{"text":1691,"config":1692},"Sustainability",{"href":1693,"dataGaName":1691,"dataGaLocation":1487},"/sustainability/",{"text":1695,"config":1696},"Diversity, inclusion and belonging (DIB)",{"href":1697,"dataGaName":1698,"dataGaLocation":1487},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1348,"config":1700},{"href":1350,"dataGaName":1351,"dataGaLocation":1487},{"text":1358,"config":1702},{"href":1360,"dataGaName":1361,"dataGaLocation":1487},{"text":1363,"config":1704},{"href":1365,"dataGaName":1366,"dataGaLocation":1487},{"text":1706,"config":1707},"Modern Slavery Transparency Statement",{"href":1708,"dataGaName":1709,"dataGaLocation":1487},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1711},[1712,1715,1718],{"text":1713,"config":1714},"Terms",{"href":1539,"dataGaName":1540,"dataGaLocation":1487},{"text":1716,"config":1717},"Cookies",{"dataGaName":1549,"dataGaLocation":1487,"id":1550,"isOneTrustButton":1027},{"text":1719,"config":1720},"Privacy",{"href":1544,"dataGaName":1545,"dataGaLocation":1487},[1722,1736],{"id":1723,"title":7,"body":1023,"config":1724,"content":1726,"description":1023,"extension":1730,"meta":1731,"navigation":1027,"path":1732,"seo":1733,"stem":1734,"__hash__":1735},"blogAuthors/en-us/blog/authors/joe-randazzo.yml",{"template":1725},"BlogAuthor",{"name":7,"config":1727},{"headshot":1728,"ctfId":1729},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664711/Blog/Author%20Headshots/randazzo.jpg","5DxpEbIVcwN2ukwiEMsHlH","yml",{},"/en-us/blog/authors/joe-randazzo",{},"en-us/blog/authors/joe-randazzo","Kg6ZOiBKQgjjlIpsfIAWHsug3iGMaAK1trTdXg4BaFI",{"id":1737,"title":8,"body":1023,"config":1738,"content":1739,"description":1023,"extension":1730,"meta":1743,"navigation":1027,"path":1744,"seo":1745,"stem":1746,"__hash__":1747},"blogAuthors/en-us/blog/authors/madou-coulibaly.yml",{"template":1725},{"name":8,"config":1740},{"headshot":1741,"ctfId":1742},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679848/Blog/Author%20Headshots/madou-headshot.jpg","madou",{},"/en-us/blog/authors/madou-coulibaly",{},"en-us/blog/authors/madou-coulibaly","B1ujB-U-HU1uDfrGilJbCxfUUm6TJB_H1DRGY_p32OA",[1749,1758,1766],{"title":1750,"description":1751,"heroImage":1752,"category":1019,"date":1753,"authors":1754,"slug":1757,"externalUrl":1023},"Confidential AI for GitLab Self-Hosted","Give developers AI coding agents in GitLab Duo without source code leaving a hardware-encrypted boundary — no GPUs needed.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1773866173/vte9qh8rriznvyclhkes.png","2026-08-06",[1755,1756],"Mathias Ewald","Martin Paloncy, Edgeless Systems","confidential-ai-for-gitlab-self-hosted",{"title":1759,"description":1760,"heroImage":1761,"category":1019,"date":1762,"authors":1763,"slug":1765,"externalUrl":1023},"Green DevOps: Why carbon measurement belongs in your CI/CD pipeline","CI/CD pipelines have a hidden carbon cost. Here's why measuring it matters, and how you can get started with Eco CI and Carmen in GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1765809212/noh0mdfn9o94ry9ykura.png","2026-07-09",[1764],"Lysanne Pinto","green-devops-carbon-measurement-cicd-pipeline",{"title":1767,"description":1768,"heroImage":1769,"category":1019,"date":1770,"authors":1771,"slug":1773,"externalUrl":1023},"How to build CI/CD observability at scale","This practical guide to GitLab pipeline analytics helps self-managed users gain operational insights using Prometheus and Grafana.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1774465167/n5hlvrsrheadeccyr1oz.png","2026-04-28",[1772],"Paul Meresanu","how-to-build-ci-cd-observability-at-scale",{"promotions":1775},[1776,1790,1802,1814],{"id":1777,"categories":1778,"header":1780,"text":1781,"button":1782,"image":1787},"ai-modernization",[1779],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1783,"config":1784},"Get your AI maturity score",{"href":1785,"dataGaName":1786,"dataGaLocation":1252},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1788},{"src":1789},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1791,"categories":1792,"header":1794,"text":1781,"button":1795,"image":1799},"devops-modernization",[1793,1586],"product","Are you just managing tools or shipping innovation?",{"text":1796,"config":1797},"Get your DevOps maturity score",{"href":1798,"dataGaName":1786,"dataGaLocation":1252},"/assessments/devops-modernization-assessment/",{"config":1800},{"src":1801},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1803,"categories":1804,"header":1806,"text":1781,"button":1807,"image":1811},"security-modernization",[1805],"security","Are you trading speed for security?",{"text":1808,"config":1809},"Get your security maturity score",{"href":1810,"dataGaName":1786,"dataGaLocation":1252},"/assessments/security-modernization-assessment/",{"config":1812},{"src":1813},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1815,"paths":1816,"header":1819,"text":1820,"button":1821,"image":1826},"github-azure-migration",[1817,1818],"migration-from-azure-devops-to-gitlab","integrating-azure-devops-scm-and-gitlab","Is your team ready for GitHub's Azure move?","GitHub is already rebuilding around Azure. Find out what it means for you.",{"text":1822,"config":1823},"See how GitLab compares to GitHub",{"href":1824,"dataGaName":1825,"dataGaLocation":1252},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1827},{"src":1801},{"header":1829,"blurb":1830,"button":1831,"secondaryButton":1836},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1832,"config":1833},"Get your free trial",{"href":1834,"dataGaName":1051,"dataGaLocation":1835},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1525,"config":1837},{"href":1377,"dataGaName":1056,"dataGaLocation":1835},1786803751884]