[{"data":1,"prerenderedAt":1268},["ShallowReactive",2],{"/blog/how-gitlab-automates-releases":3,"navigation-en-us":486,"banner-en-us":913,"footer-en-us":922,"blog-post-authors-en-us-Jackie Meshell":1166,"blog-related-posts-en-us-how-gitlab-automates-releases":1180,"blog-promotions-en-us":1204,"next-steps-en-us":1258},{"id":4,"title":5,"authors":6,"body":8,"category":466,"date":467,"description":468,"extension":469,"externalUrl":470,"faq":470,"featured":471,"heroImage":472,"meta":473,"navigation":474,"path":475,"seo":476,"slug":480,"stem":481,"tags":482,"template":484,"updatedDate":470,"__hash__":485},"blogPosts/en-us/blog/how-gitlab-automates-releases.md","How GitLab is automating release generation in .gitlab-ci.yml",[7],"Jackie Meshell",{"type":9,"value":10,"toc":458},"minimark",[11,16,38,51,77,81,90,191,206,219,222,226,233,285,293,298,309,315,320,328,333,338,343,348,354,359,363,378,413,416,454],[12,13,15],"h2",{"id":14},"why-does-release-generation-need-to-be-automated","Why does release generation need to be automated?",[17,18,19,20,26,27,31,32,37],"p",{},"Release Management, a group within the ",[21,22,25],"a",{"href":23,"rel":24},"https://handbook.gitlab.com/handbook/engineering/deployments-and-releases/",[],"Release stage",", is about unblocking users as they continuously deliver value to their customers. A part of this can be seen in how users create Release tags to track production deployments and in that adoption of the Release features, users are deploying more with GitLab. We can also see a correlation between users adopting Releases to deploy with GitLab and leveraging more paid features.\nWe discovered the automation of creating these releases for our users was difficult and documented the needs for Release generation from the ",[28,29,30],"code",{},".gitlab-ci.yml"," file in our epic, ",[21,33,36],{"href":34,"rel":35},"https://gitlab.com/groups/gitlab-org/-/epics/2510",[],"gitlab&2510",". The highlights of the user pains around the release process include a:",[39,40,41,45,48],"ol",{},[42,43,44],"li",{},"desire to avoid leaving the CLI to complete release jobs or tasks",[42,46,47],{},"need for the tag creation to be associated with a pipeline",[42,49,50],{},"simpler way to include release creation within GitLab as a part of the CI/CD processes",[17,52,53,54,58,59,64,65,70,71,76],{},"Not only do users want to automatically create releases within their ",[21,55,57],{"href":56},"/topics/ci-cd/","CI/CD",", many of the other solutions such as ",[21,60,63],{"href":61,"rel":62},"https://docs.microsoft.com/en-us/azure/devops/pipelines/release/?view=azure-devops",[],"Azure Pipelines",", ",[21,66,69],{"href":67,"rel":68},"https://docs.xebialabs.com/v.9.5/xl-release/how-to/work-with-xl-yaml-format/",[],"XebiaLabs",", and ",[21,72,75],{"href":73,"rel":74},"https://www.jenkins.io/blog/configuring-jenkins-pipeline-with-yaml-file/",[],"Cloudbees",", all feature a way to deploy and create releases from the YAML.",[12,78,80],{"id":79},"how-did-we-discover-that-we-needed-a-tool-to-create-the-release","How did we discover that we needed a tool to create the release?",[17,82,83,84,89],{},"The Release Management team underwent a few calls with a GitLab Maintainer, ",[21,85,88],{"href":86,"rel":87},"https://gitlab.com/ayufan",[],"Kamil Trzciński",", to help decide the correct path forward. There were several scenarios we considered.",[91,92,93,109],"table",{},[94,95,96],"thead",{},[97,98,99,103,106],"tr",{},[100,101,102],"th",{},"Option",[100,104,105],{},"Pros",[100,107,108],{},"Cons",[110,111,112,134,163],"tbody",{},[97,113,114,121,124],{},[115,116,117],"td",{},[118,119,120],"strong",{},"Generate Release from Rails",[115,122,123],{},"1. Simple addition of token and YAML job",[115,125,126,127,130,131,133],{},"1. Rails would be too heavy",[128,129],"br",{},"2. High potential for errors and slowness",[128,132],{},"3. Least performant option",[97,135,136,141,153],{},[115,137,138],{},[118,139,140],{},"Create an independent CLI tool",[115,142,143,144,146,147,149,150,152],{},"1. Independent — users can use it without downloading the whole Runner command",[128,145],{},"2. Can be owned by the Release team",[128,148],{},"3. The intention and domain of the CLI is very specific and users won't get confused",[128,151],{},"4. We can have the code in any repo",[115,154,155,156,159,160],{},"1. Some code duplication from ",[28,157,158],{},"gitlab-runner-helper"," command to auth with ",[28,161,162],{},"CI_JOB_TOKEN",[97,164,165,170,173],{},[115,166,167],{},[118,168,169],{},"Create a runner helper",[115,171,172],{},"1. Much quicker since it's just copy/pasting a file and changing the command name and URL",[115,174,175,176,178,179,181,182,184,185,187,188,190],{},"1. The user has to download the ",[28,177,158],{}," binary",[128,180],{},"2. Many actions required to use",[128,183],{},"3. Not as discoverable",[128,186],{},"4. Coupled and dependent on the Runner team",[128,189],{},"5. Must follow the same release version scheme as GitLab Runner",[17,192,193,194,199,200,205],{},"We learned quickly that Rails was not the right place to generate a release as a result of performance and we also learned the logic was too much for the GitLab Runner to handle. This was discussed in a chat with ",[21,195,198],{"href":196,"rel":197},"https://gitlab.com/steveazz-dr",[],"Steve Azzopardi"," from the Runner Team, ",[21,201,204],{"href":202,"rel":203},"https://gitlab.com/sean_carroll",[],"Sean Carroll"," from Release Management, and of course the product teammates.",[207,208,211,212],"figure",{"className":209},[210],"video_container","\n  ",[213,214,218],"iframe",{"src":215,"frameBorder":216,"allowFullScreen":217},"https://youtube.com/embed/bfbnjEKZ9yw","0","true"," ",[17,220,221],{},"Thus, the team moved forward with the independent CLI and began developing this tool.",[12,223,225],{"id":224},"how-does-the-release-cli-work","How does the release-cli work?",[17,227,228,229,232],{},"The release-cli tool is written in Go and can be called directly to create a Release via the API, given the right ",[28,230,231],{},"job token"," and parameters are provided. The more likely way users will interact with this tool will be in the YAML file as a job:",[234,235,240],"pre",{"className":236,"code":237,"language":238,"meta":239,"style":239},"language-yaml shiki shiki-themes github-light","release_upload:\n  image: registry.gitlab.com/gitlab-org/release-cli:v0.1.0\n  script:\n    - gitlab-releaser create --name=\"My Release\" --description=\"My Release description\"\n","yaml","",[28,241,242,255,268,276],{"__ignoreMap":239},[243,244,247,251],"span",{"class":245,"line":246},"line",1,[243,248,250],{"class":249},"shJU0","release_upload",[243,252,254],{"class":253},"sgsFI",":\n",[243,256,258,261,264],{"class":245,"line":257},2,[243,259,260],{"class":249},"  image",[243,262,263],{"class":253},": ",[243,265,267],{"class":266},"sYBdl","registry.gitlab.com/gitlab-org/release-cli:v0.1.0\n",[243,269,271,274],{"class":245,"line":270},3,[243,272,273],{"class":249},"  script",[243,275,254],{"class":253},[243,277,279,282],{"class":245,"line":278},4,[243,280,281],{"class":253},"    - ",[243,283,284],{"class":266},"gitlab-releaser create --name=\"My Release\" --description=\"My Release description\"\n",[17,286,287],{},[288,289],"img",{"alt":290,"src":291,"title":292},"Architecture of Release-cli","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397942/blog/Content%20Images/archdiagram.png","release-cli architecture",[294,295,297],"h3",{"id":296},"steps-for-the-release-cli","Steps for the release-cli",[39,299,300],{},[42,301,302,303,306,307],{},"The release-cli will instruct the ",[28,304,305],{},"release"," node of ",[28,308,30],{},[310,311,312],"ul",{},[42,313,314],{},"This will convert the actions of creating the release into commands and pass those to the Runner.",[39,316,317],{"start":257},[42,318,319],{},"YAML exposed as Steps",[310,321,322],{},[42,323,324,325,327],{},"The release node of the ",[28,326,30],{}," configuration file is converted into Steps and made available via API endpoint.",[39,329,330],{"start":270},[42,331,332],{},"Runner calls CLI on Job success",[310,334,335],{},[42,336,337],{},"The Runner executes the Job, and upon success calls the Release CLI. The evaluation of the Release must be created is made by the CLI, so this step implies the Runner always calls the Release CLI at the end of a successful Job.",[39,339,340],{"start":278},[42,341,342],{},"CLI retrieves Release Steps",[310,344,345],{},[42,346,347],{},"The Release CLI calls the Rails API to retrieve the release configuration (as Steps).",[39,349,351],{"start":350},5,[42,352,353],{},"CLI creates Release",[310,355,356],{},[42,357,358],{},"The Release CLI makes an API call to Rails to create the Release.",[12,360,362],{"id":361},"what-is-next-for-the-release-cli","What is next for the release-cli?",[17,364,365,366,371,372,377],{},"We currently have the first iteration of the release-cli complete, which looks like:\n",[288,367],{"alt":368,"src":369,"title":370},"Architecture2 of Release-cli","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782398138/blog/Content%20Images/current_cli.png","release-cli current architecture","\nThis MVC implemented via ",[21,373,376],{"href":374,"rel":375},"https://gitlab.com/gitlab-org/gitlab/-/issues/199253",[],"gitlab#199253",", has enabled:",[310,379,380,388,399,402],{},[42,381,382,383],{},"use of the ",[21,384,387],{"href":385,"rel":386},"https://gitlab.com/gitlab-org/release-cli",[],"GitLab Release CLI docker image",[42,389,390,391,394,395,398],{},"the ",[28,392,393],{},"--name"," and ",[28,396,397],{},"--description"," parameters for a Release",[42,400,401],{},"calling the Releases API to create a Release with name and description",[42,403,404,405,408,409,412],{},"access to all CI variables, including ",[28,406,407],{},"$CI_JOB_TOKEN"," for authentication to the GitLab Releases API and ",[28,410,411],{},"$CI_PROJECT_ID"," to create the Release",[17,414,415],{},"The Release Management team will expand the tool to be able to manage many tasks for the Release generation. These features include:",[39,417,418,430,438,446],{},[42,419,420,421,424,425],{},"Expose ",[28,422,423],{},":release"," yaml as steps via ",[21,426,429],{"href":427,"rel":428},"https://gitlab.com/gitlab-org/gitlab/-/issues/199250",[],"gitlab#199250",[42,431,432,433],{},"Support file uploads to Releases via ",[21,434,437],{"href":435,"rel":436},"https://gitlab.com/gitlab-org/gitlab/-/issues/17838",[],"gitlab#17838",[42,439,440,441],{},"Support binary files in Releases via ",[21,442,445],{"href":443,"rel":444},"https://gitlab.com/gitlab-org/gitlab/-/issues/35893",[],"gitlab#35893",[42,447,448,449],{},"Automatically create Release notes in Releases via ",[21,450,453],{"href":451,"rel":452},"https://gitlab.com/gitlab-org/gitlab/-/issues/15563",[],"gitlab#15563",[455,456,457],"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":239,"searchDepth":257,"depth":257,"links":459},[460,461,462,465],{"id":14,"depth":257,"text":15},{"id":79,"depth":257,"text":80},{"id":224,"depth":257,"text":225,"children":463},[464],{"id":296,"depth":270,"text":297},{"id":361,"depth":257,"text":362},"unfiltered","2020-05-07","Under the covers look at the tooling behind creating releases from `.gitlab-ci.yml` with a Go command line interface","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672765/Blog/Hero%20Images/generator.jpg",{},true,"/en-us/blog/how-gitlab-automates-releases",{"title":5,"description":468,"ogTitle":5,"ogDescription":468,"noIndex":471,"ogImage":472,"ogUrl":477,"ogSiteName":478,"ogType":479,"canonicalUrls":477},"https://about.gitlab.com/blog/how-gitlab-automates-releases","https://about.gitlab.com","article","how-gitlab-automates-releases","en-us/blog/how-gitlab-automates-releases",[483,483,483],"agile","BlogPost","lMulTFHesh5x5ClBQs4Pq3SXYvxyjDeXEwmauTZFn30",{"logo":487,"freeTrial":492,"sales":497,"login":502,"items":507,"search":833,"minimal":864,"duo":883,"switchNav":892,"pricingDeployment":903},{"config":488},{"href":489,"dataGaName":490,"dataGaLocation":491},"/","gitlab logo","header",{"text":493,"config":494},"Get free trial",{"href":495,"dataGaName":496,"dataGaLocation":491},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":498,"config":499},"Request a demo",{"href":500,"dataGaName":501,"dataGaLocation":491},"/sales/?contact-topic=request-demo","sales",{"text":503,"config":504},"Sign in",{"href":505,"dataGaName":506,"dataGaLocation":491},"https://gitlab.com/users/sign_in/","sign in",[508,537,636,641,755,811],{"text":509,"config":510,"menu":512},"Platform",{"dataNavLevelOne":511},"platform",{"type":513,"columns":514},"cards",[515,521,529],{"title":509,"description":516,"link":517},"The intelligent orchestration platform for DevSecOps",{"text":518,"config":519},"Explore our Platform",{"href":520,"dataGaName":511,"dataGaLocation":491},"/platform/",{"title":522,"description":523,"link":524},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":525,"config":526},"Meet GitLab Duo",{"href":527,"dataGaName":528,"dataGaLocation":491},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":530,"description":531,"link":532},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":533,"config":534},"Learn more",{"href":535,"dataGaName":536,"dataGaLocation":491},"/why-gitlab/","why gitlab",{"text":538,"left":474,"config":539,"menu":541},"Product",{"dataNavLevelOne":540},"solutions",{"type":542,"link":543,"columns":547,"feature":615},"lists",{"text":544,"config":545},"View all Solutions",{"href":546,"dataGaName":540,"dataGaLocation":491},"/solutions/",[548,571,594],{"title":549,"description":550,"link":551,"items":556},"Automation","CI/CD and automation to accelerate deployment",{"config":552},{"icon":553,"href":554,"dataGaName":555,"dataGaLocation":491},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[557,560,563,567],{"text":57,"config":558},{"href":559,"dataGaLocation":491,"dataGaName":57},"/solutions/continuous-integration/",{"text":522,"config":561},{"href":527,"dataGaLocation":491,"dataGaName":562},"gitlab duo agent platform - product menu",{"text":564,"config":565},"Source Code Management",{"href":566,"dataGaLocation":491,"dataGaName":564},"/solutions/source-code-management/",{"text":568,"config":569},"Automated Software Delivery",{"href":554,"dataGaLocation":491,"dataGaName":570},"Automated software delivery",{"title":572,"description":573,"link":574,"items":579},"Security","Deliver code faster without compromising security",{"config":575},{"href":576,"dataGaName":577,"dataGaLocation":491,"icon":578},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[580,584,589],{"text":581,"config":582},"Application Security Testing",{"href":576,"dataGaName":583,"dataGaLocation":491},"Application security testing",{"text":585,"config":586},"Software Supply Chain Security",{"href":587,"dataGaLocation":491,"dataGaName":588},"/solutions/supply-chain/","Software supply chain security",{"text":590,"config":591},"Software Compliance",{"href":592,"dataGaName":593,"dataGaLocation":491},"/solutions/software-compliance/","software compliance",{"title":595,"link":596,"items":601},"Measurement",{"config":597},{"icon":598,"href":599,"dataGaName":600,"dataGaLocation":491},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[602,606,610],{"text":603,"config":604},"Visibility & Measurement",{"href":599,"dataGaLocation":491,"dataGaName":605},"Visibility and Measurement",{"text":607,"config":608},"Value Stream Management",{"href":609,"dataGaLocation":491,"dataGaName":607},"/solutions/value-stream-management/",{"text":611,"config":612},"Analytics & Insights",{"href":613,"dataGaLocation":491,"dataGaName":614},"/solutions/analytics-and-insights/","Analytics and insights",{"title":616,"type":542,"items":617},"GitLab for",[618,624,630],{"text":619,"config":620},"Enterprise",{"icon":621,"href":622,"dataGaLocation":491,"dataGaName":623},"Building","/enterprise/","enterprise",{"text":625,"config":626},"Small Business",{"icon":627,"href":628,"dataGaLocation":491,"dataGaName":629},"Work","/small-business/","small business",{"text":631,"config":632},"Public Sector",{"icon":633,"href":634,"dataGaLocation":491,"dataGaName":635},"Organization","/solutions/public-sector/","public sector",{"text":637,"config":638},"Pricing",{"href":639,"dataGaName":640,"dataGaLocation":491,"dataNavLevelOne":640},"/pricing/","pricing",{"text":642,"config":643,"menu":645},"Resources",{"dataNavLevelOne":644},"resources",{"type":542,"link":646,"columns":650,"feature":744},{"text":647,"config":648},"View all resources",{"href":649,"dataGaName":644,"dataGaLocation":491},"/resources/",[651,684,711],{"title":652,"items":653},"Getting started",[654,659,664,669,674,679],{"text":655,"config":656},"Install",{"href":657,"dataGaName":658,"dataGaLocation":491},"/install/","install",{"text":660,"config":661},"Quick start guides",{"href":662,"dataGaName":663,"dataGaLocation":491},"/get-started/","quick setup checklists",{"text":665,"config":666},"Learn",{"href":667,"dataGaLocation":491,"dataGaName":668},"https://university.gitlab.com/","learn",{"text":670,"config":671},"Product documentation",{"href":672,"dataGaName":673,"dataGaLocation":491},"https://docs.gitlab.com/","product documentation",{"text":675,"config":676},"Best practice videos",{"href":677,"dataGaName":678,"dataGaLocation":491},"/getting-started-videos/","best practice videos",{"text":680,"config":681},"Integrations",{"href":682,"dataGaName":683,"dataGaLocation":491},"/integrations/","integrations",{"title":685,"items":686},"Discover",[687,692,697,702,706],{"text":688,"config":689},"Customer success stories",{"href":690,"dataGaName":691,"dataGaLocation":491},"/customers/","customer success stories",{"text":693,"config":694},"Blog",{"href":695,"dataGaName":696,"dataGaLocation":491},"/blog/","blog",{"text":698,"config":699},"Demo Hub",{"href":700,"dataGaName":701,"dataGaLocation":491},"/demo-hub/","demo hub",{"text":703,"config":704},"The Source",{"href":705,"dataGaName":696,"dataGaLocation":491},"/the-source/",{"text":707,"config":708},"Remote",{"href":709,"dataGaName":710,"dataGaLocation":491},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":712,"items":713},"Connect",[714,719,724,729,734,739],{"text":715,"config":716},"GitLab Services",{"href":717,"dataGaName":718,"dataGaLocation":491},"/services/","services",{"text":720,"config":721},"Contribute",{"href":722,"dataGaName":723,"dataGaLocation":491},"https://contributors.gitlab.com","contribute",{"text":725,"config":726},"Community",{"href":727,"dataGaName":728,"dataGaLocation":491},"/community/","community",{"text":730,"config":731},"Forum",{"href":732,"dataGaName":733,"dataGaLocation":491},"https://forum.gitlab.com/","forum",{"text":735,"config":736},"Events",{"href":737,"dataGaName":738,"dataGaLocation":491},"/events/","events",{"text":740,"config":741},"Partners",{"href":742,"dataGaName":743,"dataGaLocation":491},"/partners/","partners",{"config":745,"title":748,"text":749,"link":750},{"background":746,"textColor":747},"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":751,"config":752},"Read the latest",{"href":753,"dataGaName":754,"dataGaLocation":491},"/whats-new/","whats new",{"text":756,"config":757,"menu":759},"Company",{"dataNavLevelOne":758},"company",{"type":542,"columns":760},[761],{"items":762},[763,768,774,776,781,786,791,796,801,806],{"text":764,"config":765},"About",{"href":766,"dataGaName":767,"dataGaLocation":491},"/company/","about",{"text":769,"config":770,"footerGa":773},"Jobs",{"href":771,"dataGaName":772,"dataGaLocation":491},"/jobs/","jobs",{"dataGaName":772},{"text":735,"config":775},{"href":737,"dataGaName":738,"dataGaLocation":491},{"text":777,"config":778},"Leadership",{"href":779,"dataGaName":780,"dataGaLocation":491},"/company/team/e-group/","leadership",{"text":782,"config":783},"Handbook",{"href":784,"dataGaName":785,"dataGaLocation":491},"https://handbook.gitlab.com/","handbook",{"text":787,"config":788},"Investor relations",{"href":789,"dataGaName":790,"dataGaLocation":491},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":792,"config":793},"Trust Center",{"href":794,"dataGaName":795,"dataGaLocation":491},"/security/","trust center",{"text":797,"config":798},"AI Transparency Center",{"href":799,"dataGaName":800,"dataGaLocation":491},"/ai-transparency-center/","ai transparency center",{"text":802,"config":803},"Newsletter",{"href":804,"dataGaName":805,"dataGaLocation":491},"/company/contact/#contact-forms","newsletter",{"text":807,"config":808},"Press",{"href":809,"dataGaName":810,"dataGaLocation":491},"/press/","press",{"text":812,"config":813,"menu":814},"Contact us",{"dataNavLevelOne":758},{"type":542,"columns":815},[816],{"items":817},[818,823,828],{"text":819,"config":820},"Talk to sales",{"href":821,"dataGaName":822,"dataGaLocation":491},"/sales/","talk to sales",{"text":824,"config":825},"Support portal",{"href":826,"dataGaName":827,"dataGaLocation":491},"https://support.gitlab.com/hc/en-us","support portal",{"text":829,"config":830},"Customer portal",{"href":831,"dataGaName":832,"dataGaLocation":491},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":834,"login":835,"suggestions":842},"Close",{"text":836,"link":837},"To search repositories and projects, login to",{"text":838,"config":839},"gitlab.com",{"href":505,"dataGaName":840,"dataGaLocation":841},"search login","search",{"text":843,"default":844},"Suggestions",[845,847,851,853,857,861],{"text":522,"config":846},{"href":527,"dataGaName":522,"dataGaLocation":841},{"text":848,"config":849},"Code Suggestions (AI)",{"href":850,"dataGaName":848,"dataGaLocation":841},"/solutions/code-suggestions/",{"text":57,"config":852},{"href":559,"dataGaName":57,"dataGaLocation":841},{"text":854,"config":855},"GitLab on AWS",{"href":856,"dataGaName":854,"dataGaLocation":841},"/partners/technology-partners/aws/",{"text":858,"config":859},"GitLab on Google Cloud",{"href":860,"dataGaName":858,"dataGaLocation":841},"/partners/technology-partners/google-cloud-platform/",{"text":862,"config":863},"Why GitLab?",{"href":535,"dataGaName":862,"dataGaLocation":841},{"freeTrial":865,"mobileIcon":870,"desktopIcon":875,"secondaryButton":878},{"text":866,"config":867},"Start free trial",{"href":868,"dataGaName":496,"dataGaLocation":869},"https://gitlab.com/-/trials/new/","nav",{"altText":871,"config":872},"Gitlab Icon",{"src":873,"dataGaName":874,"dataGaLocation":869},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":871,"config":876},{"src":877,"dataGaName":874,"dataGaLocation":869},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":879,"config":880},"Get Started",{"href":881,"dataGaName":882,"dataGaLocation":869},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":884,"mobileIcon":888,"desktopIcon":890},{"text":885,"config":886},"Learn more about GitLab Duo",{"href":527,"dataGaName":887,"dataGaLocation":869},"gitlab duo",{"altText":871,"config":889},{"src":873,"dataGaName":874,"dataGaLocation":869},{"altText":871,"config":891},{"src":877,"dataGaName":874,"dataGaLocation":869},{"button":893,"mobileIcon":898,"desktopIcon":900},{"text":894,"config":895},"/switch",{"href":896,"dataGaName":897,"dataGaLocation":869},"#contact","switch",{"altText":871,"config":899},{"src":873,"dataGaName":874,"dataGaLocation":869},{"altText":871,"config":901},{"src":902,"dataGaName":874,"dataGaLocation":869},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":904,"mobileIcon":909,"desktopIcon":911},{"text":905,"config":906},"Back to pricing",{"href":639,"dataGaName":907,"dataGaLocation":869,"icon":908},"back to pricing","GoBack",{"altText":871,"config":910},{"src":873,"dataGaName":874,"dataGaLocation":869},{"altText":871,"config":912},{"src":877,"dataGaName":874,"dataGaLocation":869},{"title":914,"titleMobile":915,"button":916,"config":921},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":533,"config":917},{"href":918,"dataGaName":919,"dataGaLocation":920},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":305,"disabled":471},{"data":923},{"text":924,"source":925,"edit":931,"contribute":936,"config":941,"items":946,"minimal":1155},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":926,"config":927},"View page source",{"href":928,"dataGaName":929,"dataGaLocation":930},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":932,"config":933},"Edit this page",{"href":934,"dataGaName":935,"dataGaLocation":930},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":937,"config":938},"Please contribute",{"href":939,"dataGaName":940,"dataGaLocation":930},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":942,"facebook":943,"youtube":944,"linkedin":945},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[947,994,1047,1091,1123],{"title":637,"links":948,"subMenu":963},[949,953,958],{"text":950,"config":951},"View plans",{"href":639,"dataGaName":952,"dataGaLocation":930},"view plans",{"text":954,"config":955},"Why Premium?",{"href":956,"dataGaName":957,"dataGaLocation":930},"/pricing/premium/","why premium",{"text":959,"config":960},"Why Ultimate?",{"href":961,"dataGaName":962,"dataGaLocation":930},"/pricing/ultimate/","why ultimate",[964],{"title":965,"links":966},"Contact Us",[967,970,972,974,979,984,989],{"text":968,"config":969},"Contact sales",{"href":821,"dataGaName":501,"dataGaLocation":930},{"text":824,"config":971},{"href":826,"dataGaName":827,"dataGaLocation":930},{"text":829,"config":973},{"href":831,"dataGaName":832,"dataGaLocation":930},{"text":975,"config":976},"Status",{"href":977,"dataGaName":978,"dataGaLocation":930},"https://status.gitlab.com/","status",{"text":980,"config":981},"Terms of use",{"href":982,"dataGaName":983,"dataGaLocation":930},"/terms/","terms of use",{"text":985,"config":986},"Privacy statement",{"href":987,"dataGaName":988,"dataGaLocation":930},"/privacy/","privacy statement",{"text":990,"config":991},"Cookie preferences",{"dataGaName":992,"dataGaLocation":930,"id":993,"isOneTrustButton":474},"cookie preferences","ot-sdk-btn",{"title":538,"links":995,"subMenu":1004},[996,1000],{"text":997,"config":998},"DevSecOps platform",{"href":520,"dataGaName":999,"dataGaLocation":930},"devsecops platform",{"text":1001,"config":1002},"AI-Assisted Development",{"href":527,"dataGaName":1003,"dataGaLocation":930},"ai-assisted development",[1005],{"title":1006,"links":1007},"Topics",[1008,1012,1017,1022,1027,1032,1037,1042],{"text":1009,"config":1010},"CICD",{"href":56,"dataGaName":1011,"dataGaLocation":930},"cicd",{"text":1013,"config":1014},"GitOps",{"href":1015,"dataGaName":1016,"dataGaLocation":930},"/topics/gitops/","gitops",{"text":1018,"config":1019},"DevOps",{"href":1020,"dataGaName":1021,"dataGaLocation":930},"/topics/devops/","devops",{"text":1023,"config":1024},"Version Control",{"href":1025,"dataGaName":1026,"dataGaLocation":930},"/topics/version-control/","version control",{"text":1028,"config":1029},"DevSecOps",{"href":1030,"dataGaName":1031,"dataGaLocation":930},"/topics/devsecops/","devsecops",{"text":1033,"config":1034},"Cloud Native",{"href":1035,"dataGaName":1036,"dataGaLocation":930},"/topics/cloud-native/","cloud native",{"text":1038,"config":1039},"AI for Coding",{"href":1040,"dataGaName":1041,"dataGaLocation":930},"/topics/devops/ai-for-coding/","ai for coding",{"text":1043,"config":1044},"Agentic AI",{"href":1045,"dataGaName":1046,"dataGaLocation":930},"/topics/agentic-ai/","agentic ai",{"title":1048,"links":1049},"Solutions",[1050,1052,1054,1059,1063,1066,1070,1073,1075,1078,1081,1086],{"text":581,"config":1051},{"href":576,"dataGaName":581,"dataGaLocation":930},{"text":570,"config":1053},{"href":554,"dataGaName":555,"dataGaLocation":930},{"text":1055,"config":1056},"Agile development",{"href":1057,"dataGaName":1058,"dataGaLocation":930},"/solutions/agile-delivery/","agile delivery",{"text":1060,"config":1061},"SCM",{"href":566,"dataGaName":1062,"dataGaLocation":930},"source code management",{"text":1009,"config":1064},{"href":559,"dataGaName":1065,"dataGaLocation":930},"continuous integration & delivery",{"text":1067,"config":1068},"Value stream management",{"href":609,"dataGaName":1069,"dataGaLocation":930},"value stream management",{"text":1013,"config":1071},{"href":1072,"dataGaName":1016,"dataGaLocation":930},"/solutions/gitops/",{"text":619,"config":1074},{"href":622,"dataGaName":623,"dataGaLocation":930},{"text":1076,"config":1077},"Small business",{"href":628,"dataGaName":629,"dataGaLocation":930},{"text":1079,"config":1080},"Public sector",{"href":634,"dataGaName":635,"dataGaLocation":930},{"text":1082,"config":1083},"Education",{"href":1084,"dataGaName":1085,"dataGaLocation":930},"/solutions/education/","education",{"text":1087,"config":1088},"Financial services",{"href":1089,"dataGaName":1090,"dataGaLocation":930},"/solutions/finance/","financial services",{"title":642,"links":1092},[1093,1095,1097,1099,1102,1104,1107,1109,1111,1113,1115,1117,1119,1121],{"text":655,"config":1094},{"href":657,"dataGaName":658,"dataGaLocation":930},{"text":660,"config":1096},{"href":662,"dataGaName":663,"dataGaLocation":930},{"text":665,"config":1098},{"href":667,"dataGaName":668,"dataGaLocation":930},{"text":670,"config":1100},{"href":672,"dataGaName":1101,"dataGaLocation":930},"docs",{"text":693,"config":1103},{"href":695,"dataGaName":696,"dataGaLocation":930},{"text":1105,"config":1106},"What's new",{"href":753,"dataGaName":754,"dataGaLocation":930},{"text":688,"config":1108},{"href":690,"dataGaName":691,"dataGaLocation":930},{"text":707,"config":1110},{"href":709,"dataGaName":710,"dataGaLocation":930},{"text":715,"config":1112},{"href":717,"dataGaName":718,"dataGaLocation":930},{"text":720,"config":1114},{"href":722,"dataGaName":723,"dataGaLocation":930},{"text":725,"config":1116},{"href":727,"dataGaName":728,"dataGaLocation":930},{"text":730,"config":1118},{"href":732,"dataGaName":733,"dataGaLocation":930},{"text":735,"config":1120},{"href":737,"dataGaName":738,"dataGaLocation":930},{"text":740,"config":1122},{"href":742,"dataGaName":743,"dataGaLocation":930},{"title":756,"links":1124},[1125,1127,1129,1131,1133,1135,1139,1144,1146,1148,1150],{"text":764,"config":1126},{"href":766,"dataGaName":758,"dataGaLocation":930},{"text":769,"config":1128},{"href":771,"dataGaName":772,"dataGaLocation":930},{"text":777,"config":1130},{"href":779,"dataGaName":780,"dataGaLocation":930},{"text":782,"config":1132},{"href":784,"dataGaName":785,"dataGaLocation":930},{"text":787,"config":1134},{"href":789,"dataGaName":790,"dataGaLocation":930},{"text":1136,"config":1137},"Sustainability",{"href":1138,"dataGaName":1136,"dataGaLocation":930},"/sustainability/",{"text":1140,"config":1141},"Diversity, inclusion and belonging (DIB)",{"href":1142,"dataGaName":1143,"dataGaLocation":930},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":792,"config":1145},{"href":794,"dataGaName":795,"dataGaLocation":930},{"text":802,"config":1147},{"href":804,"dataGaName":805,"dataGaLocation":930},{"text":807,"config":1149},{"href":809,"dataGaName":810,"dataGaLocation":930},{"text":1151,"config":1152},"Modern Slavery Transparency Statement",{"href":1153,"dataGaName":1154,"dataGaLocation":930},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1156},[1157,1160,1163],{"text":1158,"config":1159},"Terms",{"href":982,"dataGaName":983,"dataGaLocation":930},{"text":1161,"config":1162},"Cookies",{"dataGaName":992,"dataGaLocation":930,"id":993,"isOneTrustButton":474},{"text":1164,"config":1165},"Privacy",{"href":987,"dataGaName":988,"dataGaLocation":930},[1167],{"id":1168,"title":7,"body":470,"config":1169,"content":1171,"description":470,"extension":1174,"meta":1175,"navigation":474,"path":1176,"seo":1177,"stem":1178,"__hash__":1179},"blogAuthors/en-us/blog/authors/jackie-meshell.yml",{"template":1170},"BlogAuthor",{"name":7,"config":1172},{"headshot":239,"ctfId":1173},"jmeshell","yml",{},"/en-us/blog/authors/jackie-meshell",{},"en-us/blog/authors/jackie-meshell","yrBYUQpN3SczvQoFs8kZDIqM4LXhuxOGjiyJAQcpNDI",[1181,1189,1197],{"title":1182,"description":1183,"heroImage":1184,"category":466,"date":1185,"authors":1186,"slug":1188,"externalUrl":470},"CEO Shadow Takeaways from Jacie","Recap of my experience in the CEO Shadow Program.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664102/Blog/Hero%20Images/gitlab-values-cover.png","2021-05-18",[1187],"Jacie Bandur","ceo-shadow-recap",{"title":1190,"description":1191,"heroImage":1192,"category":466,"date":1193,"authors":1194,"slug":1196,"externalUrl":470},"Why I love contributing to GitLab","Making small meaningful changes is what it's all about.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679501/Blog/Hero%20Images/new-feature.png","2021-05-11",[1195],"Austin Regnery","why-i-love-contributing-to-gitlab",{"title":1198,"description":1199,"heroImage":1200,"category":466,"date":1193,"authors":1201,"slug":1203,"externalUrl":470},"Placebo Lines on the Pipeline Graph","Have you noticed the connecting lines missing on your pipelines lately? Here's why","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679507/Blog/Hero%20Images/ci-cd.png",[1202],"Sam Beckham","placebo-lines-on-the-pipeline-graph",{"promotions":1205},[1206,1220,1232,1244],{"id":1207,"categories":1208,"header":1210,"text":1211,"button":1212,"image":1217},"ai-modernization",[1209],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1213,"config":1214},"Get your AI maturity score",{"href":1215,"dataGaName":1216,"dataGaLocation":696},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1218},{"src":1219},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1221,"categories":1222,"header":1224,"text":1211,"button":1225,"image":1229},"devops-modernization",[1223,1031],"product","Are you just managing tools or shipping innovation?",{"text":1226,"config":1227},"Get your DevOps maturity score",{"href":1228,"dataGaName":1216,"dataGaLocation":696},"/assessments/devops-modernization-assessment/",{"config":1230},{"src":1231},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1233,"categories":1234,"header":1236,"text":1211,"button":1237,"image":1241},"security-modernization",[1235],"security","Are you trading speed for security?",{"text":1238,"config":1239},"Get your security maturity score",{"href":1240,"dataGaName":1216,"dataGaLocation":696},"/assessments/security-modernization-assessment/",{"config":1242},{"src":1243},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1245,"paths":1246,"header":1249,"text":1250,"button":1251,"image":1256},"github-azure-migration",[1247,1248],"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":1252,"config":1253},"See how GitLab compares to GitHub",{"href":1254,"dataGaName":1255,"dataGaLocation":696},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1257},{"src":1231},{"header":1259,"blurb":1260,"button":1261,"secondaryButton":1266},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1262,"config":1263},"Get your free trial",{"href":1264,"dataGaName":496,"dataGaLocation":1265},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":968,"config":1267},{"href":821,"dataGaName":501,"dataGaLocation":1265},1786803734539]