[{"data":1,"prerenderedAt":1286},["ShallowReactive",2],{"/blog/android-cicd-with-gitlab":3,"navigation-en-us":501,"banner-en-us":928,"footer-en-us":938,"blog-post-authors-en-us-Darby Frey":1181,"blog-related-posts-en-us-android-cicd-with-gitlab":1196,"blog-promotions-en-us":1222,"next-steps-en-us":1276},{"id":4,"title":5,"authors":6,"body":8,"category":481,"date":482,"description":483,"extension":484,"externalUrl":485,"faq":485,"featured":486,"heroImage":487,"meta":488,"navigation":126,"path":489,"seo":490,"slug":494,"stem":495,"tags":496,"template":499,"updatedDate":485,"__hash__":500},"blogPosts/en-us/blog/android-cicd-with-gitlab.md","Tutorial: Android CI/CD with GitLab",[7],"Darby Frey",{"type":9,"value":10,"toc":464},"minimark",[11,22,25,33,42,47,65,76,80,87,91,99,137,140,148,151,155,158,164,170,183,190,194,197,202,209,215,220,228,241,247,254,258,265,272,278,284,290,296,302,306,309,344,353,359,365,369,372,387,396,400,403,409,412,418,426,430,433,437,446,450,457,460],[12,13,14,15,21],"p",{},"Mention the word keystore and all Android developers in a 5km radius will suddenly have a small feeling of panic. Attempting to automate a ",[16,17,20],"a",{"href":18,"rel":19},"https://docs.gitlab.com/ci/",[],"CI/CD"," pipeline to deploy an app can be frustrating, and configuring Google Play access and code signing is at the heart of the problem.",[12,23,24],{},"But fear not! GitLab Mobile DevOps is here to make this process easier and faster, and I am here to guide you.",[12,26,27,32],{},[16,28,31],{"href":29,"rel":30},"https://docs.gitlab.com/ci/mobile_devops/",[],"GitLab Mobile DevOps"," is a collection of features built right into GitLab to solve the biggest challenges mobile teams face in establishing a DevOps practice.",[12,34,35,36,41],{},"In this blog post, I’ll demonstrate how to set up an automated CI/CD pipeline using GitLab and ",[16,37,40],{"href":38,"rel":39},"https://fastlane.tools/",[],"fastlane",".",[43,44,46],"h2",{"id":45},"prerequisites-to-get-started-there-are-a-few-prerequisites-youll-need","Prerequisites To get started, there are a few prerequisites you’ll need:",[48,49,50,58],"ul",{},[51,52,53,54],"li",{},"A Google Play developer account - ",[16,55,56],{"href":56,"rel":57},"https://play.google.com/console",[],[51,59,60,61],{},"Ruby and Android Studio installed on your local machine ",[16,62,63],{"href":63,"rel":64},"https://docs.fastlane.tools/getting-started/android/setup/",[],[66,67,68],"blockquote",{},[12,69,70,71],{},"Try your hand at the ",[16,72,75],{"href":73,"rel":74},"https://about.gitlab.com/blog/ios-cicd-with-gitlab/",[],"iOS CI/CD for GitLab tutorial",[43,77,79],{"id":78},"reference-project","Reference project",[12,81,82,83,41],{},"For this tutorial, we’ll use the Android demo project for reference: ",[16,84,85],{"href":85,"rel":86},"https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/demo-projects/android_demo",[],[43,88,90],{"id":89},"install-fastlane","Install fastlane",[12,92,93,94,98],{},"If you haven’t done so yet, the first step will be to install fastlane. Do this by creating a file in the root of your project called ",[95,96,97],"code",{},"Gemfile",". Give it the following contents:",[100,101,106],"pre",{"className":102,"code":103,"language":104,"meta":105,"style":105},"language-ruby shiki shiki-themes github-light","source \"https://rubygems.org\"\n\ngem \"fastlane\"\n","ruby","",[95,107,108,121,128],{"__ignoreMap":105},[109,110,113,117],"span",{"class":111,"line":112},"line",1,[109,114,116],{"class":115},"sgsFI","source ",[109,118,120],{"class":119},"sYBdl","\"https://rubygems.org\"\n",[109,122,124],{"class":111,"line":123},2,[109,125,127],{"emptyLinePlaceholder":126},true,"\n",[109,129,131,134],{"class":111,"line":130},3,[109,132,133],{"class":115},"gem ",[109,135,136],{"class":119},"\"fastlane\"\n",[12,138,139],{},"Then, from the terminal in your project, run:",[100,141,146],{"className":142,"code":144,"language":145,"meta":105},[143],"language-text","bundle install.\n","text",[95,147,144],{"__ignoreMap":105},[12,149,150],{},"This command will install fastlane, and all of its related dependencies.",[43,152,154],{"id":153},"initialize-fastlane","Initialize fastlane",[12,156,157],{},"Now that fastlane is installed, we can set it up for our project. Run the following command from the terminal in your project. You’ll be asked to enter your package name, so enter that. When prompted for the JSON secret file, you can skip that for now, and you can answer \"no\" to the questions about metadata management.",[100,159,162],{"className":160,"code":161,"language":145,"meta":105},[143],"bundle exec fastlane init\n",[95,163,161],{"__ignoreMap":105},[12,165,166],{},[167,168],"img",{"alt":154,"src":169},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397780/blog/Content%20Images/2023-06-13-android-cicd-with-gitlab/fastlane-init.png",[12,171,172,173,175,176,179,180,41],{},"Running this command will create a new folder in your project called ",[95,174,40],{},". This folder will contain two files ",[95,177,178],{},"Appfile"," and ",[95,181,182],{},"Fastfile",[12,184,185,186,41],{},"The Appfile contains the configuration information for the app, and the Fastfile has some sample code that we will replace later. See the fastlane docs for more information about the configuration details in the Appfile: ",[16,187,188],{"href":188,"rel":189},"https://docs.fastlane.tools/advanced/Appfile/",[],[43,191,193],{"id":192},"code-signing","Code signing",[12,195,196],{},"Next are the steps for code signing.",[198,199,201],"h3",{"id":200},"create-a-keystore","Create a keystore",[12,203,204,205,208],{},"The next step is to create a keystore and properties files for code signing. Run the following command to generate a keystore in the project root called ",[95,206,207],{},"release-keystore.jks",":",[100,210,213],{"className":211,"code":212,"language":145,"meta":105},[143],"keytool -genkey -v -keystore release-keystore.jks -storepass password -alias release -keypass password -keyalg RSA -keysize 2048 -validity 10000\n",[95,214,212],{"__ignoreMap":105},[12,216,217],{},[167,218],{"alt":201,"src":219},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397780/blog/Content%20Images/2023-06-13-android-cicd-with-gitlab/keytool-genkey.png",[12,221,222,223,41],{},"More information is available in the ",[16,224,227],{"href":225,"rel":226},"https://download.java.net/java/early_access/loom/docs/specs/man/keytool.html",[],"keytool docs",[12,229,230,231,236,237,240],{},"The next step is to create a properties file to be used by ",[16,232,235],{"href":233,"rel":234},"https://gradle.org/_",[],"Gradle",". Create a file in the project root called ",[95,238,239],{},"release-keystore.properties",", with the following contents:",[100,242,245],{"className":243,"code":244,"language":145,"meta":105},[143],"storeFile=../release-keystore.jks\nkeyAlias=release\nkeyPassword=password\nstorePassword=password\n",[95,246,244],{"__ignoreMap":105},[12,248,249,250,253],{},"Also, be sure to add both files to your ",[95,251,252],{},".gitignore"," file so they aren't committed to version control.",[198,255,257],{"id":256},"configure-gradle","Configure Gradle",[12,259,260,261,264],{},"Next, configure Gradle to use the newly created keystore. In the ",[95,262,263],{},"app/build.gradle"," file, add the following:",[12,266,267,271],{},[268,269,270],"strong",{},"1."," Right after the plugins section, add:",[100,273,276],{"className":274,"code":275,"language":145,"meta":105},[143],"def keystoreProperties = new Properties()\ndef keystorePropertiesFile = rootProject.file('release-keystore.properties')\nif (keystorePropertiesFile.exists()) {\n    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))\n}\n",[95,277,275],{"__ignoreMap":105},[12,279,280,283],{},[268,281,282],{},"2."," Before Build Types, add:",[100,285,288],{"className":286,"code":287,"language":145,"meta":105},[143],"signingConfigs {\n    release {\n     keyAlias keystoreProperties['keyAlias']\n     keyPassword keystoreProperties['keyPassword']\n     storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null\n     storePassword keystoreProperties['storePassword']\n    }\n}\n",[95,289,287],{"__ignoreMap":105},[12,291,292,295],{},[268,293,294],{},"3."," Lastly, add the signingConfig to the release build type:",[100,297,300],{"className":298,"code":299,"language":145,"meta":105},[143],"signingConfig signingConfigs.release\n",[95,301,299],{"__ignoreMap":105},[43,303,305],{"id":304},"upload-keystore-to-gitlab-secure-files","Upload keystore to GitLab secure files",[12,307,308],{},"Next, upload your keystore files to GitLab so they can be used in CI/CD jobs.",[310,311,312,319,325,331,337],"ol",{},[51,313,314,315,318],{},"On the top bar, select ",[268,316,317],{},"Menu > Projects"," and find your project.",[51,320,321,322,41],{},"On the left sidebar, select ",[268,323,324],{},"Settings > CI/CD",[51,326,327,328,41],{},"In the Secure Files section, select ",[268,329,330],{},"Expand",[51,332,333,334,41],{},"Select ",[268,335,336],{},"Upload File",[51,338,339,340,343],{},"Find the file to upload, select ",[268,341,342],{},"Open",", and the file upload begins immediately. The file shows up in the list when the upload is complete.",[12,345,346,347,349,350,352],{},"Do this for both the ",[95,348,207],{}," file and the ",[95,351,239],{}," file.",[12,354,355],{},[167,356],{"alt":357,"src":358},"Upload Secure File","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397781/blog/Content%20Images/2023-06-13-android-cicd-with-gitlab/upload-secure-file.png",[12,360,361],{},[167,362],{"alt":363,"src":364},"List Secure Files","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397781/blog/Content%20Images/2023-06-13-android-cicd-with-gitlab/list-secure-files.png",[43,366,368],{"id":367},"create-a-cicd-pipeline","Create a CI/CD pipeline",[12,370,371],{},"With the configuration in place, now copy the contents of the .gitlab-ci.yml and fastlane/Fastfile below to the project.",[12,373,374,375,380,381,386],{},"This ",[16,376,379],{"href":377,"rel":378},"https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/demo-projects/android_demo/-/blob/main/.gitlab-ci.yml",[],".gitlab-ci.yml"," has all the configuration needed to run the test, build, and beta jobs.\nThe ",[16,382,385],{"href":383,"rel":384},"https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/demo-projects/android_demo/-/blob/main/fastlane/Fastfile",[],"fastlane/Fastfile"," is an example that can be customized to specific project settings.",[12,388,389,390,395],{},"Note: This fastlane configuration uses plugins. See the ",[16,391,394],{"href":392,"rel":393},"https://docs.fastlane.tools/plugins/using-plugins/",[],"docs"," for instructions on how to configure your project for fastlane plugins.",[43,397,399],{"id":398},"create-an-app-in-the-google-play-console","Create an app in the Google Play Console",[12,401,402],{},"Next, generate a build of your app locally and upload it to seed a new app entry in the Google Play Console. Run the following command locally:",[100,404,407],{"className":405,"code":406,"language":145,"meta":105},[143],"bundle exec fastlane build\n",[95,408,406],{"__ignoreMap":105},[12,410,411],{},"This command will create a signed build of the app at",[100,413,416],{"className":414,"code":415,"language":145,"meta":105},[143],"build/outputs/bundle/release/app-release.aab\n",[95,417,415],{"__ignoreMap":105},[12,419,420,421,425],{},"With the signed build ready to go, log in to the ",[16,422,424],{"href":56,"rel":423},[],"Google Play Console"," and create a new app and seed it with the initial build.",[43,427,429],{"id":428},"configure-google-play-integration","Configure Google Play integration",[12,431,432],{},"The last thing to set up is the Google Play integration in GitLab. To do so, first, create a Google service account.",[198,434,436],{"id":435},"create-a-google-service-account","Create a Google service account",[12,438,439,440,445],{},"Follow the ",[16,441,444],{"href":442,"rel":443},"https://docs.fastlane.tools/actions/supply/#setup",[],"instructions"," for setting up a service account in Google Cloud Platform and granting that account access to the project in Google Play.",[198,447,449],{"id":448},"enable-google-play-integration","Enable Google Play integration",[12,451,439,452,456],{},[16,453,444],{"href":454,"rel":455},"https://docs.gitlab.com/user/project/integrations/google_play/",[]," for configuring the Google Play integration by providing a package name and the JSON key file just generated for the service account.",[12,458,459],{},"This is a simplified CI/CD configuration that created three CI/CD jobs to run each of the lanes in fastlane on the GitLab Runners. The test and build jobs will run for all CI/CD pipelines, and the beta job will only be run on CI/CD pipelines on the main branch. The beta job is manually triggered, so you can control when the beta release is pushed to Google Play.\nWith these configurations in place, commit all of these changes and push them up to your project. The CI/CD pipeline will kick off, and you can see these jobs in action.",[461,462,463],"style",{},"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":105,"searchDepth":123,"depth":123,"links":465},[466,467,468,469,470,474,475,476,477],{"id":45,"depth":123,"text":46},{"id":78,"depth":123,"text":79},{"id":89,"depth":123,"text":90},{"id":153,"depth":123,"text":154},{"id":192,"depth":123,"text":193,"children":471},[472,473],{"id":200,"depth":130,"text":201},{"id":256,"depth":130,"text":257},{"id":304,"depth":123,"text":305},{"id":367,"depth":123,"text":368},{"id":398,"depth":123,"text":399},{"id":428,"depth":123,"text":429,"children":478},[479,480],{"id":435,"depth":130,"text":436},{"id":448,"depth":130,"text":449},"engineering","2023-06-13","Learn how to create an automated Android CI/CD pipeline using GitLab and fastlane.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669316/Blog/Hero%20Images/angela-compagnone-4Iyg6cNU7sI-unsplash.jpg",{},"/en-us/blog/android-cicd-with-gitlab",{"title":5,"description":483,"ogTitle":5,"ogDescription":483,"noIndex":486,"ogImage":487,"ogUrl":491,"ogSiteName":492,"ogType":493,"canonicalUrls":491},"https://about.gitlab.com/blog/android-cicd-with-gitlab","https://about.gitlab.com","article","android-cicd-with-gitlab","en-us/blog/android-cicd-with-gitlab",[497,20,498],"DevOps","tutorial","BlogPost","VhspuWK7XkSEoqKcuEMe6ogVB8b1rqNlfNqpQSRXRrM",{"logo":502,"freeTrial":507,"sales":512,"login":517,"items":522,"search":848,"minimal":879,"duo":898,"switchNav":907,"pricingDeployment":918},{"config":503},{"href":504,"dataGaName":505,"dataGaLocation":506},"/","gitlab logo","header",{"text":508,"config":509},"Get free trial",{"href":510,"dataGaName":511,"dataGaLocation":506},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":513,"config":514},"Request a demo",{"href":515,"dataGaName":516,"dataGaLocation":506},"/sales/?contact-topic=request-demo","sales",{"text":518,"config":519},"Sign in",{"href":520,"dataGaName":521,"dataGaLocation":506},"https://gitlab.com/users/sign_in/","sign in",[523,552,651,656,770,826],{"text":524,"config":525,"menu":527},"Platform",{"dataNavLevelOne":526},"platform",{"type":528,"columns":529},"cards",[530,536,544],{"title":524,"description":531,"link":532},"The intelligent orchestration platform for DevSecOps",{"text":533,"config":534},"Explore our Platform",{"href":535,"dataGaName":526,"dataGaLocation":506},"/platform/",{"title":537,"description":538,"link":539},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":540,"config":541},"Meet GitLab Duo",{"href":542,"dataGaName":543,"dataGaLocation":506},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":545,"description":546,"link":547},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":548,"config":549},"Learn more",{"href":550,"dataGaName":551,"dataGaLocation":506},"/why-gitlab/","why gitlab",{"text":553,"left":126,"config":554,"menu":556},"Product",{"dataNavLevelOne":555},"solutions",{"type":557,"link":558,"columns":562,"feature":630},"lists",{"text":559,"config":560},"View all Solutions",{"href":561,"dataGaName":555,"dataGaLocation":506},"/solutions/",[563,586,609],{"title":564,"description":565,"link":566,"items":571},"Automation","CI/CD and automation to accelerate deployment",{"config":567},{"icon":568,"href":569,"dataGaName":570,"dataGaLocation":506},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[572,575,578,582],{"text":20,"config":573},{"href":574,"dataGaLocation":506,"dataGaName":20},"/solutions/continuous-integration/",{"text":537,"config":576},{"href":542,"dataGaLocation":506,"dataGaName":577},"gitlab duo agent platform - product menu",{"text":579,"config":580},"Source Code Management",{"href":581,"dataGaLocation":506,"dataGaName":579},"/solutions/source-code-management/",{"text":583,"config":584},"Automated Software Delivery",{"href":569,"dataGaLocation":506,"dataGaName":585},"Automated software delivery",{"title":587,"description":588,"link":589,"items":594},"Security","Deliver code faster without compromising security",{"config":590},{"href":591,"dataGaName":592,"dataGaLocation":506,"icon":593},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[595,599,604],{"text":596,"config":597},"Application Security Testing",{"href":591,"dataGaName":598,"dataGaLocation":506},"Application security testing",{"text":600,"config":601},"Software Supply Chain Security",{"href":602,"dataGaLocation":506,"dataGaName":603},"/solutions/supply-chain/","Software supply chain security",{"text":605,"config":606},"Software Compliance",{"href":607,"dataGaName":608,"dataGaLocation":506},"/solutions/software-compliance/","software compliance",{"title":610,"link":611,"items":616},"Measurement",{"config":612},{"icon":613,"href":614,"dataGaName":615,"dataGaLocation":506},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[617,621,625],{"text":618,"config":619},"Visibility & Measurement",{"href":614,"dataGaLocation":506,"dataGaName":620},"Visibility and Measurement",{"text":622,"config":623},"Value Stream Management",{"href":624,"dataGaLocation":506,"dataGaName":622},"/solutions/value-stream-management/",{"text":626,"config":627},"Analytics & Insights",{"href":628,"dataGaLocation":506,"dataGaName":629},"/solutions/analytics-and-insights/","Analytics and insights",{"title":631,"type":557,"items":632},"GitLab for",[633,639,645],{"text":634,"config":635},"Enterprise",{"icon":636,"href":637,"dataGaLocation":506,"dataGaName":638},"Building","/enterprise/","enterprise",{"text":640,"config":641},"Small Business",{"icon":642,"href":643,"dataGaLocation":506,"dataGaName":644},"Work","/small-business/","small business",{"text":646,"config":647},"Public Sector",{"icon":648,"href":649,"dataGaLocation":506,"dataGaName":650},"Organization","/solutions/public-sector/","public sector",{"text":652,"config":653},"Pricing",{"href":654,"dataGaName":655,"dataGaLocation":506,"dataNavLevelOne":655},"/pricing/","pricing",{"text":657,"config":658,"menu":660},"Resources",{"dataNavLevelOne":659},"resources",{"type":557,"link":661,"columns":665,"feature":759},{"text":662,"config":663},"View all resources",{"href":664,"dataGaName":659,"dataGaLocation":506},"/resources/",[666,699,726],{"title":667,"items":668},"Getting started",[669,674,679,684,689,694],{"text":670,"config":671},"Install",{"href":672,"dataGaName":673,"dataGaLocation":506},"/install/","install",{"text":675,"config":676},"Quick start guides",{"href":677,"dataGaName":678,"dataGaLocation":506},"/get-started/","quick setup checklists",{"text":680,"config":681},"Learn",{"href":682,"dataGaLocation":506,"dataGaName":683},"https://university.gitlab.com/","learn",{"text":685,"config":686},"Product documentation",{"href":687,"dataGaName":688,"dataGaLocation":506},"https://docs.gitlab.com/","product documentation",{"text":690,"config":691},"Best practice videos",{"href":692,"dataGaName":693,"dataGaLocation":506},"/getting-started-videos/","best practice videos",{"text":695,"config":696},"Integrations",{"href":697,"dataGaName":698,"dataGaLocation":506},"/integrations/","integrations",{"title":700,"items":701},"Discover",[702,707,712,717,721],{"text":703,"config":704},"Customer success stories",{"href":705,"dataGaName":706,"dataGaLocation":506},"/customers/","customer success stories",{"text":708,"config":709},"Blog",{"href":710,"dataGaName":711,"dataGaLocation":506},"/blog/","blog",{"text":713,"config":714},"Demo Hub",{"href":715,"dataGaName":716,"dataGaLocation":506},"/demo-hub/","demo hub",{"text":718,"config":719},"The Source",{"href":720,"dataGaName":711,"dataGaLocation":506},"/the-source/",{"text":722,"config":723},"Remote",{"href":724,"dataGaName":725,"dataGaLocation":506},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":727,"items":728},"Connect",[729,734,739,744,749,754],{"text":730,"config":731},"GitLab Services",{"href":732,"dataGaName":733,"dataGaLocation":506},"/services/","services",{"text":735,"config":736},"Contribute",{"href":737,"dataGaName":738,"dataGaLocation":506},"https://contributors.gitlab.com","contribute",{"text":740,"config":741},"Community",{"href":742,"dataGaName":743,"dataGaLocation":506},"/community/","community",{"text":745,"config":746},"Forum",{"href":747,"dataGaName":748,"dataGaLocation":506},"https://forum.gitlab.com/","forum",{"text":750,"config":751},"Events",{"href":752,"dataGaName":753,"dataGaLocation":506},"/events/","events",{"text":755,"config":756},"Partners",{"href":757,"dataGaName":758,"dataGaLocation":506},"/partners/","partners",{"config":760,"title":763,"text":764,"link":765},{"background":761,"textColor":762},"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":766,"config":767},"Read the latest",{"href":768,"dataGaName":769,"dataGaLocation":506},"/whats-new/","whats new",{"text":771,"config":772,"menu":774},"Company",{"dataNavLevelOne":773},"company",{"type":557,"columns":775},[776],{"items":777},[778,783,789,791,796,801,806,811,816,821],{"text":779,"config":780},"About",{"href":781,"dataGaName":782,"dataGaLocation":506},"/company/","about",{"text":784,"config":785,"footerGa":788},"Jobs",{"href":786,"dataGaName":787,"dataGaLocation":506},"/jobs/","jobs",{"dataGaName":787},{"text":750,"config":790},{"href":752,"dataGaName":753,"dataGaLocation":506},{"text":792,"config":793},"Leadership",{"href":794,"dataGaName":795,"dataGaLocation":506},"/company/team/e-group/","leadership",{"text":797,"config":798},"Handbook",{"href":799,"dataGaName":800,"dataGaLocation":506},"https://handbook.gitlab.com/","handbook",{"text":802,"config":803},"Investor relations",{"href":804,"dataGaName":805,"dataGaLocation":506},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":807,"config":808},"Trust Center",{"href":809,"dataGaName":810,"dataGaLocation":506},"/security/","trust center",{"text":812,"config":813},"AI Transparency Center",{"href":814,"dataGaName":815,"dataGaLocation":506},"/ai-transparency-center/","ai transparency center",{"text":817,"config":818},"Newsletter",{"href":819,"dataGaName":820,"dataGaLocation":506},"/company/contact/#contact-forms","newsletter",{"text":822,"config":823},"Press",{"href":824,"dataGaName":825,"dataGaLocation":506},"/press/","press",{"text":827,"config":828,"menu":829},"Contact us",{"dataNavLevelOne":773},{"type":557,"columns":830},[831],{"items":832},[833,838,843],{"text":834,"config":835},"Talk to sales",{"href":836,"dataGaName":837,"dataGaLocation":506},"/sales/","talk to sales",{"text":839,"config":840},"Support portal",{"href":841,"dataGaName":842,"dataGaLocation":506},"https://support.gitlab.com/hc/en-us","support portal",{"text":844,"config":845},"Customer portal",{"href":846,"dataGaName":847,"dataGaLocation":506},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":849,"login":850,"suggestions":857},"Close",{"text":851,"link":852},"To search repositories and projects, login to",{"text":853,"config":854},"gitlab.com",{"href":520,"dataGaName":855,"dataGaLocation":856},"search login","search",{"text":858,"default":859},"Suggestions",[860,862,866,868,872,876],{"text":537,"config":861},{"href":542,"dataGaName":537,"dataGaLocation":856},{"text":863,"config":864},"Code Suggestions (AI)",{"href":865,"dataGaName":863,"dataGaLocation":856},"/solutions/code-suggestions/",{"text":20,"config":867},{"href":574,"dataGaName":20,"dataGaLocation":856},{"text":869,"config":870},"GitLab on AWS",{"href":871,"dataGaName":869,"dataGaLocation":856},"/partners/technology-partners/aws/",{"text":873,"config":874},"GitLab on Google Cloud",{"href":875,"dataGaName":873,"dataGaLocation":856},"/partners/technology-partners/google-cloud-platform/",{"text":877,"config":878},"Why GitLab?",{"href":550,"dataGaName":877,"dataGaLocation":856},{"freeTrial":880,"mobileIcon":885,"desktopIcon":890,"secondaryButton":893},{"text":881,"config":882},"Start free trial",{"href":883,"dataGaName":511,"dataGaLocation":884},"https://gitlab.com/-/trials/new/","nav",{"altText":886,"config":887},"Gitlab Icon",{"src":888,"dataGaName":889,"dataGaLocation":884},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":886,"config":891},{"src":892,"dataGaName":889,"dataGaLocation":884},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":894,"config":895},"Get Started",{"href":896,"dataGaName":897,"dataGaLocation":884},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":899,"mobileIcon":903,"desktopIcon":905},{"text":900,"config":901},"Learn more about GitLab Duo",{"href":542,"dataGaName":902,"dataGaLocation":884},"gitlab duo",{"altText":886,"config":904},{"src":888,"dataGaName":889,"dataGaLocation":884},{"altText":886,"config":906},{"src":892,"dataGaName":889,"dataGaLocation":884},{"button":908,"mobileIcon":913,"desktopIcon":915},{"text":909,"config":910},"/switch",{"href":911,"dataGaName":912,"dataGaLocation":884},"#contact","switch",{"altText":886,"config":914},{"src":888,"dataGaName":889,"dataGaLocation":884},{"altText":886,"config":916},{"src":917,"dataGaName":889,"dataGaLocation":884},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":919,"mobileIcon":924,"desktopIcon":926},{"text":920,"config":921},"Back to pricing",{"href":654,"dataGaName":922,"dataGaLocation":884,"icon":923},"back to pricing","GoBack",{"altText":886,"config":925},{"src":888,"dataGaName":889,"dataGaLocation":884},{"altText":886,"config":927},{"src":892,"dataGaName":889,"dataGaLocation":884},{"title":929,"titleMobile":930,"button":931,"config":936},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":548,"config":932},{"href":933,"dataGaName":934,"dataGaLocation":935},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":937,"disabled":486},"release",{"data":939},{"text":940,"source":941,"edit":947,"contribute":952,"config":957,"items":962,"minimal":1170},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":942,"config":943},"View page source",{"href":944,"dataGaName":945,"dataGaLocation":946},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":948,"config":949},"Edit this page",{"href":950,"dataGaName":951,"dataGaLocation":946},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":953,"config":954},"Please contribute",{"href":955,"dataGaName":956,"dataGaLocation":946},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":958,"facebook":959,"youtube":960,"linkedin":961},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[963,1010,1063,1107,1138],{"title":652,"links":964,"subMenu":979},[965,969,974],{"text":966,"config":967},"View plans",{"href":654,"dataGaName":968,"dataGaLocation":946},"view plans",{"text":970,"config":971},"Why Premium?",{"href":972,"dataGaName":973,"dataGaLocation":946},"/pricing/premium/","why premium",{"text":975,"config":976},"Why Ultimate?",{"href":977,"dataGaName":978,"dataGaLocation":946},"/pricing/ultimate/","why ultimate",[980],{"title":981,"links":982},"Contact Us",[983,986,988,990,995,1000,1005],{"text":984,"config":985},"Contact sales",{"href":836,"dataGaName":516,"dataGaLocation":946},{"text":839,"config":987},{"href":841,"dataGaName":842,"dataGaLocation":946},{"text":844,"config":989},{"href":846,"dataGaName":847,"dataGaLocation":946},{"text":991,"config":992},"Status",{"href":993,"dataGaName":994,"dataGaLocation":946},"https://status.gitlab.com/","status",{"text":996,"config":997},"Terms of use",{"href":998,"dataGaName":999,"dataGaLocation":946},"/terms/","terms of use",{"text":1001,"config":1002},"Privacy statement",{"href":1003,"dataGaName":1004,"dataGaLocation":946},"/privacy/","privacy statement",{"text":1006,"config":1007},"Cookie preferences",{"dataGaName":1008,"dataGaLocation":946,"id":1009,"isOneTrustButton":126},"cookie preferences","ot-sdk-btn",{"title":553,"links":1011,"subMenu":1020},[1012,1016],{"text":1013,"config":1014},"DevSecOps platform",{"href":535,"dataGaName":1015,"dataGaLocation":946},"devsecops platform",{"text":1017,"config":1018},"AI-Assisted Development",{"href":542,"dataGaName":1019,"dataGaLocation":946},"ai-assisted development",[1021],{"title":1022,"links":1023},"Topics",[1024,1029,1034,1038,1043,1048,1053,1058],{"text":1025,"config":1026},"CICD",{"href":1027,"dataGaName":1028,"dataGaLocation":946},"/topics/ci-cd/","cicd",{"text":1030,"config":1031},"GitOps",{"href":1032,"dataGaName":1033,"dataGaLocation":946},"/topics/gitops/","gitops",{"text":497,"config":1035},{"href":1036,"dataGaName":1037,"dataGaLocation":946},"/topics/devops/","devops",{"text":1039,"config":1040},"Version Control",{"href":1041,"dataGaName":1042,"dataGaLocation":946},"/topics/version-control/","version control",{"text":1044,"config":1045},"DevSecOps",{"href":1046,"dataGaName":1047,"dataGaLocation":946},"/topics/devsecops/","devsecops",{"text":1049,"config":1050},"Cloud Native",{"href":1051,"dataGaName":1052,"dataGaLocation":946},"/topics/cloud-native/","cloud native",{"text":1054,"config":1055},"AI for Coding",{"href":1056,"dataGaName":1057,"dataGaLocation":946},"/topics/devops/ai-for-coding/","ai for coding",{"text":1059,"config":1060},"Agentic AI",{"href":1061,"dataGaName":1062,"dataGaLocation":946},"/topics/agentic-ai/","agentic ai",{"title":1064,"links":1065},"Solutions",[1066,1068,1070,1075,1079,1082,1086,1089,1091,1094,1097,1102],{"text":596,"config":1067},{"href":591,"dataGaName":596,"dataGaLocation":946},{"text":585,"config":1069},{"href":569,"dataGaName":570,"dataGaLocation":946},{"text":1071,"config":1072},"Agile development",{"href":1073,"dataGaName":1074,"dataGaLocation":946},"/solutions/agile-delivery/","agile delivery",{"text":1076,"config":1077},"SCM",{"href":581,"dataGaName":1078,"dataGaLocation":946},"source code management",{"text":1025,"config":1080},{"href":574,"dataGaName":1081,"dataGaLocation":946},"continuous integration & delivery",{"text":1083,"config":1084},"Value stream management",{"href":624,"dataGaName":1085,"dataGaLocation":946},"value stream management",{"text":1030,"config":1087},{"href":1088,"dataGaName":1033,"dataGaLocation":946},"/solutions/gitops/",{"text":634,"config":1090},{"href":637,"dataGaName":638,"dataGaLocation":946},{"text":1092,"config":1093},"Small business",{"href":643,"dataGaName":644,"dataGaLocation":946},{"text":1095,"config":1096},"Public sector",{"href":649,"dataGaName":650,"dataGaLocation":946},{"text":1098,"config":1099},"Education",{"href":1100,"dataGaName":1101,"dataGaLocation":946},"/solutions/education/","education",{"text":1103,"config":1104},"Financial services",{"href":1105,"dataGaName":1106,"dataGaLocation":946},"/solutions/finance/","financial services",{"title":657,"links":1108},[1109,1111,1113,1115,1117,1119,1122,1124,1126,1128,1130,1132,1134,1136],{"text":670,"config":1110},{"href":672,"dataGaName":673,"dataGaLocation":946},{"text":675,"config":1112},{"href":677,"dataGaName":678,"dataGaLocation":946},{"text":680,"config":1114},{"href":682,"dataGaName":683,"dataGaLocation":946},{"text":685,"config":1116},{"href":687,"dataGaName":394,"dataGaLocation":946},{"text":708,"config":1118},{"href":710,"dataGaName":711,"dataGaLocation":946},{"text":1120,"config":1121},"What's new",{"href":768,"dataGaName":769,"dataGaLocation":946},{"text":703,"config":1123},{"href":705,"dataGaName":706,"dataGaLocation":946},{"text":722,"config":1125},{"href":724,"dataGaName":725,"dataGaLocation":946},{"text":730,"config":1127},{"href":732,"dataGaName":733,"dataGaLocation":946},{"text":735,"config":1129},{"href":737,"dataGaName":738,"dataGaLocation":946},{"text":740,"config":1131},{"href":742,"dataGaName":743,"dataGaLocation":946},{"text":745,"config":1133},{"href":747,"dataGaName":748,"dataGaLocation":946},{"text":750,"config":1135},{"href":752,"dataGaName":753,"dataGaLocation":946},{"text":755,"config":1137},{"href":757,"dataGaName":758,"dataGaLocation":946},{"title":771,"links":1139},[1140,1142,1144,1146,1148,1150,1154,1159,1161,1163,1165],{"text":779,"config":1141},{"href":781,"dataGaName":773,"dataGaLocation":946},{"text":784,"config":1143},{"href":786,"dataGaName":787,"dataGaLocation":946},{"text":792,"config":1145},{"href":794,"dataGaName":795,"dataGaLocation":946},{"text":797,"config":1147},{"href":799,"dataGaName":800,"dataGaLocation":946},{"text":802,"config":1149},{"href":804,"dataGaName":805,"dataGaLocation":946},{"text":1151,"config":1152},"Sustainability",{"href":1153,"dataGaName":1151,"dataGaLocation":946},"/sustainability/",{"text":1155,"config":1156},"Diversity, inclusion and belonging (DIB)",{"href":1157,"dataGaName":1158,"dataGaLocation":946},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":807,"config":1160},{"href":809,"dataGaName":810,"dataGaLocation":946},{"text":817,"config":1162},{"href":819,"dataGaName":820,"dataGaLocation":946},{"text":822,"config":1164},{"href":824,"dataGaName":825,"dataGaLocation":946},{"text":1166,"config":1167},"Modern Slavery Transparency Statement",{"href":1168,"dataGaName":1169,"dataGaLocation":946},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1171},[1172,1175,1178],{"text":1173,"config":1174},"Terms",{"href":998,"dataGaName":999,"dataGaLocation":946},{"text":1176,"config":1177},"Cookies",{"dataGaName":1008,"dataGaLocation":946,"id":1009,"isOneTrustButton":126},{"text":1179,"config":1180},"Privacy",{"href":1003,"dataGaName":1004,"dataGaLocation":946},[1182],{"id":1183,"title":7,"body":485,"config":1184,"content":1186,"description":485,"extension":1190,"meta":1191,"navigation":126,"path":1192,"seo":1193,"stem":1194,"__hash__":1195},"blogAuthors/en-us/blog/authors/darby-frey.yml",{"template":1185},"BlogAuthor",{"name":7,"config":1187},{"headshot":1188,"ctfId":1189},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668565/Blog/Author%20Headshots/darbyfrey-headshot.png","darbyfrey","yml",{},"/en-us/blog/authors/darby-frey",{},"en-us/blog/authors/darby-frey","lqGN1mYG_LRXzRujnkqXvcZHmVHEKoeXrwJofasmK_8",[1197,1206,1214],{"title":1198,"description":1199,"heroImage":1200,"category":481,"date":1201,"authors":1202,"slug":1205,"externalUrl":485},"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",[1203,1204],"Mathias Ewald","Martin Paloncy, Edgeless Systems","confidential-ai-for-gitlab-self-hosted",{"title":1207,"description":1208,"heroImage":1209,"category":481,"date":1210,"authors":1211,"slug":1213,"externalUrl":485},"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",[1212],"Lysanne Pinto","green-devops-carbon-measurement-cicd-pipeline",{"title":1215,"description":1216,"heroImage":1217,"category":481,"date":1218,"authors":1219,"slug":1221,"externalUrl":485},"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",[1220],"Paul Meresanu","how-to-build-ci-cd-observability-at-scale",{"promotions":1223},[1224,1238,1250,1262],{"id":1225,"categories":1226,"header":1228,"text":1229,"button":1230,"image":1235},"ai-modernization",[1227],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1231,"config":1232},"Get your AI maturity score",{"href":1233,"dataGaName":1234,"dataGaLocation":711},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1236},{"src":1237},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1239,"categories":1240,"header":1242,"text":1229,"button":1243,"image":1247},"devops-modernization",[1241,1047],"product","Are you just managing tools or shipping innovation?",{"text":1244,"config":1245},"Get your DevOps maturity score",{"href":1246,"dataGaName":1234,"dataGaLocation":711},"/assessments/devops-modernization-assessment/",{"config":1248},{"src":1249},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1251,"categories":1252,"header":1254,"text":1229,"button":1255,"image":1259},"security-modernization",[1253],"security","Are you trading speed for security?",{"text":1256,"config":1257},"Get your security maturity score",{"href":1258,"dataGaName":1234,"dataGaLocation":711},"/assessments/security-modernization-assessment/",{"config":1260},{"src":1261},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1263,"paths":1264,"header":1267,"text":1268,"button":1269,"image":1274},"github-azure-migration",[1265,1266],"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":1270,"config":1271},"See how GitLab compares to GitHub",{"href":1272,"dataGaName":1273,"dataGaLocation":711},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1275},{"src":1249},{"header":1277,"blurb":1278,"button":1279,"secondaryButton":1284},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1280,"config":1281},"Get your free trial",{"href":1282,"dataGaName":511,"dataGaLocation":1283},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":984,"config":1285},{"href":836,"dataGaName":516,"dataGaLocation":1283},1786803744651]