[{"data":1,"prerenderedAt":716},["ShallowReactive",2],{"/en-us/blog/behind-the-scenes-how-we-built-review-apps/":3,"navigation-en-us":32,"banner-en-us":461,"footer-en-us":478,"Mark Pundsack":688,"next-steps-en-us":701},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":22,"_id":25,"_type":26,"title":27,"_source":28,"_file":29,"_stem":30,"_extension":31},"/en-us/blog/behind-the-scenes-how-we-built-review-apps","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Behind the scenes: How we built Review Apps","GitLab's Head of Product shares an inside look at iterating on one of our latest features","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749668402/Blog/Hero%20Images/code-gitlab-tanuki.png","https://about.gitlab.com/blog/behind-the-scenes-how-we-built-review-apps","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Behind the scenes: How we built Review Apps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mark Pundsack\"}],\n        \"datePublished\": \"2017-01-04\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21},[18],"Mark Pundsack","2017-01-04","A bunch of us on the GitLab team have known for a while just how important\nreview apps are. Even though this wasn’t something that a lot of customers\nasked for, we knew we had to tackle it because of how we'd seen it transform\na developer's flow. We also knew that tightly integrating it into GitLab\nwould make it even better. Although our aspirations for the feature started\nout gigantic and magical, we ultimately constrained them to the practical\nand concrete. Here's a behind-the-scenes look at how we iterated and shipped\n[Review Apps](https://docs.gitlab.com/ee/ci/review_apps/) over the last 3\nreleases.\n\n\n\u003C!-- more -->\n\n\nFull disclosure: I used to work at Heroku on the team that shipped [Heroku\nReview\nApps](https://devcenter.heroku.com/articles/github-integration-review-apps),\nand some of that work was inspired by a tool called\n[Fourchette](https://github.com/rainforestapp/fourchette), which was created\nby the great folks at [Rainforest QA](https://www.rainforestqa.com/). Even\noutside of my personal bias, our CEO, CI Lead and others had seen things\nlike this elsewhere and saw how transformative it could be.\n\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/CteZol_7pxo?start=1713\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\nThere are a ton of different ways we could have shipped it. We started\nmonths ago, mostly discussing asynchronously on GitLab issues, with big\nideas that made Review Apps seem kind of daunting. We had ideas for black\nmagic to detect Kubernetes settings, configure all the review app stuff for\nyou, make them work only for merge requests rather than for every branch,\netc. It felt like something that might not ship for months, if not years,\nbecause of all the complexity and dependencies.\n\n\nBut then a few of us got together to see how we could simplify, starting\nwith a written proposal, then collaborating in a Google Doc, then a live\nchat over Google Hangouts, and we came up with what we felt would be the\nsmallest thing we could do to enable the functionality. We shared that\nproposal back on the public issue. After a couple days, we pushed it even\nfurther and really cut the scope.\n\n\nHere are a few links to some of the issues we went through, starting with a\nlarge meta issue, down to a concrete proposal and then counterproposal,\nuntil finally, the winning proposal emerged:\n\n\n* [#3286](https://gitlab.com/gitlab-org/gitlab-ce/issues/3286) - [Epic]\nGitLab Deploy, _opened 1 year ago_\n\n* [#14698](https://gitlab.com/gitlab-org/gitlab-ce/issues/14698) - Container\nscheduler for 4 use cases, _9 months ago_\n\n* [#20255](https://gitlab.com/gitlab-org/gitlab-ce/issues/20255) - [Meta]\nReview Apps, _5 months ago_\n\n* [#20054](https://gitlab.com/gitlab-org/gitlab-ce/issues/20054) - Review\nApps as Runner job, _5 months ago_\n\n* [#21411](https://gitlab.com/gitlab-org/gitlab-ce/issues/21411) - How do we\ndo deploys, _4 months ago_\n\n* [#21971](https://gitlab.com/gitlab-org/gitlab-ce/issues/21971) - Dynamic\nenvironments aka Review Apps, _3 months ago_\n\n\n## 8.12\n\n\nWe initially offered experimental support for Review Apps in GitLab 8.12. At\nthat point, we had reduced it to just one or two seemingly small changes to\nthe `.gitlab-ci.yml` format. Specifically, we let you specify the URL of an\nenvironment in `.gitlab-ci.yml` (rather than just in the web UI), and we let\nyou use variables within the environment name and URL. Trivial, right? One\nextra keyword and another small change enabled environments to now be\n“dynamic,” which is the core of Review Apps.\n\n\n```yaml\n\nreview_apps:\n  environment:\n    name: review/$CI_BUILD_REF_NAME\n    url: http://$CI_BUILD_REF_NAME.review.gitlab.com/\n```\n\n\n## 8.13\n\n\nThen in 8.13 we implemented another key piece: the ability to delete or stop\napps. Again, there were all sorts of complex ideas for how to solve this,\nbut we settled on the smallest change possible that enabled the feature. In\nthis case, that was reusing our existing concept of manual actions, or jobs\nthat run in a pipeline only when a user triggers them manually from the web\nUI. So we said, if you can script how to delete your app, just create a\nmanual action job for it. Then we added a new keyword in `.gitlab-ci.yml` so\nyou could identify which of these jobs stopped the environment, and we\ndisplayed a different UI for that - now you get a little square stop button\ninstead of the triangle play button. Again, pretty trivial.\n\n\n```yaml\n\nreview:\n  environment:\n    name: review/$app\n    on_stop: stop_review\n\nstop_review:\n  script: echo Delete My App\n  when: manual\n  environment:\n    name: review/$app\n    action: stop\n```\n\n\n## 8.14\n\n\nMost recently, in the 8.14 release, we made it so that we automatically\ndetect when a branch is deleted, and run that manual action automatically\nfor you. We also realized that with tons of Review Apps, your environments\nlist might get unmanageable. To mitigate this, we came up with the\nconvention that if you named your review app starting with a common name and\nthen a slash, we’d treat that like a folder by which to group your apps, so\nthe interface can show a bunch of Review Apps behind a collapsed folder.\nOnce again, these are relatively small changes.\n\n\n* Auto-stop on branch delete\n\n* Folders in environment list\n\n\n## Wrap up\n\n\nUltimately this really complex, life changing feature was broken down into 3\nreleases of the minimal viable change.\n\n\nWhile we say Review Apps is now complete, it’s not finished. In fact, we\nhave a saying that nothing is ever finished because we’re always looking for\nthe minimal change, and then iterating. By shipping smaller pieces, we not\nonly deliver faster, but we learn from what’s been shipped, and then iterate\nsmarter.\n\n\nWe’ve now got follow-on issues to look at simplifying the `.gitlab-ci.yml`\nsyntax for Review Apps, and even adding back some of that magic we\noriginally envisioned. We’ll continue to iterate, and your feedback is key\nto us shipping better.\n\n\n* [#25138](https://gitlab.com/gitlab-org/gitlab-ce/issues/25138) - Simplify\n`.gitlab-ci.yml` syntax for stopping Review Apps\n\n* [#24197](https://gitlab.com/gitlab-org/gitlab-ce/issues/24197) - Smart\ndeploy\n\n* [#23580](https://gitlab.com/gitlab-org/gitlab-ce/issues/23580) - Auto\ndeploy\n\n\n_Tweet us [@GitLab](https://twitter.com/gitlab), check out our [job\nopenings](/jobs/), or add your questions and suggestions to our [issue\ntracker](https://gitlab.com/gitlab-org/gitlab-ce/issues)!_\n","engineering",{"slug":23,"featured":6,"template":24},"behind-the-scenes-how-we-built-review-apps","BlogPost","content:en-us:blog:behind-the-scenes-how-we-built-review-apps.yml","yaml","Behind The Scenes How We Built Review Apps","content","en-us/blog/behind-the-scenes-how-we-built-review-apps.yml","en-us/blog/behind-the-scenes-how-we-built-review-apps","yml",{"_path":33,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"data":35,"_id":457,"_type":26,"title":458,"_source":28,"_file":459,"_stem":460,"_extension":31},"/shared/en-us/main-navigation","en-us",{"logo":36,"freeTrial":41,"sales":46,"login":51,"items":56,"search":388,"minimal":419,"duo":438,"pricingDeployment":447},{"config":37},{"href":38,"dataGaName":39,"dataGaLocation":40},"/","gitlab logo","header",{"text":42,"config":43},"Get free trial",{"href":44,"dataGaName":45,"dataGaLocation":40},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":47,"config":48},"Talk to sales",{"href":49,"dataGaName":50,"dataGaLocation":40},"/sales/","sales",{"text":52,"config":53},"Sign in",{"href":54,"dataGaName":55,"dataGaLocation":40},"https://gitlab.com/users/sign_in/","sign in",[57,101,199,204,309,369],{"text":58,"config":59,"cards":61,"footer":84},"Platform",{"dataNavLevelOne":60},"platform",[62,68,76],{"title":58,"description":63,"link":64},"The most comprehensive AI-powered DevSecOps Platform",{"text":65,"config":66},"Explore our Platform",{"href":67,"dataGaName":60,"dataGaLocation":40},"/platform/",{"title":69,"description":70,"link":71},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":72,"config":73},"Meet GitLab Duo",{"href":74,"dataGaName":75,"dataGaLocation":40},"/gitlab-duo/","gitlab duo ai",{"title":77,"description":78,"link":79},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":80,"config":81},"Learn more",{"href":82,"dataGaName":83,"dataGaLocation":40},"/why-gitlab/","why gitlab",{"title":85,"items":86},"Get started with",[87,92,97],{"text":88,"config":89},"Platform Engineering",{"href":90,"dataGaName":91,"dataGaLocation":40},"/solutions/platform-engineering/","platform engineering",{"text":93,"config":94},"Developer Experience",{"href":95,"dataGaName":96,"dataGaLocation":40},"/developer-experience/","Developer experience",{"text":98,"config":99},"MLOps",{"href":100,"dataGaName":98,"dataGaLocation":40},"/topics/devops/the-role-of-ai-in-devops/",{"text":102,"left":103,"config":104,"link":106,"lists":110,"footer":181},"Product",true,{"dataNavLevelOne":105},"solutions",{"text":107,"config":108},"View all Solutions",{"href":109,"dataGaName":105,"dataGaLocation":40},"/solutions/",[111,136,160],{"title":112,"description":113,"link":114,"items":119},"Automation","CI/CD and automation to accelerate deployment",{"config":115},{"icon":116,"href":117,"dataGaName":118,"dataGaLocation":40},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[120,124,128,132],{"text":121,"config":122},"CI/CD",{"href":123,"dataGaLocation":40,"dataGaName":121},"/solutions/continuous-integration/",{"text":125,"config":126},"AI-Assisted Development",{"href":74,"dataGaLocation":40,"dataGaName":127},"AI assisted development",{"text":129,"config":130},"Source Code Management",{"href":131,"dataGaLocation":40,"dataGaName":129},"/solutions/source-code-management/",{"text":133,"config":134},"Automated Software Delivery",{"href":117,"dataGaLocation":40,"dataGaName":135},"Automated software delivery",{"title":137,"description":138,"link":139,"items":144},"Security","Deliver code faster without compromising security",{"config":140},{"href":141,"dataGaName":142,"dataGaLocation":40,"icon":143},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[145,150,155],{"text":146,"config":147},"Application Security Testing",{"href":148,"dataGaName":149,"dataGaLocation":40},"/solutions/application-security-testing/","Application security testing",{"text":151,"config":152},"Software Supply Chain Security",{"href":153,"dataGaLocation":40,"dataGaName":154},"/solutions/supply-chain/","Software supply chain security",{"text":156,"config":157},"Software Compliance",{"href":158,"dataGaName":159,"dataGaLocation":40},"/solutions/software-compliance/","software compliance",{"title":161,"link":162,"items":167},"Measurement",{"config":163},{"icon":164,"href":165,"dataGaName":166,"dataGaLocation":40},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[168,172,176],{"text":169,"config":170},"Visibility & Measurement",{"href":165,"dataGaLocation":40,"dataGaName":171},"Visibility and Measurement",{"text":173,"config":174},"Value Stream Management",{"href":175,"dataGaLocation":40,"dataGaName":173},"/solutions/value-stream-management/",{"text":177,"config":178},"Analytics & Insights",{"href":179,"dataGaLocation":40,"dataGaName":180},"/solutions/analytics-and-insights/","Analytics and insights",{"title":182,"items":183},"GitLab for",[184,189,194],{"text":185,"config":186},"Enterprise",{"href":187,"dataGaLocation":40,"dataGaName":188},"/enterprise/","enterprise",{"text":190,"config":191},"Small Business",{"href":192,"dataGaLocation":40,"dataGaName":193},"/small-business/","small business",{"text":195,"config":196},"Public Sector",{"href":197,"dataGaLocation":40,"dataGaName":198},"/solutions/public-sector/","public sector",{"text":200,"config":201},"Pricing",{"href":202,"dataGaName":203,"dataGaLocation":40,"dataNavLevelOne":203},"/pricing/","pricing",{"text":205,"config":206,"link":208,"lists":212,"feature":296},"Resources",{"dataNavLevelOne":207},"resources",{"text":209,"config":210},"View all resources",{"href":211,"dataGaName":207,"dataGaLocation":40},"/resources/",[213,246,268],{"title":214,"items":215},"Getting started",[216,221,226,231,236,241],{"text":217,"config":218},"Install",{"href":219,"dataGaName":220,"dataGaLocation":40},"/install/","install",{"text":222,"config":223},"Quick start guides",{"href":224,"dataGaName":225,"dataGaLocation":40},"/get-started/","quick setup checklists",{"text":227,"config":228},"Learn",{"href":229,"dataGaLocation":40,"dataGaName":230},"https://university.gitlab.com/","learn",{"text":232,"config":233},"Product documentation",{"href":234,"dataGaName":235,"dataGaLocation":40},"https://docs.gitlab.com/","product documentation",{"text":237,"config":238},"Best practice videos",{"href":239,"dataGaName":240,"dataGaLocation":40},"/getting-started-videos/","best practice videos",{"text":242,"config":243},"Integrations",{"href":244,"dataGaName":245,"dataGaLocation":40},"/integrations/","integrations",{"title":247,"items":248},"Discover",[249,254,258,263],{"text":250,"config":251},"Customer success stories",{"href":252,"dataGaName":253,"dataGaLocation":40},"/customers/","customer success stories",{"text":255,"config":256},"Blog",{"href":257,"dataGaName":5,"dataGaLocation":40},"/blog/",{"text":259,"config":260},"Remote",{"href":261,"dataGaName":262,"dataGaLocation":40},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":264,"config":265},"TeamOps",{"href":266,"dataGaName":267,"dataGaLocation":40},"/teamops/","teamops",{"title":269,"items":270},"Connect",[271,276,281,286,291],{"text":272,"config":273},"GitLab Services",{"href":274,"dataGaName":275,"dataGaLocation":40},"/services/","services",{"text":277,"config":278},"Community",{"href":279,"dataGaName":280,"dataGaLocation":40},"/community/","community",{"text":282,"config":283},"Forum",{"href":284,"dataGaName":285,"dataGaLocation":40},"https://forum.gitlab.com/","forum",{"text":287,"config":288},"Events",{"href":289,"dataGaName":290,"dataGaLocation":40},"/events/","events",{"text":292,"config":293},"Partners",{"href":294,"dataGaName":295,"dataGaLocation":40},"/partners/","partners",{"backgroundColor":297,"textColor":298,"text":299,"image":300,"link":304},"#2f2a6b","#fff","Insights for the future of software development",{"altText":301,"config":302},"the source promo card",{"src":303},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":305,"config":306},"Read the latest",{"href":307,"dataGaName":308,"dataGaLocation":40},"/the-source/","the source",{"text":310,"config":311,"lists":313},"Company",{"dataNavLevelOne":312},"company",[314],{"items":315},[316,321,327,329,334,339,344,349,354,359,364],{"text":317,"config":318},"About",{"href":319,"dataGaName":320,"dataGaLocation":40},"/company/","about",{"text":322,"config":323,"footerGa":326},"Jobs",{"href":324,"dataGaName":325,"dataGaLocation":40},"/jobs/","jobs",{"dataGaName":325},{"text":287,"config":328},{"href":289,"dataGaName":290,"dataGaLocation":40},{"text":330,"config":331},"Leadership",{"href":332,"dataGaName":333,"dataGaLocation":40},"/company/team/e-group/","leadership",{"text":335,"config":336},"Team",{"href":337,"dataGaName":338,"dataGaLocation":40},"/company/team/","team",{"text":340,"config":341},"Handbook",{"href":342,"dataGaName":343,"dataGaLocation":40},"https://handbook.gitlab.com/","handbook",{"text":345,"config":346},"Investor relations",{"href":347,"dataGaName":348,"dataGaLocation":40},"https://ir.gitlab.com/","investor relations",{"text":350,"config":351},"Trust Center",{"href":352,"dataGaName":353,"dataGaLocation":40},"/security/","trust center",{"text":355,"config":356},"AI Transparency Center",{"href":357,"dataGaName":358,"dataGaLocation":40},"/ai-transparency-center/","ai transparency center",{"text":360,"config":361},"Newsletter",{"href":362,"dataGaName":363,"dataGaLocation":40},"/company/contact/","newsletter",{"text":365,"config":366},"Press",{"href":367,"dataGaName":368,"dataGaLocation":40},"/press/","press",{"text":370,"config":371,"lists":372},"Contact us",{"dataNavLevelOne":312},[373],{"items":374},[375,378,383],{"text":47,"config":376},{"href":49,"dataGaName":377,"dataGaLocation":40},"talk to sales",{"text":379,"config":380},"Get help",{"href":381,"dataGaName":382,"dataGaLocation":40},"/support/","get help",{"text":384,"config":385},"Customer portal",{"href":386,"dataGaName":387,"dataGaLocation":40},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":389,"login":390,"suggestions":397},"Close",{"text":391,"link":392},"To search repositories and projects, login to",{"text":393,"config":394},"gitlab.com",{"href":54,"dataGaName":395,"dataGaLocation":396},"search login","search",{"text":398,"default":399},"Suggestions",[400,402,406,408,412,416],{"text":69,"config":401},{"href":74,"dataGaName":69,"dataGaLocation":396},{"text":403,"config":404},"Code Suggestions (AI)",{"href":405,"dataGaName":403,"dataGaLocation":396},"/solutions/code-suggestions/",{"text":121,"config":407},{"href":123,"dataGaName":121,"dataGaLocation":396},{"text":409,"config":410},"GitLab on AWS",{"href":411,"dataGaName":409,"dataGaLocation":396},"/partners/technology-partners/aws/",{"text":413,"config":414},"GitLab on Google Cloud",{"href":415,"dataGaName":413,"dataGaLocation":396},"/partners/technology-partners/google-cloud-platform/",{"text":417,"config":418},"Why GitLab?",{"href":82,"dataGaName":417,"dataGaLocation":396},{"freeTrial":420,"mobileIcon":425,"desktopIcon":430,"secondaryButton":433},{"text":421,"config":422},"Start free trial",{"href":423,"dataGaName":45,"dataGaLocation":424},"https://gitlab.com/-/trials/new/","nav",{"altText":426,"config":427},"Gitlab Icon",{"src":428,"dataGaName":429,"dataGaLocation":424},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":426,"config":431},{"src":432,"dataGaName":429,"dataGaLocation":424},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":434,"config":435},"Get Started",{"href":436,"dataGaName":437,"dataGaLocation":424},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":439,"mobileIcon":443,"desktopIcon":445},{"text":440,"config":441},"Learn more about GitLab Duo",{"href":74,"dataGaName":442,"dataGaLocation":424},"gitlab duo",{"altText":426,"config":444},{"src":428,"dataGaName":429,"dataGaLocation":424},{"altText":426,"config":446},{"src":432,"dataGaName":429,"dataGaLocation":424},{"freeTrial":448,"mobileIcon":453,"desktopIcon":455},{"text":449,"config":450},"Back to pricing",{"href":202,"dataGaName":451,"dataGaLocation":424,"icon":452},"back to pricing","GoBack",{"altText":426,"config":454},{"src":428,"dataGaName":429,"dataGaLocation":424},{"altText":426,"config":456},{"src":432,"dataGaName":429,"dataGaLocation":424},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":462,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"title":463,"button":464,"image":469,"config":473,"_id":475,"_type":26,"_source":28,"_file":476,"_stem":477,"_extension":31},"/shared/en-us/banner","is now in public beta!",{"text":465,"config":466},"Try the Beta",{"href":467,"dataGaName":468,"dataGaLocation":40},"/gitlab-duo/agent-platform/","duo banner",{"altText":470,"config":471},"GitLab Duo Agent Platform",{"src":472},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":474},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":479,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"data":480,"_id":684,"_type":26,"title":685,"_source":28,"_file":686,"_stem":687,"_extension":31},"/shared/en-us/main-footer",{"text":481,"source":482,"edit":488,"contribute":493,"config":498,"items":503,"minimal":676},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":483,"config":484},"View page source",{"href":485,"dataGaName":486,"dataGaLocation":487},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":489,"config":490},"Edit this page",{"href":491,"dataGaName":492,"dataGaLocation":487},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":494,"config":495},"Please contribute",{"href":496,"dataGaName":497,"dataGaLocation":487},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":499,"facebook":500,"youtube":501,"linkedin":502},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[504,527,583,612,646],{"title":58,"links":505,"subMenu":510},[506],{"text":507,"config":508},"DevSecOps platform",{"href":67,"dataGaName":509,"dataGaLocation":487},"devsecops platform",[511],{"title":200,"links":512},[513,517,522],{"text":514,"config":515},"View plans",{"href":202,"dataGaName":516,"dataGaLocation":487},"view plans",{"text":518,"config":519},"Why Premium?",{"href":520,"dataGaName":521,"dataGaLocation":487},"/pricing/premium/","why premium",{"text":523,"config":524},"Why Ultimate?",{"href":525,"dataGaName":526,"dataGaLocation":487},"/pricing/ultimate/","why ultimate",{"title":528,"links":529},"Solutions",[530,535,537,539,544,549,553,556,560,565,567,570,573,578],{"text":531,"config":532},"Digital transformation",{"href":533,"dataGaName":534,"dataGaLocation":487},"/topics/digital-transformation/","digital transformation",{"text":146,"config":536},{"href":148,"dataGaName":146,"dataGaLocation":487},{"text":135,"config":538},{"href":117,"dataGaName":118,"dataGaLocation":487},{"text":540,"config":541},"Agile development",{"href":542,"dataGaName":543,"dataGaLocation":487},"/solutions/agile-delivery/","agile delivery",{"text":545,"config":546},"Cloud transformation",{"href":547,"dataGaName":548,"dataGaLocation":487},"/topics/cloud-native/","cloud transformation",{"text":550,"config":551},"SCM",{"href":131,"dataGaName":552,"dataGaLocation":487},"source code management",{"text":121,"config":554},{"href":123,"dataGaName":555,"dataGaLocation":487},"continuous integration & delivery",{"text":557,"config":558},"Value stream management",{"href":175,"dataGaName":559,"dataGaLocation":487},"value stream management",{"text":561,"config":562},"GitOps",{"href":563,"dataGaName":564,"dataGaLocation":487},"/solutions/gitops/","gitops",{"text":185,"config":566},{"href":187,"dataGaName":188,"dataGaLocation":487},{"text":568,"config":569},"Small business",{"href":192,"dataGaName":193,"dataGaLocation":487},{"text":571,"config":572},"Public sector",{"href":197,"dataGaName":198,"dataGaLocation":487},{"text":574,"config":575},"Education",{"href":576,"dataGaName":577,"dataGaLocation":487},"/solutions/education/","education",{"text":579,"config":580},"Financial services",{"href":581,"dataGaName":582,"dataGaLocation":487},"/solutions/finance/","financial services",{"title":205,"links":584},[585,587,589,591,594,596,598,600,602,604,606,608,610],{"text":217,"config":586},{"href":219,"dataGaName":220,"dataGaLocation":487},{"text":222,"config":588},{"href":224,"dataGaName":225,"dataGaLocation":487},{"text":227,"config":590},{"href":229,"dataGaName":230,"dataGaLocation":487},{"text":232,"config":592},{"href":234,"dataGaName":593,"dataGaLocation":487},"docs",{"text":255,"config":595},{"href":257,"dataGaName":5,"dataGaLocation":487},{"text":250,"config":597},{"href":252,"dataGaName":253,"dataGaLocation":487},{"text":259,"config":599},{"href":261,"dataGaName":262,"dataGaLocation":487},{"text":272,"config":601},{"href":274,"dataGaName":275,"dataGaLocation":487},{"text":264,"config":603},{"href":266,"dataGaName":267,"dataGaLocation":487},{"text":277,"config":605},{"href":279,"dataGaName":280,"dataGaLocation":487},{"text":282,"config":607},{"href":284,"dataGaName":285,"dataGaLocation":487},{"text":287,"config":609},{"href":289,"dataGaName":290,"dataGaLocation":487},{"text":292,"config":611},{"href":294,"dataGaName":295,"dataGaLocation":487},{"title":310,"links":613},[614,616,618,620,622,624,626,630,635,637,639,641],{"text":317,"config":615},{"href":319,"dataGaName":312,"dataGaLocation":487},{"text":322,"config":617},{"href":324,"dataGaName":325,"dataGaLocation":487},{"text":330,"config":619},{"href":332,"dataGaName":333,"dataGaLocation":487},{"text":335,"config":621},{"href":337,"dataGaName":338,"dataGaLocation":487},{"text":340,"config":623},{"href":342,"dataGaName":343,"dataGaLocation":487},{"text":345,"config":625},{"href":347,"dataGaName":348,"dataGaLocation":487},{"text":627,"config":628},"Sustainability",{"href":629,"dataGaName":627,"dataGaLocation":487},"/sustainability/",{"text":631,"config":632},"Diversity, inclusion and belonging (DIB)",{"href":633,"dataGaName":634,"dataGaLocation":487},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":350,"config":636},{"href":352,"dataGaName":353,"dataGaLocation":487},{"text":360,"config":638},{"href":362,"dataGaName":363,"dataGaLocation":487},{"text":365,"config":640},{"href":367,"dataGaName":368,"dataGaLocation":487},{"text":642,"config":643},"Modern Slavery Transparency Statement",{"href":644,"dataGaName":645,"dataGaLocation":487},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":647,"links":648},"Contact Us",[649,652,654,656,661,666,671],{"text":650,"config":651},"Contact an expert",{"href":49,"dataGaName":50,"dataGaLocation":487},{"text":379,"config":653},{"href":381,"dataGaName":382,"dataGaLocation":487},{"text":384,"config":655},{"href":386,"dataGaName":387,"dataGaLocation":487},{"text":657,"config":658},"Status",{"href":659,"dataGaName":660,"dataGaLocation":487},"https://status.gitlab.com/","status",{"text":662,"config":663},"Terms of use",{"href":664,"dataGaName":665,"dataGaLocation":487},"/terms/","terms of use",{"text":667,"config":668},"Privacy statement",{"href":669,"dataGaName":670,"dataGaLocation":487},"/privacy/","privacy statement",{"text":672,"config":673},"Cookie preferences",{"dataGaName":674,"dataGaLocation":487,"id":675,"isOneTrustButton":103},"cookie preferences","ot-sdk-btn",{"items":677},[678,680,682],{"text":662,"config":679},{"href":664,"dataGaName":665,"dataGaLocation":487},{"text":667,"config":681},{"href":669,"dataGaName":670,"dataGaLocation":487},{"text":672,"config":683},{"dataGaName":674,"dataGaLocation":487,"id":675,"isOneTrustButton":103},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[689],{"_path":690,"_dir":691,"_draft":6,"_partial":6,"_locale":7,"content":692,"config":696,"_id":698,"_type":26,"title":18,"_source":28,"_file":699,"_stem":700,"_extension":31},"/en-us/blog/authors/mark-pundsack","authors",{"name":18,"config":693},{"headshot":694,"ctfId":695},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659488/Blog/Author%20Headshots/gitlab-logo-extra-whitespace.png","markpundsack",{"template":697},"BlogAuthor","content:en-us:blog:authors:mark-pundsack.yml","en-us/blog/authors/mark-pundsack.yml","en-us/blog/authors/mark-pundsack",{"_path":702,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"header":703,"eyebrow":704,"blurb":705,"button":706,"secondaryButton":710,"_id":712,"_type":26,"title":713,"_source":28,"_file":714,"_stem":715,"_extension":31},"/shared/en-us/next-steps","Start shipping better software faster","50%+ of the Fortune 100 trust GitLab","See what your team can do with the intelligent\n\n\nDevSecOps platform.\n",{"text":42,"config":707},{"href":708,"dataGaName":45,"dataGaLocation":709},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":47,"config":711},{"href":49,"dataGaName":50,"dataGaLocation":709},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1758326248468]