[{"data":1,"prerenderedAt":1148},["ShallowReactive",2],{"/blog/a-ci-component-builders-journey":3,"navigation-en-us":360,"banner-en-us":787,"footer-en-us":797,"blog-post-authors-en-us-Darwin Sanoy":1042,"blog-related-posts-en-us-a-ci-component-builders-journey":1059,"blog-promotions-en-us":1084,"next-steps-en-us":1138},{"id":4,"title":5,"authors":6,"body":8,"category":338,"date":339,"description":340,"extension":341,"externalUrl":342,"faq":342,"featured":343,"heroImage":344,"meta":345,"navigation":346,"path":347,"seo":348,"slug":352,"stem":353,"tags":354,"template":358,"updatedDate":342,"__hash__":359},"blogPosts/en-us/blog/a-ci-component-builders-journey.md","A CI/CD component builder's journey",[7],"Darwin Sanoy",{"type":9,"value":10,"toc":312},"minimark",[11,15,18,28,37,40,63,68,71,81,84,93,96,105,113,122,125,134,137,146,149,158,161,170,176,182,186,189,200,203,207,232,236,249,252,272,275,278],[12,13,14],"p",{},"I've always found it fascinating that my father, a heavy-duty mechanic by trade, would make his own tools for challenging jobs for which his industry had not yet built a fit-to-purpose tool. Little did I realize I'd become a tool builder in IT, which has been one of my loves for many years now.",[12,16,17],{},"I have been building GitLab CI/CD includable, shared templates since starting with GitLab over four years ago. They were designed in a specific way for others to depend directly on them – similar to the dependency managers you see in application languages like Node.js NPM, Python Pypi, and .NET NuGet.",[12,19,20,21,27],{},"GitLab itself has had long experience in building these shared CI dependencies through ",[22,23,26],"a",{"href":24,"rel":25},"https://docs.gitlab.com/topics/autodevops/",[],"Auto DevOps"," and all of our security scanning suite of tools.",[12,29,30,31,36],{},"With the introduction of ",[22,32,35],{"href":33,"rel":34},"https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/",[],"GitLab CI/CD Catalog",", this long-running approach is formalized into a way for everyone to publish GitLab CI/CD components for use by anyone in the world.",[12,38,39],{},"Some of they key upgrades compared to the shared templates approach include:",[41,42,43,51,57],"ul",{},[44,45,46,50],"li",{},[47,48,49],"strong",{},"Independent component versions"," are a new versioning mechanism that no longer relies on inheriting containers versions. GitLab CI/CD component versions bundle together the CI code and any number of containers (or no containers) behind a single CI/CD component version. The concepts of stable, production-grade DevSecOps require the ability to peg dependency versions in automation – for exactly the same reasons and benefits that this is done in production-grade application code.",[44,52,53,56],{},[47,54,55],{},"Global visibility (with control)"," is available through the catalog at GitLab.com (or global to your company on a self-managed instance). Individual component visibility is also subject to the security settings of it's source project - so you can publish components to secure groups.",[44,58,59,62],{},[47,60,61],{},"Catalog metadata,"," like most code-sharing mechanisms, is needed data to make decisions about which components to use.",[64,65,67],"h2",{"id":66},"lets-show-some-code","Let's show some code",[12,69,70],{},"I much prefer to show than tell, so let's look at a few component examples - all of which also publish their sources publicly (click on the title to access the component).",[72,73,75,76],"h3",{"id":74},"_1-hello-world","1. ",[22,77,80],{"href":78,"rel":79},"https://gitlab.com/explore/catalog/guided-explorations/ci-components/hello-world",[],"Hello World",[12,82,83],{},"I noticed that there was not yet a Hello World component that could show the minimum viable component, both the results and the source. This particular example shows how to \"componentize\" just CI code.",[72,85,87,88],{"id":86},"_2-hello-world-container","2. ",[22,89,92],{"href":90,"rel":91},"https://gitlab.com/explore/catalog/guided-explorations/ci-components/hello-world-container",[],"Hello World Container",[12,94,95],{},"Frequently a CI/CD component will require a container to be fully functional. This example includes a container that is published in the same project as the component itself.",[72,97,99,100],{"id":98},"_3-gitversion-ultimate-auto-semversioning","3. ",[22,101,104],{"href":102,"rel":103},"https://gitlab.com/explore/catalog/guided-explorations/ci-components/ultimate-auto-semversioning",[],"GitVersion Ultimate Auto Semversioning",[12,106,107,108,112],{},"This component automates the venerable \"GitVersion\" utility, which completely automates selecting the next semversion for your software without having to store the last version – even for busy repositories where many production-possible candidates are being worked on at once. One of the building principles this component follows is the principle of \"least configuration\" or \"default to doing the most useful thing with zero configuration.\" In this case, if your project does not contain a ",[109,110,111],"code",{},"GitVersion.yml",", the component creates the one that an individual unfamiliar with GitVersion might find to be the most useful starting point.",[72,114,116,117],{"id":115},"_4-amazon-codeguru-secure-sast-scanner","4. ",[22,118,121],{"href":119,"rel":120},"https://gitlab.com/explore/catalog/guided-explorations/ci-components/aws/amazon-codeguru-secure-sast",[],"Amazon CodeGuru Secure SAST Scanner",[12,123,124],{},"This component is a security scanner and, as such, follows some security scanning best practices I have implemented during recent years. For instance, if it detects that you are licensed for GitLab Ultimate, it has the scanner output GitLab's SAST JSON format, which integrates the findings just like native GitLab scanner findings. The findings appear in MRs and dashboards and can be the target of security policy merge approvals. If, however, you are not licensed for GitLab Ultimate, the scanner outputs JUNIT XML so that you have some basic, non-diffed findings visualization in the pipeline \"Test Results\" tab. It also only activates if there are file types it can scan and disables if the GitLab SAST_DISABLED property is turned on.",[72,126,128,129],{"id":127},"_5-checkov-iac-sast","5. ",[22,130,133],{"href":131,"rel":132},"https://gitlab.com/explore/catalog/guided-explorations/ci-components/checkov-iac-sast",[],"Checkov IaC SAST",[12,135,136],{},"Checkov IaC SAST is another security scanner component that also follows the above security scanner principles, but specifically for the file types it is capable of scanning. A critical best practice of many of these components is pegging container tags for stability - but doing so through a \"component input\" with a default value. This allows component users to test with and peg to a newer or older version than you last tested with. So your shared dependency then offers stability, but with flexibility.",[72,138,140,141],{"id":139},"_6-super-linter","6. ",[22,142,145],{"href":143,"rel":144},"https://gitlab.com/guided-explorations/ci-components/super-linter",[],"Super-Linter",[12,147,148],{},"Super-Linter is a community-driven conglomeration of many linters for many languages. It originally started life as a GitHub Action, so this particular example demonstrates some of the ease of porting open source GitHub Actions to GitLab CI/CD components. A best practice aspect to many of my components is to always link to working example code with the component in action. This also allows you to do easy testing when performing updates.",[72,150,152,153],{"id":151},"_7-kaniko","7. ",[22,154,157],{"href":155,"rel":156},"https://gitlab.com/explore/catalog/guided-explorations/ci-components/kaniko",[],"Kaniko",[12,159,160],{},"Kaniko is a container that can build containers without Docker-in-Docker (DinD) privileged mode requirement. This component supports many OpenContainers labels and multi-arch builds.",[72,162,164,165],{"id":163},"_8-ci-component-publishing-utilities","8. ",[22,166,169],{"href":167,"rel":168},"https://gitlab.com/explore/catalog/guided-explorations/ci-components/ci-component-pub",[],"CI Component Publishing Utilities",[12,171,172,173,175],{},"As I built more components, I noticed that my \"component publishing CI code\" was being duplicated many times - and that makes it a candidate for becoming a component itself. All the other components here leverage this component. It also uses components itself, so it uses ",[47,174,104],{}," to get the next version.",[12,177,178,179,181],{},"And if you're wondering, yes, CI Component Publishing Utilities publishes itself. In many of my components I have expanded the standard \"Inputs\" README section to \"Inputs and Configuration\" and I have added a column to show whether configurations are happening via inputs or variables. While you generally want to favor inputs, there are times when variables give more flexibility or you just want to document that the user can get perform key configurations of the underlying utilities via environment variables that the utility already supports. CI Component Publishing Utilities also uses the ",[47,180,157],{}," CI component to build a container with the same version if it finds a Dockerfile at the root of your project (or you tell it where one is with a variable). This synchronizes the version of components and containers that support them. It also handles multi-arch container builds - see the documentation linked above to learn more!",[64,183,185],{"id":184},"getting-started-with-component-templates","Getting started with component templates",[12,187,188],{},"The Hello World components function as my own personal templates for starting a new component. They incorporate the CI Component Publishing Utilities and a reasonably good README.",[12,190,191,192,195,196,199],{},"For components that contain only CI code, I start by copying the source of ",[22,193,80],{"href":78,"rel":194},[]," and for ones that require a container, I start with ",[22,197,92],{"href":90,"rel":198},[],". I generally copy just the source into a new project so that I have a clean commit history.",[12,201,202],{},"When I feel the component is stable and well developed I do a manual pipeline run and force the version to 1.1.0 or greater. The CI Component Publishing Utilities will then auto-increment the version from there.",[64,204,206],{"id":205},"ci-component-builders-guides-and-practices","CI component Builders Guides and practices",[12,208,209,214,215,220,221,225,226,231],{},[22,210,213],{"href":211,"rel":212},"https://gitlab.com/guided-explorations/ci-components/gitlab-profile",[],"Darwins CI Component Builders Guide"," - I was also interested in publishing my approach to building components and what better way to get visibility than as a CI/CD component? BTW, the ",[22,216,219],{"href":217,"rel":218},"https://docs.gitlab.com/ci/components/",[],"GitLab Pipeline Authoring"," team that created the CI/CD component architecture and ",[22,222,224],{"href":33,"rel":223},[],"CI/CD Catalog"," has some great best practices published at ",[22,227,230],{"href":228,"rel":229},"https://docs.gitlab.com/ci/components/#best-practices",[],"CI components best practices",". The practices I publish reference these ones, but I also have quite a few I follow that are specific to my own lessons learned.",[64,233,235],{"id":234},"finding-the-cicd-components-and-their-sources","Finding the CI/CD components and their sources",[12,237,238,239,242,243,248],{},"The ",[22,240,35],{"href":33,"rel":241},[]," is still undergoing innovation in searchability. However, the description from the source project is free-form searchable, so by including standard text in the descriptions of all my component source projects, I have created the ability for users to ",[22,244,247],{"href":245,"rel":246},"https://gitlab.com/explore/catalog?search=Part+of+the+DarwinJS+Builder+Component+Library",[],"find all of the ones I've created in the catalog",".",[12,250,251],{},"To make my component source findable regardless of its location on GitLab.com:",[41,253,254,262],{},[44,255,256,257,248],{},"I add a repository topic to all the projects called ",[22,258,261],{"href":259,"rel":260},"https://gitlab.com/explore/projects/topics/DarwinJS+Component+Builder+Libary",[],"DarwinJS Component Builder Library",[44,263,264,265,248],{},"I tag with the organic tag I found called ",[22,266,269],{"href":267,"rel":268},"https://gitlab.com/explore/projects/topics/GitLab+CICD+Components",[],[109,270,271],{},"GitLab CICD Components",[12,273,274],{},"Both of the above techniques can help you provide an index to your components and their source if you are inclined to do so.",[12,276,277],{},"I hope that my CI/CD component building journey will be helpful to you now and in the future.",[279,280,281,284],"blockquote",{},[12,282,283],{},"Learn more about the CI/CD Catalog and components:",[41,285,286,292,299,305],{},[44,287,288],{},[22,289,291],{"href":33,"rel":290},[],"CI/CD Catalog goes GA: No more building pipelines from scratch",[44,293,294],{},[22,295,298],{"href":296,"rel":297},"https://about.gitlab.com/blog/faq-gitlab-ci-cd-catalog/",[],"FAQ: GitLab CI/CD Catalog",[44,300,301],{},[22,302,304],{"href":217,"rel":303},[],"Documentation: CI/CD components and CI/CD Catalog",[44,306,307],{},[22,308,311],{"href":309,"rel":310},"https://about.gitlab.com/blog/introducing-ci-components/",[],"Introducing CI/CD components and how to use them in GitLab",{"title":313,"searchDepth":314,"depth":314,"links":315},"",2,[316,335,336,337],{"id":66,"depth":314,"text":67,"children":317},[318,321,323,325,327,329,331,333],{"id":74,"depth":319,"text":320},3,"1. Hello World",{"id":86,"depth":319,"text":322},"2. Hello World Container",{"id":98,"depth":319,"text":324},"3. GitVersion Ultimate Auto Semversioning",{"id":115,"depth":319,"text":326},"4. Amazon CodeGuru Secure SAST Scanner",{"id":127,"depth":319,"text":328},"5. Checkov IaC SAST",{"id":139,"depth":319,"text":330},"6. Super-Linter",{"id":151,"depth":319,"text":332},"7. Kaniko",{"id":163,"depth":319,"text":334},"8. CI Component Publishing Utilities",{"id":184,"depth":314,"text":185},{"id":205,"depth":314,"text":206},{"id":234,"depth":314,"text":235},"open-source","2024-06-04","Learn how a creator of shared, includable templates upskilled by migrating the templates to GitLab CI/CD components and the CI/CD Catalog.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663857/Blog/Hero%20Images/blog-image-template-1800x945__12_.png",{},true,"/en-us/blog/a-ci-component-builders-journey",{"title":5,"description":340,"ogTitle":5,"ogDescription":340,"noIndex":343,"ogImage":344,"ogUrl":349,"ogSiteName":350,"ogType":351,"canonicalUrls":349},"https://about.gitlab.com/blog/a-ci-component-builders-journey","https://about.gitlab.com","article","a-ci-component-builders-journey","en-us/blog/a-ci-component-builders-journey",[355,356,357],"CI/CD","CI","CD","BlogPost","pErKZfBwZ3NCWnUcnyM3nrU5NPcxO2mVa7hNfAhXaos",{"logo":361,"freeTrial":366,"sales":371,"login":376,"items":381,"search":707,"minimal":738,"duo":757,"switchNav":766,"pricingDeployment":777},{"config":362},{"href":363,"dataGaName":364,"dataGaLocation":365},"/","gitlab logo","header",{"text":367,"config":368},"Get free trial",{"href":369,"dataGaName":370,"dataGaLocation":365},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":372,"config":373},"Request a demo",{"href":374,"dataGaName":375,"dataGaLocation":365},"/sales/?contact-topic=request-demo","sales",{"text":377,"config":378},"Sign in",{"href":379,"dataGaName":380,"dataGaLocation":365},"https://gitlab.com/users/sign_in/","sign in",[382,411,510,515,629,685],{"text":383,"config":384,"menu":386},"Platform",{"dataNavLevelOne":385},"platform",{"type":387,"columns":388},"cards",[389,395,403],{"title":383,"description":390,"link":391},"The intelligent orchestration platform for DevSecOps",{"text":392,"config":393},"Explore our Platform",{"href":394,"dataGaName":385,"dataGaLocation":365},"/platform/",{"title":396,"description":397,"link":398},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":399,"config":400},"Meet GitLab Duo",{"href":401,"dataGaName":402,"dataGaLocation":365},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":404,"description":405,"link":406},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":407,"config":408},"Learn more",{"href":409,"dataGaName":410,"dataGaLocation":365},"/why-gitlab/","why gitlab",{"text":412,"left":346,"config":413,"menu":415},"Product",{"dataNavLevelOne":414},"solutions",{"type":416,"link":417,"columns":421,"feature":489},"lists",{"text":418,"config":419},"View all Solutions",{"href":420,"dataGaName":414,"dataGaLocation":365},"/solutions/",[422,445,468],{"title":423,"description":424,"link":425,"items":430},"Automation","CI/CD and automation to accelerate deployment",{"config":426},{"icon":427,"href":428,"dataGaName":429,"dataGaLocation":365},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[431,434,437,441],{"text":355,"config":432},{"href":433,"dataGaLocation":365,"dataGaName":355},"/solutions/continuous-integration/",{"text":396,"config":435},{"href":401,"dataGaLocation":365,"dataGaName":436},"gitlab duo agent platform - product menu",{"text":438,"config":439},"Source Code Management",{"href":440,"dataGaLocation":365,"dataGaName":438},"/solutions/source-code-management/",{"text":442,"config":443},"Automated Software Delivery",{"href":428,"dataGaLocation":365,"dataGaName":444},"Automated software delivery",{"title":446,"description":447,"link":448,"items":453},"Security","Deliver code faster without compromising security",{"config":449},{"href":450,"dataGaName":451,"dataGaLocation":365,"icon":452},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[454,458,463],{"text":455,"config":456},"Application Security Testing",{"href":450,"dataGaName":457,"dataGaLocation":365},"Application security testing",{"text":459,"config":460},"Software Supply Chain Security",{"href":461,"dataGaLocation":365,"dataGaName":462},"/solutions/supply-chain/","Software supply chain security",{"text":464,"config":465},"Software Compliance",{"href":466,"dataGaName":467,"dataGaLocation":365},"/solutions/software-compliance/","software compliance",{"title":469,"link":470,"items":475},"Measurement",{"config":471},{"icon":472,"href":473,"dataGaName":474,"dataGaLocation":365},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[476,480,484],{"text":477,"config":478},"Visibility & Measurement",{"href":473,"dataGaLocation":365,"dataGaName":479},"Visibility and Measurement",{"text":481,"config":482},"Value Stream Management",{"href":483,"dataGaLocation":365,"dataGaName":481},"/solutions/value-stream-management/",{"text":485,"config":486},"Analytics & Insights",{"href":487,"dataGaLocation":365,"dataGaName":488},"/solutions/analytics-and-insights/","Analytics and insights",{"title":490,"type":416,"items":491},"GitLab for",[492,498,504],{"text":493,"config":494},"Enterprise",{"icon":495,"href":496,"dataGaLocation":365,"dataGaName":497},"Building","/enterprise/","enterprise",{"text":499,"config":500},"Small Business",{"icon":501,"href":502,"dataGaLocation":365,"dataGaName":503},"Work","/small-business/","small business",{"text":505,"config":506},"Public Sector",{"icon":507,"href":508,"dataGaLocation":365,"dataGaName":509},"Organization","/solutions/public-sector/","public sector",{"text":511,"config":512},"Pricing",{"href":513,"dataGaName":514,"dataGaLocation":365,"dataNavLevelOne":514},"/pricing/","pricing",{"text":516,"config":517,"menu":519},"Resources",{"dataNavLevelOne":518},"resources",{"type":416,"link":520,"columns":524,"feature":618},{"text":521,"config":522},"View all resources",{"href":523,"dataGaName":518,"dataGaLocation":365},"/resources/",[525,558,585],{"title":526,"items":527},"Getting started",[528,533,538,543,548,553],{"text":529,"config":530},"Install",{"href":531,"dataGaName":532,"dataGaLocation":365},"/install/","install",{"text":534,"config":535},"Quick start guides",{"href":536,"dataGaName":537,"dataGaLocation":365},"/get-started/","quick setup checklists",{"text":539,"config":540},"Learn",{"href":541,"dataGaLocation":365,"dataGaName":542},"https://university.gitlab.com/","learn",{"text":544,"config":545},"Product documentation",{"href":546,"dataGaName":547,"dataGaLocation":365},"https://docs.gitlab.com/","product documentation",{"text":549,"config":550},"Best practice videos",{"href":551,"dataGaName":552,"dataGaLocation":365},"/getting-started-videos/","best practice videos",{"text":554,"config":555},"Integrations",{"href":556,"dataGaName":557,"dataGaLocation":365},"/integrations/","integrations",{"title":559,"items":560},"Discover",[561,566,571,576,580],{"text":562,"config":563},"Customer success stories",{"href":564,"dataGaName":565,"dataGaLocation":365},"/customers/","customer success stories",{"text":567,"config":568},"Blog",{"href":569,"dataGaName":570,"dataGaLocation":365},"/blog/","blog",{"text":572,"config":573},"Demo Hub",{"href":574,"dataGaName":575,"dataGaLocation":365},"/demo-hub/","demo hub",{"text":577,"config":578},"The Source",{"href":579,"dataGaName":570,"dataGaLocation":365},"/the-source/",{"text":581,"config":582},"Remote",{"href":583,"dataGaName":584,"dataGaLocation":365},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":586,"items":587},"Connect",[588,593,598,603,608,613],{"text":589,"config":590},"GitLab Services",{"href":591,"dataGaName":592,"dataGaLocation":365},"/services/","services",{"text":594,"config":595},"Contribute",{"href":596,"dataGaName":597,"dataGaLocation":365},"https://contributors.gitlab.com","contribute",{"text":599,"config":600},"Community",{"href":601,"dataGaName":602,"dataGaLocation":365},"/community/","community",{"text":604,"config":605},"Forum",{"href":606,"dataGaName":607,"dataGaLocation":365},"https://forum.gitlab.com/","forum",{"text":609,"config":610},"Events",{"href":611,"dataGaName":612,"dataGaLocation":365},"/events/","events",{"text":614,"config":615},"Partners",{"href":616,"dataGaName":617,"dataGaLocation":365},"/partners/","partners",{"config":619,"title":622,"text":623,"link":624},{"background":620,"textColor":621},"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":625,"config":626},"Read the latest",{"href":627,"dataGaName":628,"dataGaLocation":365},"/whats-new/","whats new",{"text":630,"config":631,"menu":633},"Company",{"dataNavLevelOne":632},"company",{"type":416,"columns":634},[635],{"items":636},[637,642,648,650,655,660,665,670,675,680],{"text":638,"config":639},"About",{"href":640,"dataGaName":641,"dataGaLocation":365},"/company/","about",{"text":643,"config":644,"footerGa":647},"Jobs",{"href":645,"dataGaName":646,"dataGaLocation":365},"/jobs/","jobs",{"dataGaName":646},{"text":609,"config":649},{"href":611,"dataGaName":612,"dataGaLocation":365},{"text":651,"config":652},"Leadership",{"href":653,"dataGaName":654,"dataGaLocation":365},"/company/team/e-group/","leadership",{"text":656,"config":657},"Handbook",{"href":658,"dataGaName":659,"dataGaLocation":365},"https://handbook.gitlab.com/","handbook",{"text":661,"config":662},"Investor relations",{"href":663,"dataGaName":664,"dataGaLocation":365},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":666,"config":667},"Trust Center",{"href":668,"dataGaName":669,"dataGaLocation":365},"/security/","trust center",{"text":671,"config":672},"AI Transparency Center",{"href":673,"dataGaName":674,"dataGaLocation":365},"/ai-transparency-center/","ai transparency center",{"text":676,"config":677},"Newsletter",{"href":678,"dataGaName":679,"dataGaLocation":365},"/company/contact/#contact-forms","newsletter",{"text":681,"config":682},"Press",{"href":683,"dataGaName":684,"dataGaLocation":365},"/press/","press",{"text":686,"config":687,"menu":688},"Contact us",{"dataNavLevelOne":632},{"type":416,"columns":689},[690],{"items":691},[692,697,702],{"text":693,"config":694},"Talk to sales",{"href":695,"dataGaName":696,"dataGaLocation":365},"/sales/","talk to sales",{"text":698,"config":699},"Support portal",{"href":700,"dataGaName":701,"dataGaLocation":365},"https://support.gitlab.com/hc/en-us","support portal",{"text":703,"config":704},"Customer portal",{"href":705,"dataGaName":706,"dataGaLocation":365},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":708,"login":709,"suggestions":716},"Close",{"text":710,"link":711},"To search repositories and projects, login to",{"text":712,"config":713},"gitlab.com",{"href":379,"dataGaName":714,"dataGaLocation":715},"search login","search",{"text":717,"default":718},"Suggestions",[719,721,725,727,731,735],{"text":396,"config":720},{"href":401,"dataGaName":396,"dataGaLocation":715},{"text":722,"config":723},"Code Suggestions (AI)",{"href":724,"dataGaName":722,"dataGaLocation":715},"/solutions/code-suggestions/",{"text":355,"config":726},{"href":433,"dataGaName":355,"dataGaLocation":715},{"text":728,"config":729},"GitLab on AWS",{"href":730,"dataGaName":728,"dataGaLocation":715},"/partners/technology-partners/aws/",{"text":732,"config":733},"GitLab on Google Cloud",{"href":734,"dataGaName":732,"dataGaLocation":715},"/partners/technology-partners/google-cloud-platform/",{"text":736,"config":737},"Why GitLab?",{"href":409,"dataGaName":736,"dataGaLocation":715},{"freeTrial":739,"mobileIcon":744,"desktopIcon":749,"secondaryButton":752},{"text":740,"config":741},"Start free trial",{"href":742,"dataGaName":370,"dataGaLocation":743},"https://gitlab.com/-/trials/new/","nav",{"altText":745,"config":746},"Gitlab Icon",{"src":747,"dataGaName":748,"dataGaLocation":743},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":745,"config":750},{"src":751,"dataGaName":748,"dataGaLocation":743},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":753,"config":754},"Get Started",{"href":755,"dataGaName":756,"dataGaLocation":743},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":758,"mobileIcon":762,"desktopIcon":764},{"text":759,"config":760},"Learn more about GitLab Duo",{"href":401,"dataGaName":761,"dataGaLocation":743},"gitlab duo",{"altText":745,"config":763},{"src":747,"dataGaName":748,"dataGaLocation":743},{"altText":745,"config":765},{"src":751,"dataGaName":748,"dataGaLocation":743},{"button":767,"mobileIcon":772,"desktopIcon":774},{"text":768,"config":769},"/switch",{"href":770,"dataGaName":771,"dataGaLocation":743},"#contact","switch",{"altText":745,"config":773},{"src":747,"dataGaName":748,"dataGaLocation":743},{"altText":745,"config":775},{"src":776,"dataGaName":748,"dataGaLocation":743},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":778,"mobileIcon":783,"desktopIcon":785},{"text":779,"config":780},"Back to pricing",{"href":513,"dataGaName":781,"dataGaLocation":743,"icon":782},"back to pricing","GoBack",{"altText":745,"config":784},{"src":747,"dataGaName":748,"dataGaLocation":743},{"altText":745,"config":786},{"src":751,"dataGaName":748,"dataGaLocation":743},{"title":788,"titleMobile":789,"button":790,"config":795},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":407,"config":791},{"href":792,"dataGaName":793,"dataGaLocation":794},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":796,"disabled":343},"release",{"data":798},{"text":799,"source":800,"edit":806,"contribute":811,"config":816,"items":821,"minimal":1031},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":801,"config":802},"View page source",{"href":803,"dataGaName":804,"dataGaLocation":805},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":807,"config":808},"Edit this page",{"href":809,"dataGaName":810,"dataGaLocation":805},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":812,"config":813},"Please contribute",{"href":814,"dataGaName":815,"dataGaLocation":805},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":817,"facebook":818,"youtube":819,"linkedin":820},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[822,869,923,967,999],{"title":511,"links":823,"subMenu":838},[824,828,833],{"text":825,"config":826},"View plans",{"href":513,"dataGaName":827,"dataGaLocation":805},"view plans",{"text":829,"config":830},"Why Premium?",{"href":831,"dataGaName":832,"dataGaLocation":805},"/pricing/premium/","why premium",{"text":834,"config":835},"Why Ultimate?",{"href":836,"dataGaName":837,"dataGaLocation":805},"/pricing/ultimate/","why ultimate",[839],{"title":840,"links":841},"Contact Us",[842,845,847,849,854,859,864],{"text":843,"config":844},"Contact sales",{"href":695,"dataGaName":375,"dataGaLocation":805},{"text":698,"config":846},{"href":700,"dataGaName":701,"dataGaLocation":805},{"text":703,"config":848},{"href":705,"dataGaName":706,"dataGaLocation":805},{"text":850,"config":851},"Status",{"href":852,"dataGaName":853,"dataGaLocation":805},"https://status.gitlab.com/","status",{"text":855,"config":856},"Terms of use",{"href":857,"dataGaName":858,"dataGaLocation":805},"/terms/","terms of use",{"text":860,"config":861},"Privacy statement",{"href":862,"dataGaName":863,"dataGaLocation":805},"/privacy/","privacy statement",{"text":865,"config":866},"Cookie preferences",{"dataGaName":867,"dataGaLocation":805,"id":868,"isOneTrustButton":346},"cookie preferences","ot-sdk-btn",{"title":412,"links":870,"subMenu":879},[871,875],{"text":872,"config":873},"DevSecOps platform",{"href":394,"dataGaName":874,"dataGaLocation":805},"devsecops platform",{"text":876,"config":877},"AI-Assisted Development",{"href":401,"dataGaName":878,"dataGaLocation":805},"ai-assisted development",[880],{"title":881,"links":882},"Topics",[883,888,893,898,903,908,913,918],{"text":884,"config":885},"CICD",{"href":886,"dataGaName":887,"dataGaLocation":805},"/topics/ci-cd/","cicd",{"text":889,"config":890},"GitOps",{"href":891,"dataGaName":892,"dataGaLocation":805},"/topics/gitops/","gitops",{"text":894,"config":895},"DevOps",{"href":896,"dataGaName":897,"dataGaLocation":805},"/topics/devops/","devops",{"text":899,"config":900},"Version Control",{"href":901,"dataGaName":902,"dataGaLocation":805},"/topics/version-control/","version control",{"text":904,"config":905},"DevSecOps",{"href":906,"dataGaName":907,"dataGaLocation":805},"/topics/devsecops/","devsecops",{"text":909,"config":910},"Cloud Native",{"href":911,"dataGaName":912,"dataGaLocation":805},"/topics/cloud-native/","cloud native",{"text":914,"config":915},"AI for Coding",{"href":916,"dataGaName":917,"dataGaLocation":805},"/topics/devops/ai-for-coding/","ai for coding",{"text":919,"config":920},"Agentic AI",{"href":921,"dataGaName":922,"dataGaLocation":805},"/topics/agentic-ai/","agentic ai",{"title":924,"links":925},"Solutions",[926,928,930,935,939,942,946,949,951,954,957,962],{"text":455,"config":927},{"href":450,"dataGaName":455,"dataGaLocation":805},{"text":444,"config":929},{"href":428,"dataGaName":429,"dataGaLocation":805},{"text":931,"config":932},"Agile development",{"href":933,"dataGaName":934,"dataGaLocation":805},"/solutions/agile-delivery/","agile delivery",{"text":936,"config":937},"SCM",{"href":440,"dataGaName":938,"dataGaLocation":805},"source code management",{"text":884,"config":940},{"href":433,"dataGaName":941,"dataGaLocation":805},"continuous integration & delivery",{"text":943,"config":944},"Value stream management",{"href":483,"dataGaName":945,"dataGaLocation":805},"value stream management",{"text":889,"config":947},{"href":948,"dataGaName":892,"dataGaLocation":805},"/solutions/gitops/",{"text":493,"config":950},{"href":496,"dataGaName":497,"dataGaLocation":805},{"text":952,"config":953},"Small business",{"href":502,"dataGaName":503,"dataGaLocation":805},{"text":955,"config":956},"Public sector",{"href":508,"dataGaName":509,"dataGaLocation":805},{"text":958,"config":959},"Education",{"href":960,"dataGaName":961,"dataGaLocation":805},"/solutions/education/","education",{"text":963,"config":964},"Financial services",{"href":965,"dataGaName":966,"dataGaLocation":805},"/solutions/finance/","financial services",{"title":516,"links":968},[969,971,973,975,978,980,983,985,987,989,991,993,995,997],{"text":529,"config":970},{"href":531,"dataGaName":532,"dataGaLocation":805},{"text":534,"config":972},{"href":536,"dataGaName":537,"dataGaLocation":805},{"text":539,"config":974},{"href":541,"dataGaName":542,"dataGaLocation":805},{"text":544,"config":976},{"href":546,"dataGaName":977,"dataGaLocation":805},"docs",{"text":567,"config":979},{"href":569,"dataGaName":570,"dataGaLocation":805},{"text":981,"config":982},"What's new",{"href":627,"dataGaName":628,"dataGaLocation":805},{"text":562,"config":984},{"href":564,"dataGaName":565,"dataGaLocation":805},{"text":581,"config":986},{"href":583,"dataGaName":584,"dataGaLocation":805},{"text":589,"config":988},{"href":591,"dataGaName":592,"dataGaLocation":805},{"text":594,"config":990},{"href":596,"dataGaName":597,"dataGaLocation":805},{"text":599,"config":992},{"href":601,"dataGaName":602,"dataGaLocation":805},{"text":604,"config":994},{"href":606,"dataGaName":607,"dataGaLocation":805},{"text":609,"config":996},{"href":611,"dataGaName":612,"dataGaLocation":805},{"text":614,"config":998},{"href":616,"dataGaName":617,"dataGaLocation":805},{"title":630,"links":1000},[1001,1003,1005,1007,1009,1011,1015,1020,1022,1024,1026],{"text":638,"config":1002},{"href":640,"dataGaName":632,"dataGaLocation":805},{"text":643,"config":1004},{"href":645,"dataGaName":646,"dataGaLocation":805},{"text":651,"config":1006},{"href":653,"dataGaName":654,"dataGaLocation":805},{"text":656,"config":1008},{"href":658,"dataGaName":659,"dataGaLocation":805},{"text":661,"config":1010},{"href":663,"dataGaName":664,"dataGaLocation":805},{"text":1012,"config":1013},"Sustainability",{"href":1014,"dataGaName":1012,"dataGaLocation":805},"/sustainability/",{"text":1016,"config":1017},"Diversity, inclusion and belonging (DIB)",{"href":1018,"dataGaName":1019,"dataGaLocation":805},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":666,"config":1021},{"href":668,"dataGaName":669,"dataGaLocation":805},{"text":676,"config":1023},{"href":678,"dataGaName":679,"dataGaLocation":805},{"text":681,"config":1025},{"href":683,"dataGaName":684,"dataGaLocation":805},{"text":1027,"config":1028},"Modern Slavery Transparency Statement",{"href":1029,"dataGaName":1030,"dataGaLocation":805},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1032},[1033,1036,1039],{"text":1034,"config":1035},"Terms",{"href":857,"dataGaName":858,"dataGaLocation":805},{"text":1037,"config":1038},"Cookies",{"dataGaName":867,"dataGaLocation":805,"id":868,"isOneTrustButton":346},{"text":1040,"config":1041},"Privacy",{"href":862,"dataGaName":863,"dataGaLocation":805},[1043],{"id":1044,"title":7,"body":342,"config":1045,"content":1047,"description":342,"extension":1053,"meta":1054,"navigation":346,"path":1055,"seo":1056,"stem":1057,"__hash__":1058},"blogAuthors/en-us/blog/authors/darwin-sanoy.yml",{"template":1046},"BlogAuthor",{"role":1048,"name":7,"config":1049},"Field Chief Cloud Architect",{"headshot":1050,"linkedin":1051,"ctfId":1052},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659751/Blog/Author%20Headshots/Darwin-Sanoy-headshot-395-square-gitlab-teampage-avatar.png","https://linkedin.com/in/darwinsanoy","DarwinJS","yml",{},"/en-us/blog/authors/darwin-sanoy",{},"en-us/blog/authors/darwin-sanoy","UkMMwmU5o2e6Y-wBltA9E_z96LvHuB-bG6VW9DsLzIY",[1060,1068,1076],{"title":1061,"description":1062,"heroImage":1063,"category":338,"date":1064,"authors":1065,"slug":1067,"externalUrl":342},"What's new in Git 2.55.0?","Learn about the new features and changes in Git 2.55, including a new git-history(1) fixup command, an fsmonitor daemon for Linux, pushing to remote groups, and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782732487/ztwgrvlolpifo01vj8qc.png","2026-06-29",[1066],"Toon Claes","whats-new-in-git-2-55-0",{"title":1069,"description":1070,"heroImage":1071,"category":338,"date":1072,"authors":1073,"slug":1075,"externalUrl":342},"GitLab AI Hackathon 2026: Meet the winners","Nearly 7,000 developers built 600+ AI agents and flows on GitLab Duo Agent Platform. Find out who won and what they created.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1776457632/llddiylsgwuze0u1rjks.png","2026-04-22",[1074],"Nick Veenhof","gitlab-ai-hackathon-2026-meet-the-winners",{"title":1077,"description":1078,"heroImage":1079,"category":338,"date":1080,"authors":1081,"slug":1083,"externalUrl":342},"What’s new in Git 2.54.0?","Learn about release contributions, including new repository maintenance, a new command to edit commit history, a replacement for git-sizer(1), and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782734716/ztwgrvlolpifo01vj8qc.png","2026-04-20",[1082],"Patrick Steinhardt","whats-new-in-git-2-54-0",{"promotions":1085},[1086,1100,1112,1124],{"id":1087,"categories":1088,"header":1090,"text":1091,"button":1092,"image":1097},"ai-modernization",[1089],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1093,"config":1094},"Get your AI maturity score",{"href":1095,"dataGaName":1096,"dataGaLocation":570},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1098},{"src":1099},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1101,"categories":1102,"header":1104,"text":1091,"button":1105,"image":1109},"devops-modernization",[1103,907],"product","Are you just managing tools or shipping innovation?",{"text":1106,"config":1107},"Get your DevOps maturity score",{"href":1108,"dataGaName":1096,"dataGaLocation":570},"/assessments/devops-modernization-assessment/",{"config":1110},{"src":1111},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1113,"categories":1114,"header":1116,"text":1091,"button":1117,"image":1121},"security-modernization",[1115],"security","Are you trading speed for security?",{"text":1118,"config":1119},"Get your security maturity score",{"href":1120,"dataGaName":1096,"dataGaLocation":570},"/assessments/security-modernization-assessment/",{"config":1122},{"src":1123},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1125,"paths":1126,"header":1129,"text":1130,"button":1131,"image":1136},"github-azure-migration",[1127,1128],"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":1132,"config":1133},"See how GitLab compares to GitHub",{"href":1134,"dataGaName":1135,"dataGaLocation":570},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1137},{"src":1111},{"header":1139,"blurb":1140,"button":1141,"secondaryButton":1146},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1142,"config":1143},"Get your free trial",{"href":1144,"dataGaName":370,"dataGaLocation":1145},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":843,"config":1147},{"href":695,"dataGaName":375,"dataGaLocation":1145},1786803760995]