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