[{"data":1,"prerenderedAt":760},["ShallowReactive",2],{"/en-us/blog/upgrade-to-rails5":3,"navigation-en-us":37,"banner-en-us":464,"footer-en-us":481,"Jan Provaznik":726,"next-steps-en-us":739,"footer-source-/en-us/blog/upgrade-to-rails5/":754},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":27,"_id":30,"_type":31,"title":32,"_source":33,"_file":34,"_stem":35,"_extension":36},"/en-us/blog/upgrade-to-rails5","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"The road to Rails 5","Senior Backend Engineer Jan Provaznik shares some of the challenges we encountered when upgrading GitLab to Rails 5 – and how we overcame them.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683399/Blog/Hero%20Images/road-to-rails-5.jpg","https://about.gitlab.com/blog/upgrade-to-rails5","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"The road to Rails 5\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jan Provaznik\"}],\n        \"datePublished\": \"2019-05-28\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22},[18],"Jan Provaznik","2019-05-28","With [Rails 6 coming\nsoon](https://weblog.rubyonrails.org/2018/12/20/timeline-for-the-release-of-Rails-6-0/)\nit's a good time to look back at the journey we took when upgrading GitLab\nto Rails 5, which was not so long ago.\n\n\n[Our issue for upgrading to Rails\n5](https://gitlab.com/gitlab-org/gitlab-ce/issues/14286) was around for\nquite a while, largely because it was difficult to switch such a big project\nas GitLab instantly to the next major version. Here is a brief story about\nhow we solved this upgrade challenge.\n\n\n## Our solution? Cut it into pieces\n\n\nThe upgrade to Rails 5 was first prepared as a one big merge request. The\nnice thing about this approach is that when the merge request is ready, you\ncan just merge the single merge request without dealing with any backward\ncompatibility. The [first\nattempt](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5555) had\nlower priority and it was later replaced with a [second\nattempt](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12841). But\nfor the GitLab codebase this merge request became pretty big: 151 commits,\nover 120 pushes, and more than 1000 changed files. Then it was almost\nimpossible to get such merge request ready to be merged and keep it up to\ndate without hitting problems with conflicts.\n\n\nRather than trying to get the upgrade done in a single merge request, a\ncouple of changes made it possible to run the application either on Rails 4\nor 5 depending on an environment variable. The application was still running\non Rails 4 by default, but we were able to run it on Rails 5 either locally\nor in CI just by setting `RAILS5` and `BUNDLE_GEMFILE` environment\nvariables. This allowed us to split the upgrade into many small issues.\nTypically each issue addressed one specific type of error in CI, so with\neach fix there were fewer failing tests in CI. Another major benefit was\nthat then it was significantly easier to split the work between more people\nand to get an overview of who was working on what issue.\n\n\nA Rails version-specific Gemfile was loaded depending on the `RAILS5` and\n`BUNDLE_GEMFILE` environment variable. Here is an example of [enabling Rails\n5 in rspec](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18140):\n\n\n```ruby\n\ngemfile = %w[1 true].include?(ENV[\"RAILS5\"]) ? \"Gemfile.rails5\" : \"Gemfile\"\n\nENV['BUNDLE_GEMFILE'] ||= File.expand_path(\"../#{gemfile}\", __dir__)\n\n```\n\n\nThe content of\n[Gemfile.rails5](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17761):\n\n\n```ruby\n\n# BUNDLE_GEMFILE=Gemfile.rails5 bundle install\n\n\nENV[\"RAILS5\"] = \"true\"\n\n\ngemfile = File.expand_path(\"../Gemfile\", __FILE__)\n\n\neval(File.read(gemfile), nil, gemfile)\n\n```\n\n\nAnd the Gemfile:\n\n\n```ruby\n\ndef rails5?\n  %w[1 true].include?(ENV[\"RAILS5\"])\nend\n\n￼\n\ngem_versions = {}\n\ngem_versions['activerecord_sane_schema_dumper'] = rails5? ? '1.0'      :\n'0.2'\n\ngem_versions['default_value_for']               = rails5? ? '~> 3.0.5' : '~>\n3.0.0'\n\ngem_versions['html-pipeline']                   = rails5? ? '~> 2.6.0' : '~>\n1.11.0'\n\ngem_versions['rails']                           = rails5? ? '5.0.6'    :\n'4.2.10'\n\ngem_versions['rails-i18n']                      = rails5? ? '~> 5.1'   : '~>\n4.0.9'\n\n```\n\n\nThere were situations when a fix for Rails 5 was not compatible with Rails 4\nand two different versions of code were needed, typically an Active Record\nquery. For this purpose we used a simple helper method `Gitlab.rails5?` to\ncheck which version was being used and added code for each version. It was\npretty easy to remove all Rails 4-compatible code in the cleanup phase when\nwe upgraded to Rails 5 just by searching for `Gitlab.rails5?` in our\ncodebase.\n\n\nAn example of the check used in `lib/gitlab/database.rb`:\n\n\n```ruby\n\ndef self.cached_table_exists?(table_name)\n  if Gitlab.rails5?\n    connection.schema_cache.data_source_exists?(table_name)\n  else\n    connection.schema_cache.table_exists?(table_name)\n  end\nend\n\n```\n\n\n## Upgrade process\n\n\nTo be able to address upgrade issues in small, separate pieces, we did the\nfollowing steps during the upgrade process:\n\n\n* [Allowed GitLab to run both with Rails 4 and\n5](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17761), but keep\nRails 4 default.\n\n* We also [added support both for Rails 4 and 5 into\nGDK](https://gitlab.com/gitlab-org/gitlab-development-kit/merge_requests/497).\n\n* Fixed all issues until it fully worked with Rails 5 and CI was green.\n\n* Did manual testing to make sure everything will work after the upgrade.\n\n* [Switched to Rails 5 by\ndefault](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21492), (but\nkept Rails 4 code).\n\n* Still enforced compatibility with Rails 4 (by running CI both with Rails 4\nand 5) in case we had to switch back because of a blocker issue.\n\n* Dropped Rails 4 compatibility when we were sure everything worked.\nReleases are done monthly, so we removed Rails 4 code after the next\nrelease.\n\n\n## Major challenges\n\n\n### Active Record changes\n\n\nIn some places we use `Arel` directly and there were various incompatible\nchanges (e.g. [`IN` statement\nissue](https://github.com/rails/arel/issues/531) solved by [this\nfix](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19796)) which\ncaused some of our SQL queries to stop working on Rails 5. (Almost) all of\nthem were discovered during the preparation phase thanks to good test\ncoverage. A list of [database-related changes is\nhere](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?label_name%5B%5D=rails5&label_name%5B%5D=database&scope=all&state=all).\n\n\n### Monkey patches\n\n\nWe keep various monkey patches (either not-merged-yet upstream fixes or\ncustom extensions), many of which required refactoring with the major\nupgrade. The positive is that we were able to get rid of some of them.\n\n\n### Keeping Rails 5 CI green\n\n\nThere was quite a long period between the moment we had all Rails 5 issues\nfixed and the moment we really switched the master branch to Rails 5.\n\nDuring this period we used a scheduled pipeline which ran daily on CE and EE\nmaster branches on Rails 5, so we knew quickly when a new incompatibility\nissue was introduced.\n\nAnother option was running CI jobs both for Rails 4 and 5 for each merge\nrequest and making it mandatory to pass all jobs. The disadvantage of this\noption was it would take twice as much time to run CI.\n\n\nUnfortunately there were many new incompatibility issues introduced during\nthis period. Next time it would be better to run CI for each merge request,\nboth with Rails 4 and 5, although it would require twice as much CI runtime.\n\n\n## Production release\n\n\nOnce we had all known issues in our codebase fixed, we still had additional\nsteps to make sure we didn't hit a critical issue when releasing the next\nversion. [We tracked these steps in this\nissue](https://gitlab.com/gitlab-org/gitlab-ce/issues/48991). We switched\nmaster branches to Rails 5 at the beginning of the development cycle (each\ncycle is one month long). We then ran CI jobs both with Rails 5 (default)\nand 4 (to keep backward compatibility). Timing was important because during\nthe development cycle we discovered a couple of issues and we had enough\ntime to fix them before release. After the release of the next version\n(11.6), when we were sure that we would not have to switch back to Rails 4,\nwe removed Rails 4 both from CI and from the codebase.\n\n\nAlthough it took longer than expected, I think this upgrade was successful\nbecause it didn't cause any production issues. There were a few [major\nissues](https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&utf8=%E2%9C%93&state=closed&label_name[]=rails5&label_name[]=P1)\ndiscovered after switching the master branch, but we were able to fix them\nquickly before release.\n\n\nThis upgrade was done with huge help from our community – especially\n[@blackst0ne](https://gitlab.com/blackst0ne) and\n[@jlemaes](https://gitlab.com/jlemaes). Thank you!\n\n\n## Next steps\n\n\n* The upgrade to Rails 5.1 is [happening\nnow](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24852).\n\n* The upgrade to Rails 5.2 is [still in\nprogress](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8877) –\nunfortunately there are many incompatibilities.\n\n\nBecause upgrades to 5.1 and 5.2 should be relatively small, we aim to do\neach upgrade in a single merge request. The upgrade to Rails 6 is expected\nto be bigger, so hopefully the same approach we used for Rails 5 upgrade\nwill be useful in this case too.\n\n\nPhoto by Cody Board on [Unsplash](https://unsplash.com/photos/2hu-SSktidc)\n\n{: .note}\n","engineering",[23,24,25,26],"collaboration","production","open source","community",{"slug":28,"featured":6,"template":29},"upgrade-to-rails5","BlogPost","content:en-us:blog:upgrade-to-rails5.yml","yaml","Upgrade To Rails5","content","en-us/blog/upgrade-to-rails5.yml","en-us/blog/upgrade-to-rails5","yml",{"_path":38,"_dir":39,"_draft":6,"_partial":6,"_locale":7,"data":40,"_id":460,"_type":31,"title":461,"_source":33,"_file":462,"_stem":463,"_extension":36},"/shared/en-us/main-navigation","en-us",{"logo":41,"freeTrial":46,"sales":51,"login":56,"items":61,"search":391,"minimal":422,"duo":441,"pricingDeployment":450},{"config":42},{"href":43,"dataGaName":44,"dataGaLocation":45},"/","gitlab logo","header",{"text":47,"config":48},"Get free trial",{"href":49,"dataGaName":50,"dataGaLocation":45},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":52,"config":53},"Talk to sales",{"href":54,"dataGaName":55,"dataGaLocation":45},"/sales/","sales",{"text":57,"config":58},"Sign in",{"href":59,"dataGaName":60,"dataGaLocation":45},"https://gitlab.com/users/sign_in/","sign in",[62,106,203,208,312,372],{"text":63,"config":64,"cards":66,"footer":89},"Platform",{"dataNavLevelOne":65},"platform",[67,73,81],{"title":63,"description":68,"link":69},"The most comprehensive AI-powered DevSecOps Platform",{"text":70,"config":71},"Explore our Platform",{"href":72,"dataGaName":65,"dataGaLocation":45},"/platform/",{"title":74,"description":75,"link":76},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":77,"config":78},"Meet GitLab Duo",{"href":79,"dataGaName":80,"dataGaLocation":45},"/gitlab-duo/","gitlab duo ai",{"title":82,"description":83,"link":84},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":85,"config":86},"Learn more",{"href":87,"dataGaName":88,"dataGaLocation":45},"/why-gitlab/","why gitlab",{"title":90,"items":91},"Get started with",[92,97,102],{"text":93,"config":94},"Platform Engineering",{"href":95,"dataGaName":96,"dataGaLocation":45},"/solutions/platform-engineering/","platform engineering",{"text":98,"config":99},"Developer Experience",{"href":100,"dataGaName":101,"dataGaLocation":45},"/developer-experience/","Developer experience",{"text":103,"config":104},"MLOps",{"href":105,"dataGaName":103,"dataGaLocation":45},"/topics/devops/the-role-of-ai-in-devops/",{"text":107,"left":108,"config":109,"link":111,"lists":115,"footer":185},"Product",true,{"dataNavLevelOne":110},"solutions",{"text":112,"config":113},"View all Solutions",{"href":114,"dataGaName":110,"dataGaLocation":45},"/solutions/",[116,141,164],{"title":117,"description":118,"link":119,"items":124},"Automation","CI/CD and automation to accelerate deployment",{"config":120},{"icon":121,"href":122,"dataGaName":123,"dataGaLocation":45},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[125,129,133,137],{"text":126,"config":127},"CI/CD",{"href":128,"dataGaLocation":45,"dataGaName":126},"/solutions/continuous-integration/",{"text":130,"config":131},"AI-Assisted Development",{"href":79,"dataGaLocation":45,"dataGaName":132},"AI assisted development",{"text":134,"config":135},"Source Code Management",{"href":136,"dataGaLocation":45,"dataGaName":134},"/solutions/source-code-management/",{"text":138,"config":139},"Automated Software Delivery",{"href":122,"dataGaLocation":45,"dataGaName":140},"Automated software delivery",{"title":142,"description":143,"link":144,"items":149},"Security","Deliver code faster without compromising security",{"config":145},{"href":146,"dataGaName":147,"dataGaLocation":45,"icon":148},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[150,154,159],{"text":151,"config":152},"Application Security Testing",{"href":146,"dataGaName":153,"dataGaLocation":45},"Application security testing",{"text":155,"config":156},"Software Supply Chain Security",{"href":157,"dataGaLocation":45,"dataGaName":158},"/solutions/supply-chain/","Software supply chain security",{"text":160,"config":161},"Software Compliance",{"href":162,"dataGaName":163,"dataGaLocation":45},"/solutions/software-compliance/","software compliance",{"title":165,"link":166,"items":171},"Measurement",{"config":167},{"icon":168,"href":169,"dataGaName":170,"dataGaLocation":45},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[172,176,180],{"text":173,"config":174},"Visibility & Measurement",{"href":169,"dataGaLocation":45,"dataGaName":175},"Visibility and Measurement",{"text":177,"config":178},"Value Stream Management",{"href":179,"dataGaLocation":45,"dataGaName":177},"/solutions/value-stream-management/",{"text":181,"config":182},"Analytics & Insights",{"href":183,"dataGaLocation":45,"dataGaName":184},"/solutions/analytics-and-insights/","Analytics and insights",{"title":186,"items":187},"GitLab for",[188,193,198],{"text":189,"config":190},"Enterprise",{"href":191,"dataGaLocation":45,"dataGaName":192},"/enterprise/","enterprise",{"text":194,"config":195},"Small Business",{"href":196,"dataGaLocation":45,"dataGaName":197},"/small-business/","small business",{"text":199,"config":200},"Public Sector",{"href":201,"dataGaLocation":45,"dataGaName":202},"/solutions/public-sector/","public sector",{"text":204,"config":205},"Pricing",{"href":206,"dataGaName":207,"dataGaLocation":45,"dataNavLevelOne":207},"/pricing/","pricing",{"text":209,"config":210,"link":212,"lists":216,"feature":299},"Resources",{"dataNavLevelOne":211},"resources",{"text":213,"config":214},"View all resources",{"href":215,"dataGaName":211,"dataGaLocation":45},"/resources/",[217,250,272],{"title":218,"items":219},"Getting started",[220,225,230,235,240,245],{"text":221,"config":222},"Install",{"href":223,"dataGaName":224,"dataGaLocation":45},"/install/","install",{"text":226,"config":227},"Quick start guides",{"href":228,"dataGaName":229,"dataGaLocation":45},"/get-started/","quick setup checklists",{"text":231,"config":232},"Learn",{"href":233,"dataGaLocation":45,"dataGaName":234},"https://university.gitlab.com/","learn",{"text":236,"config":237},"Product documentation",{"href":238,"dataGaName":239,"dataGaLocation":45},"https://docs.gitlab.com/","product documentation",{"text":241,"config":242},"Best practice videos",{"href":243,"dataGaName":244,"dataGaLocation":45},"/getting-started-videos/","best practice videos",{"text":246,"config":247},"Integrations",{"href":248,"dataGaName":249,"dataGaLocation":45},"/integrations/","integrations",{"title":251,"items":252},"Discover",[253,258,262,267],{"text":254,"config":255},"Customer success stories",{"href":256,"dataGaName":257,"dataGaLocation":45},"/customers/","customer success stories",{"text":259,"config":260},"Blog",{"href":261,"dataGaName":5,"dataGaLocation":45},"/blog/",{"text":263,"config":264},"Remote",{"href":265,"dataGaName":266,"dataGaLocation":45},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":268,"config":269},"TeamOps",{"href":270,"dataGaName":271,"dataGaLocation":45},"/teamops/","teamops",{"title":273,"items":274},"Connect",[275,280,284,289,294],{"text":276,"config":277},"GitLab Services",{"href":278,"dataGaName":279,"dataGaLocation":45},"/services/","services",{"text":281,"config":282},"Community",{"href":283,"dataGaName":26,"dataGaLocation":45},"/community/",{"text":285,"config":286},"Forum",{"href":287,"dataGaName":288,"dataGaLocation":45},"https://forum.gitlab.com/","forum",{"text":290,"config":291},"Events",{"href":292,"dataGaName":293,"dataGaLocation":45},"/events/","events",{"text":295,"config":296},"Partners",{"href":297,"dataGaName":298,"dataGaLocation":45},"/partners/","partners",{"backgroundColor":300,"textColor":301,"text":302,"image":303,"link":307},"#2f2a6b","#fff","Insights for the future of software development",{"altText":304,"config":305},"the source promo card",{"src":306},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":308,"config":309},"Read the latest",{"href":310,"dataGaName":311,"dataGaLocation":45},"/the-source/","the source",{"text":313,"config":314,"lists":316},"Company",{"dataNavLevelOne":315},"company",[317],{"items":318},[319,324,330,332,337,342,347,352,357,362,367],{"text":320,"config":321},"About",{"href":322,"dataGaName":323,"dataGaLocation":45},"/company/","about",{"text":325,"config":326,"footerGa":329},"Jobs",{"href":327,"dataGaName":328,"dataGaLocation":45},"/jobs/","jobs",{"dataGaName":328},{"text":290,"config":331},{"href":292,"dataGaName":293,"dataGaLocation":45},{"text":333,"config":334},"Leadership",{"href":335,"dataGaName":336,"dataGaLocation":45},"/company/team/e-group/","leadership",{"text":338,"config":339},"Team",{"href":340,"dataGaName":341,"dataGaLocation":45},"/company/team/","team",{"text":343,"config":344},"Handbook",{"href":345,"dataGaName":346,"dataGaLocation":45},"https://handbook.gitlab.com/","handbook",{"text":348,"config":349},"Investor relations",{"href":350,"dataGaName":351,"dataGaLocation":45},"https://ir.gitlab.com/","investor relations",{"text":353,"config":354},"Trust Center",{"href":355,"dataGaName":356,"dataGaLocation":45},"/security/","trust center",{"text":358,"config":359},"AI Transparency Center",{"href":360,"dataGaName":361,"dataGaLocation":45},"/ai-transparency-center/","ai transparency center",{"text":363,"config":364},"Newsletter",{"href":365,"dataGaName":366,"dataGaLocation":45},"/company/contact/","newsletter",{"text":368,"config":369},"Press",{"href":370,"dataGaName":371,"dataGaLocation":45},"/press/","press",{"text":373,"config":374,"lists":375},"Contact us",{"dataNavLevelOne":315},[376],{"items":377},[378,381,386],{"text":52,"config":379},{"href":54,"dataGaName":380,"dataGaLocation":45},"talk to sales",{"text":382,"config":383},"Support portal",{"href":384,"dataGaName":385,"dataGaLocation":45},"https://support.gitlab.com","support portal",{"text":387,"config":388},"Customer portal",{"href":389,"dataGaName":390,"dataGaLocation":45},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":392,"login":393,"suggestions":400},"Close",{"text":394,"link":395},"To search repositories and projects, login to",{"text":396,"config":397},"gitlab.com",{"href":59,"dataGaName":398,"dataGaLocation":399},"search login","search",{"text":401,"default":402},"Suggestions",[403,405,409,411,415,419],{"text":74,"config":404},{"href":79,"dataGaName":74,"dataGaLocation":399},{"text":406,"config":407},"Code Suggestions (AI)",{"href":408,"dataGaName":406,"dataGaLocation":399},"/solutions/code-suggestions/",{"text":126,"config":410},{"href":128,"dataGaName":126,"dataGaLocation":399},{"text":412,"config":413},"GitLab on AWS",{"href":414,"dataGaName":412,"dataGaLocation":399},"/partners/technology-partners/aws/",{"text":416,"config":417},"GitLab on Google Cloud",{"href":418,"dataGaName":416,"dataGaLocation":399},"/partners/technology-partners/google-cloud-platform/",{"text":420,"config":421},"Why GitLab?",{"href":87,"dataGaName":420,"dataGaLocation":399},{"freeTrial":423,"mobileIcon":428,"desktopIcon":433,"secondaryButton":436},{"text":424,"config":425},"Start free trial",{"href":426,"dataGaName":50,"dataGaLocation":427},"https://gitlab.com/-/trials/new/","nav",{"altText":429,"config":430},"Gitlab Icon",{"src":431,"dataGaName":432,"dataGaLocation":427},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":429,"config":434},{"src":435,"dataGaName":432,"dataGaLocation":427},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":437,"config":438},"Get Started",{"href":439,"dataGaName":440,"dataGaLocation":427},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":442,"mobileIcon":446,"desktopIcon":448},{"text":443,"config":444},"Learn more about GitLab Duo",{"href":79,"dataGaName":445,"dataGaLocation":427},"gitlab duo",{"altText":429,"config":447},{"src":431,"dataGaName":432,"dataGaLocation":427},{"altText":429,"config":449},{"src":435,"dataGaName":432,"dataGaLocation":427},{"freeTrial":451,"mobileIcon":456,"desktopIcon":458},{"text":452,"config":453},"Back to pricing",{"href":206,"dataGaName":454,"dataGaLocation":427,"icon":455},"back to pricing","GoBack",{"altText":429,"config":457},{"src":431,"dataGaName":432,"dataGaLocation":427},{"altText":429,"config":459},{"src":435,"dataGaName":432,"dataGaLocation":427},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":465,"_dir":39,"_draft":6,"_partial":6,"_locale":7,"title":466,"button":467,"image":472,"config":476,"_id":478,"_type":31,"_source":33,"_file":479,"_stem":480,"_extension":36},"/shared/en-us/banner","is now in public beta!",{"text":468,"config":469},"Try the Beta",{"href":470,"dataGaName":471,"dataGaLocation":45},"/gitlab-duo/agent-platform/","duo banner",{"altText":473,"config":474},"GitLab Duo Agent Platform",{"src":475},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":477},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":482,"_dir":39,"_draft":6,"_partial":6,"_locale":7,"data":483,"_id":722,"_type":31,"title":723,"_source":33,"_file":724,"_stem":725,"_extension":36},"/shared/en-us/main-footer",{"text":484,"source":485,"edit":491,"contribute":496,"config":501,"items":506,"minimal":714},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":486,"config":487},"View page source",{"href":488,"dataGaName":489,"dataGaLocation":490},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":492,"config":493},"Edit this page",{"href":494,"dataGaName":495,"dataGaLocation":490},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":497,"config":498},"Please contribute",{"href":499,"dataGaName":500,"dataGaLocation":490},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":502,"facebook":503,"youtube":504,"linkedin":505},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[507,554,607,651,680],{"title":204,"links":508,"subMenu":523},[509,513,518],{"text":510,"config":511},"View plans",{"href":206,"dataGaName":512,"dataGaLocation":490},"view plans",{"text":514,"config":515},"Why Premium?",{"href":516,"dataGaName":517,"dataGaLocation":490},"/pricing/premium/","why premium",{"text":519,"config":520},"Why Ultimate?",{"href":521,"dataGaName":522,"dataGaLocation":490},"/pricing/ultimate/","why ultimate",[524],{"title":525,"links":526},"Contact Us",[527,530,532,534,539,544,549],{"text":528,"config":529},"Contact sales",{"href":54,"dataGaName":55,"dataGaLocation":490},{"text":382,"config":531},{"href":384,"dataGaName":385,"dataGaLocation":490},{"text":387,"config":533},{"href":389,"dataGaName":390,"dataGaLocation":490},{"text":535,"config":536},"Status",{"href":537,"dataGaName":538,"dataGaLocation":490},"https://status.gitlab.com/","status",{"text":540,"config":541},"Terms of use",{"href":542,"dataGaName":543,"dataGaLocation":490},"/terms/","terms of use",{"text":545,"config":546},"Privacy statement",{"href":547,"dataGaName":548,"dataGaLocation":490},"/privacy/","privacy statement",{"text":550,"config":551},"Cookie preferences",{"dataGaName":552,"dataGaLocation":490,"id":553,"isOneTrustButton":108},"cookie preferences","ot-sdk-btn",{"title":107,"links":555,"subMenu":563},[556,560],{"text":557,"config":558},"DevSecOps platform",{"href":72,"dataGaName":559,"dataGaLocation":490},"devsecops platform",{"text":130,"config":561},{"href":79,"dataGaName":562,"dataGaLocation":490},"ai-assisted development",[564],{"title":565,"links":566},"Topics",[567,572,577,582,587,592,597,602],{"text":568,"config":569},"CICD",{"href":570,"dataGaName":571,"dataGaLocation":490},"/topics/ci-cd/","cicd",{"text":573,"config":574},"GitOps",{"href":575,"dataGaName":576,"dataGaLocation":490},"/topics/gitops/","gitops",{"text":578,"config":579},"DevOps",{"href":580,"dataGaName":581,"dataGaLocation":490},"/topics/devops/","devops",{"text":583,"config":584},"Version Control",{"href":585,"dataGaName":586,"dataGaLocation":490},"/topics/version-control/","version control",{"text":588,"config":589},"DevSecOps",{"href":590,"dataGaName":591,"dataGaLocation":490},"/topics/devsecops/","devsecops",{"text":593,"config":594},"Cloud Native",{"href":595,"dataGaName":596,"dataGaLocation":490},"/topics/cloud-native/","cloud native",{"text":598,"config":599},"AI for Coding",{"href":600,"dataGaName":601,"dataGaLocation":490},"/topics/devops/ai-for-coding/","ai for coding",{"text":603,"config":604},"Agentic AI",{"href":605,"dataGaName":606,"dataGaLocation":490},"/topics/agentic-ai/","agentic ai",{"title":608,"links":609},"Solutions",[610,612,614,619,623,626,630,633,635,638,641,646],{"text":151,"config":611},{"href":146,"dataGaName":151,"dataGaLocation":490},{"text":140,"config":613},{"href":122,"dataGaName":123,"dataGaLocation":490},{"text":615,"config":616},"Agile development",{"href":617,"dataGaName":618,"dataGaLocation":490},"/solutions/agile-delivery/","agile delivery",{"text":620,"config":621},"SCM",{"href":136,"dataGaName":622,"dataGaLocation":490},"source code management",{"text":568,"config":624},{"href":128,"dataGaName":625,"dataGaLocation":490},"continuous integration & delivery",{"text":627,"config":628},"Value stream management",{"href":179,"dataGaName":629,"dataGaLocation":490},"value stream management",{"text":573,"config":631},{"href":632,"dataGaName":576,"dataGaLocation":490},"/solutions/gitops/",{"text":189,"config":634},{"href":191,"dataGaName":192,"dataGaLocation":490},{"text":636,"config":637},"Small business",{"href":196,"dataGaName":197,"dataGaLocation":490},{"text":639,"config":640},"Public sector",{"href":201,"dataGaName":202,"dataGaLocation":490},{"text":642,"config":643},"Education",{"href":644,"dataGaName":645,"dataGaLocation":490},"/solutions/education/","education",{"text":647,"config":648},"Financial services",{"href":649,"dataGaName":650,"dataGaLocation":490},"/solutions/finance/","financial services",{"title":209,"links":652},[653,655,657,659,662,664,666,668,670,672,674,676,678],{"text":221,"config":654},{"href":223,"dataGaName":224,"dataGaLocation":490},{"text":226,"config":656},{"href":228,"dataGaName":229,"dataGaLocation":490},{"text":231,"config":658},{"href":233,"dataGaName":234,"dataGaLocation":490},{"text":236,"config":660},{"href":238,"dataGaName":661,"dataGaLocation":490},"docs",{"text":259,"config":663},{"href":261,"dataGaName":5,"dataGaLocation":490},{"text":254,"config":665},{"href":256,"dataGaName":257,"dataGaLocation":490},{"text":263,"config":667},{"href":265,"dataGaName":266,"dataGaLocation":490},{"text":276,"config":669},{"href":278,"dataGaName":279,"dataGaLocation":490},{"text":268,"config":671},{"href":270,"dataGaName":271,"dataGaLocation":490},{"text":281,"config":673},{"href":283,"dataGaName":26,"dataGaLocation":490},{"text":285,"config":675},{"href":287,"dataGaName":288,"dataGaLocation":490},{"text":290,"config":677},{"href":292,"dataGaName":293,"dataGaLocation":490},{"text":295,"config":679},{"href":297,"dataGaName":298,"dataGaLocation":490},{"title":313,"links":681},[682,684,686,688,690,692,694,698,703,705,707,709],{"text":320,"config":683},{"href":322,"dataGaName":315,"dataGaLocation":490},{"text":325,"config":685},{"href":327,"dataGaName":328,"dataGaLocation":490},{"text":333,"config":687},{"href":335,"dataGaName":336,"dataGaLocation":490},{"text":338,"config":689},{"href":340,"dataGaName":341,"dataGaLocation":490},{"text":343,"config":691},{"href":345,"dataGaName":346,"dataGaLocation":490},{"text":348,"config":693},{"href":350,"dataGaName":351,"dataGaLocation":490},{"text":695,"config":696},"Sustainability",{"href":697,"dataGaName":695,"dataGaLocation":490},"/sustainability/",{"text":699,"config":700},"Diversity, inclusion and belonging (DIB)",{"href":701,"dataGaName":702,"dataGaLocation":490},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":353,"config":704},{"href":355,"dataGaName":356,"dataGaLocation":490},{"text":363,"config":706},{"href":365,"dataGaName":366,"dataGaLocation":490},{"text":368,"config":708},{"href":370,"dataGaName":371,"dataGaLocation":490},{"text":710,"config":711},"Modern Slavery Transparency Statement",{"href":712,"dataGaName":713,"dataGaLocation":490},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":715},[716,718,720],{"text":540,"config":717},{"href":542,"dataGaName":543,"dataGaLocation":490},{"text":545,"config":719},{"href":547,"dataGaName":548,"dataGaLocation":490},{"text":550,"config":721},{"dataGaName":552,"dataGaLocation":490,"id":553,"isOneTrustButton":108},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[727],{"_path":728,"_dir":729,"_draft":6,"_partial":6,"_locale":7,"content":730,"config":734,"_id":736,"_type":31,"title":18,"_source":33,"_file":737,"_stem":738,"_extension":36},"/en-us/blog/authors/jan-provaznik","authors",{"name":18,"config":731},{"headshot":732,"ctfId":733},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683397/Blog/Author%20Headshots/jprovaznik-headshot.png","jprovaznik",{"template":735},"BlogAuthor","content:en-us:blog:authors:jan-provaznik.yml","en-us/blog/authors/jan-provaznik.yml","en-us/blog/authors/jan-provaznik",{"_path":740,"_dir":39,"_draft":6,"_partial":6,"_locale":7,"header":741,"eyebrow":742,"blurb":743,"button":744,"secondaryButton":748,"_id":750,"_type":31,"title":751,"_source":33,"_file":752,"_stem":753,"_extension":36},"/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":47,"config":745},{"href":746,"dataGaName":50,"dataGaLocation":747},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":52,"config":749},{"href":54,"dataGaName":55,"dataGaLocation":747},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":755,"content":756,"config":759,"_id":30,"_type":31,"title":32,"_source":33,"_file":34,"_stem":35,"_extension":36},{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},{"title":9,"description":10,"authors":757,"heroImage":11,"date":19,"body":20,"category":21,"tags":758},[18],[23,24,25,26],{"slug":28,"featured":6,"template":29},1761814416484]