[{"data":1,"prerenderedAt":699},["ShallowReactive",2],{"/en-us/blog/gitlab-todos-feature-highlight/":3,"navigation-en-us":32,"banner-en-us":448,"footer-en-us":460,"Douglas Alexandre":671,"next-steps-en-us":684},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":22,"_id":25,"_type":26,"title":27,"_source":28,"_file":29,"_stem":30,"_extension":31},"/en-us/blog/gitlab-todos-feature-highlight","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Feature Highlight: Todos","In this blog post I'll guide you through the Todos feature we introduced in GitLab 8.5 and also tell you how this feature came to life.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749684608/Blog/Hero%20Images/taking-notes.jpg","https://about.gitlab.com/blog/gitlab-todos-feature-highlight","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Feature Highlight: Todos\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Douglas Alexandre\"}],\n        \"datePublished\": \"2016-03-02\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21},[18],"Douglas Alexandre","2016-03-02","\n\nIn this blog post I'll guide you through the \"Todos\" feature we introduced in\n[GitLab 8.5](/releases/2016/02/22/gitlab-8-5-released/)\nand also tell you how this feature came to life.\nWe'll also talk about how you can contribute to GitLab.\n\n\u003C!-- more -->\n\n### First let’s look at this feature\n\nWhen you log into GitLab, you'll want to see where you should spend your time,\nwhere your team members need help, where you need to take some action, or what\nyou need to keep an eye on. All without the mess of a huge pile of e-mail\nnotifications.\n\nWhen an issue or merge request is assigned to you, or when you are `@mentioned`\nin a comment, this triggers a notification and you may get an e-mail, depending\non your notification settings. Starting from GitLab 8.5, these actions will\nalso add a notice in your Todos list, which you can access by clicking the\nround gray icon next to the search bar in the upper right corner.\n\n![Todos screenshot showing a list of items to check on](https://about.gitlab.com/images/blogimages/todos-screenshot.jpg)\n\nYou can then respond to the todo by performing an action to the corresponding\nissue or merge request. This action can include changing the milestone, adding\na label, commenting on the issue and pretty much everything that adds extra\ninformation to the issue/merge request.\n\nIn case where you think no action is needed, you can manually mark the todo as\n**Done** and it will disappear from your Todos list.\n\nIn order for a todo to be marked as done, the action must be coming from you.\nSo, if you close/merge the related issue or merge request yourself, and you had\na todo for that, it will automatically get marked as done. On the other hand,if\nsomeone else closes, merges or takes action on the issue or merge request, your\ntodo will remain pending. This makes sense because you may need to give\nattention to an issue even if it has been resolved.\n\nAnother thing is that you won't have a gazillion Todos about the same issue or\nmerge request. There is just one todo per issue or merge request, you won’t be\nannoyed repeatedly.\n\nNext, let’s see how this feature came to life.\n\n### How we developed this feature\n\nIt was just a few weeks before the 8.5 release when\n[Dmitry](https://twitter.com/dzaporozhets) asked me to work on this feature.\nIn fact, that was a lot of work to be done in such a short time and I actually\ndelivered this task on the last release candidate before our release day.\nAs it turned out, people were quite surprised and happy to have this feature in\n8.5.\n\nThere had been a long discussion about this feature, but no one had touched it\nyet. The original proposal was very complicated, there were a lot of comments\non the issue too, with a more active discussion in the last two months.\n\nFinally, after considering all the options,\n[Dmitry commented on the issue][comment] and greatly simplified it.\n\nI was excited about taking on the challenge. Not only because I knew it would\nbe an important feature, but it would also be a feature that most people will\nuse every day. This is the second major feature I've worked on since I started\nat GitLab in December. Previously, I had worked on the GitHub import project\nwhich came out in GitLab 8.4.\n\nI needed to learn quite a lot of the GitLab codebase in order to create this\nfeature. And then, while I was reading the code, I was surprised to discover it\nwas going to be much easier than I thought. My epiphany was that we already had\nthe Activity feed system in place which I could reuse. As it turned out, it was\ngoing to be very easy to implement this feature.\n\nAt the beginning, I spent the first week reading the code, understanding how\nthe system worked, discovering the points that we needed to trigger a todo. I\nwrote some guidelines about what I needed to achieve and then I started writing\nthe actual code by the end of the week. Yep, most of the coding was done in one\nweek.\n\nAt first, I needed to investigate how the Activity feed system works.\n\n![Screenshot of activity feed](https://about.gitlab.com/images/blogimages/activity-feed-screenshot.jpg)\n\nThen, I plugged in another service to trigger the todo when an issue or merge\nrequest is assigned to someone, or when someone is `@mentioned` in a comment or\nthe issue description. After this, I just needed to make sure that when someone\ncompleted whatever they thought is needed on the issue or merge request, the\ntodo will be marked as **Done**.\n\nDepending on the action that someone made on the issue or merge request, we\nneed to know exactly what attributes were changed. This is specially important\nto know when Todos are automatically marked as **Done**.\n\nTo know what changed inside a issue or merge request, we used the\n[Rails ActiveModel::Dirty API][dirty] that allows us to quick track what\nattributes on a model have changed, even after the model was saved.\n\nThe `ActiveModel::Dirty` works very well, except that it doesn't track changes\non associations. So how we determine what changed inside the association? For\nexample, how to check if a label was added, or removed from an issue or merge\nrequest? To accomplish this, we came with a boring solution, where we receive\nthe old items of the association through a parameter, and compare it with\nthe current association to check if something has changed.\n\nThe method that checks if at least one valid attribute has changed, is the\nfollowing:\n\n```ruby\ndef has_changes?(issuable, options = {})\n  valid_attrs = [:title, :description, :assignee_id, :milestone_id, :target_branch]\n\n  attrs_changed = valid_attrs.any? do |attr|\n    issuable.previous_changes.include?(attr.to_s)\n  end\n\n  old_labels = options[:old_labels]\n  labels_changed = old_labels && issuable.labels != old_labels\n\n  attrs_changed || labels_changed\nend\n```\n\nA quick note about this code snippet is that it will run _after_ the model was\nsaved, so `previous_changes` is the method that we need to call, and it returns\na hash with the attributes that were changed before the model was saved.\n\nWe can see on the following snippet that other GitLab features, like\nthe system note and the notification service, also use this API to trigger an\naction after certain attributes have changed:\n\n```ruby\nif issue.previous_changes.include?('assignee_id')\n  create_assignee_note(issue)\n  notification_service.reassigned_issue(issue, current_user)\n  todo_service.reassigned_issue(issue, current_user)\nend\n```\n\nTo get an idea about the points that trigger an action related to Todos,\nyou can take a look at the source code of the [TodoService] class, that\ndescribes the expected behavior for each of these points.\n\nMy colleague, [Douwe](https://twitter.com/DouweM), guided me through some of\nthese edge cases and helped me a lot with daily code reviews. Together we\nconsidered the aspects of the functionality. I had to make many changes during\nthe review period, but that worked out well in the end.\n\nSome people asked for changes which we thought didn't fit for what we were\ntrying to achieve. There was for example a request to be notified of Todos on\ncommits. We ultimately decided against this request since there are no clear\nactions to take on a commit, except for replying to a comment. Most of the time\nyou’re actually working on an issue or a merge request, this is where the action\nhappens.\n\n### About that name\n\nThere was a long discussion about naming the feature. In the beginning this\nfeature was called 'Notification System'. Then 'Action Center'. Then 'Todos'.\nThen 'Tasks', and finally 'Task Queue' was chosen.\n\nBut Douwe and Sytse discussed the naming for the umpteenth time, and concluded\nthat 'Todos' would be the best name since 'Tasks' is already used (by us and\nGitHub) for the Markdown checklist.\n\nTodo makes more sense to me than a Task, you just need to take a look at it.\nTasks are obligations. A Todo is just a reminder, and as such, maybe it is\nrelevant for you and you'll take a look or maybe you'll just mark it as done.\n\n### Conclusion\n\nI'm really happy to have worked on a feature that people will use every day!\nIt's a simple feature and even though we've only been using it a few days,\nwe can't imagine how we managed to work without it.\n\nThis Tweet from a user pretty much sums it up.\n\n\u003Cblockquote class=\"twitter-tweet\" data-lang=\"en\">\u003Cp lang=\"en\" dir=\"ltr\">.\u003Ca href=\"https://twitter.com/gitlab\">@gitlab\u003C/a>&#39;s new ToDos feature is simply amazing. Simple feature but something you cannot live without once you tried it.\u003C/p>&mdash; Tero Tasanen (@ttasanen) \u003Ca href=\"https://twitter.com/ttasanen/status/702249244950974464\">February 23, 2016\u003C/a>\u003C/blockquote>\n\u003Cscript async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\">\u003C/script>\n\nFor more information you can [read our documentation][doc].\n\n","company",{"slug":23,"featured":6,"template":24},"gitlab-todos-feature-highlight","BlogPost","content:en-us:blog:gitlab-todos-feature-highlight.yml","yaml","Gitlab Todos Feature Highlight","content","en-us/blog/gitlab-todos-feature-highlight.yml","en-us/blog/gitlab-todos-feature-highlight","yml",{"_path":33,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"data":35,"_id":444,"_type":26,"title":445,"_source":28,"_file":446,"_stem":447,"_extension":31},"/shared/en-us/main-navigation","en-us",{"logo":36,"freeTrial":41,"sales":46,"login":51,"items":56,"search":385,"minimal":416,"duo":435},{"config":37},{"href":38,"dataGaName":39,"dataGaLocation":40},"/","gitlab logo","header",{"text":42,"config":43},"Get free trial",{"href":44,"dataGaName":45,"dataGaLocation":40},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":47,"config":48},"Talk to sales",{"href":49,"dataGaName":50,"dataGaLocation":40},"/sales/","sales",{"text":52,"config":53},"Sign in",{"href":54,"dataGaName":55,"dataGaLocation":40},"https://gitlab.com/users/sign_in/","sign in",[57,101,197,202,307,366],{"text":58,"config":59,"cards":61,"footer":84},"Platform",{"dataNavLevelOne":60},"platform",[62,68,76],{"title":58,"description":63,"link":64},"The most comprehensive AI-powered DevSecOps Platform",{"text":65,"config":66},"Explore our Platform",{"href":67,"dataGaName":60,"dataGaLocation":40},"/platform/",{"title":69,"description":70,"link":71},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":72,"config":73},"Meet GitLab Duo",{"href":74,"dataGaName":75,"dataGaLocation":40},"/gitlab-duo/","gitlab duo ai",{"title":77,"description":78,"link":79},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":80,"config":81},"Learn more",{"href":82,"dataGaName":83,"dataGaLocation":40},"/why-gitlab/","why gitlab",{"title":85,"items":86},"Get started with",[87,92,97],{"text":88,"config":89},"Platform Engineering",{"href":90,"dataGaName":91,"dataGaLocation":40},"/solutions/platform-engineering/","platform engineering",{"text":93,"config":94},"Developer Experience",{"href":95,"dataGaName":96,"dataGaLocation":40},"/developer-experience/","Developer experience",{"text":98,"config":99},"MLOps",{"href":100,"dataGaName":98,"dataGaLocation":40},"/topics/devops/the-role-of-ai-in-devops/",{"text":102,"left":103,"config":104,"link":106,"lists":110,"footer":179},"Product",true,{"dataNavLevelOne":105},"solutions",{"text":107,"config":108},"View all Solutions",{"href":109,"dataGaName":105,"dataGaLocation":40},"/solutions/",[111,136,158],{"title":112,"description":113,"link":114,"items":119},"Automation","CI/CD and automation to accelerate deployment",{"config":115},{"icon":116,"href":117,"dataGaName":118,"dataGaLocation":40},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[120,124,128,132],{"text":121,"config":122},"CI/CD",{"href":123,"dataGaLocation":40,"dataGaName":121},"/solutions/continuous-integration/",{"text":125,"config":126},"AI-Assisted Development",{"href":74,"dataGaLocation":40,"dataGaName":127},"AI assisted development",{"text":129,"config":130},"Source Code Management",{"href":131,"dataGaLocation":40,"dataGaName":129},"/solutions/source-code-management/",{"text":133,"config":134},"Automated Software Delivery",{"href":117,"dataGaLocation":40,"dataGaName":135},"Automated software delivery",{"title":137,"description":138,"link":139,"items":144},"Security","Deliver code faster without compromising security",{"config":140},{"href":141,"dataGaName":142,"dataGaLocation":40,"icon":143},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[145,148,153],{"text":146,"config":147},"Security & Compliance",{"href":141,"dataGaLocation":40,"dataGaName":146},{"text":149,"config":150},"Software Supply Chain Security",{"href":151,"dataGaLocation":40,"dataGaName":152},"/solutions/supply-chain/","Software supply chain security",{"text":154,"config":155},"Compliance & Governance",{"href":156,"dataGaLocation":40,"dataGaName":157},"/solutions/continuous-software-compliance/","Compliance and governance",{"title":159,"link":160,"items":165},"Measurement",{"config":161},{"icon":162,"href":163,"dataGaName":164,"dataGaLocation":40},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[166,170,174],{"text":167,"config":168},"Visibility & Measurement",{"href":163,"dataGaLocation":40,"dataGaName":169},"Visibility and Measurement",{"text":171,"config":172},"Value Stream Management",{"href":173,"dataGaLocation":40,"dataGaName":171},"/solutions/value-stream-management/",{"text":175,"config":176},"Analytics & Insights",{"href":177,"dataGaLocation":40,"dataGaName":178},"/solutions/analytics-and-insights/","Analytics and insights",{"title":180,"items":181},"GitLab for",[182,187,192],{"text":183,"config":184},"Enterprise",{"href":185,"dataGaLocation":40,"dataGaName":186},"/enterprise/","enterprise",{"text":188,"config":189},"Small Business",{"href":190,"dataGaLocation":40,"dataGaName":191},"/small-business/","small business",{"text":193,"config":194},"Public Sector",{"href":195,"dataGaLocation":40,"dataGaName":196},"/solutions/public-sector/","public sector",{"text":198,"config":199},"Pricing",{"href":200,"dataGaName":201,"dataGaLocation":40,"dataNavLevelOne":201},"/pricing/","pricing",{"text":203,"config":204,"link":206,"lists":210,"feature":294},"Resources",{"dataNavLevelOne":205},"resources",{"text":207,"config":208},"View all resources",{"href":209,"dataGaName":205,"dataGaLocation":40},"/resources/",[211,244,266],{"title":212,"items":213},"Getting started",[214,219,224,229,234,239],{"text":215,"config":216},"Install",{"href":217,"dataGaName":218,"dataGaLocation":40},"/install/","install",{"text":220,"config":221},"Quick start guides",{"href":222,"dataGaName":223,"dataGaLocation":40},"/get-started/","quick setup checklists",{"text":225,"config":226},"Learn",{"href":227,"dataGaLocation":40,"dataGaName":228},"https://university.gitlab.com/","learn",{"text":230,"config":231},"Product documentation",{"href":232,"dataGaName":233,"dataGaLocation":40},"https://docs.gitlab.com/","product documentation",{"text":235,"config":236},"Best practice videos",{"href":237,"dataGaName":238,"dataGaLocation":40},"/getting-started-videos/","best practice videos",{"text":240,"config":241},"Integrations",{"href":242,"dataGaName":243,"dataGaLocation":40},"/integrations/","integrations",{"title":245,"items":246},"Discover",[247,252,256,261],{"text":248,"config":249},"Customer success stories",{"href":250,"dataGaName":251,"dataGaLocation":40},"/customers/","customer success stories",{"text":253,"config":254},"Blog",{"href":255,"dataGaName":5,"dataGaLocation":40},"/blog/",{"text":257,"config":258},"Remote",{"href":259,"dataGaName":260,"dataGaLocation":40},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":262,"config":263},"TeamOps",{"href":264,"dataGaName":265,"dataGaLocation":40},"/teamops/","teamops",{"title":267,"items":268},"Connect",[269,274,279,284,289],{"text":270,"config":271},"GitLab Services",{"href":272,"dataGaName":273,"dataGaLocation":40},"/services/","services",{"text":275,"config":276},"Community",{"href":277,"dataGaName":278,"dataGaLocation":40},"/community/","community",{"text":280,"config":281},"Forum",{"href":282,"dataGaName":283,"dataGaLocation":40},"https://forum.gitlab.com/","forum",{"text":285,"config":286},"Events",{"href":287,"dataGaName":288,"dataGaLocation":40},"/events/","events",{"text":290,"config":291},"Partners",{"href":292,"dataGaName":293,"dataGaLocation":40},"/partners/","partners",{"backgroundColor":295,"textColor":296,"text":297,"image":298,"link":302},"#2f2a6b","#fff","Insights for the future of software development",{"altText":299,"config":300},"the source promo card",{"src":301},"/images/navigation/the-source-promo-card.svg",{"text":303,"config":304},"Read the latest",{"href":305,"dataGaName":306,"dataGaLocation":40},"/the-source/","the source",{"text":308,"config":309,"lists":310},"Company",{"dataNavLevelOne":21},[311],{"items":312},[313,318,324,326,331,336,341,346,351,356,361],{"text":314,"config":315},"About",{"href":316,"dataGaName":317,"dataGaLocation":40},"/company/","about",{"text":319,"config":320,"footerGa":323},"Jobs",{"href":321,"dataGaName":322,"dataGaLocation":40},"/jobs/","jobs",{"dataGaName":322},{"text":285,"config":325},{"href":287,"dataGaName":288,"dataGaLocation":40},{"text":327,"config":328},"Leadership",{"href":329,"dataGaName":330,"dataGaLocation":40},"/company/team/e-group/","leadership",{"text":332,"config":333},"Team",{"href":334,"dataGaName":335,"dataGaLocation":40},"/company/team/","team",{"text":337,"config":338},"Handbook",{"href":339,"dataGaName":340,"dataGaLocation":40},"https://handbook.gitlab.com/","handbook",{"text":342,"config":343},"Investor relations",{"href":344,"dataGaName":345,"dataGaLocation":40},"https://ir.gitlab.com/","investor relations",{"text":347,"config":348},"Trust Center",{"href":349,"dataGaName":350,"dataGaLocation":40},"/security/","trust center",{"text":352,"config":353},"AI Transparency Center",{"href":354,"dataGaName":355,"dataGaLocation":40},"/ai-transparency-center/","ai transparency center",{"text":357,"config":358},"Newsletter",{"href":359,"dataGaName":360,"dataGaLocation":40},"/company/contact/","newsletter",{"text":362,"config":363},"Press",{"href":364,"dataGaName":365,"dataGaLocation":40},"/press/","press",{"text":367,"config":368,"lists":369},"Contact us",{"dataNavLevelOne":21},[370],{"items":371},[372,375,380],{"text":47,"config":373},{"href":49,"dataGaName":374,"dataGaLocation":40},"talk to sales",{"text":376,"config":377},"Get help",{"href":378,"dataGaName":379,"dataGaLocation":40},"/support/","get help",{"text":381,"config":382},"Customer portal",{"href":383,"dataGaName":384,"dataGaLocation":40},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":386,"login":387,"suggestions":394},"Close",{"text":388,"link":389},"To search repositories and projects, login to",{"text":390,"config":391},"gitlab.com",{"href":54,"dataGaName":392,"dataGaLocation":393},"search login","search",{"text":395,"default":396},"Suggestions",[397,399,403,405,409,413],{"text":69,"config":398},{"href":74,"dataGaName":69,"dataGaLocation":393},{"text":400,"config":401},"Code Suggestions (AI)",{"href":402,"dataGaName":400,"dataGaLocation":393},"/solutions/code-suggestions/",{"text":121,"config":404},{"href":123,"dataGaName":121,"dataGaLocation":393},{"text":406,"config":407},"GitLab on AWS",{"href":408,"dataGaName":406,"dataGaLocation":393},"/partners/technology-partners/aws/",{"text":410,"config":411},"GitLab on Google Cloud",{"href":412,"dataGaName":410,"dataGaLocation":393},"/partners/technology-partners/google-cloud-platform/",{"text":414,"config":415},"Why GitLab?",{"href":82,"dataGaName":414,"dataGaLocation":393},{"freeTrial":417,"mobileIcon":422,"desktopIcon":427,"secondaryButton":430},{"text":418,"config":419},"Start free trial",{"href":420,"dataGaName":45,"dataGaLocation":421},"https://gitlab.com/-/trials/new/","nav",{"altText":423,"config":424},"Gitlab Icon",{"src":425,"dataGaName":426,"dataGaLocation":421},"/images/brand/gitlab-logo-tanuki.svg","gitlab icon",{"altText":423,"config":428},{"src":429,"dataGaName":426,"dataGaLocation":421},"/images/brand/gitlab-logo-type.svg",{"text":431,"config":432},"Get Started",{"href":433,"dataGaName":434,"dataGaLocation":421},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":436,"mobileIcon":440,"desktopIcon":442},{"text":437,"config":438},"Learn more about GitLab Duo",{"href":74,"dataGaName":439,"dataGaLocation":421},"gitlab duo",{"altText":423,"config":441},{"src":425,"dataGaName":426,"dataGaLocation":421},{"altText":423,"config":443},{"src":429,"dataGaName":426,"dataGaLocation":421},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":449,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"title":450,"button":451,"config":455,"_id":457,"_type":26,"_source":28,"_file":458,"_stem":459,"_extension":31},"/shared/en-us/banner","GitLab Duo Agent Platform is now in public beta!",{"text":80,"config":452},{"href":453,"dataGaName":454,"dataGaLocation":40},"/gitlab-duo/agent-platform/","duo banner",{"layout":456},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":461,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"data":462,"_id":667,"_type":26,"title":668,"_source":28,"_file":669,"_stem":670,"_extension":31},"/shared/en-us/main-footer",{"text":463,"source":464,"edit":470,"contribute":475,"config":480,"items":485,"minimal":659},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":465,"config":466},"View page source",{"href":467,"dataGaName":468,"dataGaLocation":469},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":471,"config":472},"Edit this page",{"href":473,"dataGaName":474,"dataGaLocation":469},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":476,"config":477},"Please contribute",{"href":478,"dataGaName":479,"dataGaLocation":469},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":481,"facebook":482,"youtube":483,"linkedin":484},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[486,509,566,595,629],{"title":58,"links":487,"subMenu":492},[488],{"text":489,"config":490},"DevSecOps platform",{"href":67,"dataGaName":491,"dataGaLocation":469},"devsecops platform",[493],{"title":198,"links":494},[495,499,504],{"text":496,"config":497},"View plans",{"href":200,"dataGaName":498,"dataGaLocation":469},"view plans",{"text":500,"config":501},"Why Premium?",{"href":502,"dataGaName":503,"dataGaLocation":469},"/pricing/premium/","why premium",{"text":505,"config":506},"Why Ultimate?",{"href":507,"dataGaName":508,"dataGaLocation":469},"/pricing/ultimate/","why ultimate",{"title":510,"links":511},"Solutions",[512,517,520,522,527,532,536,539,543,548,550,553,556,561],{"text":513,"config":514},"Digital transformation",{"href":515,"dataGaName":516,"dataGaLocation":469},"/topics/digital-transformation/","digital transformation",{"text":146,"config":518},{"href":141,"dataGaName":519,"dataGaLocation":469},"security & compliance",{"text":135,"config":521},{"href":117,"dataGaName":118,"dataGaLocation":469},{"text":523,"config":524},"Agile development",{"href":525,"dataGaName":526,"dataGaLocation":469},"/solutions/agile-delivery/","agile delivery",{"text":528,"config":529},"Cloud transformation",{"href":530,"dataGaName":531,"dataGaLocation":469},"/topics/cloud-native/","cloud transformation",{"text":533,"config":534},"SCM",{"href":131,"dataGaName":535,"dataGaLocation":469},"source code management",{"text":121,"config":537},{"href":123,"dataGaName":538,"dataGaLocation":469},"continuous integration & delivery",{"text":540,"config":541},"Value stream management",{"href":173,"dataGaName":542,"dataGaLocation":469},"value stream management",{"text":544,"config":545},"GitOps",{"href":546,"dataGaName":547,"dataGaLocation":469},"/solutions/gitops/","gitops",{"text":183,"config":549},{"href":185,"dataGaName":186,"dataGaLocation":469},{"text":551,"config":552},"Small business",{"href":190,"dataGaName":191,"dataGaLocation":469},{"text":554,"config":555},"Public sector",{"href":195,"dataGaName":196,"dataGaLocation":469},{"text":557,"config":558},"Education",{"href":559,"dataGaName":560,"dataGaLocation":469},"/solutions/education/","education",{"text":562,"config":563},"Financial services",{"href":564,"dataGaName":565,"dataGaLocation":469},"/solutions/finance/","financial services",{"title":203,"links":567},[568,570,572,574,577,579,581,583,585,587,589,591,593],{"text":215,"config":569},{"href":217,"dataGaName":218,"dataGaLocation":469},{"text":220,"config":571},{"href":222,"dataGaName":223,"dataGaLocation":469},{"text":225,"config":573},{"href":227,"dataGaName":228,"dataGaLocation":469},{"text":230,"config":575},{"href":232,"dataGaName":576,"dataGaLocation":469},"docs",{"text":253,"config":578},{"href":255,"dataGaName":5,"dataGaLocation":469},{"text":248,"config":580},{"href":250,"dataGaName":251,"dataGaLocation":469},{"text":257,"config":582},{"href":259,"dataGaName":260,"dataGaLocation":469},{"text":270,"config":584},{"href":272,"dataGaName":273,"dataGaLocation":469},{"text":262,"config":586},{"href":264,"dataGaName":265,"dataGaLocation":469},{"text":275,"config":588},{"href":277,"dataGaName":278,"dataGaLocation":469},{"text":280,"config":590},{"href":282,"dataGaName":283,"dataGaLocation":469},{"text":285,"config":592},{"href":287,"dataGaName":288,"dataGaLocation":469},{"text":290,"config":594},{"href":292,"dataGaName":293,"dataGaLocation":469},{"title":308,"links":596},[597,599,601,603,605,607,609,613,618,620,622,624],{"text":314,"config":598},{"href":316,"dataGaName":21,"dataGaLocation":469},{"text":319,"config":600},{"href":321,"dataGaName":322,"dataGaLocation":469},{"text":327,"config":602},{"href":329,"dataGaName":330,"dataGaLocation":469},{"text":332,"config":604},{"href":334,"dataGaName":335,"dataGaLocation":469},{"text":337,"config":606},{"href":339,"dataGaName":340,"dataGaLocation":469},{"text":342,"config":608},{"href":344,"dataGaName":345,"dataGaLocation":469},{"text":610,"config":611},"Sustainability",{"href":612,"dataGaName":610,"dataGaLocation":469},"/sustainability/",{"text":614,"config":615},"Diversity, inclusion and belonging (DIB)",{"href":616,"dataGaName":617,"dataGaLocation":469},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":347,"config":619},{"href":349,"dataGaName":350,"dataGaLocation":469},{"text":357,"config":621},{"href":359,"dataGaName":360,"dataGaLocation":469},{"text":362,"config":623},{"href":364,"dataGaName":365,"dataGaLocation":469},{"text":625,"config":626},"Modern Slavery Transparency Statement",{"href":627,"dataGaName":628,"dataGaLocation":469},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":630,"links":631},"Contact Us",[632,635,637,639,644,649,654],{"text":633,"config":634},"Contact an expert",{"href":49,"dataGaName":50,"dataGaLocation":469},{"text":376,"config":636},{"href":378,"dataGaName":379,"dataGaLocation":469},{"text":381,"config":638},{"href":383,"dataGaName":384,"dataGaLocation":469},{"text":640,"config":641},"Status",{"href":642,"dataGaName":643,"dataGaLocation":469},"https://status.gitlab.com/","status",{"text":645,"config":646},"Terms of use",{"href":647,"dataGaName":648,"dataGaLocation":469},"/terms/","terms of use",{"text":650,"config":651},"Privacy statement",{"href":652,"dataGaName":653,"dataGaLocation":469},"/privacy/","privacy statement",{"text":655,"config":656},"Cookie preferences",{"dataGaName":657,"dataGaLocation":469,"id":658,"isOneTrustButton":103},"cookie preferences","ot-sdk-btn",{"items":660},[661,663,665],{"text":645,"config":662},{"href":647,"dataGaName":648,"dataGaLocation":469},{"text":650,"config":664},{"href":652,"dataGaName":653,"dataGaLocation":469},{"text":655,"config":666},{"dataGaName":657,"dataGaLocation":469,"id":658,"isOneTrustButton":103},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[672],{"_path":673,"_dir":674,"_draft":6,"_partial":6,"_locale":7,"content":675,"config":679,"_id":681,"_type":26,"title":18,"_source":28,"_file":682,"_stem":683,"_extension":31},"/en-us/blog/authors/douglas-alexandre","authors",{"name":18,"config":676},{"headshot":677,"ctfId":678},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659488/Blog/Author%20Headshots/gitlab-logo-extra-whitespace.png","Douglas-Alexandre",{"template":680},"BlogAuthor","content:en-us:blog:authors:douglas-alexandre.yml","en-us/blog/authors/douglas-alexandre.yml","en-us/blog/authors/douglas-alexandre",{"_path":685,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"header":686,"eyebrow":687,"blurb":688,"button":689,"secondaryButton":693,"_id":695,"_type":26,"title":696,"_source":28,"_file":697,"_stem":698,"_extension":31},"/shared/en-us/next-steps","Start shipping better software faster","50%+ of the Fortune 100 trust GitLab","See what your team can do with the intelligent\n\n\nDevSecOps platform.\n",{"text":42,"config":690},{"href":691,"dataGaName":45,"dataGaLocation":692},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":47,"config":694},{"href":49,"dataGaName":50,"dataGaLocation":692},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1753475379161]