[{"data":1,"prerenderedAt":1509},["ShallowReactive",2],{"/blog/working-with-yaml-gitlab-ci-android":3,"navigation-en-us":724,"banner-en-us":1150,"footer-en-us":1160,"blog-post-authors-en-us-Renato Stanic":1405,"blog-related-posts-en-us-working-with-yaml-gitlab-ci-android":1419,"blog-promotions-en-us":1445,"next-steps-en-us":1499},{"id":4,"title":5,"authors":6,"body":8,"category":698,"date":699,"description":700,"extension":701,"externalUrl":702,"faq":702,"featured":703,"heroImage":704,"meta":705,"navigation":77,"path":712,"seo":713,"slug":717,"stem":718,"tags":719,"template":722,"updatedDate":702,"__hash__":723},"blogPosts/en-us/blog/working-with-yaml-gitlab-ci-android.md","Working with YAML in GitLab CI from the Android perspective",[7],"Renato Stanic",{"type":9,"value":10,"toc":688},"minimark",[11,21,24,29,37,97,100,245,264,269,276,331,345,367,371,378,432,458,462,468,476,502,506,522,528,551,555,561,567,586,590,597,639,654,658,661,667,673,684],[12,13,14,15,20],"p",{},"Using ",[16,17,19],"a",{"href":18},"/solutions/continuous-integration/","continuous integration in our everyday workflow"," can help us a lot with faster and iterative development, and having CI do checks every time we change our codebase helps us with deal with fear of modifying code.",[12,22,23],{},"Deploying app builds manually takes time and leaves us idle while we could be developing new and exciting features instead. Here at Undabot we are using GitLab CI for continuous integration. GitLab CI uses a YAML file for job configuration. In this blog post we will go through a sample YAML configuration for Android projects and describe the main YAML building blocks with common Android CI jobs.",[25,26,28],"h3",{"id":27},"yaml-intro","YAML intro",[12,30,31,32,36],{},"The YAML file defines a set of jobs with constraints stating when they should be run. The jobs are defined as top-level elements with a name and always have to contain at least the ",[33,34,35],"code",{},"script"," clause:",[38,39,44],"pre",{"className":40,"code":41,"language":42,"meta":43,"style":43},"language-yaml shiki shiki-themes github-light","helloworld_job:\n  script: \"echo Hello World!\"\n\nassemble_job:\n  script: \"./gradlew assembleRelease\"\n\n","yaml","",[33,45,46,59,72,79,87],{"__ignoreMap":43},[47,48,51,55],"span",{"class":49,"line":50},"line",1,[47,52,54],{"class":53},"shJU0","helloworld_job",[47,56,58],{"class":57},"sgsFI",":\n",[47,60,62,65,68],{"class":49,"line":61},2,[47,63,64],{"class":53},"  script",[47,66,67],{"class":57},": ",[47,69,71],{"class":70},"sYBdl","\"echo Hello World!\"\n",[47,73,75],{"class":49,"line":74},3,[47,76,78],{"emptyLinePlaceholder":77},true,"\n",[47,80,82,85],{"class":49,"line":81},4,[47,83,84],{"class":53},"assemble_job",[47,86,58],{"class":57},[47,88,90,92,94],{"class":49,"line":89},5,[47,91,64],{"class":53},[47,93,67],{"class":57},[47,95,96],{"class":70},"\"./gradlew assembleRelease\"\n",[12,98,99],{},"YAML syntax allows for more complex job definitions than in the above example:",[38,101,103],{"className":40,"code":102,"language":42,"meta":43,"style":43},"before_script:\n  - bundle install\n\nafter_script:\n  - rm secrets\n\nstages:\n  - build\n  - test\n  - deploy\n\nhelloworld_job:\n  stage: build\n  script:\n    - echo Hello World\n  only:\n    - master\n  tags:\n    - android\n\n",[33,104,105,112,120,124,131,138,143,151,159,167,175,180,187,197,204,213,221,229,237],{"__ignoreMap":43},[47,106,107,110],{"class":49,"line":50},[47,108,109],{"class":53},"before_script",[47,111,58],{"class":57},[47,113,114,117],{"class":49,"line":61},[47,115,116],{"class":57},"  - ",[47,118,119],{"class":70},"bundle install\n",[47,121,122],{"class":49,"line":74},[47,123,78],{"emptyLinePlaceholder":77},[47,125,126,129],{"class":49,"line":81},[47,127,128],{"class":53},"after_script",[47,130,58],{"class":57},[47,132,133,135],{"class":49,"line":89},[47,134,116],{"class":57},[47,136,137],{"class":70},"rm secrets\n",[47,139,141],{"class":49,"line":140},6,[47,142,78],{"emptyLinePlaceholder":77},[47,144,146,149],{"class":49,"line":145},7,[47,147,148],{"class":53},"stages",[47,150,58],{"class":57},[47,152,154,156],{"class":49,"line":153},8,[47,155,116],{"class":57},[47,157,158],{"class":70},"build\n",[47,160,162,164],{"class":49,"line":161},9,[47,163,116],{"class":57},[47,165,166],{"class":70},"test\n",[47,168,170,172],{"class":49,"line":169},10,[47,171,116],{"class":57},[47,173,174],{"class":70},"deploy\n",[47,176,178],{"class":49,"line":177},11,[47,179,78],{"emptyLinePlaceholder":77},[47,181,183,185],{"class":49,"line":182},12,[47,184,54],{"class":53},[47,186,58],{"class":57},[47,188,190,193,195],{"class":49,"line":189},13,[47,191,192],{"class":53},"  stage",[47,194,67],{"class":57},[47,196,158],{"class":70},[47,198,200,202],{"class":49,"line":199},14,[47,201,64],{"class":53},[47,203,58],{"class":57},[47,205,207,210],{"class":49,"line":206},15,[47,208,209],{"class":57},"    - ",[47,211,212],{"class":70},"echo Hello World\n",[47,214,216,219],{"class":49,"line":215},16,[47,217,218],{"class":53},"  only",[47,220,58],{"class":57},[47,222,224,226],{"class":49,"line":223},17,[47,225,209],{"class":57},[47,227,228],{"class":70},"master\n",[47,230,232,235],{"class":49,"line":231},18,[47,233,234],{"class":53},"  tags",[47,236,58],{"class":57},[47,238,240,242],{"class":49,"line":239},19,[47,241,209],{"class":57},[47,243,244],{"class":70},"android\n",[12,246,247,249,250,252,253,255,256,259,260,263],{},[33,248,109],{}," – commands that run before each jobs script\n",[33,251,128],{}," – commands that run after each jobs script\n",[33,254,148],{}," – used to define build stages\n",[33,257,258],{},"only"," – defines the names of branches and tags for which the job will run\n",[33,261,262],{},"tags"," – used to select specific Runners from the list of all Runners that are allowed to run this project.",[265,266,268],"h2",{"id":267},"initial-setup-for-android","Initial setup for Android",[12,270,271,272,275],{},"First step is to create a YAML file called ",[33,273,274],{},"gitlab-ci.yml"," in root directory of your Android project and add the following code:",[38,277,279],{"className":40,"code":278,"language":42,"meta":43,"style":43},"before_script:\n  - export ANDROID_HOME=\"$HOME/Library/Android/sdk\"\n  - bundle install\nstages:\n  - build\n  - test\n  - quality_assurance\n  - deploy\n\n",[33,280,281,287,294,300,306,312,318,325],{"__ignoreMap":43},[47,282,283,285],{"class":49,"line":50},[47,284,109],{"class":53},[47,286,58],{"class":57},[47,288,289,291],{"class":49,"line":61},[47,290,116],{"class":57},[47,292,293],{"class":70},"export ANDROID_HOME=\"$HOME/Library/Android/sdk\"\n",[47,295,296,298],{"class":49,"line":74},[47,297,116],{"class":57},[47,299,119],{"class":70},[47,301,302,304],{"class":49,"line":81},[47,303,148],{"class":53},[47,305,58],{"class":57},[47,307,308,310],{"class":49,"line":89},[47,309,116],{"class":57},[47,311,158],{"class":70},[47,313,314,316],{"class":49,"line":140},[47,315,116],{"class":57},[47,317,166],{"class":70},[47,319,320,322],{"class":49,"line":145},[47,321,116],{"class":57},[47,323,324],{"class":70},"quality_assurance\n",[47,326,327,329],{"class":49,"line":153},[47,328,116],{"class":57},[47,330,174],{"class":70},[12,332,333,334,336,337,340,341,344],{},"In ",[33,335,109],{}," we execute these two commands:\n",[33,338,339],{},"- export ANDROID_HOME=\"$HOME/Library/Android/sdk”","– sets Android home environment variable to be available for all other jobs and Gradle tasks\n",[33,342,343],{},"- bundle install"," – we are using fastlane for task automation and Bundler to manage Ruby gems so we need to run bundle install to make sure everything is installed correctly.",[12,346,347,348,350,351,354,355,358,359,362,363,366],{},"In the ",[33,349,148],{}," section we define four build stages:\n",[33,352,353],{},"- build","– for build jobs\n",[33,356,357],{},"- test","– for test jobs that include unit and instrumentation tests\n",[33,360,361],{},"- quality_assurance","– for jobs that run all of our QA tools\n",[33,364,365],{},"- deploy","– for deployment jobs",[265,368,370],{"id":369},"build-stage","Build stage",[12,372,373,374,377],{},"This job (",[33,375,376],{},"build_job",") is used to create an APK artifact that can be used to test the app manually or to upload it to the Play Store.",[38,379,381],{"className":40,"code":380,"language":42,"meta":43,"style":43},"build_job:\n  stage: build\n  script:\n    - ./gradlew clean assembleRelease\n  artifacts:\n    paths:\n      - app/build/outputs/\n",[33,382,383,389,397,403,410,417,424],{"__ignoreMap":43},[47,384,385,387],{"class":49,"line":50},[47,386,376],{"class":53},[47,388,58],{"class":57},[47,390,391,393,395],{"class":49,"line":61},[47,392,192],{"class":53},[47,394,67],{"class":57},[47,396,158],{"class":70},[47,398,399,401],{"class":49,"line":74},[47,400,64],{"class":53},[47,402,58],{"class":57},[47,404,405,407],{"class":49,"line":81},[47,406,209],{"class":57},[47,408,409],{"class":70},"./gradlew clean assembleRelease\n",[47,411,412,415],{"class":49,"line":89},[47,413,414],{"class":53},"  artifacts",[47,416,58],{"class":57},[47,418,419,422],{"class":49,"line":140},[47,420,421],{"class":53},"    paths",[47,423,58],{"class":57},[47,425,426,429],{"class":49,"line":145},[47,427,428],{"class":57},"      - ",[47,430,431],{"class":70},"app/build/outputs/\n",[12,433,434,437,438,441,442,445,446,449,450,453,454,457],{},[33,435,436],{},"build_job:","– name of the CI job\n",[33,439,440],{},"stage: build","– it gets executed in the build stage\n",[33,443,444],{},"./gradlew clean assembleRelease","– executes Gradle command to create a release APK\n",[33,447,448],{},"artifacts:","– job section that defines list of files and directories that are attached to a job after completion.\n",[33,451,452],{},"paths:","– output file paths\n",[33,455,456],{},"app/build/outputs","– directory path of our APK",[265,459,461],{"id":460},"unit-tests","Unit tests",[12,463,373,464,467],{},[33,465,466],{},"unit_tests",") runs our unit tests in a test stage. Every time they fail, a report artifact will be created. Each report artifact expires within four days of creation.",[38,469,474],{"className":470,"code":472,"language":473,"meta":43},[471],"language-text","unit_tests:\n  stage: test\n  script:\n    - ./gradlew test\n  artifacts:\n    name: \"reports_${CI_PROJECT_NAME}_${CI_BUILD_REF_NAME}\"\n    when: on_failure\n    expire_in: 4 days\n    paths:\n      - app/build/reports/tests/\n","text",[33,475,472],{"__ignoreMap":43},[12,477,478,481,482,485,486,489,490,493,494,497,498,501],{},[33,479,480],{},"./gradlew test","– run Gradle command that triggers our unit tests artifacts:\n",[33,483,484],{},"name:","– defines artifact name by using environment variables\n",[33,487,488],{},"CI_PROJECT_NAME","– project name that is currently being built\n",[33,491,492],{},"CI_BUILD_REF_NAME","– branch or tag name for which project is built\n",[33,495,496],{},"when:","– defines when is it created (on_success, on_failure, always)\n",[33,499,500],{},"expire_in:","– defines when is it expired, after artifact has expired it gets deleted from CI",[265,503,505],{"id":504},"instrumentation-tests","Instrumentation tests",[12,507,373,508,511,512,517,518,521],{},[33,509,510],{},"instrumentation_tests",") runs all of our instrumentation tests in a test stage by starting a windowless emulator without sound and animations followed by a ",[16,513,516],{"href":514,"rel":515},"https://gist.github.com/anonymous/614aafb2d8710865c688684a8657a141",[],"custom bash script"," that waits for the emulator to start, after which the device is unlocked by sending key event 82. When the emulator is ready we run the Gradle command for instrumentation tests. Once all tests finished running, the emulator is killed with a ",[16,519,516],{"href":514,"rel":520},[],".",[38,523,526],{"className":524,"code":525,"language":473,"meta":43},[471],"instrumentation_tests:\n  stage: test\n  script:\n    - emulator -avd testAVD -no-audio -no-window &\n    - ./ci/android-wait-for-emulator.sh\n    - adb devices\n    - adb shell settings put global window_animation_scale 0 &\n    - adb shell settings put global transition_animation_scale 0 &\n    - adb shell settings put global animator_duration_scale 0 &\n    - adb shell input keyevent 82 &\n    - ./gradlew connectedAndroidTest\n    - ./ci/stop-emulators.sh\n  artifacts:\n    name: \"reports_${CI_PROJECT_NAME}_${CI_BUILD_REF_NAME}\"\n    when: on_failure\n    expire_in: 4 days\n    paths:\n      - app/build/reports/androidTests/connected/\n",[33,527,525],{"__ignoreMap":43},[12,529,530,533,536,537,540,541,544,547,550],{},[33,531,532],{},"- emulator - avd testAVD -no-audio -no-window &",[33,534,535],{},"- ./ci/android-wait-for-emulator.sh","\nStarts the emulator and waits for it to boot.\n",[33,538,539],{},"- adb devices","\nDisplays list of found devices in GitLab web terminal.\n",[33,542,543],{},"- adb shell settings put global window_animation_scale 0 &",[33,545,546],{},"- adb shell settings put global transition_animation_scale 0 &",[33,548,549],{},"- abd shell settings put global animator_duration_scale 0 &","\nDisables all animations and transitions.",[265,552,554],{"id":553},"static-analysis","Static analysis",[12,556,373,557,560],{},[33,558,559],{},"static_analysis",") runs all of static code analysis in QA stage. This is a tricky area especially if you are working on a project with a lot of legacy code. My suggestion would be to disable all of the rules and start fixing them one at the time. Tools used for static analysis are lint, checkstyle, pmd and findbugs.",[38,562,565],{"className":563,"code":564,"language":473,"meta":43},[471],"static_analysis:\n  stage: quality_assurance\n  script:\n    - ./gradlew lint\n    - ./gradlew checkstyle\n    - ./gradlew pmd\n    - ./gradlew findbugs\n  artifacts:\n    name: \"reports_${CI_PROJECT_NAME}_${CI_BUILD_REF_NAME}\"\n    when: on_failure\n    expire_in: 4 days\n    paths:\n      - app/build/reports/\n",[33,566,564],{"__ignoreMap":43},[12,568,569,572,575,578,581,582,585],{},[33,570,571],{},"- ./gradlew lint",[33,573,574],{},"- ./gradlew checkstyle",[33,576,577],{},"- ./gradlew pmd",[33,579,580],{},"- ./gradlew findbugs","\nGradle commands that trigger QA tools.\n",[33,583,584],{},"- app/build/reports"," – path to our QA reports",[265,587,589],{"id":588},"deploy-stage","Deploy stage",[12,591,592,593,596],{},"The final job (",[33,594,595],{},"deploy_internal",") deploys the app to the QA team in deploy stage. You don’t want to deploy every time you commit something so this step is set as manual. Manual jobs are triggered via GitLab web interface by pressing the play button in your pipeline list. If you are using fastlane as your deployment tool, the last job will look like the following code:",[38,598,600],{"className":40,"code":599,"language":42,"meta":43,"style":43},"deploy_internal:\n  stage: deploy\n  script:\n    - bundle exec fastlane android deploy_lane\n  when: manual\n",[33,601,602,608,616,622,629],{"__ignoreMap":43},[47,603,604,606],{"class":49,"line":50},[47,605,595],{"class":53},[47,607,58],{"class":57},[47,609,610,612,614],{"class":49,"line":61},[47,611,192],{"class":53},[47,613,67],{"class":57},[47,615,174],{"class":70},[47,617,618,620],{"class":49,"line":74},[47,619,64],{"class":53},[47,621,58],{"class":57},[47,623,624,626],{"class":49,"line":81},[47,625,209],{"class":57},[47,627,628],{"class":70},"bundle exec fastlane android deploy_lane\n",[47,630,631,634,636],{"class":49,"line":89},[47,632,633],{"class":53},"  when",[47,635,67],{"class":57},[47,637,638],{"class":70},"manual\n",[12,640,641,644,645,648,649],{},[33,642,643],{},"- bundle exec fastlane android deploy_lane","– executes fastlane deploy lane that deploys app to the QA team\n",[33,646,647],{},"when: manual"," – defines ",[16,650,653],{"href":651,"rel":652},"https://docs.gitlab.com/ci/yaml/#when",[],"when is a job executed",[265,655,657],{"id":656},"theres-plenty-more","There’s plenty more",[12,659,660],{},"Setting up Android continuous integration with GitLab CI is great and supports plenty of cool features a lot more than we showed. Hopefully this short introduction was helpful and is going to motivate you to discover more features on your own.",[12,662,663,664,666],{},"Complete ",[33,665,274],{},":",[38,668,671],{"className":669,"code":670,"language":473,"meta":43},[471],"before_script:\n  - export ANDROID_HOME=\"$HOME/Library/Android/sdk\"\n  - bundle install\n\nstages:\n- build\n- test\n- quality_assurance\n- deploy\n\nbuild_job:\n  stage: build\n  script:\n    - ./gradlew clean assembleRelease\n  artifacts:\n    paths:\n    - app/build/outputs/\n\nunit_tests:\n  stage: test\n  script:\n    - ./gradlew test\n  artifacts:\n    name: \"reports_${CI_PROJECT_NAME}_${CI_BUILD_REF_NAME}\"\n    when: on_failure\n    expire_in: 4 days\n    paths:\n      - app/build/reports/tests/\n\ninstrumentation_tests:\n  stage: test\n  script:\n    - emulator -avd testAVD -no-audio -no-window &\n    - ./ci/android-wait-for-emulator.sh\n    - adb devices\n    - adb shell settings put global window_animation_scale 0 &\n    - adb shell settings put global transition_animation_scale 0 &\n    - adb shell settings put global animator_duration_scale 0 &\n    - adb shell input keyevent 82 &\n    - ./gradlew connectedAndroidTest\n    - ./ci/stop-emulators.sh\n  artifacts:\n    name: \"reports_${CI_PROJECT_NAME}_${CI_BUILD_REF_NAME}\"\n    when: on_failure\n    expire_in: 4 days\n    paths:\n      - app/build/reports/androidTests/connected/\n\nstatic_analysis:\n  stage: quality_assurance\n  script:\n    - ./gradlew lint\n    - ./gradlew checkstyle\n    - ./gradlew pmd\n    - ./gradlew findbugs\n  artifacts:\n    name: \"reports_${CI_PROJECT_NAME}_${CI_BUILD_REF_NAME}\"\n    when: on_failure\n    expire_in: 4 days\n    paths:\n      - app/build/reports/\n\ndeploy_internal:\n  stage: deploy\n  script:\n    - bundle exec fastlane android deploy_lane\n  when: manual\n",[33,672,670],{"__ignoreMap":43},[12,674,675],{},[676,677,678,683],"em",{},[16,679,682],{"href":680,"rel":681},"https://blog.undabot.com/working-with-yaml-in-gitlab-ci-from-android-perspective-b8cf54b5b911",[],"Working with YAML in GitLab CI from an Android perspective"," was originally published on Undabot's blog.",[685,686,687],"style",{},"html pre.shiki code .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html .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);}",{"title":43,"searchDepth":61,"depth":61,"links":689},[690,691,692,693,694,695,696,697],{"id":27,"depth":74,"text":28},{"id":267,"depth":61,"text":268},{"id":369,"depth":61,"text":370},{"id":460,"depth":61,"text":461},{"id":504,"depth":61,"text":505},{"id":553,"depth":61,"text":554},{"id":588,"depth":61,"text":589},{"id":656,"depth":61,"text":657},"engineering","2017-11-20","Guest author Renato Stanic shares a sample YAML configuration for Android projects, which helps his team with faster, more iterative development.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665524/Blog/Hero%20Images/yaml-gitlab-ci-android.png",{"excerpt":706},{"type":9,"value":707},[708],[12,709,14,710,20],{},[16,711,19],{"href":18},"/en-us/blog/working-with-yaml-gitlab-ci-android",{"title":5,"description":700,"ogTitle":5,"ogDescription":700,"noIndex":703,"ogImage":704,"ogUrl":714,"ogSiteName":715,"ogType":716,"canonicalUrls":714},"https://about.gitlab.com/blog/working-with-yaml-gitlab-ci-android","https://about.gitlab.com","article","working-with-yaml-gitlab-ci-android","en-us/blog/working-with-yaml-gitlab-ci-android",[720,721],"CI/CD","user stories","BlogPost","s8DO-8szpZ_whNnZXLWi3D1jZBTmHC_X5uHPXEhJWQI",{"logo":725,"freeTrial":730,"sales":735,"login":740,"items":745,"search":1070,"minimal":1101,"duo":1120,"switchNav":1129,"pricingDeployment":1140},{"config":726},{"href":727,"dataGaName":728,"dataGaLocation":729},"/","gitlab logo","header",{"text":731,"config":732},"Get free trial",{"href":733,"dataGaName":734,"dataGaLocation":729},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":736,"config":737},"Request a demo",{"href":738,"dataGaName":739,"dataGaLocation":729},"/sales/?contact-topic=request-demo","sales",{"text":741,"config":742},"Sign in",{"href":743,"dataGaName":744,"dataGaLocation":729},"https://gitlab.com/users/sign_in/","sign in",[746,775,873,878,992,1048],{"text":747,"config":748,"menu":750},"Platform",{"dataNavLevelOne":749},"platform",{"type":751,"columns":752},"cards",[753,759,767],{"title":747,"description":754,"link":755},"The intelligent orchestration platform for DevSecOps",{"text":756,"config":757},"Explore our Platform",{"href":758,"dataGaName":749,"dataGaLocation":729},"/platform/",{"title":760,"description":761,"link":762},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":763,"config":764},"Meet GitLab Duo",{"href":765,"dataGaName":766,"dataGaLocation":729},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":768,"description":769,"link":770},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":771,"config":772},"Learn more",{"href":773,"dataGaName":774,"dataGaLocation":729},"/why-gitlab/","why gitlab",{"text":776,"left":77,"config":777,"menu":779},"Product",{"dataNavLevelOne":778},"solutions",{"type":780,"link":781,"columns":785,"feature":852},"lists",{"text":782,"config":783},"View all Solutions",{"href":784,"dataGaName":778,"dataGaLocation":729},"/solutions/",[786,808,831],{"title":787,"description":788,"link":789,"items":794},"Automation","CI/CD and automation to accelerate deployment",{"config":790},{"icon":791,"href":792,"dataGaName":793,"dataGaLocation":729},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[795,797,800,804],{"text":720,"config":796},{"href":18,"dataGaLocation":729,"dataGaName":720},{"text":760,"config":798},{"href":765,"dataGaLocation":729,"dataGaName":799},"gitlab duo agent platform - product menu",{"text":801,"config":802},"Source Code Management",{"href":803,"dataGaLocation":729,"dataGaName":801},"/solutions/source-code-management/",{"text":805,"config":806},"Automated Software Delivery",{"href":792,"dataGaLocation":729,"dataGaName":807},"Automated software delivery",{"title":809,"description":810,"link":811,"items":816},"Security","Deliver code faster without compromising security",{"config":812},{"href":813,"dataGaName":814,"dataGaLocation":729,"icon":815},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[817,821,826],{"text":818,"config":819},"Application Security Testing",{"href":813,"dataGaName":820,"dataGaLocation":729},"Application security testing",{"text":822,"config":823},"Software Supply Chain Security",{"href":824,"dataGaLocation":729,"dataGaName":825},"/solutions/supply-chain/","Software supply chain security",{"text":827,"config":828},"Software Compliance",{"href":829,"dataGaName":830,"dataGaLocation":729},"/solutions/software-compliance/","software compliance",{"title":832,"link":833,"items":838},"Measurement",{"config":834},{"icon":835,"href":836,"dataGaName":837,"dataGaLocation":729},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[839,843,847],{"text":840,"config":841},"Visibility & Measurement",{"href":836,"dataGaLocation":729,"dataGaName":842},"Visibility and Measurement",{"text":844,"config":845},"Value Stream Management",{"href":846,"dataGaLocation":729,"dataGaName":844},"/solutions/value-stream-management/",{"text":848,"config":849},"Analytics & Insights",{"href":850,"dataGaLocation":729,"dataGaName":851},"/solutions/analytics-and-insights/","Analytics and insights",{"title":853,"type":780,"items":854},"GitLab for",[855,861,867],{"text":856,"config":857},"Enterprise",{"icon":858,"href":859,"dataGaLocation":729,"dataGaName":860},"Building","/enterprise/","enterprise",{"text":862,"config":863},"Small Business",{"icon":864,"href":865,"dataGaLocation":729,"dataGaName":866},"Work","/small-business/","small business",{"text":868,"config":869},"Public Sector",{"icon":870,"href":871,"dataGaLocation":729,"dataGaName":872},"Organization","/solutions/public-sector/","public sector",{"text":874,"config":875},"Pricing",{"href":876,"dataGaName":877,"dataGaLocation":729,"dataNavLevelOne":877},"/pricing/","pricing",{"text":879,"config":880,"menu":882},"Resources",{"dataNavLevelOne":881},"resources",{"type":780,"link":883,"columns":887,"feature":981},{"text":884,"config":885},"View all resources",{"href":886,"dataGaName":881,"dataGaLocation":729},"/resources/",[888,921,948],{"title":889,"items":890},"Getting started",[891,896,901,906,911,916],{"text":892,"config":893},"Install",{"href":894,"dataGaName":895,"dataGaLocation":729},"/install/","install",{"text":897,"config":898},"Quick start guides",{"href":899,"dataGaName":900,"dataGaLocation":729},"/get-started/","quick setup checklists",{"text":902,"config":903},"Learn",{"href":904,"dataGaLocation":729,"dataGaName":905},"https://university.gitlab.com/","learn",{"text":907,"config":908},"Product documentation",{"href":909,"dataGaName":910,"dataGaLocation":729},"https://docs.gitlab.com/","product documentation",{"text":912,"config":913},"Best practice videos",{"href":914,"dataGaName":915,"dataGaLocation":729},"/getting-started-videos/","best practice videos",{"text":917,"config":918},"Integrations",{"href":919,"dataGaName":920,"dataGaLocation":729},"/integrations/","integrations",{"title":922,"items":923},"Discover",[924,929,934,939,943],{"text":925,"config":926},"Customer success stories",{"href":927,"dataGaName":928,"dataGaLocation":729},"/customers/","customer success stories",{"text":930,"config":931},"Blog",{"href":932,"dataGaName":933,"dataGaLocation":729},"/blog/","blog",{"text":935,"config":936},"Demo Hub",{"href":937,"dataGaName":938,"dataGaLocation":729},"/demo-hub/","demo hub",{"text":940,"config":941},"The Source",{"href":942,"dataGaName":933,"dataGaLocation":729},"/the-source/",{"text":944,"config":945},"Remote",{"href":946,"dataGaName":947,"dataGaLocation":729},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":949,"items":950},"Connect",[951,956,961,966,971,976],{"text":952,"config":953},"GitLab Services",{"href":954,"dataGaName":955,"dataGaLocation":729},"/services/","services",{"text":957,"config":958},"Contribute",{"href":959,"dataGaName":960,"dataGaLocation":729},"https://contributors.gitlab.com","contribute",{"text":962,"config":963},"Community",{"href":964,"dataGaName":965,"dataGaLocation":729},"/community/","community",{"text":967,"config":968},"Forum",{"href":969,"dataGaName":970,"dataGaLocation":729},"https://forum.gitlab.com/","forum",{"text":972,"config":973},"Events",{"href":974,"dataGaName":975,"dataGaLocation":729},"/events/","events",{"text":977,"config":978},"Partners",{"href":979,"dataGaName":980,"dataGaLocation":729},"/partners/","partners",{"config":982,"title":985,"text":986,"link":987},{"background":983,"textColor":984},"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":988,"config":989},"Read the latest",{"href":990,"dataGaName":991,"dataGaLocation":729},"/whats-new/","whats new",{"text":993,"config":994,"menu":996},"Company",{"dataNavLevelOne":995},"company",{"type":780,"columns":997},[998],{"items":999},[1000,1005,1011,1013,1018,1023,1028,1033,1038,1043],{"text":1001,"config":1002},"About",{"href":1003,"dataGaName":1004,"dataGaLocation":729},"/company/","about",{"text":1006,"config":1007,"footerGa":1010},"Jobs",{"href":1008,"dataGaName":1009,"dataGaLocation":729},"/jobs/","jobs",{"dataGaName":1009},{"text":972,"config":1012},{"href":974,"dataGaName":975,"dataGaLocation":729},{"text":1014,"config":1015},"Leadership",{"href":1016,"dataGaName":1017,"dataGaLocation":729},"/company/team/e-group/","leadership",{"text":1019,"config":1020},"Handbook",{"href":1021,"dataGaName":1022,"dataGaLocation":729},"https://handbook.gitlab.com/","handbook",{"text":1024,"config":1025},"Investor relations",{"href":1026,"dataGaName":1027,"dataGaLocation":729},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1029,"config":1030},"Trust Center",{"href":1031,"dataGaName":1032,"dataGaLocation":729},"/security/","trust center",{"text":1034,"config":1035},"AI Transparency Center",{"href":1036,"dataGaName":1037,"dataGaLocation":729},"/ai-transparency-center/","ai transparency center",{"text":1039,"config":1040},"Newsletter",{"href":1041,"dataGaName":1042,"dataGaLocation":729},"/company/contact/#contact-forms","newsletter",{"text":1044,"config":1045},"Press",{"href":1046,"dataGaName":1047,"dataGaLocation":729},"/press/","press",{"text":1049,"config":1050,"menu":1051},"Contact us",{"dataNavLevelOne":995},{"type":780,"columns":1052},[1053],{"items":1054},[1055,1060,1065],{"text":1056,"config":1057},"Talk to sales",{"href":1058,"dataGaName":1059,"dataGaLocation":729},"/sales/","talk to sales",{"text":1061,"config":1062},"Support portal",{"href":1063,"dataGaName":1064,"dataGaLocation":729},"https://support.gitlab.com/hc/en-us","support portal",{"text":1066,"config":1067},"Customer portal",{"href":1068,"dataGaName":1069,"dataGaLocation":729},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1071,"login":1072,"suggestions":1079},"Close",{"text":1073,"link":1074},"To search repositories and projects, login to",{"text":1075,"config":1076},"gitlab.com",{"href":743,"dataGaName":1077,"dataGaLocation":1078},"search login","search",{"text":1080,"default":1081},"Suggestions",[1082,1084,1088,1090,1094,1098],{"text":760,"config":1083},{"href":765,"dataGaName":760,"dataGaLocation":1078},{"text":1085,"config":1086},"Code Suggestions (AI)",{"href":1087,"dataGaName":1085,"dataGaLocation":1078},"/solutions/code-suggestions/",{"text":720,"config":1089},{"href":18,"dataGaName":720,"dataGaLocation":1078},{"text":1091,"config":1092},"GitLab on AWS",{"href":1093,"dataGaName":1091,"dataGaLocation":1078},"/partners/technology-partners/aws/",{"text":1095,"config":1096},"GitLab on Google Cloud",{"href":1097,"dataGaName":1095,"dataGaLocation":1078},"/partners/technology-partners/google-cloud-platform/",{"text":1099,"config":1100},"Why GitLab?",{"href":773,"dataGaName":1099,"dataGaLocation":1078},{"freeTrial":1102,"mobileIcon":1107,"desktopIcon":1112,"secondaryButton":1115},{"text":1103,"config":1104},"Start free trial",{"href":1105,"dataGaName":734,"dataGaLocation":1106},"https://gitlab.com/-/trials/new/","nav",{"altText":1108,"config":1109},"Gitlab Icon",{"src":1110,"dataGaName":1111,"dataGaLocation":1106},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1108,"config":1113},{"src":1114,"dataGaName":1111,"dataGaLocation":1106},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1116,"config":1117},"Get Started",{"href":1118,"dataGaName":1119,"dataGaLocation":1106},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1121,"mobileIcon":1125,"desktopIcon":1127},{"text":1122,"config":1123},"Learn more about GitLab Duo",{"href":765,"dataGaName":1124,"dataGaLocation":1106},"gitlab duo",{"altText":1108,"config":1126},{"src":1110,"dataGaName":1111,"dataGaLocation":1106},{"altText":1108,"config":1128},{"src":1114,"dataGaName":1111,"dataGaLocation":1106},{"button":1130,"mobileIcon":1135,"desktopIcon":1137},{"text":1131,"config":1132},"/switch",{"href":1133,"dataGaName":1134,"dataGaLocation":1106},"#contact","switch",{"altText":1108,"config":1136},{"src":1110,"dataGaName":1111,"dataGaLocation":1106},{"altText":1108,"config":1138},{"src":1139,"dataGaName":1111,"dataGaLocation":1106},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1141,"mobileIcon":1146,"desktopIcon":1148},{"text":1142,"config":1143},"Back to pricing",{"href":876,"dataGaName":1144,"dataGaLocation":1106,"icon":1145},"back to pricing","GoBack",{"altText":1108,"config":1147},{"src":1110,"dataGaName":1111,"dataGaLocation":1106},{"altText":1108,"config":1149},{"src":1114,"dataGaName":1111,"dataGaLocation":1106},{"title":1151,"titleMobile":1152,"button":1153,"config":1158},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":771,"config":1154},{"href":1155,"dataGaName":1156,"dataGaLocation":1157},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":1159,"disabled":703},"release",{"data":1161},{"text":1162,"source":1163,"edit":1169,"contribute":1174,"config":1179,"items":1184,"minimal":1394},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1164,"config":1165},"View page source",{"href":1166,"dataGaName":1167,"dataGaLocation":1168},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1170,"config":1171},"Edit this page",{"href":1172,"dataGaName":1173,"dataGaLocation":1168},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1175,"config":1176},"Please contribute",{"href":1177,"dataGaName":1178,"dataGaLocation":1168},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1180,"facebook":1181,"youtube":1182,"linkedin":1183},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1185,1232,1286,1330,1362],{"title":874,"links":1186,"subMenu":1201},[1187,1191,1196],{"text":1188,"config":1189},"View plans",{"href":876,"dataGaName":1190,"dataGaLocation":1168},"view plans",{"text":1192,"config":1193},"Why Premium?",{"href":1194,"dataGaName":1195,"dataGaLocation":1168},"/pricing/premium/","why premium",{"text":1197,"config":1198},"Why Ultimate?",{"href":1199,"dataGaName":1200,"dataGaLocation":1168},"/pricing/ultimate/","why ultimate",[1202],{"title":1203,"links":1204},"Contact Us",[1205,1208,1210,1212,1217,1222,1227],{"text":1206,"config":1207},"Contact sales",{"href":1058,"dataGaName":739,"dataGaLocation":1168},{"text":1061,"config":1209},{"href":1063,"dataGaName":1064,"dataGaLocation":1168},{"text":1066,"config":1211},{"href":1068,"dataGaName":1069,"dataGaLocation":1168},{"text":1213,"config":1214},"Status",{"href":1215,"dataGaName":1216,"dataGaLocation":1168},"https://status.gitlab.com/","status",{"text":1218,"config":1219},"Terms of use",{"href":1220,"dataGaName":1221,"dataGaLocation":1168},"/terms/","terms of use",{"text":1223,"config":1224},"Privacy statement",{"href":1225,"dataGaName":1226,"dataGaLocation":1168},"/privacy/","privacy statement",{"text":1228,"config":1229},"Cookie preferences",{"dataGaName":1230,"dataGaLocation":1168,"id":1231,"isOneTrustButton":77},"cookie preferences","ot-sdk-btn",{"title":776,"links":1233,"subMenu":1242},[1234,1238],{"text":1235,"config":1236},"DevSecOps platform",{"href":758,"dataGaName":1237,"dataGaLocation":1168},"devsecops platform",{"text":1239,"config":1240},"AI-Assisted Development",{"href":765,"dataGaName":1241,"dataGaLocation":1168},"ai-assisted development",[1243],{"title":1244,"links":1245},"Topics",[1246,1251,1256,1261,1266,1271,1276,1281],{"text":1247,"config":1248},"CICD",{"href":1249,"dataGaName":1250,"dataGaLocation":1168},"/topics/ci-cd/","cicd",{"text":1252,"config":1253},"GitOps",{"href":1254,"dataGaName":1255,"dataGaLocation":1168},"/topics/gitops/","gitops",{"text":1257,"config":1258},"DevOps",{"href":1259,"dataGaName":1260,"dataGaLocation":1168},"/topics/devops/","devops",{"text":1262,"config":1263},"Version Control",{"href":1264,"dataGaName":1265,"dataGaLocation":1168},"/topics/version-control/","version control",{"text":1267,"config":1268},"DevSecOps",{"href":1269,"dataGaName":1270,"dataGaLocation":1168},"/topics/devsecops/","devsecops",{"text":1272,"config":1273},"Cloud Native",{"href":1274,"dataGaName":1275,"dataGaLocation":1168},"/topics/cloud-native/","cloud native",{"text":1277,"config":1278},"AI for Coding",{"href":1279,"dataGaName":1280,"dataGaLocation":1168},"/topics/devops/ai-for-coding/","ai for coding",{"text":1282,"config":1283},"Agentic AI",{"href":1284,"dataGaName":1285,"dataGaLocation":1168},"/topics/agentic-ai/","agentic ai",{"title":1287,"links":1288},"Solutions",[1289,1291,1293,1298,1302,1305,1309,1312,1314,1317,1320,1325],{"text":818,"config":1290},{"href":813,"dataGaName":818,"dataGaLocation":1168},{"text":807,"config":1292},{"href":792,"dataGaName":793,"dataGaLocation":1168},{"text":1294,"config":1295},"Agile development",{"href":1296,"dataGaName":1297,"dataGaLocation":1168},"/solutions/agile-delivery/","agile delivery",{"text":1299,"config":1300},"SCM",{"href":803,"dataGaName":1301,"dataGaLocation":1168},"source code management",{"text":1247,"config":1303},{"href":18,"dataGaName":1304,"dataGaLocation":1168},"continuous integration & delivery",{"text":1306,"config":1307},"Value stream management",{"href":846,"dataGaName":1308,"dataGaLocation":1168},"value stream management",{"text":1252,"config":1310},{"href":1311,"dataGaName":1255,"dataGaLocation":1168},"/solutions/gitops/",{"text":856,"config":1313},{"href":859,"dataGaName":860,"dataGaLocation":1168},{"text":1315,"config":1316},"Small business",{"href":865,"dataGaName":866,"dataGaLocation":1168},{"text":1318,"config":1319},"Public sector",{"href":871,"dataGaName":872,"dataGaLocation":1168},{"text":1321,"config":1322},"Education",{"href":1323,"dataGaName":1324,"dataGaLocation":1168},"/solutions/education/","education",{"text":1326,"config":1327},"Financial services",{"href":1328,"dataGaName":1329,"dataGaLocation":1168},"/solutions/finance/","financial services",{"title":879,"links":1331},[1332,1334,1336,1338,1341,1343,1346,1348,1350,1352,1354,1356,1358,1360],{"text":892,"config":1333},{"href":894,"dataGaName":895,"dataGaLocation":1168},{"text":897,"config":1335},{"href":899,"dataGaName":900,"dataGaLocation":1168},{"text":902,"config":1337},{"href":904,"dataGaName":905,"dataGaLocation":1168},{"text":907,"config":1339},{"href":909,"dataGaName":1340,"dataGaLocation":1168},"docs",{"text":930,"config":1342},{"href":932,"dataGaName":933,"dataGaLocation":1168},{"text":1344,"config":1345},"What's new",{"href":990,"dataGaName":991,"dataGaLocation":1168},{"text":925,"config":1347},{"href":927,"dataGaName":928,"dataGaLocation":1168},{"text":944,"config":1349},{"href":946,"dataGaName":947,"dataGaLocation":1168},{"text":952,"config":1351},{"href":954,"dataGaName":955,"dataGaLocation":1168},{"text":957,"config":1353},{"href":959,"dataGaName":960,"dataGaLocation":1168},{"text":962,"config":1355},{"href":964,"dataGaName":965,"dataGaLocation":1168},{"text":967,"config":1357},{"href":969,"dataGaName":970,"dataGaLocation":1168},{"text":972,"config":1359},{"href":974,"dataGaName":975,"dataGaLocation":1168},{"text":977,"config":1361},{"href":979,"dataGaName":980,"dataGaLocation":1168},{"title":993,"links":1363},[1364,1366,1368,1370,1372,1374,1378,1383,1385,1387,1389],{"text":1001,"config":1365},{"href":1003,"dataGaName":995,"dataGaLocation":1168},{"text":1006,"config":1367},{"href":1008,"dataGaName":1009,"dataGaLocation":1168},{"text":1014,"config":1369},{"href":1016,"dataGaName":1017,"dataGaLocation":1168},{"text":1019,"config":1371},{"href":1021,"dataGaName":1022,"dataGaLocation":1168},{"text":1024,"config":1373},{"href":1026,"dataGaName":1027,"dataGaLocation":1168},{"text":1375,"config":1376},"Sustainability",{"href":1377,"dataGaName":1375,"dataGaLocation":1168},"/sustainability/",{"text":1379,"config":1380},"Diversity, inclusion and belonging (DIB)",{"href":1381,"dataGaName":1382,"dataGaLocation":1168},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1029,"config":1384},{"href":1031,"dataGaName":1032,"dataGaLocation":1168},{"text":1039,"config":1386},{"href":1041,"dataGaName":1042,"dataGaLocation":1168},{"text":1044,"config":1388},{"href":1046,"dataGaName":1047,"dataGaLocation":1168},{"text":1390,"config":1391},"Modern Slavery Transparency Statement",{"href":1392,"dataGaName":1393,"dataGaLocation":1168},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1395},[1396,1399,1402],{"text":1397,"config":1398},"Terms",{"href":1220,"dataGaName":1221,"dataGaLocation":1168},{"text":1400,"config":1401},"Cookies",{"dataGaName":1230,"dataGaLocation":1168,"id":1231,"isOneTrustButton":77},{"text":1403,"config":1404},"Privacy",{"href":1225,"dataGaName":1226,"dataGaLocation":1168},[1406],{"id":1407,"title":7,"body":702,"config":1408,"content":1410,"description":702,"extension":1413,"meta":1414,"navigation":77,"path":1415,"seo":1416,"stem":1417,"__hash__":1418},"blogAuthors/en-us/blog/authors/renato-stanic.yml",{"template":1409},"BlogAuthor",{"name":7,"config":1411},{"headshot":43,"ctfId":1412},"rstanic12","yml",{},"/en-us/blog/authors/renato-stanic",{},"en-us/blog/authors/renato-stanic","TieJQBujppfl6Ncho9HteaS07QHk9i1rwvfTcCvyra4",[1420,1429,1437],{"title":1421,"description":1422,"heroImage":1423,"category":698,"date":1424,"authors":1425,"slug":1428,"externalUrl":702},"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",[1426,1427],"Mathias Ewald","Martin Paloncy, Edgeless Systems","confidential-ai-for-gitlab-self-hosted",{"title":1430,"description":1431,"heroImage":1432,"category":698,"date":1433,"authors":1434,"slug":1436,"externalUrl":702},"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",[1435],"Lysanne Pinto","green-devops-carbon-measurement-cicd-pipeline",{"title":1438,"description":1439,"heroImage":1440,"category":698,"date":1441,"authors":1442,"slug":1444,"externalUrl":702},"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",[1443],"Paul Meresanu","how-to-build-ci-cd-observability-at-scale",{"promotions":1446},[1447,1461,1473,1485],{"id":1448,"categories":1449,"header":1451,"text":1452,"button":1453,"image":1458},"ai-modernization",[1450],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1454,"config":1455},"Get your AI maturity score",{"href":1456,"dataGaName":1457,"dataGaLocation":933},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1459},{"src":1460},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1462,"categories":1463,"header":1465,"text":1452,"button":1466,"image":1470},"devops-modernization",[1464,1270],"product","Are you just managing tools or shipping innovation?",{"text":1467,"config":1468},"Get your DevOps maturity score",{"href":1469,"dataGaName":1457,"dataGaLocation":933},"/assessments/devops-modernization-assessment/",{"config":1471},{"src":1472},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1474,"categories":1475,"header":1477,"text":1452,"button":1478,"image":1482},"security-modernization",[1476],"security","Are you trading speed for security?",{"text":1479,"config":1480},"Get your security maturity score",{"href":1481,"dataGaName":1457,"dataGaLocation":933},"/assessments/security-modernization-assessment/",{"config":1483},{"src":1484},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1486,"paths":1487,"header":1490,"text":1491,"button":1492,"image":1497},"github-azure-migration",[1488,1489],"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":1493,"config":1494},"See how GitLab compares to GitHub",{"href":1495,"dataGaName":1496,"dataGaLocation":933},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1498},{"src":1472},{"header":1500,"blurb":1501,"button":1502,"secondaryButton":1507},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1503,"config":1504},"Get your free trial",{"href":1505,"dataGaName":734,"dataGaLocation":1506},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1206,"config":1508},{"href":1058,"dataGaName":739,"dataGaLocation":1506},1786803756829]