[{"data":1,"prerenderedAt":705},["ShallowReactive",2],{"/en-us/blog/engineering-managers-automate-their-jobs/":3,"navigation-en-us":36,"banner-en-us":452,"footer-en-us":467,"Seth Berger":678,"next-steps-en-us":690},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":26,"_id":29,"_type":30,"title":31,"_source":32,"_file":33,"_stem":34,"_extension":35},"/en-us/blog/engineering-managers-automate-their-jobs","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"How GitLab automates engineering management","At GitLab we know automation is engineering's best friend. Here's a deep dive into three scripts we use regularly to keep big projects on track.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663397/Blog/Hero%20Images/logoforblogpost.jpg","https://about.gitlab.com/blog/engineering-managers-automate-their-jobs","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How GitLab automates engineering management\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Seth Berger\"}],\n        \"datePublished\": \"2021-11-16\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22},[18],"Seth Berger","2021-11-16","\n\nAs an engineer, figuring out how to automate your work becomes an important aspect of your job. From writing powerful dotfiles, to customizing bash scripts, to writing robust and rigorous tests, engineers regularly look for ways to automate their repetitive work. \n\nAt GitLab, engineering managers are no different and are constantly looking for ways to automate their work. I asked engineering managers at GitLab to share their automation scripts and their responses were overflowing. \n\nFrom automating their [1:1 document creation](https://www.youtube.com/watch?v=gqFbZi8Hyoc), to integrating [GitLab with Google Sheets](https://gitlab.com/-/snippets/2200407), to writing utilities to [provide executive summaries](https://gitlab.com/gitlab-org/secure/tools/report-scripts), GitLab team members take advantage of the [rich API that GitLab](https://docs.gitlab.com/ee/api/) provides to organize the mountains of information that they sort through on a regular basis. \n\nFor this blog post, I’m sharing a [repo](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries) that contains just a few of the many scripts that our team members use. These scripts were originally written by engineering manager [Rachel Nienaber](/company/team/#rnienaber). Rachel’s Infrastructure team is tasked with the exciting work of coordinating large scale infrastructure and code improvements. The work involves coordinating and sequencing lots of issues and epics, and ensuring the work gets done at just the right time and in the right order. Because of the breadth and scale of the work, she has created a handful of scripts that parse issues and epics in order to gain better visibility into the work that needs to be done. \n\nIn the repo, there are three scripts. I’ll provide a quick overview of the first two, and then dive into the code on the last one. \n\n* [Issues not in epics ](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/master/issues_not_in_epics.rb)\n* [Epic summary](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/master/epic_summary.rb)\n* [Epic/Issue relationship ](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/master/epic_issue_relationships.rb)\n\n**Issues not in epics**\n\nSince the Infrastructure team leans on [epics](https://docs.gitlab.com/ee/user/group/epics/) to organize their issues, they also want to be able to organize work that may not be part of an epic. The [`issues_not_in_epics.rb`](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/master/issues_not_in_epics.rb) script iterates through issues not in an epic and updates the description of a single hard-coded [issue](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/538) with a table summarizing those issues. The script is run on a daily basis via a scheduled pipeline. This ensures that issues do not slip through the cracks. \n\n**Epic summary**\n\nThis script, [`epic_summary.rb`](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/master/epic_summary.rb), was written to solve the problem of having to look in multiple places to understand the status of each project. By grouping all status information into one place it’s easy to see what the team is working on, and what projects will be coming up next. \n\nAs input it takes a designated epic ID and updates the description of that epic by crawling sub-epics and extracting the following data from those epics:\n\n* The person responsible for delivering a sub-epic (at GitLab we use the term [Directly Responsible Individual or DRI](/handbook/people-group/directly-responsible-individuals/))\n* The latest status update for the epic as inputted by an engineer in an epic description\n* The number of sub-epics\n* Links to a board showing the issues constituting that epic\n\nYou can see an example of the output from the script on this [epic](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/148).\n\nPart of what makes this script simple is that the Infrastructure team always updates the bottom of all their epic descriptions with the following markdown.\n\n```markdown\n## Status {DATE}\n{commentary of the status}\n```\n\nBy consistently using that very simple markdown, the following snippet of code can reliably extract the status for each epic:\n\n```rb\n if description!= nil && description.index(\"## Status\")\n\n    end_location = description.length\n\n    if description.index(\"mermaid\")\n      end_location = description.index(\"mermaid\")-6\n    end\n\n    status = description[description.index(\"## Status\")+10..end_location]\n  end\n```\n\nThe code above certainly won’t win any algorithm challenges, but that’s kind of the point and what we aim to do with [boring solutions](/blog/boring-solutions-faster-iteration/). \n\nYou’ll notice the code above adjusts what is parsed to exclude a mermaid diagram that might appear after the `## Status` markdown.  That diagram gets maintained with the [epic_issue_relationship.rb](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/master/epic_issue_relationships.rb) script. \n\n**Epic issue relationship**\n\nThis script updates either a specific epic or all epics, depending on the command line option,  with a [mermaid diagram](https://mermaid-js.github.io/) that shows the relationship between issues and the order that those issues need to be completed by examining how they are related to one another. Adding a mermaid diagram to the description was introduced by [Sean McGivern](/company/team/#smcgivern), a staff engineer on the Scalability team. It creates brilliant diagrams like this one from this [epic](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/579).\n\n![Mermaid Diagram](https://about.gitlab.com/images/blogimages/2021-11-16-engineering-managers/issue_relation.png)\n\nLet’s walk through the code.\n\nThe script uses the Docopt gem to parse and accept several input parameters. \n\n```rb\noptions = Docopt::docopt(docstring)\ntoken = options.fetch('--token')\ngroup_id = options.fetch('--groupid')\nepic_id = options.fetch('--epicid', nil)\ndry_run = options.fetch('--dry-run', false)\n```\nThen a connection to the GitLab instance is created, taking advantage of the [GitLab gem](https://github.com/NARKOZ/gitlab) which is extended in [`lib/gitlab_client/epics.rb`](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/main/lib/gitlab_client/epics.rb) to include a few extra methods. \n\n```rb\nGitlab.configure do |config|\n  config.endpoint = 'https://gitlab.com/api/v4'\n  config.private_token = token\nend\n```\n\nIf an epic id is passed in, then the `update_mermaid` will run only for a specific epic. Otherwise, the code searches for epics that match the two labels, `workflow-infra::In Progress` and `team::Scalability` and are also `opened`. Only when the matching epics do not have child epics,  is `update_mermaid` run. \n\n```rb\nif epic_id\n  update_mermaid(token: token, group_id: group_id, epic_id: epic_id, dry_run: dry_run)\nelse\n  Gitlab.epics(group_id, 'workflow-infra::In Progress,team::Scalability', options: { state: 'opened' }).each do |epic|\n    if Gitlab.epic_epics(epic['group_id'], epic['iid']).count == 0\n      update_mermaid(token: token, group_id: group_id, epic_id: epic['iid'], dry_run: dry_run)\n    end\n  end\nend\n```\nFinally the most exciting part of the script is the method `update_mermaid` method. \n\nBelow the code sets up variables, and looks to see if a mermaid diagram exists in the epic description that it should populate. Note, that if a mermaid diagram does not exist in the epic already, this script will not create one. Each epic should already have a mermaid diagram placeholder inserted after the status header.\n\n```rb\ndef update_mermaid(token:, group_id:, epic_id:, dry_run:)\n  in_epic = Set.new\n  from_relations = Set.new\n  relations = Set.new\n  mermaid = ['graph TD']\n  original_description = Gitlab.epic(group_id, epic_id).description\n\n  unless original_description =~ MERMAID_REGEX\n    puts \"#{epic_id} does not have a Mermaid diagram\"\n    return\n  end\n```\n\nNext the code iterates through each of the issues in the epic and assigns a graph_id for each issue that will be part of the mermaid diagram. It also adds the `key_fields` to the `in_epic` Set. The code assigns `title` along with an emoji so that the mermaid diagram is visually richer. After that the graph nodes are added to the mermaid diagram. \n\n```rb\n Gitlab.epic_issues(group_id, epic_id).each do |issue|\n    iid = issue['iid']\n    graph_id = id(issue)\n\n    in_epic \u003C\u003C key_fields(issue)\n\n    title = \"##{iid}\"\n    title = \"🎯 #{title}\" if issue['labels'].include?('exit criterion')\n    if issue['state'] == 'closed'\n      title = \"✅ #{title}\"\n    elsif issue['assignees'].any?\n      title = \"⏳ #{title}\"\n    end\n\n    mermaid \u003C\u003C \"  #{graph_id}[\\\"#{title}\\\"]\"\n    mermaid \u003C\u003C \"  click #{graph_id} \\\"#{issue['web_url']}\\\" \\\"#{issue['title'].gsub('\"', \"'\")}\\\"\"\n\n```\nAfter adding the graph nodes above, the code iterates through the links associated with each issue. The code determines if the issue is blocked by or blocks another issue. Knowing the direction of this relationship defines which direction the arrow in the mermaid diagram should point.  \n\nThe code also adds both the issue and link to the `from_relations` set, which will automatically deduplicate entries.\n\n```rb\n    Gitlab.issue_links(issue['project_id'], issue['iid']).each do |link|\n      case link['link_type']\n      when 'is_blocked_by'\n        source = id(link)\n        destination = graph_id\n      when 'blocks'\n        source = graph_id\n        destination = id(link)\n      else\n        next\n      end\n\n      from_relations \u003C\u003C key_fields(issue)\n      from_relations \u003C\u003C key_fields(link)\n\n      unless relations.include?([source, destination])\n        mermaid \u003C\u003C \"  #{source} --> #{destination}\"\n        relations \u003C\u003C [source, destination]\n      end\n    end\n```\n\nFinally, the code looks at the “extra” issues, which are issues that are not directly part of the epic, but are related to issues in the epic. These are the most important issues to ensure are on the diagram, since they represent issue dependencies that are outside the epic and would otherwise not show up when viewing an epic page in GitLab. \n\nThe code then updates the epic description by calling the GitLab API and setting the new description. \n\n```rb\n  (from_relations - in_epic).each do |extra_issue|\n    mermaid \u003C\u003C \"  #{id(extra_issue)}[\\\"❌ ##{extra_issue['iid']}\\\"]\"\n    mermaid \u003C\u003C \"  click #{id(extra_issue)} \\\"#{extra_issue['web_url']}\\\" \\\"#{extra_issue['title'].gsub('\"', \"'\")}\\\"\"\n  end\n\n  mermaid_string = mermaid.join(\"\\n\")\n  new_description = original_description\n                        .gsub(MERMAID_REGEX,\n                              \"\\n\\\\1\\n```mermaid\\n#{mermaid_string}\\n```\\n\")\n\n    Gitlab.edit_epic(group_id, epic_id, description: new_description)\nend\n```\n\nThe above scripts help engineering managers efficiently know about all the issues their team members are working on, the status of their team’s epics and how all the work fits together.  \n\nThe scripts only rely on team members doing two things manually: \n\n* Updating an epic’s status on a periodic basis\n* Creating relationships between related issues.  \n\nThe scripts can be run as part of a regular scheduled [pipeline](https://gitlab.com/gitlab-org/secure/tools/epic-issue-summaries/-/blob/main/.gitlab-ci.yml). With the reports generated on a scheduled basis, engineering managers can regularly get summarized information that helps make them and their teams more productive.\n","company",[23,24,25],"workflow","inside GitLab","collaboration",{"slug":27,"featured":6,"template":28},"engineering-managers-automate-their-jobs","BlogPost","content:en-us:blog:engineering-managers-automate-their-jobs.yml","yaml","Engineering Managers Automate Their Jobs","content","en-us/blog/engineering-managers-automate-their-jobs.yml","en-us/blog/engineering-managers-automate-their-jobs","yml",{"_path":37,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"data":39,"_id":448,"_type":30,"title":449,"_source":32,"_file":450,"_stem":451,"_extension":35},"/shared/en-us/main-navigation","en-us",{"logo":40,"freeTrial":45,"sales":50,"login":55,"items":60,"search":389,"minimal":420,"duo":439},{"config":41},{"href":42,"dataGaName":43,"dataGaLocation":44},"/","gitlab logo","header",{"text":46,"config":47},"Get free trial",{"href":48,"dataGaName":49,"dataGaLocation":44},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":51,"config":52},"Talk to sales",{"href":53,"dataGaName":54,"dataGaLocation":44},"/sales/","sales",{"text":56,"config":57},"Sign in",{"href":58,"dataGaName":59,"dataGaLocation":44},"https://gitlab.com/users/sign_in/","sign in",[61,105,201,206,311,370],{"text":62,"config":63,"cards":65,"footer":88},"Platform",{"dataNavLevelOne":64},"platform",[66,72,80],{"title":62,"description":67,"link":68},"The most comprehensive AI-powered DevSecOps Platform",{"text":69,"config":70},"Explore our Platform",{"href":71,"dataGaName":64,"dataGaLocation":44},"/platform/",{"title":73,"description":74,"link":75},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":76,"config":77},"Meet GitLab Duo",{"href":78,"dataGaName":79,"dataGaLocation":44},"/gitlab-duo/","gitlab duo ai",{"title":81,"description":82,"link":83},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":84,"config":85},"Learn more",{"href":86,"dataGaName":87,"dataGaLocation":44},"/why-gitlab/","why gitlab",{"title":89,"items":90},"Get started with",[91,96,101],{"text":92,"config":93},"Platform Engineering",{"href":94,"dataGaName":95,"dataGaLocation":44},"/solutions/platform-engineering/","platform engineering",{"text":97,"config":98},"Developer Experience",{"href":99,"dataGaName":100,"dataGaLocation":44},"/developer-experience/","Developer experience",{"text":102,"config":103},"MLOps",{"href":104,"dataGaName":102,"dataGaLocation":44},"/topics/devops/the-role-of-ai-in-devops/",{"text":106,"left":107,"config":108,"link":110,"lists":114,"footer":183},"Product",true,{"dataNavLevelOne":109},"solutions",{"text":111,"config":112},"View all Solutions",{"href":113,"dataGaName":109,"dataGaLocation":44},"/solutions/",[115,140,162],{"title":116,"description":117,"link":118,"items":123},"Automation","CI/CD and automation to accelerate deployment",{"config":119},{"icon":120,"href":121,"dataGaName":122,"dataGaLocation":44},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[124,128,132,136],{"text":125,"config":126},"CI/CD",{"href":127,"dataGaLocation":44,"dataGaName":125},"/solutions/continuous-integration/",{"text":129,"config":130},"AI-Assisted Development",{"href":78,"dataGaLocation":44,"dataGaName":131},"AI assisted development",{"text":133,"config":134},"Source Code Management",{"href":135,"dataGaLocation":44,"dataGaName":133},"/solutions/source-code-management/",{"text":137,"config":138},"Automated Software Delivery",{"href":121,"dataGaLocation":44,"dataGaName":139},"Automated software delivery",{"title":141,"description":142,"link":143,"items":148},"Security","Deliver code faster without compromising security",{"config":144},{"href":145,"dataGaName":146,"dataGaLocation":44,"icon":147},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[149,152,157],{"text":150,"config":151},"Security & Compliance",{"href":145,"dataGaLocation":44,"dataGaName":150},{"text":153,"config":154},"Software Supply Chain Security",{"href":155,"dataGaLocation":44,"dataGaName":156},"/solutions/supply-chain/","Software supply chain security",{"text":158,"config":159},"Compliance & Governance",{"href":160,"dataGaLocation":44,"dataGaName":161},"/solutions/continuous-software-compliance/","Compliance and governance",{"title":163,"link":164,"items":169},"Measurement",{"config":165},{"icon":166,"href":167,"dataGaName":168,"dataGaLocation":44},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[170,174,178],{"text":171,"config":172},"Visibility & Measurement",{"href":167,"dataGaLocation":44,"dataGaName":173},"Visibility and Measurement",{"text":175,"config":176},"Value Stream Management",{"href":177,"dataGaLocation":44,"dataGaName":175},"/solutions/value-stream-management/",{"text":179,"config":180},"Analytics & Insights",{"href":181,"dataGaLocation":44,"dataGaName":182},"/solutions/analytics-and-insights/","Analytics and insights",{"title":184,"items":185},"GitLab for",[186,191,196],{"text":187,"config":188},"Enterprise",{"href":189,"dataGaLocation":44,"dataGaName":190},"/enterprise/","enterprise",{"text":192,"config":193},"Small Business",{"href":194,"dataGaLocation":44,"dataGaName":195},"/small-business/","small business",{"text":197,"config":198},"Public Sector",{"href":199,"dataGaLocation":44,"dataGaName":200},"/solutions/public-sector/","public sector",{"text":202,"config":203},"Pricing",{"href":204,"dataGaName":205,"dataGaLocation":44,"dataNavLevelOne":205},"/pricing/","pricing",{"text":207,"config":208,"link":210,"lists":214,"feature":298},"Resources",{"dataNavLevelOne":209},"resources",{"text":211,"config":212},"View all resources",{"href":213,"dataGaName":209,"dataGaLocation":44},"/resources/",[215,248,270],{"title":216,"items":217},"Getting started",[218,223,228,233,238,243],{"text":219,"config":220},"Install",{"href":221,"dataGaName":222,"dataGaLocation":44},"/install/","install",{"text":224,"config":225},"Quick start guides",{"href":226,"dataGaName":227,"dataGaLocation":44},"/get-started/","quick setup checklists",{"text":229,"config":230},"Learn",{"href":231,"dataGaLocation":44,"dataGaName":232},"https://university.gitlab.com/","learn",{"text":234,"config":235},"Product documentation",{"href":236,"dataGaName":237,"dataGaLocation":44},"https://docs.gitlab.com/","product documentation",{"text":239,"config":240},"Best practice videos",{"href":241,"dataGaName":242,"dataGaLocation":44},"/getting-started-videos/","best practice videos",{"text":244,"config":245},"Integrations",{"href":246,"dataGaName":247,"dataGaLocation":44},"/integrations/","integrations",{"title":249,"items":250},"Discover",[251,256,260,265],{"text":252,"config":253},"Customer success stories",{"href":254,"dataGaName":255,"dataGaLocation":44},"/customers/","customer success stories",{"text":257,"config":258},"Blog",{"href":259,"dataGaName":5,"dataGaLocation":44},"/blog/",{"text":261,"config":262},"Remote",{"href":263,"dataGaName":264,"dataGaLocation":44},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":266,"config":267},"TeamOps",{"href":268,"dataGaName":269,"dataGaLocation":44},"/teamops/","teamops",{"title":271,"items":272},"Connect",[273,278,283,288,293],{"text":274,"config":275},"GitLab Services",{"href":276,"dataGaName":277,"dataGaLocation":44},"/services/","services",{"text":279,"config":280},"Community",{"href":281,"dataGaName":282,"dataGaLocation":44},"/community/","community",{"text":284,"config":285},"Forum",{"href":286,"dataGaName":287,"dataGaLocation":44},"https://forum.gitlab.com/","forum",{"text":289,"config":290},"Events",{"href":291,"dataGaName":292,"dataGaLocation":44},"/events/","events",{"text":294,"config":295},"Partners",{"href":296,"dataGaName":297,"dataGaLocation":44},"/partners/","partners",{"backgroundColor":299,"textColor":300,"text":301,"image":302,"link":306},"#2f2a6b","#fff","Insights for the future of software development",{"altText":303,"config":304},"the source promo card",{"src":305},"/images/navigation/the-source-promo-card.svg",{"text":307,"config":308},"Read the latest",{"href":309,"dataGaName":310,"dataGaLocation":44},"/the-source/","the source",{"text":312,"config":313,"lists":314},"Company",{"dataNavLevelOne":21},[315],{"items":316},[317,322,328,330,335,340,345,350,355,360,365],{"text":318,"config":319},"About",{"href":320,"dataGaName":321,"dataGaLocation":44},"/company/","about",{"text":323,"config":324,"footerGa":327},"Jobs",{"href":325,"dataGaName":326,"dataGaLocation":44},"/jobs/","jobs",{"dataGaName":326},{"text":289,"config":329},{"href":291,"dataGaName":292,"dataGaLocation":44},{"text":331,"config":332},"Leadership",{"href":333,"dataGaName":334,"dataGaLocation":44},"/company/team/e-group/","leadership",{"text":336,"config":337},"Team",{"href":338,"dataGaName":339,"dataGaLocation":44},"/company/team/","team",{"text":341,"config":342},"Handbook",{"href":343,"dataGaName":344,"dataGaLocation":44},"https://handbook.gitlab.com/","handbook",{"text":346,"config":347},"Investor relations",{"href":348,"dataGaName":349,"dataGaLocation":44},"https://ir.gitlab.com/","investor relations",{"text":351,"config":352},"Trust Center",{"href":353,"dataGaName":354,"dataGaLocation":44},"/security/","trust center",{"text":356,"config":357},"AI Transparency Center",{"href":358,"dataGaName":359,"dataGaLocation":44},"/ai-transparency-center/","ai transparency center",{"text":361,"config":362},"Newsletter",{"href":363,"dataGaName":364,"dataGaLocation":44},"/company/contact/","newsletter",{"text":366,"config":367},"Press",{"href":368,"dataGaName":369,"dataGaLocation":44},"/press/","press",{"text":371,"config":372,"lists":373},"Contact us",{"dataNavLevelOne":21},[374],{"items":375},[376,379,384],{"text":51,"config":377},{"href":53,"dataGaName":378,"dataGaLocation":44},"talk to sales",{"text":380,"config":381},"Get help",{"href":382,"dataGaName":383,"dataGaLocation":44},"/support/","get help",{"text":385,"config":386},"Customer portal",{"href":387,"dataGaName":388,"dataGaLocation":44},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":390,"login":391,"suggestions":398},"Close",{"text":392,"link":393},"To search repositories and projects, login to",{"text":394,"config":395},"gitlab.com",{"href":58,"dataGaName":396,"dataGaLocation":397},"search login","search",{"text":399,"default":400},"Suggestions",[401,403,407,409,413,417],{"text":73,"config":402},{"href":78,"dataGaName":73,"dataGaLocation":397},{"text":404,"config":405},"Code Suggestions (AI)",{"href":406,"dataGaName":404,"dataGaLocation":397},"/solutions/code-suggestions/",{"text":125,"config":408},{"href":127,"dataGaName":125,"dataGaLocation":397},{"text":410,"config":411},"GitLab on AWS",{"href":412,"dataGaName":410,"dataGaLocation":397},"/partners/technology-partners/aws/",{"text":414,"config":415},"GitLab on Google Cloud",{"href":416,"dataGaName":414,"dataGaLocation":397},"/partners/technology-partners/google-cloud-platform/",{"text":418,"config":419},"Why GitLab?",{"href":86,"dataGaName":418,"dataGaLocation":397},{"freeTrial":421,"mobileIcon":426,"desktopIcon":431,"secondaryButton":434},{"text":422,"config":423},"Start free trial",{"href":424,"dataGaName":49,"dataGaLocation":425},"https://gitlab.com/-/trials/new/","nav",{"altText":427,"config":428},"Gitlab Icon",{"src":429,"dataGaName":430,"dataGaLocation":425},"/images/brand/gitlab-logo-tanuki.svg","gitlab icon",{"altText":427,"config":432},{"src":433,"dataGaName":430,"dataGaLocation":425},"/images/brand/gitlab-logo-type.svg",{"text":435,"config":436},"Get Started",{"href":437,"dataGaName":438,"dataGaLocation":425},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":440,"mobileIcon":444,"desktopIcon":446},{"text":441,"config":442},"Learn more about GitLab Duo",{"href":78,"dataGaName":443,"dataGaLocation":425},"gitlab duo",{"altText":427,"config":445},{"src":429,"dataGaName":430,"dataGaLocation":425},{"altText":427,"config":447},{"src":433,"dataGaName":430,"dataGaLocation":425},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":453,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"title":454,"button":455,"image":459,"config":462,"_id":464,"_type":30,"_source":32,"_file":465,"_stem":466,"_extension":35},"/shared/en-us/banner","is now in public beta!",{"text":84,"config":456},{"href":457,"dataGaName":458,"dataGaLocation":44},"/gitlab-duo/agent-platform/","duo banner",{"config":460},{"src":461},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":463},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":468,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"data":469,"_id":674,"_type":30,"title":675,"_source":32,"_file":676,"_stem":677,"_extension":35},"/shared/en-us/main-footer",{"text":470,"source":471,"edit":477,"contribute":482,"config":487,"items":492,"minimal":666},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":472,"config":473},"View page source",{"href":474,"dataGaName":475,"dataGaLocation":476},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":478,"config":479},"Edit this page",{"href":480,"dataGaName":481,"dataGaLocation":476},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":483,"config":484},"Please contribute",{"href":485,"dataGaName":486,"dataGaLocation":476},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":488,"facebook":489,"youtube":490,"linkedin":491},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[493,516,573,602,636],{"title":62,"links":494,"subMenu":499},[495],{"text":496,"config":497},"DevSecOps platform",{"href":71,"dataGaName":498,"dataGaLocation":476},"devsecops platform",[500],{"title":202,"links":501},[502,506,511],{"text":503,"config":504},"View plans",{"href":204,"dataGaName":505,"dataGaLocation":476},"view plans",{"text":507,"config":508},"Why Premium?",{"href":509,"dataGaName":510,"dataGaLocation":476},"/pricing/premium/","why premium",{"text":512,"config":513},"Why Ultimate?",{"href":514,"dataGaName":515,"dataGaLocation":476},"/pricing/ultimate/","why ultimate",{"title":517,"links":518},"Solutions",[519,524,527,529,534,539,543,546,550,555,557,560,563,568],{"text":520,"config":521},"Digital transformation",{"href":522,"dataGaName":523,"dataGaLocation":476},"/topics/digital-transformation/","digital transformation",{"text":150,"config":525},{"href":145,"dataGaName":526,"dataGaLocation":476},"security & compliance",{"text":139,"config":528},{"href":121,"dataGaName":122,"dataGaLocation":476},{"text":530,"config":531},"Agile development",{"href":532,"dataGaName":533,"dataGaLocation":476},"/solutions/agile-delivery/","agile delivery",{"text":535,"config":536},"Cloud transformation",{"href":537,"dataGaName":538,"dataGaLocation":476},"/topics/cloud-native/","cloud transformation",{"text":540,"config":541},"SCM",{"href":135,"dataGaName":542,"dataGaLocation":476},"source code management",{"text":125,"config":544},{"href":127,"dataGaName":545,"dataGaLocation":476},"continuous integration & delivery",{"text":547,"config":548},"Value stream management",{"href":177,"dataGaName":549,"dataGaLocation":476},"value stream management",{"text":551,"config":552},"GitOps",{"href":553,"dataGaName":554,"dataGaLocation":476},"/solutions/gitops/","gitops",{"text":187,"config":556},{"href":189,"dataGaName":190,"dataGaLocation":476},{"text":558,"config":559},"Small business",{"href":194,"dataGaName":195,"dataGaLocation":476},{"text":561,"config":562},"Public sector",{"href":199,"dataGaName":200,"dataGaLocation":476},{"text":564,"config":565},"Education",{"href":566,"dataGaName":567,"dataGaLocation":476},"/solutions/education/","education",{"text":569,"config":570},"Financial services",{"href":571,"dataGaName":572,"dataGaLocation":476},"/solutions/finance/","financial services",{"title":207,"links":574},[575,577,579,581,584,586,588,590,592,594,596,598,600],{"text":219,"config":576},{"href":221,"dataGaName":222,"dataGaLocation":476},{"text":224,"config":578},{"href":226,"dataGaName":227,"dataGaLocation":476},{"text":229,"config":580},{"href":231,"dataGaName":232,"dataGaLocation":476},{"text":234,"config":582},{"href":236,"dataGaName":583,"dataGaLocation":476},"docs",{"text":257,"config":585},{"href":259,"dataGaName":5,"dataGaLocation":476},{"text":252,"config":587},{"href":254,"dataGaName":255,"dataGaLocation":476},{"text":261,"config":589},{"href":263,"dataGaName":264,"dataGaLocation":476},{"text":274,"config":591},{"href":276,"dataGaName":277,"dataGaLocation":476},{"text":266,"config":593},{"href":268,"dataGaName":269,"dataGaLocation":476},{"text":279,"config":595},{"href":281,"dataGaName":282,"dataGaLocation":476},{"text":284,"config":597},{"href":286,"dataGaName":287,"dataGaLocation":476},{"text":289,"config":599},{"href":291,"dataGaName":292,"dataGaLocation":476},{"text":294,"config":601},{"href":296,"dataGaName":297,"dataGaLocation":476},{"title":312,"links":603},[604,606,608,610,612,614,616,620,625,627,629,631],{"text":318,"config":605},{"href":320,"dataGaName":21,"dataGaLocation":476},{"text":323,"config":607},{"href":325,"dataGaName":326,"dataGaLocation":476},{"text":331,"config":609},{"href":333,"dataGaName":334,"dataGaLocation":476},{"text":336,"config":611},{"href":338,"dataGaName":339,"dataGaLocation":476},{"text":341,"config":613},{"href":343,"dataGaName":344,"dataGaLocation":476},{"text":346,"config":615},{"href":348,"dataGaName":349,"dataGaLocation":476},{"text":617,"config":618},"Sustainability",{"href":619,"dataGaName":617,"dataGaLocation":476},"/sustainability/",{"text":621,"config":622},"Diversity, inclusion and belonging (DIB)",{"href":623,"dataGaName":624,"dataGaLocation":476},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":351,"config":626},{"href":353,"dataGaName":354,"dataGaLocation":476},{"text":361,"config":628},{"href":363,"dataGaName":364,"dataGaLocation":476},{"text":366,"config":630},{"href":368,"dataGaName":369,"dataGaLocation":476},{"text":632,"config":633},"Modern Slavery Transparency Statement",{"href":634,"dataGaName":635,"dataGaLocation":476},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":637,"links":638},"Contact Us",[639,642,644,646,651,656,661],{"text":640,"config":641},"Contact an expert",{"href":53,"dataGaName":54,"dataGaLocation":476},{"text":380,"config":643},{"href":382,"dataGaName":383,"dataGaLocation":476},{"text":385,"config":645},{"href":387,"dataGaName":388,"dataGaLocation":476},{"text":647,"config":648},"Status",{"href":649,"dataGaName":650,"dataGaLocation":476},"https://status.gitlab.com/","status",{"text":652,"config":653},"Terms of use",{"href":654,"dataGaName":655,"dataGaLocation":476},"/terms/","terms of use",{"text":657,"config":658},"Privacy statement",{"href":659,"dataGaName":660,"dataGaLocation":476},"/privacy/","privacy statement",{"text":662,"config":663},"Cookie preferences",{"dataGaName":664,"dataGaLocation":476,"id":665,"isOneTrustButton":107},"cookie preferences","ot-sdk-btn",{"items":667},[668,670,672],{"text":652,"config":669},{"href":654,"dataGaName":655,"dataGaLocation":476},{"text":657,"config":671},{"href":659,"dataGaName":660,"dataGaLocation":476},{"text":662,"config":673},{"dataGaName":664,"dataGaLocation":476,"id":665,"isOneTrustButton":107},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[679],{"_path":680,"_dir":681,"_draft":6,"_partial":6,"_locale":7,"content":682,"config":685,"_id":687,"_type":30,"title":18,"_source":32,"_file":688,"_stem":689,"_extension":35},"/en-us/blog/authors/seth-berger","authors",{"name":18,"config":683},{"headshot":7,"ctfId":684},"sethgitlab",{"template":686},"BlogAuthor","content:en-us:blog:authors:seth-berger.yml","en-us/blog/authors/seth-berger.yml","en-us/blog/authors/seth-berger",{"_path":691,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"header":692,"eyebrow":693,"blurb":694,"button":695,"secondaryButton":699,"_id":701,"_type":30,"title":702,"_source":32,"_file":703,"_stem":704,"_extension":35},"/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":46,"config":696},{"href":697,"dataGaName":49,"dataGaLocation":698},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":51,"config":700},{"href":53,"dataGaName":54,"dataGaLocation":698},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1754424488520]