[{"data":1,"prerenderedAt":1100},["ShallowReactive",2],{"/blog/code-counting-in-gitlab":3,"navigation-en-us":311,"banner-en-us":739,"footer-en-us":749,"blog-post-authors-en-us-Darwin Sanoy":993,"blog-related-posts-en-us-code-counting-in-gitlab":1010,"blog-promotions-en-us":1036,"next-steps-en-us":1090},{"id":4,"title":5,"authors":6,"body":8,"category":289,"date":290,"description":291,"extension":292,"externalUrl":293,"faq":293,"featured":294,"heroImage":295,"meta":296,"navigation":297,"path":298,"seo":299,"slug":303,"stem":304,"tags":305,"template":309,"updatedDate":293,"__hash__":310},"blogPosts/en-us/blog/code-counting-in-gitlab.md","Lightning fast code counting for better code management intelligence",[7],"Darwin Sanoy",{"type":9,"value":10,"toc":277},"minimark",[11,15,18,21,26,36,70,73,77,80,89,106,110,113,157,161,164,167,174,181,185,197,200,204,207,210,224,228,231,240,249,252,260],[12,13,14],"p",{},"One of the earliest forms of intelligence was to simply answer the question “How many?”. Counting is one of the first things that we learn as a child. As we grow older, we come to see this deceptively simple concept as somewhat childish. Yet, upon the concept of counting, the entire discipline of statistics is founded. In turn, every discipline that benefits from statistics owes a debt of gratitude to the very humble concept of counting.",[12,16,17],{},"Many of the massive data lakes we keep are essentially vast amounts of counting. Using artificial intelligence to analyze this data, we frequently find insights we were not expecting. So it would seem that counting is somewhat of a fractal concept – it’s deceptively simple, but, when compounded, generates delightful things.",[12,19,20],{},"So if we have a thing we are trying to be more intelligent about, our first endeavor might be to count it. Let’s see how to apply that to our code stored in GitLab.",[22,23,25],"h3",{"id":24},"why-developers-count-code","Why developers count code",[12,27,28,29,35],{},"The following list is from real-world scenarios. Many of them are also asserted in Ben Boyter’s blog post ",[30,31,34],"a",{"href":32,"rel":33},"https://boyter.org/posts/why-count-lines-of-code/",[],"Why count lines of code?",". Their enumeration here is not an endorsement of the validity or accuracy of code counting for the claimed benefit and the fundamental assumptions of such models are not stated. Because code counting is essentially a form of modeling, it is also subject to George Box’s axiom: “All models are wrong, but some are useful.”",[37,38,39,43,46,55,58,61,64,67],"ul",{},[40,41,42],"li",{},"Showing the languages in a repository using an absolute metric like source lines of code helps to quickly assess if one can contribute to the project, given their own talents.",[40,44,45],{},"Cost assessment for anything which charges by “lines of code” (some code scanning and development tools may charge this way).",[40,47,48,49,54],{},"Although ",[30,50,53],{"href":51,"rel":52},"https://gitlab.com/gitlab-org/gitlab/-/issues/371038",[],"research"," shows that lines of code are not a good metric for measuring contribution, some developers have gotten used to seeing lines of code per contributor.",[40,56,57],{},"Code base shrinkage as a measure of good architecture (simplification).",[40,59,60],{},"Anything where the complexity of code affects project agility and costs. For instance, assessing and reporting status on migrating a code base to a new language.",[40,62,63],{},"Staffing a development team – understanding what language competencies are needed across the team and in what relative proportion to each other or understanding that for the entire organization’s codebase.",[40,65,66],{},"IT tooling decisions to support the needs of an organization given the most used coding languages across all repositories in the org.",[40,68,69],{},"Assessment of tech debt.",[12,71,72],{},"While it is easy to create bad models with any of the above counts, the focus of this post is to get some good counts from which you can carefully build a model.",[22,74,76],{"id":75},"toolsmithing-gitlab-ci-a-working-example-as-a-shared-ci-library","Toolsmithing GitLab CI: A working example as a shared CI library",[12,78,79],{},"The easiest way to differentiate between a “toolized” and “templated” solution is that you can simply and easily reuse this exact code without needing to change it. Many formal coding languages have the concept of shared libraries or dependencies that are essentially toolized. A templated solution consists of a starting point that you customize and then have to manage the code yourself. These can function as scaffolding for a starting point for an entire project or snippets of code that do a specific function. The fundamental difference is that when you use a template, you end up owning and managing the resultant code going forward.",[12,81,82,83,88],{},"In GitLab CI, we can create our own tooling or dependencies with a few tricks stolen from ",[30,84,87],{"href":85,"rel":86},"https://docs.gitlab.com/topics/autodevops/",[],"Auto DevOps",". These tricks are:",[90,91,92,95,98],"ol",{},[40,93,94],{},"Use includes to reference the shared managed library code (this creates a “dependency” on code that is being managed outside of your own).",[40,96,97],{},"The includable code must be written like a function where all needed inputs are either passed in, or can be collected from the environment. No hard coding is allowed because that means you’ve created a template which can’t be depended upon directly.",[40,99,100,101,105],{},"Use GitLab CI ‘functions’. I am coining this term to indicate that in GitLab you can precede a job name with a “.” (dot) and it will not be executed when it is read. Then you can create a new job using all the code in the “dot named” job and add variables by using the ",[102,103,104],"code",{},"extends:"," command keyword. By using dot named jobs in your includable code, the developer consuming the “managed shared CI dependency” can decide when, where, and how to call the toolized code.",[22,107,109],{"id":108},"the-result-a-code-counting-gitlab-ci-extension","The result: A code-counting GitLab CI extension",[12,111,112],{},"Here are some of the final design attributes of this code counting solution:",[37,114,115,118,127,136,139,142,145,148,151,154],{},[40,116,117],{},"Is extremely fast for the given task.",[40,119,120,121,126],{},"Leverages the Git clone opitimizations lessons contained in this article: ",[30,122,125],{"href":123,"rel":124},"https://acloudguru.com/blog/engineering/how-much-code-do-i-have-a-devsecops-story",[],"How much code do I have? A DevSecOps story",".",[40,128,129,130,135],{},"Uses the ",[30,131,134],{"href":132,"rel":133},"https://github.com/boyter/scc",[],"lightning fast, open source code counting tool SCC"," by Ben Boyter.",[40,137,138],{},"Is implemented as a reusable GitLab CI shared library extension.",[40,140,141],{},"Allows configuration of the file extensions that should not be checked out because they do not include source code to be counted.",[40,143,144],{},"Leverages the GitLab Run Pipeline forms capability.",[40,146,147],{},"Can enumerate and count an entire group hierarchy in GitLab, or be given a stipulated list.",[40,149,150],{},"Uses the runner token to access and read repositories by default, but can be given a specific token.",[40,152,153],{},"Uploads HTML and text artifacts that contain the code counting report.",[40,155,156],{},"Purposely emits the code counting results into CI logs for easy reference.",[22,158,160],{"id":159},"the-output","The output",[12,162,163],{},"Results are shown below in the CI log but they are also captured as an HTML artifact.",[12,165,166],{},"The clone time is also in the log for each project so that it can be verified that the cloning optimizations are making a substantial difference.",[12,168,169,170,126],{},"These particular results are counting all the code in ",[30,171,172],{"href":172,"rel":173},"https://gitlab.com/guided-explorations",[],[12,175,176],{},[177,178],"img",{"alt":179,"src":180},"codecountingcilog","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782398083/blog/Content%20Images/code-counting-in-gitlab/codecountingcilog.png",[22,182,184],{"id":183},"the-code","The code",[12,186,187,188,192,193,126],{},"The code is available in this project: ",[30,189,190],{"href":190,"rel":191},"https://gitlab.com/guided-explorations/code-metrics/ci-cd-extension-scc",[],". You can view the scanning results in the job logs of past runs here: ",[30,194,195],{"href":195,"rel":196},"https://gitlab.com/guided-explorations/code-metrics/ci-cd-extension-scc/-/pipelines",[],[12,198,199],{},"Rather than fail the entire job when a project fails to clone, the job simply logs the error from an attempted clone. This allows review of valid use cases for not being able to clone and obtains as complete of a picture as possible. The cloning error log is uploaded as a job artifact and emitted to the log.",[22,201,203],{"id":202},"innovation-mr-complexity-metrics-extension","Innovation: MR complexity metrics extension",[12,205,206],{},"During a customer engagement I was asked whether there was a way to assess how much change a Merge Request contained and mark it. This was because an operations team was missing their SLAs for deployments due to the amount of change, and, therefore, risk and review could be highly variable. However, since there was no way to estimate this without human eyes on it, MRs with a high degree of change would overrun their SLA when they couldn’t be pre-triaged.",[12,208,209],{},"I wondered if I could use the previously built code counting solution to count diffs and get a rough idea of how much change had occurred in the commits of an MR branch and then apply labels to MRs to give at rough idea of their degree of change as a sort of proxy for how much review time might be required.",[12,211,212,213,218,219,126],{},"It turned out to be plausible and you can review the ",[30,214,217],{"href":215,"rel":216},"https://gitlab.com/guided-explorations/code-metrics/git-diff-revision-activity-metrics",[],"Shared Library in Git Diff Revision Activity Metrics CI EXTENSION"," and see the results in the MRs list of this working example project that uses that code: ",[30,220,223],{"href":221,"rel":222},"https://gitlab.com/guided-explorations/code-metrics/diff-revision-activity-analytics-demo/-/merge_requests",[],"MR list for Diff Revision Activity Analytics DEMO",[22,225,227],{"id":226},"the-value-of-remote-work-water-cooler-conversations","The value of remote work water cooler conversations",[12,229,230],{},"I have to let you know why this blog was written now when this solution has been around for quite a while. You often hear about how working remotely does not allow for water cooler conversations, which in the story you’re told are where real innovation happens.",[12,232,233,234,239],{},"Within GitLab’s ",[30,235,238],{"href":236,"rel":237},"https://handbook.gitlab.com/handbook/company/culture/all-remote/guide/",[],"Remote First culture"," it is expected that anyone in the company can schedule a “coffee chat” with anyone else. The cultural expectation is that this is normal and, unless you are getting an overwhelming number of these requests, that when asked, you will find time to socially connect.",[12,241,242,243,248],{},"I received a coffee chat request from ",[30,244,247],{"href":245,"rel":246},"https://gitlab.com/tlinz",[],"Torsten Linz",", the Senior Product Manager for the Source Code Management group, to chat about my comments and linking of a working example to an issue about code counting that he had become aware of. He also wanted to see if I could help get a copy of it working in his GitLab group.",[12,250,251],{},"During that collaborative time, I discovered that my example was not working because of some major code changes in SCC and because it presumed the GitLab group to be enumerated did not need the counting job to authenticate to prove that it should have access to the projects. While we were collaborating, we fixed these problems and improved the solution to use the SCC binary, rather than depend on working Golang runtimes. After our collaborative session, as I tweaked some more, I did parameter documentation in README.md and debugged the ability to run it either with a group enumeration or a provided list of specific git repos.",[12,253,254,255,126],{},"So I owe big thanks to Torsten and to GitLab’s cultural support for remote first water cooler conversations for improving this working example to the point that it is worth sharing with a broader audience. If you’d like to know more, check out the GitLab handbook page: ",[30,256,259],{"href":257,"rel":258},"https://handbook.gitlab.com/handbook/company/culture/all-remote/informal-communication/",[],"Informal communication in an all-remote environment",[12,261,262],{},[263,264,265,266,271,272],"em",{},"Cover image by ",[30,267,270],{"href":268,"rel":269},"https://unsplash.com/@noaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText",[],"NOAA"," on ",[30,273,276],{"href":274,"rel":275},"https://unsplash.com/s/photos/lightning-fast?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText",[],"Unsplash",{"title":278,"searchDepth":279,"depth":279,"links":280},"",2,[281,283,284,285,286,287,288],{"id":24,"depth":282,"text":25},3,{"id":75,"depth":282,"text":76},{"id":108,"depth":282,"text":109},{"id":159,"depth":282,"text":160},{"id":183,"depth":282,"text":184},{"id":202,"depth":282,"text":203},{"id":226,"depth":282,"text":227},"engineering","2023-02-15","Knowledge of your code composition can come through simple counting of lines of code per language.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682614/Blog/Hero%20Images/noaa-PkHsrwNOfBE-unsplash.jpg",{},true,"/en-us/blog/code-counting-in-gitlab",{"title":5,"description":291,"ogTitle":5,"ogDescription":291,"noIndex":294,"ogImage":295,"ogUrl":300,"ogSiteName":301,"ogType":302,"canonicalUrls":300},"https://about.gitlab.com/blog/code-counting-in-gitlab","https://about.gitlab.com","article","code-counting-in-gitlab","en-us/blog/code-counting-in-gitlab",[306,307,308],"DevOps","solutions architecture","CI","BlogPost","yvsm4Uc_0ZSfHuLZA3O0WkcdS29HXFmFjRpHjvD0GCc",{"logo":312,"freeTrial":317,"sales":322,"login":327,"items":332,"search":659,"minimal":690,"duo":709,"switchNav":718,"pricingDeployment":729},{"config":313},{"href":314,"dataGaName":315,"dataGaLocation":316},"/","gitlab logo","header",{"text":318,"config":319},"Get free trial",{"href":320,"dataGaName":321,"dataGaLocation":316},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":323,"config":324},"Request a demo",{"href":325,"dataGaName":326,"dataGaLocation":316},"/sales/?contact-topic=request-demo","sales",{"text":328,"config":329},"Sign in",{"href":330,"dataGaName":331,"dataGaLocation":316},"https://gitlab.com/users/sign_in/","sign in",[333,362,462,467,581,637],{"text":334,"config":335,"menu":337},"Platform",{"dataNavLevelOne":336},"platform",{"type":338,"columns":339},"cards",[340,346,354],{"title":334,"description":341,"link":342},"The intelligent orchestration platform for DevSecOps",{"text":343,"config":344},"Explore our Platform",{"href":345,"dataGaName":336,"dataGaLocation":316},"/platform/",{"title":347,"description":348,"link":349},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":350,"config":351},"Meet GitLab Duo",{"href":352,"dataGaName":353,"dataGaLocation":316},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":355,"description":356,"link":357},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":358,"config":359},"Learn more",{"href":360,"dataGaName":361,"dataGaLocation":316},"/why-gitlab/","why gitlab",{"text":363,"left":297,"config":364,"menu":366},"Product",{"dataNavLevelOne":365},"solutions",{"type":367,"link":368,"columns":372,"feature":441},"lists",{"text":369,"config":370},"View all Solutions",{"href":371,"dataGaName":365,"dataGaLocation":316},"/solutions/",[373,397,420],{"title":374,"description":375,"link":376,"items":381},"Automation","CI/CD and automation to accelerate deployment",{"config":377},{"icon":378,"href":379,"dataGaName":380,"dataGaLocation":316},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[382,386,389,393],{"text":383,"config":384},"CI/CD",{"href":385,"dataGaLocation":316,"dataGaName":383},"/solutions/continuous-integration/",{"text":347,"config":387},{"href":352,"dataGaLocation":316,"dataGaName":388},"gitlab duo agent platform - product menu",{"text":390,"config":391},"Source Code Management",{"href":392,"dataGaLocation":316,"dataGaName":390},"/solutions/source-code-management/",{"text":394,"config":395},"Automated Software Delivery",{"href":379,"dataGaLocation":316,"dataGaName":396},"Automated software delivery",{"title":398,"description":399,"link":400,"items":405},"Security","Deliver code faster without compromising security",{"config":401},{"href":402,"dataGaName":403,"dataGaLocation":316,"icon":404},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[406,410,415],{"text":407,"config":408},"Application Security Testing",{"href":402,"dataGaName":409,"dataGaLocation":316},"Application security testing",{"text":411,"config":412},"Software Supply Chain Security",{"href":413,"dataGaLocation":316,"dataGaName":414},"/solutions/supply-chain/","Software supply chain security",{"text":416,"config":417},"Software Compliance",{"href":418,"dataGaName":419,"dataGaLocation":316},"/solutions/software-compliance/","software compliance",{"title":421,"link":422,"items":427},"Measurement",{"config":423},{"icon":424,"href":425,"dataGaName":426,"dataGaLocation":316},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[428,432,436],{"text":429,"config":430},"Visibility & Measurement",{"href":425,"dataGaLocation":316,"dataGaName":431},"Visibility and Measurement",{"text":433,"config":434},"Value Stream Management",{"href":435,"dataGaLocation":316,"dataGaName":433},"/solutions/value-stream-management/",{"text":437,"config":438},"Analytics & Insights",{"href":439,"dataGaLocation":316,"dataGaName":440},"/solutions/analytics-and-insights/","Analytics and insights",{"title":442,"type":367,"items":443},"GitLab for",[444,450,456],{"text":445,"config":446},"Enterprise",{"icon":447,"href":448,"dataGaLocation":316,"dataGaName":449},"Building","/enterprise/","enterprise",{"text":451,"config":452},"Small Business",{"icon":453,"href":454,"dataGaLocation":316,"dataGaName":455},"Work","/small-business/","small business",{"text":457,"config":458},"Public Sector",{"icon":459,"href":460,"dataGaLocation":316,"dataGaName":461},"Organization","/solutions/public-sector/","public sector",{"text":463,"config":464},"Pricing",{"href":465,"dataGaName":466,"dataGaLocation":316,"dataNavLevelOne":466},"/pricing/","pricing",{"text":468,"config":469,"menu":471},"Resources",{"dataNavLevelOne":470},"resources",{"type":367,"link":472,"columns":476,"feature":570},{"text":473,"config":474},"View all resources",{"href":475,"dataGaName":470,"dataGaLocation":316},"/resources/",[477,510,537],{"title":478,"items":479},"Getting started",[480,485,490,495,500,505],{"text":481,"config":482},"Install",{"href":483,"dataGaName":484,"dataGaLocation":316},"/install/","install",{"text":486,"config":487},"Quick start guides",{"href":488,"dataGaName":489,"dataGaLocation":316},"/get-started/","quick setup checklists",{"text":491,"config":492},"Learn",{"href":493,"dataGaLocation":316,"dataGaName":494},"https://university.gitlab.com/","learn",{"text":496,"config":497},"Product documentation",{"href":498,"dataGaName":499,"dataGaLocation":316},"https://docs.gitlab.com/","product documentation",{"text":501,"config":502},"Best practice videos",{"href":503,"dataGaName":504,"dataGaLocation":316},"/getting-started-videos/","best practice videos",{"text":506,"config":507},"Integrations",{"href":508,"dataGaName":509,"dataGaLocation":316},"/integrations/","integrations",{"title":511,"items":512},"Discover",[513,518,523,528,532],{"text":514,"config":515},"Customer success stories",{"href":516,"dataGaName":517,"dataGaLocation":316},"/customers/","customer success stories",{"text":519,"config":520},"Blog",{"href":521,"dataGaName":522,"dataGaLocation":316},"/blog/","blog",{"text":524,"config":525},"Demo Hub",{"href":526,"dataGaName":527,"dataGaLocation":316},"/demo-hub/","demo hub",{"text":529,"config":530},"The Source",{"href":531,"dataGaName":522,"dataGaLocation":316},"/the-source/",{"text":533,"config":534},"Remote",{"href":535,"dataGaName":536,"dataGaLocation":316},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":538,"items":539},"Connect",[540,545,550,555,560,565],{"text":541,"config":542},"GitLab Services",{"href":543,"dataGaName":544,"dataGaLocation":316},"/services/","services",{"text":546,"config":547},"Contribute",{"href":548,"dataGaName":549,"dataGaLocation":316},"https://contributors.gitlab.com","contribute",{"text":551,"config":552},"Community",{"href":553,"dataGaName":554,"dataGaLocation":316},"/community/","community",{"text":556,"config":557},"Forum",{"href":558,"dataGaName":559,"dataGaLocation":316},"https://forum.gitlab.com/","forum",{"text":561,"config":562},"Events",{"href":563,"dataGaName":564,"dataGaLocation":316},"/events/","events",{"text":566,"config":567},"Partners",{"href":568,"dataGaName":569,"dataGaLocation":316},"/partners/","partners",{"config":571,"title":574,"text":575,"link":576},{"background":572,"textColor":573},"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":577,"config":578},"Read the latest",{"href":579,"dataGaName":580,"dataGaLocation":316},"/whats-new/","whats new",{"text":582,"config":583,"menu":585},"Company",{"dataNavLevelOne":584},"company",{"type":367,"columns":586},[587],{"items":588},[589,594,600,602,607,612,617,622,627,632],{"text":590,"config":591},"About",{"href":592,"dataGaName":593,"dataGaLocation":316},"/company/","about",{"text":595,"config":596,"footerGa":599},"Jobs",{"href":597,"dataGaName":598,"dataGaLocation":316},"/jobs/","jobs",{"dataGaName":598},{"text":561,"config":601},{"href":563,"dataGaName":564,"dataGaLocation":316},{"text":603,"config":604},"Leadership",{"href":605,"dataGaName":606,"dataGaLocation":316},"/company/team/e-group/","leadership",{"text":608,"config":609},"Handbook",{"href":610,"dataGaName":611,"dataGaLocation":316},"https://handbook.gitlab.com/","handbook",{"text":613,"config":614},"Investor relations",{"href":615,"dataGaName":616,"dataGaLocation":316},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":618,"config":619},"Trust Center",{"href":620,"dataGaName":621,"dataGaLocation":316},"/security/","trust center",{"text":623,"config":624},"AI Transparency Center",{"href":625,"dataGaName":626,"dataGaLocation":316},"/ai-transparency-center/","ai transparency center",{"text":628,"config":629},"Newsletter",{"href":630,"dataGaName":631,"dataGaLocation":316},"/company/contact/#contact-forms","newsletter",{"text":633,"config":634},"Press",{"href":635,"dataGaName":636,"dataGaLocation":316},"/press/","press",{"text":638,"config":639,"menu":640},"Contact us",{"dataNavLevelOne":584},{"type":367,"columns":641},[642],{"items":643},[644,649,654],{"text":645,"config":646},"Talk to sales",{"href":647,"dataGaName":648,"dataGaLocation":316},"/sales/","talk to sales",{"text":650,"config":651},"Support portal",{"href":652,"dataGaName":653,"dataGaLocation":316},"https://support.gitlab.com/hc/en-us","support portal",{"text":655,"config":656},"Customer portal",{"href":657,"dataGaName":658,"dataGaLocation":316},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":660,"login":661,"suggestions":668},"Close",{"text":662,"link":663},"To search repositories and projects, login to",{"text":664,"config":665},"gitlab.com",{"href":330,"dataGaName":666,"dataGaLocation":667},"search login","search",{"text":669,"default":670},"Suggestions",[671,673,677,679,683,687],{"text":347,"config":672},{"href":352,"dataGaName":347,"dataGaLocation":667},{"text":674,"config":675},"Code Suggestions (AI)",{"href":676,"dataGaName":674,"dataGaLocation":667},"/solutions/code-suggestions/",{"text":383,"config":678},{"href":385,"dataGaName":383,"dataGaLocation":667},{"text":680,"config":681},"GitLab on AWS",{"href":682,"dataGaName":680,"dataGaLocation":667},"/partners/technology-partners/aws/",{"text":684,"config":685},"GitLab on Google Cloud",{"href":686,"dataGaName":684,"dataGaLocation":667},"/partners/technology-partners/google-cloud-platform/",{"text":688,"config":689},"Why GitLab?",{"href":360,"dataGaName":688,"dataGaLocation":667},{"freeTrial":691,"mobileIcon":696,"desktopIcon":701,"secondaryButton":704},{"text":692,"config":693},"Start free trial",{"href":694,"dataGaName":321,"dataGaLocation":695},"https://gitlab.com/-/trials/new/","nav",{"altText":697,"config":698},"Gitlab Icon",{"src":699,"dataGaName":700,"dataGaLocation":695},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":697,"config":702},{"src":703,"dataGaName":700,"dataGaLocation":695},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":705,"config":706},"Get Started",{"href":707,"dataGaName":708,"dataGaLocation":695},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":710,"mobileIcon":714,"desktopIcon":716},{"text":711,"config":712},"Learn more about GitLab Duo",{"href":352,"dataGaName":713,"dataGaLocation":695},"gitlab duo",{"altText":697,"config":715},{"src":699,"dataGaName":700,"dataGaLocation":695},{"altText":697,"config":717},{"src":703,"dataGaName":700,"dataGaLocation":695},{"button":719,"mobileIcon":724,"desktopIcon":726},{"text":720,"config":721},"/switch",{"href":722,"dataGaName":723,"dataGaLocation":695},"#contact","switch",{"altText":697,"config":725},{"src":699,"dataGaName":700,"dataGaLocation":695},{"altText":697,"config":727},{"src":728,"dataGaName":700,"dataGaLocation":695},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":730,"mobileIcon":735,"desktopIcon":737},{"text":731,"config":732},"Back to pricing",{"href":465,"dataGaName":733,"dataGaLocation":695,"icon":734},"back to pricing","GoBack",{"altText":697,"config":736},{"src":699,"dataGaName":700,"dataGaLocation":695},{"altText":697,"config":738},{"src":703,"dataGaName":700,"dataGaLocation":695},{"title":740,"titleMobile":741,"button":742,"config":747},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":358,"config":743},{"href":744,"dataGaName":745,"dataGaLocation":746},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":748,"disabled":294},"release",{"data":750},{"text":751,"source":752,"edit":758,"contribute":763,"config":768,"items":773,"minimal":982},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":753,"config":754},"View page source",{"href":755,"dataGaName":756,"dataGaLocation":757},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":759,"config":760},"Edit this page",{"href":761,"dataGaName":762,"dataGaLocation":757},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":764,"config":765},"Please contribute",{"href":766,"dataGaName":767,"dataGaLocation":757},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":769,"facebook":770,"youtube":771,"linkedin":772},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[774,821,874,918,950],{"title":463,"links":775,"subMenu":790},[776,780,785],{"text":777,"config":778},"View plans",{"href":465,"dataGaName":779,"dataGaLocation":757},"view plans",{"text":781,"config":782},"Why Premium?",{"href":783,"dataGaName":784,"dataGaLocation":757},"/pricing/premium/","why premium",{"text":786,"config":787},"Why Ultimate?",{"href":788,"dataGaName":789,"dataGaLocation":757},"/pricing/ultimate/","why ultimate",[791],{"title":792,"links":793},"Contact Us",[794,797,799,801,806,811,816],{"text":795,"config":796},"Contact sales",{"href":647,"dataGaName":326,"dataGaLocation":757},{"text":650,"config":798},{"href":652,"dataGaName":653,"dataGaLocation":757},{"text":655,"config":800},{"href":657,"dataGaName":658,"dataGaLocation":757},{"text":802,"config":803},"Status",{"href":804,"dataGaName":805,"dataGaLocation":757},"https://status.gitlab.com/","status",{"text":807,"config":808},"Terms of use",{"href":809,"dataGaName":810,"dataGaLocation":757},"/terms/","terms of use",{"text":812,"config":813},"Privacy statement",{"href":814,"dataGaName":815,"dataGaLocation":757},"/privacy/","privacy statement",{"text":817,"config":818},"Cookie preferences",{"dataGaName":819,"dataGaLocation":757,"id":820,"isOneTrustButton":297},"cookie preferences","ot-sdk-btn",{"title":363,"links":822,"subMenu":831},[823,827],{"text":824,"config":825},"DevSecOps platform",{"href":345,"dataGaName":826,"dataGaLocation":757},"devsecops platform",{"text":828,"config":829},"AI-Assisted Development",{"href":352,"dataGaName":830,"dataGaLocation":757},"ai-assisted development",[832],{"title":833,"links":834},"Topics",[835,840,845,849,854,859,864,869],{"text":836,"config":837},"CICD",{"href":838,"dataGaName":839,"dataGaLocation":757},"/topics/ci-cd/","cicd",{"text":841,"config":842},"GitOps",{"href":843,"dataGaName":844,"dataGaLocation":757},"/topics/gitops/","gitops",{"text":306,"config":846},{"href":847,"dataGaName":848,"dataGaLocation":757},"/topics/devops/","devops",{"text":850,"config":851},"Version Control",{"href":852,"dataGaName":853,"dataGaLocation":757},"/topics/version-control/","version control",{"text":855,"config":856},"DevSecOps",{"href":857,"dataGaName":858,"dataGaLocation":757},"/topics/devsecops/","devsecops",{"text":860,"config":861},"Cloud Native",{"href":862,"dataGaName":863,"dataGaLocation":757},"/topics/cloud-native/","cloud native",{"text":865,"config":866},"AI for Coding",{"href":867,"dataGaName":868,"dataGaLocation":757},"/topics/devops/ai-for-coding/","ai for coding",{"text":870,"config":871},"Agentic AI",{"href":872,"dataGaName":873,"dataGaLocation":757},"/topics/agentic-ai/","agentic ai",{"title":875,"links":876},"Solutions",[877,879,881,886,890,893,897,900,902,905,908,913],{"text":407,"config":878},{"href":402,"dataGaName":407,"dataGaLocation":757},{"text":396,"config":880},{"href":379,"dataGaName":380,"dataGaLocation":757},{"text":882,"config":883},"Agile development",{"href":884,"dataGaName":885,"dataGaLocation":757},"/solutions/agile-delivery/","agile delivery",{"text":887,"config":888},"SCM",{"href":392,"dataGaName":889,"dataGaLocation":757},"source code management",{"text":836,"config":891},{"href":385,"dataGaName":892,"dataGaLocation":757},"continuous integration & delivery",{"text":894,"config":895},"Value stream management",{"href":435,"dataGaName":896,"dataGaLocation":757},"value stream management",{"text":841,"config":898},{"href":899,"dataGaName":844,"dataGaLocation":757},"/solutions/gitops/",{"text":445,"config":901},{"href":448,"dataGaName":449,"dataGaLocation":757},{"text":903,"config":904},"Small business",{"href":454,"dataGaName":455,"dataGaLocation":757},{"text":906,"config":907},"Public sector",{"href":460,"dataGaName":461,"dataGaLocation":757},{"text":909,"config":910},"Education",{"href":911,"dataGaName":912,"dataGaLocation":757},"/solutions/education/","education",{"text":914,"config":915},"Financial services",{"href":916,"dataGaName":917,"dataGaLocation":757},"/solutions/finance/","financial services",{"title":468,"links":919},[920,922,924,926,929,931,934,936,938,940,942,944,946,948],{"text":481,"config":921},{"href":483,"dataGaName":484,"dataGaLocation":757},{"text":486,"config":923},{"href":488,"dataGaName":489,"dataGaLocation":757},{"text":491,"config":925},{"href":493,"dataGaName":494,"dataGaLocation":757},{"text":496,"config":927},{"href":498,"dataGaName":928,"dataGaLocation":757},"docs",{"text":519,"config":930},{"href":521,"dataGaName":522,"dataGaLocation":757},{"text":932,"config":933},"What's new",{"href":579,"dataGaName":580,"dataGaLocation":757},{"text":514,"config":935},{"href":516,"dataGaName":517,"dataGaLocation":757},{"text":533,"config":937},{"href":535,"dataGaName":536,"dataGaLocation":757},{"text":541,"config":939},{"href":543,"dataGaName":544,"dataGaLocation":757},{"text":546,"config":941},{"href":548,"dataGaName":549,"dataGaLocation":757},{"text":551,"config":943},{"href":553,"dataGaName":554,"dataGaLocation":757},{"text":556,"config":945},{"href":558,"dataGaName":559,"dataGaLocation":757},{"text":561,"config":947},{"href":563,"dataGaName":564,"dataGaLocation":757},{"text":566,"config":949},{"href":568,"dataGaName":569,"dataGaLocation":757},{"title":582,"links":951},[952,954,956,958,960,962,966,971,973,975,977],{"text":590,"config":953},{"href":592,"dataGaName":584,"dataGaLocation":757},{"text":595,"config":955},{"href":597,"dataGaName":598,"dataGaLocation":757},{"text":603,"config":957},{"href":605,"dataGaName":606,"dataGaLocation":757},{"text":608,"config":959},{"href":610,"dataGaName":611,"dataGaLocation":757},{"text":613,"config":961},{"href":615,"dataGaName":616,"dataGaLocation":757},{"text":963,"config":964},"Sustainability",{"href":965,"dataGaName":963,"dataGaLocation":757},"/sustainability/",{"text":967,"config":968},"Diversity, inclusion and belonging (DIB)",{"href":969,"dataGaName":970,"dataGaLocation":757},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":618,"config":972},{"href":620,"dataGaName":621,"dataGaLocation":757},{"text":628,"config":974},{"href":630,"dataGaName":631,"dataGaLocation":757},{"text":633,"config":976},{"href":635,"dataGaName":636,"dataGaLocation":757},{"text":978,"config":979},"Modern Slavery Transparency Statement",{"href":980,"dataGaName":981,"dataGaLocation":757},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":983},[984,987,990],{"text":985,"config":986},"Terms",{"href":809,"dataGaName":810,"dataGaLocation":757},{"text":988,"config":989},"Cookies",{"dataGaName":819,"dataGaLocation":757,"id":820,"isOneTrustButton":297},{"text":991,"config":992},"Privacy",{"href":814,"dataGaName":815,"dataGaLocation":757},[994],{"id":995,"title":7,"body":293,"config":996,"content":998,"description":293,"extension":1004,"meta":1005,"navigation":297,"path":1006,"seo":1007,"stem":1008,"__hash__":1009},"blogAuthors/en-us/blog/authors/darwin-sanoy.yml",{"template":997},"BlogAuthor",{"role":999,"name":7,"config":1000},"Field Chief Cloud Architect",{"headshot":1001,"linkedin":1002,"ctfId":1003},"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",[1011,1020,1028],{"title":1012,"description":1013,"heroImage":1014,"category":289,"date":1015,"authors":1016,"slug":1019,"externalUrl":293},"Confidential AI for GitLab Self-Hosted","Give developers AI coding agents in GitLab Duo without source code leaving a hardware-encrypted boundary — no GPUs needed.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1773866173/vte9qh8rriznvyclhkes.png","2026-08-06",[1017,1018],"Mathias Ewald","Martin Paloncy, Edgeless Systems","confidential-ai-for-gitlab-self-hosted",{"title":1021,"description":1022,"heroImage":1023,"category":289,"date":1024,"authors":1025,"slug":1027,"externalUrl":293},"Green DevOps: Why carbon measurement belongs in your CI/CD pipeline","CI/CD pipelines have a hidden carbon cost. Here's why measuring it matters, and how you can get started with Eco CI and Carmen in GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1765809212/noh0mdfn9o94ry9ykura.png","2026-07-09",[1026],"Lysanne Pinto","green-devops-carbon-measurement-cicd-pipeline",{"title":1029,"description":1030,"heroImage":1031,"category":289,"date":1032,"authors":1033,"slug":1035,"externalUrl":293},"How to build CI/CD observability at scale","This practical guide to GitLab pipeline analytics helps self-managed users gain operational insights using Prometheus and Grafana.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1774465167/n5hlvrsrheadeccyr1oz.png","2026-04-28",[1034],"Paul Meresanu","how-to-build-ci-cd-observability-at-scale",{"promotions":1037},[1038,1052,1064,1076],{"id":1039,"categories":1040,"header":1042,"text":1043,"button":1044,"image":1049},"ai-modernization",[1041],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1045,"config":1046},"Get your AI maturity score",{"href":1047,"dataGaName":1048,"dataGaLocation":522},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1050},{"src":1051},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1053,"categories":1054,"header":1056,"text":1043,"button":1057,"image":1061},"devops-modernization",[1055,858],"product","Are you just managing tools or shipping innovation?",{"text":1058,"config":1059},"Get your DevOps maturity score",{"href":1060,"dataGaName":1048,"dataGaLocation":522},"/assessments/devops-modernization-assessment/",{"config":1062},{"src":1063},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1065,"categories":1066,"header":1068,"text":1043,"button":1069,"image":1073},"security-modernization",[1067],"security","Are you trading speed for security?",{"text":1070,"config":1071},"Get your security maturity score",{"href":1072,"dataGaName":1048,"dataGaLocation":522},"/assessments/security-modernization-assessment/",{"config":1074},{"src":1075},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1077,"paths":1078,"header":1081,"text":1082,"button":1083,"image":1088},"github-azure-migration",[1079,1080],"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":1084,"config":1085},"See how GitLab compares to GitHub",{"href":1086,"dataGaName":1087,"dataGaLocation":522},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1089},{"src":1063},{"header":1091,"blurb":1092,"button":1093,"secondaryButton":1098},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1094,"config":1095},"Get your free trial",{"href":1096,"dataGaName":321,"dataGaLocation":1097},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":795,"config":1099},{"href":647,"dataGaName":326,"dataGaLocation":1097},1786803748335]