[{"data":1,"prerenderedAt":1639},["ShallowReactive",2],{"/blog/tutorial-how-to-set-up-your-first-gitlab-ci-cd-component":3,"navigation-en-us":842,"banner-en-us":1269,"footer-en-us":1279,"blog-post-authors-en-us-Sophia Manicor|Noah Ing":1523,"blog-related-posts-en-us-tutorial-how-to-set-up-your-first-gitlab-ci-cd-component":1549,"blog-promotions-en-us":1575,"next-steps-en-us":1629},{"id":4,"title":5,"authors":6,"body":9,"category":820,"date":821,"description":822,"extension":823,"externalUrl":824,"faq":824,"featured":116,"heroImage":825,"meta":826,"navigation":116,"path":827,"seo":828,"slug":833,"stem":834,"tags":835,"template":840,"updatedDate":824,"__hash__":841},"blogPosts/en-us/blog/tutorial-how-to-set-up-your-first-gitlab-ci-cd-component.md","Tutorial: How to set up your first GitLab CI/CD component",[7,8],"Sophia Manicor","Noah Ing",{"type":10,"value":11,"toc":813},"minimark",[12,23,32,37,50,55,67,88,279,282,353,356,381,384,388,399,413,416,517,520,523,526,583,598,606,609,612,616,626,633,702,714,717,724,731,734,738,756,762,765,771,782,786,809],[13,14,15,16,22],"p",{},"Do you use Python scripts in your GitLab CI pipelines? Do you want to create pipelines at scale? This tutorial shows how to set up your first ",[17,18,21],"a",{"href":19,"rel":20},"https://docs.gitlab.com/ci/components/",[],"GitLab CI/CD component"," to deploy Python scripts.",[13,24,25,26,31],{},"A ",[17,27,30],{"href":28,"rel":29},"https://about.gitlab.com/blog/introducing-ci-components/",[],"CI/CD component is a reusable single pipeline configuration unit",". Use components to create a small part of a larger pipeline, or even to compose a complete pipeline configuration.",[33,34,36],"h1",{"id":35},"prerequisites","Prerequisites",[38,39,40,44,47],"ul",{},[41,42,43],"li",{},"Basic Python knowledge",[41,45,46],{},"Working knowledge of GitLab CI",[41,48,49],{},"8 minutes",[51,52,54],"h2",{"id":53},"python-script","Python script",[38,56,57],{},[41,58,59],{},[60,61,62],"strong",{},[17,63,66],{"href":64,"rel":65},"https://gitlab.com/demos/templates/gitlab-python-cicd-component/-/blob/main/src/script.py?ref_type=heads",[],"The demo Python script",[13,68,69,70,75,76,81,82,87],{},"This Python script utilizes a library called ",[17,71,74],{"href":72,"rel":73},"https://docs.python.org/3/library/argparse.html",[],"ArgParse"," . ArgParse allows you to pass variables to script through the command line. This script takes in three arguments:\n",[17,77,80],{"href":78,"rel":79},"https://docs.gitlab.com/ci/yaml/#image",[],"Python_container_image",": This is the Python container image you wish to use.\n",[17,83,86],{"href":84,"rel":85},"https://docs.gitlab.com/ci/yaml/#stage",[],"Stage",": This is the GitLab CI stage in which you job will run in.\nName: This is your name.",[89,90,95],"pre",{"className":91,"code":92,"language":93,"meta":94,"style":94},"language-python shiki shiki-themes github-light","import argparse\n\nparser = argparse.ArgumentParser(description='Python CICD Component Boilerplate')\nparser.add_argument('python_container_image', type=str, help='python:3.10-slim')\nparser.add_argument('stage', type=str, help='Build')\nparser.add_argument('persons_name', type=str, help='Noah')\nargs = parser.parse_args()\n\npython_container_image = args.python_container_image\nstage = args.stage\npersons_name = args.persons_name\n","python","",[96,97,98,111,118,143,176,203,230,241,246,257,268],"code",{"__ignoreMap":94},[99,100,103,107],"span",{"class":101,"line":102},"line",1,[99,104,106],{"class":105},"sD7c4","import",[99,108,110],{"class":109},"sgsFI"," argparse\n",[99,112,114],{"class":101,"line":113},2,[99,115,117],{"emptyLinePlaceholder":116},true,"\n",[99,119,121,124,127,130,134,136,140],{"class":101,"line":120},3,[99,122,123],{"class":109},"parser ",[99,125,126],{"class":105},"=",[99,128,129],{"class":109}," argparse.ArgumentParser(",[99,131,133],{"class":132},"sqxcx","description",[99,135,126],{"class":105},[99,137,139],{"class":138},"sYBdl","'Python CICD Component Boilerplate'",[99,141,142],{"class":109},")\n",[99,144,146,149,152,155,158,160,164,166,169,171,174],{"class":101,"line":145},4,[99,147,148],{"class":109},"parser.add_argument(",[99,150,151],{"class":138},"'python_container_image'",[99,153,154],{"class":109},", ",[99,156,157],{"class":132},"type",[99,159,126],{"class":105},[99,161,163],{"class":162},"sYu0t","str",[99,165,154],{"class":109},[99,167,168],{"class":132},"help",[99,170,126],{"class":105},[99,172,173],{"class":138},"'python:3.10-slim'",[99,175,142],{"class":109},[99,177,179,181,184,186,188,190,192,194,196,198,201],{"class":101,"line":178},5,[99,180,148],{"class":109},[99,182,183],{"class":138},"'stage'",[99,185,154],{"class":109},[99,187,157],{"class":132},[99,189,126],{"class":105},[99,191,163],{"class":162},[99,193,154],{"class":109},[99,195,168],{"class":132},[99,197,126],{"class":105},[99,199,200],{"class":138},"'Build'",[99,202,142],{"class":109},[99,204,206,208,211,213,215,217,219,221,223,225,228],{"class":101,"line":205},6,[99,207,148],{"class":109},[99,209,210],{"class":138},"'persons_name'",[99,212,154],{"class":109},[99,214,157],{"class":132},[99,216,126],{"class":105},[99,218,163],{"class":162},[99,220,154],{"class":109},[99,222,168],{"class":132},[99,224,126],{"class":105},[99,226,227],{"class":138},"'Noah'",[99,229,142],{"class":109},[99,231,233,236,238],{"class":101,"line":232},7,[99,234,235],{"class":109},"args ",[99,237,126],{"class":105},[99,239,240],{"class":109}," parser.parse_args()\n",[99,242,244],{"class":101,"line":243},8,[99,245,117],{"emptyLinePlaceholder":116},[99,247,249,252,254],{"class":101,"line":248},9,[99,250,251],{"class":109},"python_container_image ",[99,253,126],{"class":105},[99,255,256],{"class":109}," args.python_container_image\n",[99,258,260,263,265],{"class":101,"line":259},10,[99,261,262],{"class":109},"stage ",[99,264,126],{"class":105},[99,266,267],{"class":109}," args.stage\n",[99,269,271,274,276],{"class":101,"line":270},11,[99,272,273],{"class":109},"persons_name ",[99,275,126],{"class":105},[99,277,278],{"class":109}," args.persons_name\n",[13,280,281],{},"This will take in these three variables and print out simple statements:",[89,283,285],{"className":91,"code":284,"language":93,"meta":94,"style":94},"print(\"You have chosen \" + python_container_image + \" as the container image\")\nprint(\"You have chosen \" + stage + \" as the stage to run this job\")\nprint(\"Thank you \" + persons_name + \"! you are succesfully using GitLab CI with a Python script.\")\n",[96,286,287,312,332],{"__ignoreMap":94},[99,288,289,292,295,298,301,304,307,310],{"class":101,"line":102},[99,290,291],{"class":162},"print",[99,293,294],{"class":109},"(",[99,296,297],{"class":138},"\"You have chosen \"",[99,299,300],{"class":105}," +",[99,302,303],{"class":109}," python_container_image ",[99,305,306],{"class":105},"+",[99,308,309],{"class":138}," \" as the container image\"",[99,311,142],{"class":109},[99,313,314,316,318,320,322,325,327,330],{"class":101,"line":113},[99,315,291],{"class":162},[99,317,294],{"class":109},[99,319,297],{"class":138},[99,321,300],{"class":105},[99,323,324],{"class":109}," stage ",[99,326,306],{"class":105},[99,328,329],{"class":138}," \" as the stage to run this job\"",[99,331,142],{"class":109},[99,333,334,336,338,341,343,346,348,351],{"class":101,"line":120},[99,335,291],{"class":162},[99,337,294],{"class":109},[99,339,340],{"class":138},"\"Thank you \"",[99,342,300],{"class":105},[99,344,345],{"class":109}," persons_name ",[99,347,306],{"class":105},[99,349,350],{"class":138}," \"! you are succesfully using GitLab CI with a Python script.\"",[99,352,142],{"class":109},[13,354,355],{},"To test this script locally, you can call on the script by utilizing the following command:",[89,357,361],{"className":358,"code":359,"language":360,"meta":94,"style":94},"language-bash shiki shiki-themes github-light","python3 src/script.py python_container_image stage name\n","bash",[96,362,363],{"__ignoreMap":94},[99,364,365,369,372,375,378],{"class":101,"line":102},[99,366,368],{"class":367},"s7eDp","python3",[99,370,371],{"class":138}," src/script.py",[99,373,374],{"class":138}," python_container_image",[99,376,377],{"class":138}," stage",[99,379,380],{"class":138}," name\n",[13,382,383],{},"Modify this script accordingly if you’d like to add in your own arguments!",[51,385,387],{"id":386},"template","Template",[38,389,390],{},[41,391,392],{},[60,393,394],{},[17,395,398],{"href":396,"rel":397},"https://gitlab.com/demos/templates/gitlab-python-cicd-component/-/blob/main/templates/template.yml?ref_type=heads",[],"Demo of template",[13,400,401,404,405,408,409,412],{},[60,402,403],{},"Note:"," As long as the ",[96,406,407],{},"gitlab-ci.yml"," is placed in the templates/directory, the CI/CD component will know to pick it up. We named our template ",[96,410,411],{},"templates.yml",", but any name would work for this YAML file.",[13,414,415],{},"Now, getting into the fun part of CI/CD components, inputs!  Inputs allow you to pass through variables into your pipeline.",[89,417,421],{"className":418,"code":419,"language":420,"meta":94,"style":94},"language-yml shiki shiki-themes github-light","spec:\n  inputs:\n    python_container_image:\n      default: python:3.10-slim\n      description: \"Define any python container image\"\n    stage:\n      default: build\n      description: \"Define the stage this job will run in\"\n    persons_name:\n      default: Noah\n      description: \"Put your name here\"\n\n","yml",[96,422,423,432,439,446,457,467,474,483,492,499,508],{"__ignoreMap":94},[99,424,425,429],{"class":101,"line":102},[99,426,428],{"class":427},"shJU0","spec",[99,430,431],{"class":109},":\n",[99,433,434,437],{"class":101,"line":113},[99,435,436],{"class":427},"  inputs",[99,438,431],{"class":109},[99,440,441,444],{"class":101,"line":120},[99,442,443],{"class":427},"    python_container_image",[99,445,431],{"class":109},[99,447,448,451,454],{"class":101,"line":145},[99,449,450],{"class":427},"      default",[99,452,453],{"class":109},": ",[99,455,456],{"class":138},"python:3.10-slim\n",[99,458,459,462,464],{"class":101,"line":178},[99,460,461],{"class":427},"      description",[99,463,453],{"class":109},[99,465,466],{"class":138},"\"Define any python container image\"\n",[99,468,469,472],{"class":101,"line":205},[99,470,471],{"class":427},"    stage",[99,473,431],{"class":109},[99,475,476,478,480],{"class":101,"line":232},[99,477,450],{"class":427},[99,479,453],{"class":109},[99,481,482],{"class":138},"build\n",[99,484,485,487,489],{"class":101,"line":243},[99,486,461],{"class":427},[99,488,453],{"class":109},[99,490,491],{"class":138},"\"Define the stage this job will run in\"\n",[99,493,494,497],{"class":101,"line":248},[99,495,496],{"class":427},"    persons_name",[99,498,431],{"class":109},[99,500,501,503,505],{"class":101,"line":259},[99,502,450],{"class":427},[99,504,453],{"class":109},[99,506,507],{"class":138},"Noah\n",[99,509,510,512,514],{"class":101,"line":270},[99,511,461],{"class":427},[99,513,453],{"class":109},[99,515,516],{"class":138},"\"Put your name here\"\n",[13,518,519],{},"Here we have defined the three inputs that are our arguments in our Python script. You can see for each input we have added in a default value – this will be what the input is set to if not overridden. If we took out this default keyword the input would become mandatory when we use our component. As it is written now, adding in these inputs when we use our component is optional due to our default values.",[13,521,522],{},"We can also set descriptions to ensure that other developers can understand what to input when they use our component. Descriptions are optional but they provide self documentation within the code itself, which is always nice.",[13,524,525],{},"After we set up our inputs, let’s write the rest of our component:",[89,527,529],{"className":418,"code":528,"language":420,"meta":94,"style":94},"component:\n  image: $[[ inputs.python_container_image ]]\n  stage: $[[ inputs.stage ]]\n  before_script:\n    - pip3 install -r src/requirements.txt\n  script: python3 src/script.py $[[ inputs.python_container_image ]] $[[ inputs.stage ]] $[[ inputs.persons_name ]]\n\n",[96,530,531,538,548,558,565,573],{"__ignoreMap":94},[99,532,533,536],{"class":101,"line":102},[99,534,535],{"class":427},"component",[99,537,431],{"class":109},[99,539,540,543,545],{"class":101,"line":113},[99,541,542],{"class":427},"  image",[99,544,453],{"class":109},[99,546,547],{"class":138},"$[[ inputs.python_container_image ]]\n",[99,549,550,553,555],{"class":101,"line":120},[99,551,552],{"class":427},"  stage",[99,554,453],{"class":109},[99,556,557],{"class":138},"$[[ inputs.stage ]]\n",[99,559,560,563],{"class":101,"line":145},[99,561,562],{"class":427},"  before_script",[99,564,431],{"class":109},[99,566,567,570],{"class":101,"line":178},[99,568,569],{"class":109},"    - ",[99,571,572],{"class":138},"pip3 install -r src/requirements.txt\n",[99,574,575,578,580],{"class":101,"line":205},[99,576,577],{"class":427},"  script",[99,579,453],{"class":109},[99,581,582],{"class":138},"python3 src/script.py $[[ inputs.python_container_image ]] $[[ inputs.stage ]] $[[ inputs.persons_name ]]\n",[13,584,585,586,589,590,593,594,597],{},"To use inputs in our component, we need to use the syntax ",[96,587,588],{},"$[[ inputs.$VARIABLE ]]",". In the above code, you can see that we use inputs to define our image and stage with  ",[96,591,592],{},"$[[ inputs.python_container_image ]]"," and   ",[96,595,596],{},"$[[ inputs.stage ]] ",".",[89,599,604],{"className":600,"code":602,"language":603,"meta":94},[601],"language-text","script: python3 src/script.py $[[ inputs.python_container_image ]] $[[ inputs.stage ]] $[[ inputs.persons_name ]]\n","text",[96,605,602],{"__ignoreMap":94},[13,607,608],{},"Diving into the script section, you can see we call upon our Python script.. We are able to pass our inputs in with the help of the ArgParse.",[13,610,611],{},"Now that you have reviewed how the Python script works and the template has been set up, it is time to use the component!",[51,613,615],{"id":614},"using-the-component","Using the component",[38,617,618],{},[41,619,620,621],{},"**",[17,622,625],{"href":623,"rel":624},"https://gitlab.com/demos/templates/gitlab-python-cicd-component/-/blob/main/.gitlab-ci.yml?ref_type=heads",[],"A demo of including the component",[13,627,628,629,632],{},"In order to utilize the CI/CD component we just created, we need to include it in the ",[96,630,631],{},".gitlab-ci.yml"," file that is in the root of our directory.",[89,634,638],{"className":635,"code":636,"language":637,"meta":94,"style":94},"language-yaml shiki shiki-themes github-light","include:\n  # include the component located in the current project from the current SHA\n  - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/template@$CI_COMMIT_SHA\n    inputs:\n      python_container_image: python:3.11-slim\n      stage: test\n      persons_name: Tanuki\n\n","yaml",[96,639,640,647,653,665,672,682,692],{"__ignoreMap":94},[99,641,642,645],{"class":101,"line":102},[99,643,644],{"class":427},"include",[99,646,431],{"class":109},[99,648,649],{"class":101,"line":113},[99,650,652],{"class":651},"sAwPA","  # include the component located in the current project from the current SHA\n",[99,654,655,658,660,662],{"class":101,"line":120},[99,656,657],{"class":109},"  - ",[99,659,535],{"class":427},[99,661,453],{"class":109},[99,663,664],{"class":138},"$CI_SERVER_FQDN/$CI_PROJECT_PATH/template@$CI_COMMIT_SHA\n",[99,666,667,670],{"class":101,"line":145},[99,668,669],{"class":427},"    inputs",[99,671,431],{"class":109},[99,673,674,677,679],{"class":101,"line":178},[99,675,676],{"class":427},"      python_container_image",[99,678,453],{"class":109},[99,680,681],{"class":138},"python:3.11-slim\n",[99,683,684,687,689],{"class":101,"line":205},[99,685,686],{"class":427},"      stage",[99,688,453],{"class":109},[99,690,691],{"class":138},"test\n",[99,693,694,697,699],{"class":101,"line":232},[99,695,696],{"class":427},"      persons_name",[99,698,453],{"class":109},[99,700,701],{"class":138},"Tanuki\n",[13,703,704,705,708,709,597],{},"One way to include it is to call upon it locally in the current project from the current ",[96,706,707],{},"Commit SHA",". You can find other ways to ",[17,710,713],{"href":711,"rel":712},"https://docs.gitlab.com/ci/components/#use-a-component",[],"reference a component in our documentation",[13,715,716],{},"To override the defaults, we have passed in other inputs so we get the correct image, stage, and name for our job.",[13,718,719,720,723],{},"Try and change the ",[96,721,722],{},"persons_names"," to your own and watch the pipeline run!",[13,725,726],{},[727,728],"img",{"alt":729,"src":730},"ci/cd component tutorial - pipeline running","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098419/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098418901.png",[13,732,733],{},"Voila! You have learned how to set up a basic C/ICD component utilizing a Python ArgParse script!",[51,735,737],{"id":736},"whats-next","What's next?",[13,739,740,741,746,747,752,753,597],{},"In the Python script, there is a commented out GitLab Python library and OS library. If you would like to interact with the GitLab API, you can uncomment these and add in a ",[17,742,745],{"href":743,"rel":744},"https://docs.gitlab.com/user/profile/personal_access_tokens/",[],"GitLab personal access token"," to the ",[17,748,751],{"href":749,"rel":750},"https://docs.gitlab.com/ci/variables/",[],"CI/CD variables"," named ",[96,754,755],{},"GLPAT",[89,757,760],{"className":758,"code":759,"language":603,"meta":94},[601],"import gitlab\nimport os\n",[96,761,759],{"__ignoreMap":94},[13,763,764],{},"Afterwards you can then interact with the GitLab API.",[89,766,769],{"className":767,"code":768,"language":603,"meta":94},[601],"glpat = os.environ['GLPAT']\n\ngl = gitlab.Gitlab(private_token=glpat)\n# SELF_HOSTED gl = gitlab.Gitlab(url='https://gitlab.example.com', private_token='xxxxxxxxxxxxxx')\ntry:\n   projects = gl.projects.list(get_all=True)\n   print(projects)\nexcept Exception as error:\n   print(\"Error:\", error)\n\n",[96,770,768],{"__ignoreMap":94},[772,773,774],"blockquote",{},[13,775,776,777,597],{},"Learn more about CI/CD components and how to avoid building pipelines from scratch with the ",[17,778,781],{"href":779,"rel":780},"https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/",[],"GitLab CI/CD Catalog",[51,783,785],{"id":784},"read-more","Read more",[38,787,788,795,802],{},[41,789,790],{},[17,791,794],{"href":792,"rel":793},"https://about.gitlab.com/blog/faq-gitlab-ci-cd-catalog/",[],"FAQ: GitLab CI/CD Catalog",[41,796,797],{},[17,798,801],{"href":799,"rel":800},"https://about.gitlab.com/blog/introducing-ci-cd-steps-a-programming-language-for-devsecops-automation/",[],"Introducing CI/CD Steps, a programming language for DevSecOps automation",[41,803,804],{},[17,805,808],{"href":806,"rel":807},"https://about.gitlab.com/blog/a-ci-component-builders-journey/",[],"A CI/CD component builder's journey",[810,811,812],"style",{},"html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sqxcx, html code.shiki .sqxcx{--shiki-default:#E36209}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 .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}",{"title":94,"searchDepth":113,"depth":113,"links":814},[815,816,817,818,819],{"id":53,"depth":113,"text":54},{"id":386,"depth":113,"text":387},{"id":614,"depth":113,"text":615},{"id":736,"depth":113,"text":737},{"id":784,"depth":113,"text":785},"engineering","2024-11-12","Use Python scripts in your GitLab CI/CD pipelines to improve usability. In this step-by-step guide, you'll learn how to get started building your own CI/CD component.","md",null,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098410/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2826%29_3lH4gZFVIGCndksN6Rlg85_1750098409928.png",{},"/en-us/blog/tutorial-how-to-set-up-your-first-gitlab-ci-cd-component",{"title":5,"description":822,"ogTitle":5,"ogDescription":822,"noIndex":829,"ogImage":825,"ogUrl":830,"ogSiteName":831,"ogType":832,"canonicalUrls":830},false,"https://about.gitlab.com/blog/tutorial-how-to-set-up-your-first-gitlab-ci-cd-component","https://about.gitlab.com","article","tutorial-how-to-set-up-your-first-gitlab-ci-cd-component","en-us/blog/tutorial-how-to-set-up-your-first-gitlab-ci-cd-component",[836,837,838,839],"CI/CD","tutorial","DevSecOps","solutions architecture","BlogPost","qwfEo32Ne_djUNE2-z2ibrWqUKJvLOxgr9UUx63-a60",{"logo":843,"freeTrial":848,"sales":853,"login":858,"items":863,"search":1189,"minimal":1220,"duo":1239,"switchNav":1248,"pricingDeployment":1259},{"config":844},{"href":845,"dataGaName":846,"dataGaLocation":847},"/","gitlab logo","header",{"text":849,"config":850},"Get free trial",{"href":851,"dataGaName":852,"dataGaLocation":847},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":854,"config":855},"Request a demo",{"href":856,"dataGaName":857,"dataGaLocation":847},"/sales/?contact-topic=request-demo","sales",{"text":859,"config":860},"Sign in",{"href":861,"dataGaName":862,"dataGaLocation":847},"https://gitlab.com/users/sign_in/","sign in",[864,893,992,997,1111,1167],{"text":865,"config":866,"menu":868},"Platform",{"dataNavLevelOne":867},"platform",{"type":869,"columns":870},"cards",[871,877,885],{"title":865,"description":872,"link":873},"The intelligent orchestration platform for DevSecOps",{"text":874,"config":875},"Explore our Platform",{"href":876,"dataGaName":867,"dataGaLocation":847},"/platform/",{"title":878,"description":879,"link":880},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":881,"config":882},"Meet GitLab Duo",{"href":883,"dataGaName":884,"dataGaLocation":847},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":886,"description":887,"link":888},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":889,"config":890},"Learn more",{"href":891,"dataGaName":892,"dataGaLocation":847},"/why-gitlab/","why gitlab",{"text":894,"left":116,"config":895,"menu":897},"Product",{"dataNavLevelOne":896},"solutions",{"type":898,"link":899,"columns":903,"feature":971},"lists",{"text":900,"config":901},"View all Solutions",{"href":902,"dataGaName":896,"dataGaLocation":847},"/solutions/",[904,927,950],{"title":905,"description":906,"link":907,"items":912},"Automation","CI/CD and automation to accelerate deployment",{"config":908},{"icon":909,"href":910,"dataGaName":911,"dataGaLocation":847},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[913,916,919,923],{"text":836,"config":914},{"href":915,"dataGaLocation":847,"dataGaName":836},"/solutions/continuous-integration/",{"text":878,"config":917},{"href":883,"dataGaLocation":847,"dataGaName":918},"gitlab duo agent platform - product menu",{"text":920,"config":921},"Source Code Management",{"href":922,"dataGaLocation":847,"dataGaName":920},"/solutions/source-code-management/",{"text":924,"config":925},"Automated Software Delivery",{"href":910,"dataGaLocation":847,"dataGaName":926},"Automated software delivery",{"title":928,"description":929,"link":930,"items":935},"Security","Deliver code faster without compromising security",{"config":931},{"href":932,"dataGaName":933,"dataGaLocation":847,"icon":934},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[936,940,945],{"text":937,"config":938},"Application Security Testing",{"href":932,"dataGaName":939,"dataGaLocation":847},"Application security testing",{"text":941,"config":942},"Software Supply Chain Security",{"href":943,"dataGaLocation":847,"dataGaName":944},"/solutions/supply-chain/","Software supply chain security",{"text":946,"config":947},"Software Compliance",{"href":948,"dataGaName":949,"dataGaLocation":847},"/solutions/software-compliance/","software compliance",{"title":951,"link":952,"items":957},"Measurement",{"config":953},{"icon":954,"href":955,"dataGaName":956,"dataGaLocation":847},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[958,962,966],{"text":959,"config":960},"Visibility & Measurement",{"href":955,"dataGaLocation":847,"dataGaName":961},"Visibility and Measurement",{"text":963,"config":964},"Value Stream Management",{"href":965,"dataGaLocation":847,"dataGaName":963},"/solutions/value-stream-management/",{"text":967,"config":968},"Analytics & Insights",{"href":969,"dataGaLocation":847,"dataGaName":970},"/solutions/analytics-and-insights/","Analytics and insights",{"title":972,"type":898,"items":973},"GitLab for",[974,980,986],{"text":975,"config":976},"Enterprise",{"icon":977,"href":978,"dataGaLocation":847,"dataGaName":979},"Building","/enterprise/","enterprise",{"text":981,"config":982},"Small Business",{"icon":983,"href":984,"dataGaLocation":847,"dataGaName":985},"Work","/small-business/","small business",{"text":987,"config":988},"Public Sector",{"icon":989,"href":990,"dataGaLocation":847,"dataGaName":991},"Organization","/solutions/public-sector/","public sector",{"text":993,"config":994},"Pricing",{"href":995,"dataGaName":996,"dataGaLocation":847,"dataNavLevelOne":996},"/pricing/","pricing",{"text":998,"config":999,"menu":1001},"Resources",{"dataNavLevelOne":1000},"resources",{"type":898,"link":1002,"columns":1006,"feature":1100},{"text":1003,"config":1004},"View all resources",{"href":1005,"dataGaName":1000,"dataGaLocation":847},"/resources/",[1007,1040,1067],{"title":1008,"items":1009},"Getting started",[1010,1015,1020,1025,1030,1035],{"text":1011,"config":1012},"Install",{"href":1013,"dataGaName":1014,"dataGaLocation":847},"/install/","install",{"text":1016,"config":1017},"Quick start guides",{"href":1018,"dataGaName":1019,"dataGaLocation":847},"/get-started/","quick setup checklists",{"text":1021,"config":1022},"Learn",{"href":1023,"dataGaLocation":847,"dataGaName":1024},"https://university.gitlab.com/","learn",{"text":1026,"config":1027},"Product documentation",{"href":1028,"dataGaName":1029,"dataGaLocation":847},"https://docs.gitlab.com/","product documentation",{"text":1031,"config":1032},"Best practice videos",{"href":1033,"dataGaName":1034,"dataGaLocation":847},"/getting-started-videos/","best practice videos",{"text":1036,"config":1037},"Integrations",{"href":1038,"dataGaName":1039,"dataGaLocation":847},"/integrations/","integrations",{"title":1041,"items":1042},"Discover",[1043,1048,1053,1058,1062],{"text":1044,"config":1045},"Customer success stories",{"href":1046,"dataGaName":1047,"dataGaLocation":847},"/customers/","customer success stories",{"text":1049,"config":1050},"Blog",{"href":1051,"dataGaName":1052,"dataGaLocation":847},"/blog/","blog",{"text":1054,"config":1055},"Demo Hub",{"href":1056,"dataGaName":1057,"dataGaLocation":847},"/demo-hub/","demo hub",{"text":1059,"config":1060},"The Source",{"href":1061,"dataGaName":1052,"dataGaLocation":847},"/the-source/",{"text":1063,"config":1064},"Remote",{"href":1065,"dataGaName":1066,"dataGaLocation":847},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":1068,"items":1069},"Connect",[1070,1075,1080,1085,1090,1095],{"text":1071,"config":1072},"GitLab Services",{"href":1073,"dataGaName":1074,"dataGaLocation":847},"/services/","services",{"text":1076,"config":1077},"Contribute",{"href":1078,"dataGaName":1079,"dataGaLocation":847},"https://contributors.gitlab.com","contribute",{"text":1081,"config":1082},"Community",{"href":1083,"dataGaName":1084,"dataGaLocation":847},"/community/","community",{"text":1086,"config":1087},"Forum",{"href":1088,"dataGaName":1089,"dataGaLocation":847},"https://forum.gitlab.com/","forum",{"text":1091,"config":1092},"Events",{"href":1093,"dataGaName":1094,"dataGaLocation":847},"/events/","events",{"text":1096,"config":1097},"Partners",{"href":1098,"dataGaName":1099,"dataGaLocation":847},"/partners/","partners",{"config":1101,"title":1104,"text":1105,"link":1106},{"background":1102,"textColor":1103},"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":1107,"config":1108},"Read the latest",{"href":1109,"dataGaName":1110,"dataGaLocation":847},"/whats-new/","whats new",{"text":1112,"config":1113,"menu":1115},"Company",{"dataNavLevelOne":1114},"company",{"type":898,"columns":1116},[1117],{"items":1118},[1119,1124,1130,1132,1137,1142,1147,1152,1157,1162],{"text":1120,"config":1121},"About",{"href":1122,"dataGaName":1123,"dataGaLocation":847},"/company/","about",{"text":1125,"config":1126,"footerGa":1129},"Jobs",{"href":1127,"dataGaName":1128,"dataGaLocation":847},"/jobs/","jobs",{"dataGaName":1128},{"text":1091,"config":1131},{"href":1093,"dataGaName":1094,"dataGaLocation":847},{"text":1133,"config":1134},"Leadership",{"href":1135,"dataGaName":1136,"dataGaLocation":847},"/company/team/e-group/","leadership",{"text":1138,"config":1139},"Handbook",{"href":1140,"dataGaName":1141,"dataGaLocation":847},"https://handbook.gitlab.com/","handbook",{"text":1143,"config":1144},"Investor relations",{"href":1145,"dataGaName":1146,"dataGaLocation":847},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1148,"config":1149},"Trust Center",{"href":1150,"dataGaName":1151,"dataGaLocation":847},"/security/","trust center",{"text":1153,"config":1154},"AI Transparency Center",{"href":1155,"dataGaName":1156,"dataGaLocation":847},"/ai-transparency-center/","ai transparency center",{"text":1158,"config":1159},"Newsletter",{"href":1160,"dataGaName":1161,"dataGaLocation":847},"/company/contact/#contact-forms","newsletter",{"text":1163,"config":1164},"Press",{"href":1165,"dataGaName":1166,"dataGaLocation":847},"/press/","press",{"text":1168,"config":1169,"menu":1170},"Contact us",{"dataNavLevelOne":1114},{"type":898,"columns":1171},[1172],{"items":1173},[1174,1179,1184],{"text":1175,"config":1176},"Talk to sales",{"href":1177,"dataGaName":1178,"dataGaLocation":847},"/sales/","talk to sales",{"text":1180,"config":1181},"Support portal",{"href":1182,"dataGaName":1183,"dataGaLocation":847},"https://support.gitlab.com/hc/en-us","support portal",{"text":1185,"config":1186},"Customer portal",{"href":1187,"dataGaName":1188,"dataGaLocation":847},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1190,"login":1191,"suggestions":1198},"Close",{"text":1192,"link":1193},"To search repositories and projects, login to",{"text":1194,"config":1195},"gitlab.com",{"href":861,"dataGaName":1196,"dataGaLocation":1197},"search login","search",{"text":1199,"default":1200},"Suggestions",[1201,1203,1207,1209,1213,1217],{"text":878,"config":1202},{"href":883,"dataGaName":878,"dataGaLocation":1197},{"text":1204,"config":1205},"Code Suggestions (AI)",{"href":1206,"dataGaName":1204,"dataGaLocation":1197},"/solutions/code-suggestions/",{"text":836,"config":1208},{"href":915,"dataGaName":836,"dataGaLocation":1197},{"text":1210,"config":1211},"GitLab on AWS",{"href":1212,"dataGaName":1210,"dataGaLocation":1197},"/partners/technology-partners/aws/",{"text":1214,"config":1215},"GitLab on Google Cloud",{"href":1216,"dataGaName":1214,"dataGaLocation":1197},"/partners/technology-partners/google-cloud-platform/",{"text":1218,"config":1219},"Why GitLab?",{"href":891,"dataGaName":1218,"dataGaLocation":1197},{"freeTrial":1221,"mobileIcon":1226,"desktopIcon":1231,"secondaryButton":1234},{"text":1222,"config":1223},"Start free trial",{"href":1224,"dataGaName":852,"dataGaLocation":1225},"https://gitlab.com/-/trials/new/","nav",{"altText":1227,"config":1228},"Gitlab Icon",{"src":1229,"dataGaName":1230,"dataGaLocation":1225},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1227,"config":1232},{"src":1233,"dataGaName":1230,"dataGaLocation":1225},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1235,"config":1236},"Get Started",{"href":1237,"dataGaName":1238,"dataGaLocation":1225},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1240,"mobileIcon":1244,"desktopIcon":1246},{"text":1241,"config":1242},"Learn more about GitLab Duo",{"href":883,"dataGaName":1243,"dataGaLocation":1225},"gitlab duo",{"altText":1227,"config":1245},{"src":1229,"dataGaName":1230,"dataGaLocation":1225},{"altText":1227,"config":1247},{"src":1233,"dataGaName":1230,"dataGaLocation":1225},{"button":1249,"mobileIcon":1254,"desktopIcon":1256},{"text":1250,"config":1251},"/switch",{"href":1252,"dataGaName":1253,"dataGaLocation":1225},"#contact","switch",{"altText":1227,"config":1255},{"src":1229,"dataGaName":1230,"dataGaLocation":1225},{"altText":1227,"config":1257},{"src":1258,"dataGaName":1230,"dataGaLocation":1225},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1260,"mobileIcon":1265,"desktopIcon":1267},{"text":1261,"config":1262},"Back to pricing",{"href":995,"dataGaName":1263,"dataGaLocation":1225,"icon":1264},"back to pricing","GoBack",{"altText":1227,"config":1266},{"src":1229,"dataGaName":1230,"dataGaLocation":1225},{"altText":1227,"config":1268},{"src":1233,"dataGaName":1230,"dataGaLocation":1225},{"title":1270,"titleMobile":1271,"button":1272,"config":1277},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":889,"config":1273},{"href":1274,"dataGaName":1275,"dataGaLocation":1276},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":1278,"disabled":829},"release",{"data":1280},{"text":1281,"source":1282,"edit":1288,"contribute":1293,"config":1298,"items":1303,"minimal":1512},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1283,"config":1284},"View page source",{"href":1285,"dataGaName":1286,"dataGaLocation":1287},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1289,"config":1290},"Edit this page",{"href":1291,"dataGaName":1292,"dataGaLocation":1287},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1294,"config":1295},"Please contribute",{"href":1296,"dataGaName":1297,"dataGaLocation":1287},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1299,"facebook":1300,"youtube":1301,"linkedin":1302},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1304,1351,1404,1448,1480],{"title":993,"links":1305,"subMenu":1320},[1306,1310,1315],{"text":1307,"config":1308},"View plans",{"href":995,"dataGaName":1309,"dataGaLocation":1287},"view plans",{"text":1311,"config":1312},"Why Premium?",{"href":1313,"dataGaName":1314,"dataGaLocation":1287},"/pricing/premium/","why premium",{"text":1316,"config":1317},"Why Ultimate?",{"href":1318,"dataGaName":1319,"dataGaLocation":1287},"/pricing/ultimate/","why ultimate",[1321],{"title":1322,"links":1323},"Contact Us",[1324,1327,1329,1331,1336,1341,1346],{"text":1325,"config":1326},"Contact sales",{"href":1177,"dataGaName":857,"dataGaLocation":1287},{"text":1180,"config":1328},{"href":1182,"dataGaName":1183,"dataGaLocation":1287},{"text":1185,"config":1330},{"href":1187,"dataGaName":1188,"dataGaLocation":1287},{"text":1332,"config":1333},"Status",{"href":1334,"dataGaName":1335,"dataGaLocation":1287},"https://status.gitlab.com/","status",{"text":1337,"config":1338},"Terms of use",{"href":1339,"dataGaName":1340,"dataGaLocation":1287},"/terms/","terms of use",{"text":1342,"config":1343},"Privacy statement",{"href":1344,"dataGaName":1345,"dataGaLocation":1287},"/privacy/","privacy statement",{"text":1347,"config":1348},"Cookie preferences",{"dataGaName":1349,"dataGaLocation":1287,"id":1350,"isOneTrustButton":116},"cookie preferences","ot-sdk-btn",{"title":894,"links":1352,"subMenu":1361},[1353,1357],{"text":1354,"config":1355},"DevSecOps platform",{"href":876,"dataGaName":1356,"dataGaLocation":1287},"devsecops platform",{"text":1358,"config":1359},"AI-Assisted Development",{"href":883,"dataGaName":1360,"dataGaLocation":1287},"ai-assisted development",[1362],{"title":1363,"links":1364},"Topics",[1365,1370,1375,1380,1385,1389,1394,1399],{"text":1366,"config":1367},"CICD",{"href":1368,"dataGaName":1369,"dataGaLocation":1287},"/topics/ci-cd/","cicd",{"text":1371,"config":1372},"GitOps",{"href":1373,"dataGaName":1374,"dataGaLocation":1287},"/topics/gitops/","gitops",{"text":1376,"config":1377},"DevOps",{"href":1378,"dataGaName":1379,"dataGaLocation":1287},"/topics/devops/","devops",{"text":1381,"config":1382},"Version Control",{"href":1383,"dataGaName":1384,"dataGaLocation":1287},"/topics/version-control/","version control",{"text":838,"config":1386},{"href":1387,"dataGaName":1388,"dataGaLocation":1287},"/topics/devsecops/","devsecops",{"text":1390,"config":1391},"Cloud Native",{"href":1392,"dataGaName":1393,"dataGaLocation":1287},"/topics/cloud-native/","cloud native",{"text":1395,"config":1396},"AI for Coding",{"href":1397,"dataGaName":1398,"dataGaLocation":1287},"/topics/devops/ai-for-coding/","ai for coding",{"text":1400,"config":1401},"Agentic AI",{"href":1402,"dataGaName":1403,"dataGaLocation":1287},"/topics/agentic-ai/","agentic ai",{"title":1405,"links":1406},"Solutions",[1407,1409,1411,1416,1420,1423,1427,1430,1432,1435,1438,1443],{"text":937,"config":1408},{"href":932,"dataGaName":937,"dataGaLocation":1287},{"text":926,"config":1410},{"href":910,"dataGaName":911,"dataGaLocation":1287},{"text":1412,"config":1413},"Agile development",{"href":1414,"dataGaName":1415,"dataGaLocation":1287},"/solutions/agile-delivery/","agile delivery",{"text":1417,"config":1418},"SCM",{"href":922,"dataGaName":1419,"dataGaLocation":1287},"source code management",{"text":1366,"config":1421},{"href":915,"dataGaName":1422,"dataGaLocation":1287},"continuous integration & delivery",{"text":1424,"config":1425},"Value stream management",{"href":965,"dataGaName":1426,"dataGaLocation":1287},"value stream management",{"text":1371,"config":1428},{"href":1429,"dataGaName":1374,"dataGaLocation":1287},"/solutions/gitops/",{"text":975,"config":1431},{"href":978,"dataGaName":979,"dataGaLocation":1287},{"text":1433,"config":1434},"Small business",{"href":984,"dataGaName":985,"dataGaLocation":1287},{"text":1436,"config":1437},"Public sector",{"href":990,"dataGaName":991,"dataGaLocation":1287},{"text":1439,"config":1440},"Education",{"href":1441,"dataGaName":1442,"dataGaLocation":1287},"/solutions/education/","education",{"text":1444,"config":1445},"Financial services",{"href":1446,"dataGaName":1447,"dataGaLocation":1287},"/solutions/finance/","financial services",{"title":998,"links":1449},[1450,1452,1454,1456,1459,1461,1464,1466,1468,1470,1472,1474,1476,1478],{"text":1011,"config":1451},{"href":1013,"dataGaName":1014,"dataGaLocation":1287},{"text":1016,"config":1453},{"href":1018,"dataGaName":1019,"dataGaLocation":1287},{"text":1021,"config":1455},{"href":1023,"dataGaName":1024,"dataGaLocation":1287},{"text":1026,"config":1457},{"href":1028,"dataGaName":1458,"dataGaLocation":1287},"docs",{"text":1049,"config":1460},{"href":1051,"dataGaName":1052,"dataGaLocation":1287},{"text":1462,"config":1463},"What's new",{"href":1109,"dataGaName":1110,"dataGaLocation":1287},{"text":1044,"config":1465},{"href":1046,"dataGaName":1047,"dataGaLocation":1287},{"text":1063,"config":1467},{"href":1065,"dataGaName":1066,"dataGaLocation":1287},{"text":1071,"config":1469},{"href":1073,"dataGaName":1074,"dataGaLocation":1287},{"text":1076,"config":1471},{"href":1078,"dataGaName":1079,"dataGaLocation":1287},{"text":1081,"config":1473},{"href":1083,"dataGaName":1084,"dataGaLocation":1287},{"text":1086,"config":1475},{"href":1088,"dataGaName":1089,"dataGaLocation":1287},{"text":1091,"config":1477},{"href":1093,"dataGaName":1094,"dataGaLocation":1287},{"text":1096,"config":1479},{"href":1098,"dataGaName":1099,"dataGaLocation":1287},{"title":1112,"links":1481},[1482,1484,1486,1488,1490,1492,1496,1501,1503,1505,1507],{"text":1120,"config":1483},{"href":1122,"dataGaName":1114,"dataGaLocation":1287},{"text":1125,"config":1485},{"href":1127,"dataGaName":1128,"dataGaLocation":1287},{"text":1133,"config":1487},{"href":1135,"dataGaName":1136,"dataGaLocation":1287},{"text":1138,"config":1489},{"href":1140,"dataGaName":1141,"dataGaLocation":1287},{"text":1143,"config":1491},{"href":1145,"dataGaName":1146,"dataGaLocation":1287},{"text":1493,"config":1494},"Sustainability",{"href":1495,"dataGaName":1493,"dataGaLocation":1287},"/sustainability/",{"text":1497,"config":1498},"Diversity, inclusion and belonging (DIB)",{"href":1499,"dataGaName":1500,"dataGaLocation":1287},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1148,"config":1502},{"href":1150,"dataGaName":1151,"dataGaLocation":1287},{"text":1158,"config":1504},{"href":1160,"dataGaName":1161,"dataGaLocation":1287},{"text":1163,"config":1506},{"href":1165,"dataGaName":1166,"dataGaLocation":1287},{"text":1508,"config":1509},"Modern Slavery Transparency Statement",{"href":1510,"dataGaName":1511,"dataGaLocation":1287},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1513},[1514,1517,1520],{"text":1515,"config":1516},"Terms",{"href":1339,"dataGaName":1340,"dataGaLocation":1287},{"text":1518,"config":1519},"Cookies",{"dataGaName":1349,"dataGaLocation":1287,"id":1350,"isOneTrustButton":116},{"text":1521,"config":1522},"Privacy",{"href":1344,"dataGaName":1345,"dataGaLocation":1287},[1524,1537],{"id":1525,"title":7,"body":824,"config":1526,"content":1528,"description":824,"extension":420,"meta":1532,"navigation":116,"path":1533,"seo":1534,"stem":1535,"__hash__":1536},"blogAuthors/en-us/blog/authors/sophia-manicor.yml",{"template":1527},"BlogAuthor",{"name":7,"config":1529},{"headshot":1530,"ctfId":1531},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665576/Blog/Author%20Headshots/sophie_manicor_headshot.png","79Msqcc9YZrC0IvTggfQ5y",{},"/en-us/blog/authors/sophia-manicor",{},"en-us/blog/authors/sophia-manicor","i6tZEYh0BGVe56GYn5Z59J7fVNHk3-yVCcPBXBlfXJY",{"id":1538,"title":8,"body":824,"config":1539,"content":1540,"description":824,"extension":420,"meta":1544,"navigation":116,"path":1545,"seo":1546,"stem":1547,"__hash__":1548},"blogAuthors/en-us/blog/authors/noah-ing.yml",{"template":1527},{"name":8,"config":1541},{"headshot":1542,"ctfId":1543},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664410/Blog/Author%20Headshots/noahing.png","noahing",{},"/en-us/blog/authors/noah-ing",{},"en-us/blog/authors/noah-ing","NHgV_yTX8kHX01mE2SSxC6hcOMw3BCWiblr8m6csLkw",[1550,1559,1567],{"title":1551,"description":1552,"heroImage":1553,"category":820,"date":1554,"authors":1555,"slug":1558,"externalUrl":824},"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",[1556,1557],"Mathias Ewald","Martin Paloncy, Edgeless Systems","confidential-ai-for-gitlab-self-hosted",{"title":1560,"description":1561,"heroImage":1562,"category":820,"date":1563,"authors":1564,"slug":1566,"externalUrl":824},"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",[1565],"Lysanne Pinto","green-devops-carbon-measurement-cicd-pipeline",{"title":1568,"description":1569,"heroImage":1570,"category":820,"date":1571,"authors":1572,"slug":1574,"externalUrl":824},"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",[1573],"Paul Meresanu","how-to-build-ci-cd-observability-at-scale",{"promotions":1576},[1577,1591,1603,1615],{"id":1578,"categories":1579,"header":1581,"text":1582,"button":1583,"image":1588},"ai-modernization",[1580],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1584,"config":1585},"Get your AI maturity score",{"href":1586,"dataGaName":1587,"dataGaLocation":1052},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1589},{"src":1590},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1592,"categories":1593,"header":1595,"text":1582,"button":1596,"image":1600},"devops-modernization",[1594,1388],"product","Are you just managing tools or shipping innovation?",{"text":1597,"config":1598},"Get your DevOps maturity score",{"href":1599,"dataGaName":1587,"dataGaLocation":1052},"/assessments/devops-modernization-assessment/",{"config":1601},{"src":1602},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1604,"categories":1605,"header":1607,"text":1582,"button":1608,"image":1612},"security-modernization",[1606],"security","Are you trading speed for security?",{"text":1609,"config":1610},"Get your security maturity score",{"href":1611,"dataGaName":1587,"dataGaLocation":1052},"/assessments/security-modernization-assessment/",{"config":1613},{"src":1614},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1616,"paths":1617,"header":1620,"text":1621,"button":1622,"image":1627},"github-azure-migration",[1618,1619],"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":1623,"config":1624},"See how GitLab compares to GitHub",{"href":1625,"dataGaName":1626,"dataGaLocation":1052},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1628},{"src":1602},{"header":1630,"blurb":1631,"button":1632,"secondaryButton":1637},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1633,"config":1634},"Get your free trial",{"href":1635,"dataGaName":852,"dataGaLocation":1636},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1325,"config":1638},{"href":1177,"dataGaName":857,"dataGaLocation":1636},1786803776030]