[{"data":1,"prerenderedAt":1546},["ShallowReactive",2],{"/blog/upgrade-to-rails5":3,"navigation-en-us":759,"banner-en-us":1186,"footer-en-us":1196,"blog-post-authors-en-us-Jan Provaznik":1441,"blog-related-posts-en-us-upgrade-to-rails5":1456,"blog-promotions-en-us":1482,"next-steps-en-us":1536},{"id":4,"title":5,"authors":6,"body":8,"category":737,"date":738,"description":739,"extension":740,"externalUrl":741,"faq":741,"featured":742,"heroImage":743,"meta":744,"navigation":205,"path":745,"seo":746,"slug":750,"stem":751,"tags":752,"template":757,"updatedDate":741,"__hash__":758},"blogPosts/en-us/blog/upgrade-to-rails5.md","The road to Rails 5",[7],"Jan Provaznik",{"type":9,"value":10,"toc":726},"minimark",[11,22,30,35,50,62,76,182,190,284,287,467,477,483,553,557,560,599,603,608,635,639,642,646,649,652,656,665,674,688,692,711,714,722],[12,13,14,15,21],"p",{},"With ",[16,17,20],"a",{"href":18,"rel":19},"https://weblog.rubyonrails.org/2018/12/20/timeline-for-the-release-of-Rails-6-0/",[],"Rails 6 coming soon"," it's a good time to look back at the journey we took when upgrading GitLab to Rails 5, which was not so long ago.",[12,23,24,29],{},[16,25,28],{"href":26,"rel":27},"https://gitlab.com/gitlab-org/gitlab-ce/issues/14286",[],"Our issue for upgrading to Rails 5"," was around for quite a while, largely because it was difficult to switch such a big project as GitLab instantly to the next major version. Here is a brief story about how we solved this upgrade challenge.",[31,32,34],"h2",{"id":33},"our-solution-cut-it-into-pieces","Our solution? Cut it into pieces",[12,36,37,38,43,44,49],{},"The upgrade to Rails 5 was first prepared as a one big merge request. The nice thing about this approach is that when the merge request is ready, you can just merge the single merge request without dealing with any backward compatibility. The ",[16,39,42],{"href":40,"rel":41},"https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5555",[],"first attempt"," had lower priority and it was later replaced with a ",[16,45,48],{"href":46,"rel":47},"https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12841",[],"second attempt",". But for the GitLab codebase this merge request became pretty big: 151 commits, over 120 pushes, and more than 1000 changed files. Then it was almost impossible to get such merge request ready to be merged and keep it up to date without hitting problems with conflicts.",[12,51,52,53,57,58,61],{},"Rather than trying to get the upgrade done in a single merge request, a couple of changes made it possible to run the application either on Rails 4 or 5 depending on an environment variable. The application was still running on Rails 4 by default, but we were able to run it on Rails 5 either locally or in CI just by setting ",[54,55,56],"code",{},"RAILS5"," and ",[54,59,60],{},"BUNDLE_GEMFILE"," environment variables. This allowed us to split the upgrade into many small issues. Typically each issue addressed one specific type of error in CI, so with each fix there were fewer failing tests in CI. Another major benefit was that then it was significantly easier to split the work between more people and to get an overview of who was working on what issue.",[12,63,64,65,57,67,69,70,75],{},"A Rails version-specific Gemfile was loaded depending on the ",[54,66,56],{},[54,68,60],{}," environment variable. Here is an example of ",[16,71,74],{"href":72,"rel":73},"https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18140",[],"enabling Rails 5 in rspec",":",[77,78,83],"pre",{"className":79,"code":80,"language":81,"meta":82,"style":82},"language-ruby shiki shiki-themes github-light","gemfile = %w[1 true].include?(ENV[\"RAILS5\"]) ? \"Gemfile.rails5\" : \"Gemfile\"\nENV['BUNDLE_GEMFILE'] ||= File.expand_path(\"../#{gemfile}\", __dir__)\n","ruby","",[54,84,85,138],{"__ignoreMap":82},[86,87,90,94,98,102,106,110,113,117,120,123,126,129,132,135],"span",{"class":88,"line":89},"line",1,[86,91,93],{"class":92},"sqxcx","gemfile",[86,95,97],{"class":96},"sD7c4"," =",[86,99,101],{"class":100},"sYBdl"," %w[1 true]",[86,103,105],{"class":104},"sgsFI",".",[86,107,109],{"class":108},"s7eDp","include?",[86,111,112],{"class":104},"(",[86,114,116],{"class":115},"sYu0t","ENV",[86,118,119],{"class":104},"[",[86,121,122],{"class":100},"\"RAILS5\"",[86,124,125],{"class":104},"]) ",[86,127,128],{"class":96},"?",[86,130,131],{"class":100}," \"Gemfile.rails5\"",[86,133,134],{"class":104}," : ",[86,136,137],{"class":100},"\"Gemfile\"\n",[86,139,141,143,145,148,151,154,157,159,162,164,167,170,173,176,179],{"class":88,"line":140},2,[86,142,116],{"class":115},[86,144,119],{"class":104},[86,146,147],{"class":100},"'BUNDLE_GEMFILE'",[86,149,150],{"class":104},"] ",[86,152,153],{"class":96},"||=",[86,155,156],{"class":115}," File",[86,158,105],{"class":104},[86,160,161],{"class":108},"expand_path",[86,163,112],{"class":104},[86,165,166],{"class":100},"\"../",[86,168,169],{"class":100},"#{gemfile}",[86,171,172],{"class":100},"\"",[86,174,175],{"class":104},", ",[86,177,178],{"class":115},"__dir__",[86,180,181],{"class":104},")\n",[12,183,184,185,75],{},"The content of ",[16,186,189],{"href":187,"rel":188},"https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17761",[],"Gemfile.rails5",[77,191,193],{"className":79,"code":192,"language":81,"meta":82,"style":82},"# BUNDLE_GEMFILE=Gemfile.rails5 bundle install\n\nENV[\"RAILS5\"] = \"true\"\n\ngemfile = File.expand_path(\"../Gemfile\", __FILE__)\n\neval(File.read(gemfile), nil, gemfile)\n",[54,194,195,201,207,224,229,254,259],{"__ignoreMap":82},[86,196,197],{"class":88,"line":89},[86,198,200],{"class":199},"sAwPA","# BUNDLE_GEMFILE=Gemfile.rails5 bundle install\n",[86,202,203],{"class":88,"line":140},[86,204,206],{"emptyLinePlaceholder":205},true,"\n",[86,208,210,212,214,216,218,221],{"class":88,"line":209},3,[86,211,116],{"class":115},[86,213,119],{"class":104},[86,215,122],{"class":100},[86,217,150],{"class":104},[86,219,220],{"class":96},"=",[86,222,223],{"class":100}," \"true\"\n",[86,225,227],{"class":88,"line":226},4,[86,228,206],{"emptyLinePlaceholder":205},[86,230,232,234,236,238,240,242,244,247,249,252],{"class":88,"line":231},5,[86,233,93],{"class":92},[86,235,97],{"class":96},[86,237,156],{"class":115},[86,239,105],{"class":104},[86,241,161],{"class":108},[86,243,112],{"class":104},[86,245,246],{"class":100},"\"../Gemfile\"",[86,248,175],{"class":104},[86,250,251],{"class":115},"__FILE__",[86,253,181],{"class":104},[86,255,257],{"class":88,"line":256},6,[86,258,206],{"emptyLinePlaceholder":205},[86,260,262,265,267,270,272,275,278,281],{"class":88,"line":261},7,[86,263,264],{"class":115},"eval",[86,266,112],{"class":104},[86,268,269],{"class":115},"File",[86,271,105],{"class":104},[86,273,274],{"class":108},"read",[86,276,277],{"class":104},"(gemfile), ",[86,279,280],{"class":115},"nil",[86,282,283],{"class":104},", gemfile)\n",[12,285,286],{},"And the Gemfile:",[77,288,290],{"className":79,"code":289,"language":81,"meta":82,"style":82},"def rails5?\n  %w[1 true].include?(ENV[\"RAILS5\"])\nend\n￼\ngem_versions = {}\ngem_versions['activerecord_sane_schema_dumper'] = rails5? ? '1.0'      : '0.2'\ngem_versions['default_value_for']               = rails5? ? '~> 3.0.5' : '~> 3.0.0'\ngem_versions['html-pipeline']                   = rails5? ? '~> 2.6.0' : '~> 1.11.0'\ngem_versions['rails']                           = rails5? ? '5.0.6'    : '4.2.10'\ngem_versions['rails-i18n']                      = rails5? ? '~> 5.1'   : '~> 4.0.9'\n",[54,291,292,300,320,325,330,340,366,390,415,441],{"__ignoreMap":82},[86,293,294,297],{"class":88,"line":89},[86,295,296],{"class":96},"def",[86,298,299],{"class":108}," rails5?\n",[86,301,302,305,307,309,311,313,315,317],{"class":88,"line":140},[86,303,304],{"class":100},"  %w[1 true]",[86,306,105],{"class":104},[86,308,109],{"class":108},[86,310,112],{"class":104},[86,312,116],{"class":115},[86,314,119],{"class":104},[86,316,122],{"class":100},[86,318,319],{"class":104},"])\n",[86,321,322],{"class":88,"line":209},[86,323,324],{"class":96},"end\n",[86,326,327],{"class":88,"line":226},[86,328,329],{"class":104},"￼\n",[86,331,332,335,337],{"class":88,"line":231},[86,333,334],{"class":92},"gem_versions",[86,336,97],{"class":96},[86,338,339],{"class":104}," {}\n",[86,341,342,345,348,350,352,355,357,360,363],{"class":88,"line":256},[86,343,344],{"class":104},"gem_versions[",[86,346,347],{"class":100},"'activerecord_sane_schema_dumper'",[86,349,150],{"class":104},[86,351,220],{"class":96},[86,353,354],{"class":104}," rails5? ",[86,356,128],{"class":96},[86,358,359],{"class":100}," '1.0'",[86,361,362],{"class":104},"      : ",[86,364,365],{"class":100},"'0.2'\n",[86,367,368,370,373,376,378,380,382,385,387],{"class":88,"line":261},[86,369,344],{"class":104},[86,371,372],{"class":100},"'default_value_for'",[86,374,375],{"class":104},"]               ",[86,377,220],{"class":96},[86,379,354],{"class":104},[86,381,128],{"class":96},[86,383,384],{"class":100}," '~> 3.0.5'",[86,386,134],{"class":104},[86,388,389],{"class":100},"'~> 3.0.0'\n",[86,391,393,395,398,401,403,405,407,410,412],{"class":88,"line":392},8,[86,394,344],{"class":104},[86,396,397],{"class":100},"'html-pipeline'",[86,399,400],{"class":104},"]                   ",[86,402,220],{"class":96},[86,404,354],{"class":104},[86,406,128],{"class":96},[86,408,409],{"class":100}," '~> 2.6.0'",[86,411,134],{"class":104},[86,413,414],{"class":100},"'~> 1.11.0'\n",[86,416,418,420,423,426,428,430,432,435,438],{"class":88,"line":417},9,[86,419,344],{"class":104},[86,421,422],{"class":100},"'rails'",[86,424,425],{"class":104},"]                           ",[86,427,220],{"class":96},[86,429,354],{"class":104},[86,431,128],{"class":96},[86,433,434],{"class":100}," '5.0.6'",[86,436,437],{"class":104},"    : ",[86,439,440],{"class":100},"'4.2.10'\n",[86,442,444,446,449,452,454,456,458,461,464],{"class":88,"line":443},10,[86,445,344],{"class":104},[86,447,448],{"class":100},"'rails-i18n'",[86,450,451],{"class":104},"]                      ",[86,453,220],{"class":96},[86,455,354],{"class":104},[86,457,128],{"class":96},[86,459,460],{"class":100}," '~> 5.1'",[86,462,463],{"class":104},"   : ",[86,465,466],{"class":100},"'~> 4.0.9'\n",[12,468,469,470,473,474,476],{},"There were situations when a fix for Rails 5 was not compatible with Rails 4 and two different versions of code were needed, typically an Active Record query. For this purpose we used a simple helper method ",[54,471,472],{},"Gitlab.rails5?"," to check which version was being used and added code for each version. It was pretty easy to remove all Rails 4-compatible code in the cleanup phase when we upgraded to Rails 5 just by searching for ",[54,475,472],{}," in our codebase.",[12,478,479,480,75],{},"An example of the check used in ",[54,481,482],{},"lib/gitlab/database.rb",[77,484,486],{"className":79,"code":485,"language":81,"meta":82,"style":82},"def 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",[54,487,488,498,511,526,531,544,549],{"__ignoreMap":82},[86,489,490,492,495],{"class":88,"line":89},[86,491,296],{"class":96},[86,493,494],{"class":108}," self.cached_table_exists?",[86,496,497],{"class":104},"(table_name)\n",[86,499,500,503,506,508],{"class":88,"line":140},[86,501,502],{"class":96},"  if",[86,504,505],{"class":115}," Gitlab",[86,507,105],{"class":104},[86,509,510],{"class":108},"rails5?\n",[86,512,513,516,519,521,524],{"class":88,"line":209},[86,514,515],{"class":104},"    connection.",[86,517,518],{"class":108},"schema_cache",[86,520,105],{"class":104},[86,522,523],{"class":108},"data_source_exists?",[86,525,497],{"class":104},[86,527,528],{"class":88,"line":226},[86,529,530],{"class":96},"  else\n",[86,532,533,535,537,539,542],{"class":88,"line":231},[86,534,515],{"class":104},[86,536,518],{"class":108},[86,538,105],{"class":104},[86,540,541],{"class":108},"table_exists?",[86,543,497],{"class":104},[86,545,546],{"class":88,"line":256},[86,547,548],{"class":96},"  end\n",[86,550,551],{"class":88,"line":261},[86,552,324],{"class":96},[31,554,556],{"id":555},"upgrade-process","Upgrade process",[12,558,559],{},"To be able to address upgrade issues in small, separate pieces, we did the following steps during the upgrade process:",[561,562,563,571,579,582,585,593,596],"ul",{},[564,565,566,570],"li",{},[16,567,569],{"href":187,"rel":568},[],"Allowed GitLab to run both with Rails 4 and 5",", but keep Rails 4 default.",[564,572,573,574,105],{},"We also ",[16,575,578],{"href":576,"rel":577},"https://gitlab.com/gitlab-org/gitlab-development-kit/merge_requests/497",[],"added support both for Rails 4 and 5 into GDK",[564,580,581],{},"Fixed all issues until it fully worked with Rails 5 and CI was green.",[564,583,584],{},"Did manual testing to make sure everything will work after the upgrade.",[564,586,587,592],{},[16,588,591],{"href":589,"rel":590},"https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21492",[],"Switched to Rails 5 by default",", (but kept Rails 4 code).",[564,594,595],{},"Still enforced compatibility with Rails 4 (by running CI both with Rails 4 and 5) in case we had to switch back because of a blocker issue.",[564,597,598],{},"Dropped Rails 4 compatibility when we were sure everything worked. Releases are done monthly, so we removed Rails 4 code after the next release.",[31,600,602],{"id":601},"major-challenges","Major challenges",[604,605,607],"h3",{"id":606},"active-record-changes","Active Record changes",[12,609,610,611,614,615,623,624,629,630,105],{},"In some places we use ",[54,612,613],{},"Arel"," directly and there were various incompatible changes (e.g. ",[16,616,619,622],{"href":617,"rel":618},"https://github.com/rails/arel/issues/531",[],[54,620,621],{},"IN"," statement issue"," solved by ",[16,625,628],{"href":626,"rel":627},"https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19796",[],"this fix",") which caused some of our SQL queries to stop working on Rails 5. (Almost) all of them were discovered during the preparation phase thanks to good test coverage. A list of ",[16,631,634],{"href":632,"rel":633},"https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?label_name%5B%5D=rails5&label_name%5B%5D=database&scope=all&state=all",[],"database-related changes is here",[604,636,638],{"id":637},"monkey-patches","Monkey patches",[12,640,641],{},"We keep various monkey patches (either not-merged-yet upstream fixes or custom extensions), many of which required refactoring with the major upgrade. The positive is that we were able to get rid of some of them.",[604,643,645],{"id":644},"keeping-rails-5-ci-green","Keeping Rails 5 CI green",[12,647,648],{},"There was quite a long period between the moment we had all Rails 5 issues fixed and the moment we really switched the master branch to Rails 5.\nDuring this period we used a scheduled pipeline which ran daily on CE and EE master branches on Rails 5, so we knew quickly when a new incompatibility issue was introduced.\nAnother option was running CI jobs both for Rails 4 and 5 for each merge request and making it mandatory to pass all jobs. The disadvantage of this option was it would take twice as much time to run CI.",[12,650,651],{},"Unfortunately there were many new incompatibility issues introduced during this period. Next time it would be better to run CI for each merge request, both with Rails 4 and 5, although it would require twice as much CI runtime.",[31,653,655],{"id":654},"production-release","Production release",[12,657,658,659,664],{},"Once we had all known issues in our codebase fixed, we still had additional steps to make sure we didn't hit a critical issue when releasing the next version. ",[16,660,663],{"href":661,"rel":662},"https://gitlab.com/gitlab-org/gitlab-ce/issues/48991",[],"We tracked these steps in this issue",". We switched master branches to Rails 5 at the beginning of the development cycle (each cycle is one month long). We then ran CI jobs both with Rails 5 (default) and 4 (to keep backward compatibility). Timing was important because during the development cycle we discovered a couple of issues and we had enough time to fix them before release. After the release of the next version (11.6), when we were sure that we would not have to switch back to Rails 4, we removed Rails 4 both from CI and from the codebase.",[12,666,667,668,673],{},"Although it took longer than expected, I think this upgrade was successful because it didn't cause any production issues. There were a few ",[16,669,672],{"href":670,"rel":671},"https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&utf8=%E2%9C%93&state=closed&label_name%5B%5D=rails5&label_name%5B%5D=P1",[],"major issues"," discovered after switching the master branch, but we were able to fix them quickly before release.",[12,675,676,677,57,682,687],{},"This upgrade was done with huge help from our community – especially ",[16,678,681],{"href":679,"rel":680},"https://gitlab.com/blackst0ne",[],"@blackst0ne",[16,683,686],{"href":684,"rel":685},"https://gitlab.com/jlemaes",[],"@jlemaes",". Thank you!",[31,689,691],{"id":690},"next-steps","Next steps",[561,693,694,702],{},[564,695,696,697,105],{},"The upgrade to Rails 5.1 is ",[16,698,701],{"href":699,"rel":700},"https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24852",[],"happening now",[564,703,704,705,710],{},"The upgrade to Rails 5.2 is ",[16,706,709],{"href":707,"rel":708},"https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8877",[],"still in progress"," – unfortunately there are many incompatibilities.",[12,712,713],{},"Because upgrades to 5.1 and 5.2 should be relatively small, we aim to do each upgrade in a single merge request. The upgrade to Rails 6 is expected to be bigger, so hopefully the same approach we used for Rails 5 upgrade will be useful in this case too.",[12,715,716,717],{},"Photo by Cody Board on ",[16,718,721],{"href":719,"rel":720},"https://unsplash.com/photos/2hu-SSktidc",[],"Unsplash",[723,724,725],"style",{},"html pre.shiki code .sqxcx, html code.shiki .sqxcx{--shiki-default:#E36209}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}",{"title":82,"searchDepth":140,"depth":140,"links":727},[728,729,730,735,736],{"id":33,"depth":140,"text":34},{"id":555,"depth":140,"text":556},{"id":601,"depth":140,"text":602,"children":731},[732,733,734],{"id":606,"depth":209,"text":607},{"id":637,"depth":209,"text":638},{"id":644,"depth":209,"text":645},{"id":654,"depth":140,"text":655},{"id":690,"depth":140,"text":691},"engineering","2019-05-28","Senior Backend Engineer Jan Provaznik shares some of the challenges we encountered when upgrading GitLab to Rails 5 – and how we overcame them.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683399/Blog/Hero%20Images/road-to-rails-5.jpg",{},"/en-us/blog/upgrade-to-rails5",{"title":5,"description":739,"ogTitle":5,"ogDescription":739,"noIndex":742,"ogImage":743,"ogUrl":747,"ogSiteName":748,"ogType":749,"canonicalUrls":747},"https://about.gitlab.com/blog/upgrade-to-rails5","https://about.gitlab.com","article","upgrade-to-rails5","en-us/blog/upgrade-to-rails5",[753,754,755,756],"collaboration","production","open source","community","BlogPost","_4MjMXo_kTKJu_EVLSRH2Qu0kbXFi8ADFA_KJ4EPmWw",{"logo":760,"freeTrial":765,"sales":770,"login":775,"items":780,"search":1106,"minimal":1137,"duo":1156,"switchNav":1165,"pricingDeployment":1176},{"config":761},{"href":762,"dataGaName":763,"dataGaLocation":764},"/","gitlab logo","header",{"text":766,"config":767},"Get free trial",{"href":768,"dataGaName":769,"dataGaLocation":764},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":771,"config":772},"Request a demo",{"href":773,"dataGaName":774,"dataGaLocation":764},"/sales/?contact-topic=request-demo","sales",{"text":776,"config":777},"Sign in",{"href":778,"dataGaName":779,"dataGaLocation":764},"https://gitlab.com/users/sign_in/","sign in",[781,810,910,915,1028,1084],{"text":782,"config":783,"menu":785},"Platform",{"dataNavLevelOne":784},"platform",{"type":786,"columns":787},"cards",[788,794,802],{"title":782,"description":789,"link":790},"The intelligent orchestration platform for DevSecOps",{"text":791,"config":792},"Explore our Platform",{"href":793,"dataGaName":784,"dataGaLocation":764},"/platform/",{"title":795,"description":796,"link":797},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":798,"config":799},"Meet GitLab Duo",{"href":800,"dataGaName":801,"dataGaLocation":764},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":803,"description":804,"link":805},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":806,"config":807},"Learn more",{"href":808,"dataGaName":809,"dataGaLocation":764},"/why-gitlab/","why gitlab",{"text":811,"left":205,"config":812,"menu":814},"Product",{"dataNavLevelOne":813},"solutions",{"type":815,"link":816,"columns":820,"feature":889},"lists",{"text":817,"config":818},"View all Solutions",{"href":819,"dataGaName":813,"dataGaLocation":764},"/solutions/",[821,845,868],{"title":822,"description":823,"link":824,"items":829},"Automation","CI/CD and automation to accelerate deployment",{"config":825},{"icon":826,"href":827,"dataGaName":828,"dataGaLocation":764},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[830,834,837,841],{"text":831,"config":832},"CI/CD",{"href":833,"dataGaLocation":764,"dataGaName":831},"/solutions/continuous-integration/",{"text":795,"config":835},{"href":800,"dataGaLocation":764,"dataGaName":836},"gitlab duo agent platform - product menu",{"text":838,"config":839},"Source Code Management",{"href":840,"dataGaLocation":764,"dataGaName":838},"/solutions/source-code-management/",{"text":842,"config":843},"Automated Software Delivery",{"href":827,"dataGaLocation":764,"dataGaName":844},"Automated software delivery",{"title":846,"description":847,"link":848,"items":853},"Security","Deliver code faster without compromising security",{"config":849},{"href":850,"dataGaName":851,"dataGaLocation":764,"icon":852},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[854,858,863],{"text":855,"config":856},"Application Security Testing",{"href":850,"dataGaName":857,"dataGaLocation":764},"Application security testing",{"text":859,"config":860},"Software Supply Chain Security",{"href":861,"dataGaLocation":764,"dataGaName":862},"/solutions/supply-chain/","Software supply chain security",{"text":864,"config":865},"Software Compliance",{"href":866,"dataGaName":867,"dataGaLocation":764},"/solutions/software-compliance/","software compliance",{"title":869,"link":870,"items":875},"Measurement",{"config":871},{"icon":872,"href":873,"dataGaName":874,"dataGaLocation":764},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[876,880,884],{"text":877,"config":878},"Visibility & Measurement",{"href":873,"dataGaLocation":764,"dataGaName":879},"Visibility and Measurement",{"text":881,"config":882},"Value Stream Management",{"href":883,"dataGaLocation":764,"dataGaName":881},"/solutions/value-stream-management/",{"text":885,"config":886},"Analytics & Insights",{"href":887,"dataGaLocation":764,"dataGaName":888},"/solutions/analytics-and-insights/","Analytics and insights",{"title":890,"type":815,"items":891},"GitLab for",[892,898,904],{"text":893,"config":894},"Enterprise",{"icon":895,"href":896,"dataGaLocation":764,"dataGaName":897},"Building","/enterprise/","enterprise",{"text":899,"config":900},"Small Business",{"icon":901,"href":902,"dataGaLocation":764,"dataGaName":903},"Work","/small-business/","small business",{"text":905,"config":906},"Public Sector",{"icon":907,"href":908,"dataGaLocation":764,"dataGaName":909},"Organization","/solutions/public-sector/","public sector",{"text":911,"config":912},"Pricing",{"href":913,"dataGaName":914,"dataGaLocation":764,"dataNavLevelOne":914},"/pricing/","pricing",{"text":916,"config":917,"menu":919},"Resources",{"dataNavLevelOne":918},"resources",{"type":815,"link":920,"columns":924,"feature":1017},{"text":921,"config":922},"View all resources",{"href":923,"dataGaName":918,"dataGaLocation":764},"/resources/",[925,958,985],{"title":926,"items":927},"Getting started",[928,933,938,943,948,953],{"text":929,"config":930},"Install",{"href":931,"dataGaName":932,"dataGaLocation":764},"/install/","install",{"text":934,"config":935},"Quick start guides",{"href":936,"dataGaName":937,"dataGaLocation":764},"/get-started/","quick setup checklists",{"text":939,"config":940},"Learn",{"href":941,"dataGaLocation":764,"dataGaName":942},"https://university.gitlab.com/","learn",{"text":944,"config":945},"Product documentation",{"href":946,"dataGaName":947,"dataGaLocation":764},"https://docs.gitlab.com/","product documentation",{"text":949,"config":950},"Best practice videos",{"href":951,"dataGaName":952,"dataGaLocation":764},"/getting-started-videos/","best practice videos",{"text":954,"config":955},"Integrations",{"href":956,"dataGaName":957,"dataGaLocation":764},"/integrations/","integrations",{"title":959,"items":960},"Discover",[961,966,971,976,980],{"text":962,"config":963},"Customer success stories",{"href":964,"dataGaName":965,"dataGaLocation":764},"/customers/","customer success stories",{"text":967,"config":968},"Blog",{"href":969,"dataGaName":970,"dataGaLocation":764},"/blog/","blog",{"text":972,"config":973},"Demo Hub",{"href":974,"dataGaName":975,"dataGaLocation":764},"/demo-hub/","demo hub",{"text":977,"config":978},"The Source",{"href":979,"dataGaName":970,"dataGaLocation":764},"/the-source/",{"text":981,"config":982},"Remote",{"href":983,"dataGaName":984,"dataGaLocation":764},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":986,"items":987},"Connect",[988,993,998,1002,1007,1012],{"text":989,"config":990},"GitLab Services",{"href":991,"dataGaName":992,"dataGaLocation":764},"/services/","services",{"text":994,"config":995},"Contribute",{"href":996,"dataGaName":997,"dataGaLocation":764},"https://contributors.gitlab.com","contribute",{"text":999,"config":1000},"Community",{"href":1001,"dataGaName":756,"dataGaLocation":764},"/community/",{"text":1003,"config":1004},"Forum",{"href":1005,"dataGaName":1006,"dataGaLocation":764},"https://forum.gitlab.com/","forum",{"text":1008,"config":1009},"Events",{"href":1010,"dataGaName":1011,"dataGaLocation":764},"/events/","events",{"text":1013,"config":1014},"Partners",{"href":1015,"dataGaName":1016,"dataGaLocation":764},"/partners/","partners",{"config":1018,"title":1021,"text":1022,"link":1023},{"background":1019,"textColor":1020},"url('https://res.cloudinary.com/about-gitlab-com/image/upload/v1777322348/qpq8yrgn8knii57omj0c.png')","#000","What’s new in GitLab","Stay updated with our latest features and improvements.",{"text":1024,"config":1025},"Read the latest",{"href":1026,"dataGaName":1027,"dataGaLocation":764},"/whats-new/","whats new",{"text":1029,"config":1030,"menu":1032},"Company",{"dataNavLevelOne":1031},"company",{"type":815,"columns":1033},[1034],{"items":1035},[1036,1041,1047,1049,1054,1059,1064,1069,1074,1079],{"text":1037,"config":1038},"About",{"href":1039,"dataGaName":1040,"dataGaLocation":764},"/company/","about",{"text":1042,"config":1043,"footerGa":1046},"Jobs",{"href":1044,"dataGaName":1045,"dataGaLocation":764},"/jobs/","jobs",{"dataGaName":1045},{"text":1008,"config":1048},{"href":1010,"dataGaName":1011,"dataGaLocation":764},{"text":1050,"config":1051},"Leadership",{"href":1052,"dataGaName":1053,"dataGaLocation":764},"/company/team/e-group/","leadership",{"text":1055,"config":1056},"Handbook",{"href":1057,"dataGaName":1058,"dataGaLocation":764},"https://handbook.gitlab.com/","handbook",{"text":1060,"config":1061},"Investor relations",{"href":1062,"dataGaName":1063,"dataGaLocation":764},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1065,"config":1066},"Trust Center",{"href":1067,"dataGaName":1068,"dataGaLocation":764},"/security/","trust center",{"text":1070,"config":1071},"AI Transparency Center",{"href":1072,"dataGaName":1073,"dataGaLocation":764},"/ai-transparency-center/","ai transparency center",{"text":1075,"config":1076},"Newsletter",{"href":1077,"dataGaName":1078,"dataGaLocation":764},"/company/contact/#contact-forms","newsletter",{"text":1080,"config":1081},"Press",{"href":1082,"dataGaName":1083,"dataGaLocation":764},"/press/","press",{"text":1085,"config":1086,"menu":1087},"Contact us",{"dataNavLevelOne":1031},{"type":815,"columns":1088},[1089],{"items":1090},[1091,1096,1101],{"text":1092,"config":1093},"Talk to sales",{"href":1094,"dataGaName":1095,"dataGaLocation":764},"/sales/","talk to sales",{"text":1097,"config":1098},"Support portal",{"href":1099,"dataGaName":1100,"dataGaLocation":764},"https://support.gitlab.com/hc/en-us","support portal",{"text":1102,"config":1103},"Customer portal",{"href":1104,"dataGaName":1105,"dataGaLocation":764},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1107,"login":1108,"suggestions":1115},"Close",{"text":1109,"link":1110},"To search repositories and projects, login to",{"text":1111,"config":1112},"gitlab.com",{"href":778,"dataGaName":1113,"dataGaLocation":1114},"search login","search",{"text":1116,"default":1117},"Suggestions",[1118,1120,1124,1126,1130,1134],{"text":795,"config":1119},{"href":800,"dataGaName":795,"dataGaLocation":1114},{"text":1121,"config":1122},"Code Suggestions (AI)",{"href":1123,"dataGaName":1121,"dataGaLocation":1114},"/solutions/code-suggestions/",{"text":831,"config":1125},{"href":833,"dataGaName":831,"dataGaLocation":1114},{"text":1127,"config":1128},"GitLab on AWS",{"href":1129,"dataGaName":1127,"dataGaLocation":1114},"/partners/technology-partners/aws/",{"text":1131,"config":1132},"GitLab on Google Cloud",{"href":1133,"dataGaName":1131,"dataGaLocation":1114},"/partners/technology-partners/google-cloud-platform/",{"text":1135,"config":1136},"Why GitLab?",{"href":808,"dataGaName":1135,"dataGaLocation":1114},{"freeTrial":1138,"mobileIcon":1143,"desktopIcon":1148,"secondaryButton":1151},{"text":1139,"config":1140},"Start free trial",{"href":1141,"dataGaName":769,"dataGaLocation":1142},"https://gitlab.com/-/trials/new/","nav",{"altText":1144,"config":1145},"Gitlab Icon",{"src":1146,"dataGaName":1147,"dataGaLocation":1142},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1144,"config":1149},{"src":1150,"dataGaName":1147,"dataGaLocation":1142},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1152,"config":1153},"Get Started",{"href":1154,"dataGaName":1155,"dataGaLocation":1142},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1157,"mobileIcon":1161,"desktopIcon":1163},{"text":1158,"config":1159},"Learn more about GitLab Duo",{"href":800,"dataGaName":1160,"dataGaLocation":1142},"gitlab duo",{"altText":1144,"config":1162},{"src":1146,"dataGaName":1147,"dataGaLocation":1142},{"altText":1144,"config":1164},{"src":1150,"dataGaName":1147,"dataGaLocation":1142},{"button":1166,"mobileIcon":1171,"desktopIcon":1173},{"text":1167,"config":1168},"/switch",{"href":1169,"dataGaName":1170,"dataGaLocation":1142},"#contact","switch",{"altText":1144,"config":1172},{"src":1146,"dataGaName":1147,"dataGaLocation":1142},{"altText":1144,"config":1174},{"src":1175,"dataGaName":1147,"dataGaLocation":1142},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1177,"mobileIcon":1182,"desktopIcon":1184},{"text":1178,"config":1179},"Back to pricing",{"href":913,"dataGaName":1180,"dataGaLocation":1142,"icon":1181},"back to pricing","GoBack",{"altText":1144,"config":1183},{"src":1146,"dataGaName":1147,"dataGaLocation":1142},{"altText":1144,"config":1185},{"src":1150,"dataGaName":1147,"dataGaLocation":1142},{"title":1187,"titleMobile":1188,"button":1189,"config":1194},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":806,"config":1190},{"href":1191,"dataGaName":1192,"dataGaLocation":1193},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":1195,"disabled":742},"release",{"data":1197},{"text":1198,"source":1199,"edit":1205,"contribute":1210,"config":1215,"items":1220,"minimal":1430},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1200,"config":1201},"View page source",{"href":1202,"dataGaName":1203,"dataGaLocation":1204},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1206,"config":1207},"Edit this page",{"href":1208,"dataGaName":1209,"dataGaLocation":1204},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1211,"config":1212},"Please contribute",{"href":1213,"dataGaName":1214,"dataGaLocation":1204},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1216,"facebook":1217,"youtube":1218,"linkedin":1219},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1221,1268,1322,1366,1398],{"title":911,"links":1222,"subMenu":1237},[1223,1227,1232],{"text":1224,"config":1225},"View plans",{"href":913,"dataGaName":1226,"dataGaLocation":1204},"view plans",{"text":1228,"config":1229},"Why Premium?",{"href":1230,"dataGaName":1231,"dataGaLocation":1204},"/pricing/premium/","why premium",{"text":1233,"config":1234},"Why Ultimate?",{"href":1235,"dataGaName":1236,"dataGaLocation":1204},"/pricing/ultimate/","why ultimate",[1238],{"title":1239,"links":1240},"Contact Us",[1241,1244,1246,1248,1253,1258,1263],{"text":1242,"config":1243},"Contact sales",{"href":1094,"dataGaName":774,"dataGaLocation":1204},{"text":1097,"config":1245},{"href":1099,"dataGaName":1100,"dataGaLocation":1204},{"text":1102,"config":1247},{"href":1104,"dataGaName":1105,"dataGaLocation":1204},{"text":1249,"config":1250},"Status",{"href":1251,"dataGaName":1252,"dataGaLocation":1204},"https://status.gitlab.com/","status",{"text":1254,"config":1255},"Terms of use",{"href":1256,"dataGaName":1257,"dataGaLocation":1204},"/terms/","terms of use",{"text":1259,"config":1260},"Privacy statement",{"href":1261,"dataGaName":1262,"dataGaLocation":1204},"/privacy/","privacy statement",{"text":1264,"config":1265},"Cookie preferences",{"dataGaName":1266,"dataGaLocation":1204,"id":1267,"isOneTrustButton":205},"cookie preferences","ot-sdk-btn",{"title":811,"links":1269,"subMenu":1278},[1270,1274],{"text":1271,"config":1272},"DevSecOps platform",{"href":793,"dataGaName":1273,"dataGaLocation":1204},"devsecops platform",{"text":1275,"config":1276},"AI-Assisted Development",{"href":800,"dataGaName":1277,"dataGaLocation":1204},"ai-assisted development",[1279],{"title":1280,"links":1281},"Topics",[1282,1287,1292,1297,1302,1307,1312,1317],{"text":1283,"config":1284},"CICD",{"href":1285,"dataGaName":1286,"dataGaLocation":1204},"/topics/ci-cd/","cicd",{"text":1288,"config":1289},"GitOps",{"href":1290,"dataGaName":1291,"dataGaLocation":1204},"/topics/gitops/","gitops",{"text":1293,"config":1294},"DevOps",{"href":1295,"dataGaName":1296,"dataGaLocation":1204},"/topics/devops/","devops",{"text":1298,"config":1299},"Version Control",{"href":1300,"dataGaName":1301,"dataGaLocation":1204},"/topics/version-control/","version control",{"text":1303,"config":1304},"DevSecOps",{"href":1305,"dataGaName":1306,"dataGaLocation":1204},"/topics/devsecops/","devsecops",{"text":1308,"config":1309},"Cloud Native",{"href":1310,"dataGaName":1311,"dataGaLocation":1204},"/topics/cloud-native/","cloud native",{"text":1313,"config":1314},"AI for Coding",{"href":1315,"dataGaName":1316,"dataGaLocation":1204},"/topics/devops/ai-for-coding/","ai for coding",{"text":1318,"config":1319},"Agentic AI",{"href":1320,"dataGaName":1321,"dataGaLocation":1204},"/topics/agentic-ai/","agentic ai",{"title":1323,"links":1324},"Solutions",[1325,1327,1329,1334,1338,1341,1345,1348,1350,1353,1356,1361],{"text":855,"config":1326},{"href":850,"dataGaName":855,"dataGaLocation":1204},{"text":844,"config":1328},{"href":827,"dataGaName":828,"dataGaLocation":1204},{"text":1330,"config":1331},"Agile development",{"href":1332,"dataGaName":1333,"dataGaLocation":1204},"/solutions/agile-delivery/","agile delivery",{"text":1335,"config":1336},"SCM",{"href":840,"dataGaName":1337,"dataGaLocation":1204},"source code management",{"text":1283,"config":1339},{"href":833,"dataGaName":1340,"dataGaLocation":1204},"continuous integration & delivery",{"text":1342,"config":1343},"Value stream management",{"href":883,"dataGaName":1344,"dataGaLocation":1204},"value stream management",{"text":1288,"config":1346},{"href":1347,"dataGaName":1291,"dataGaLocation":1204},"/solutions/gitops/",{"text":893,"config":1349},{"href":896,"dataGaName":897,"dataGaLocation":1204},{"text":1351,"config":1352},"Small business",{"href":902,"dataGaName":903,"dataGaLocation":1204},{"text":1354,"config":1355},"Public sector",{"href":908,"dataGaName":909,"dataGaLocation":1204},{"text":1357,"config":1358},"Education",{"href":1359,"dataGaName":1360,"dataGaLocation":1204},"/solutions/education/","education",{"text":1362,"config":1363},"Financial services",{"href":1364,"dataGaName":1365,"dataGaLocation":1204},"/solutions/finance/","financial services",{"title":916,"links":1367},[1368,1370,1372,1374,1377,1379,1382,1384,1386,1388,1390,1392,1394,1396],{"text":929,"config":1369},{"href":931,"dataGaName":932,"dataGaLocation":1204},{"text":934,"config":1371},{"href":936,"dataGaName":937,"dataGaLocation":1204},{"text":939,"config":1373},{"href":941,"dataGaName":942,"dataGaLocation":1204},{"text":944,"config":1375},{"href":946,"dataGaName":1376,"dataGaLocation":1204},"docs",{"text":967,"config":1378},{"href":969,"dataGaName":970,"dataGaLocation":1204},{"text":1380,"config":1381},"What's new",{"href":1026,"dataGaName":1027,"dataGaLocation":1204},{"text":962,"config":1383},{"href":964,"dataGaName":965,"dataGaLocation":1204},{"text":981,"config":1385},{"href":983,"dataGaName":984,"dataGaLocation":1204},{"text":989,"config":1387},{"href":991,"dataGaName":992,"dataGaLocation":1204},{"text":994,"config":1389},{"href":996,"dataGaName":997,"dataGaLocation":1204},{"text":999,"config":1391},{"href":1001,"dataGaName":756,"dataGaLocation":1204},{"text":1003,"config":1393},{"href":1005,"dataGaName":1006,"dataGaLocation":1204},{"text":1008,"config":1395},{"href":1010,"dataGaName":1011,"dataGaLocation":1204},{"text":1013,"config":1397},{"href":1015,"dataGaName":1016,"dataGaLocation":1204},{"title":1029,"links":1399},[1400,1402,1404,1406,1408,1410,1414,1419,1421,1423,1425],{"text":1037,"config":1401},{"href":1039,"dataGaName":1031,"dataGaLocation":1204},{"text":1042,"config":1403},{"href":1044,"dataGaName":1045,"dataGaLocation":1204},{"text":1050,"config":1405},{"href":1052,"dataGaName":1053,"dataGaLocation":1204},{"text":1055,"config":1407},{"href":1057,"dataGaName":1058,"dataGaLocation":1204},{"text":1060,"config":1409},{"href":1062,"dataGaName":1063,"dataGaLocation":1204},{"text":1411,"config":1412},"Sustainability",{"href":1413,"dataGaName":1411,"dataGaLocation":1204},"/sustainability/",{"text":1415,"config":1416},"Diversity, inclusion and belonging (DIB)",{"href":1417,"dataGaName":1418,"dataGaLocation":1204},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1065,"config":1420},{"href":1067,"dataGaName":1068,"dataGaLocation":1204},{"text":1075,"config":1422},{"href":1077,"dataGaName":1078,"dataGaLocation":1204},{"text":1080,"config":1424},{"href":1082,"dataGaName":1083,"dataGaLocation":1204},{"text":1426,"config":1427},"Modern Slavery Transparency Statement",{"href":1428,"dataGaName":1429,"dataGaLocation":1204},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1431},[1432,1435,1438],{"text":1433,"config":1434},"Terms",{"href":1256,"dataGaName":1257,"dataGaLocation":1204},{"text":1436,"config":1437},"Cookies",{"dataGaName":1266,"dataGaLocation":1204,"id":1267,"isOneTrustButton":205},{"text":1439,"config":1440},"Privacy",{"href":1261,"dataGaName":1262,"dataGaLocation":1204},[1442],{"id":1443,"title":7,"body":741,"config":1444,"content":1446,"description":741,"extension":1450,"meta":1451,"navigation":205,"path":1452,"seo":1453,"stem":1454,"__hash__":1455},"blogAuthors/en-us/blog/authors/jan-provaznik.yml",{"template":1445},"BlogAuthor",{"name":7,"config":1447},{"headshot":1448,"ctfId":1449},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683397/Blog/Author%20Headshots/jprovaznik-headshot.png","jprovaznik","yml",{},"/en-us/blog/authors/jan-provaznik",{},"en-us/blog/authors/jan-provaznik","JYWVbiLV1H7e2Iy-ml98QPczLYM46vJqPXryX69ROhk",[1457,1466,1474],{"title":1458,"description":1459,"heroImage":1460,"category":737,"date":1461,"authors":1462,"slug":1465,"externalUrl":741},"Confidential AI for GitLab Self-Hosted","Give developers AI coding agents in GitLab Duo without source code leaving a hardware-encrypted boundary — no GPUs needed.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1773866173/vte9qh8rriznvyclhkes.png","2026-08-06",[1463,1464],"Mathias Ewald","Martin Paloncy, Edgeless Systems","confidential-ai-for-gitlab-self-hosted",{"title":1467,"description":1468,"heroImage":1469,"category":737,"date":1470,"authors":1471,"slug":1473,"externalUrl":741},"Green DevOps: Why carbon measurement belongs in your CI/CD pipeline","CI/CD pipelines have a hidden carbon cost. Here's why measuring it matters, and how you can get started with Eco CI and Carmen in GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1765809212/noh0mdfn9o94ry9ykura.png","2026-07-09",[1472],"Lysanne Pinto","green-devops-carbon-measurement-cicd-pipeline",{"title":1475,"description":1476,"heroImage":1477,"category":737,"date":1478,"authors":1479,"slug":1481,"externalUrl":741},"How to build CI/CD observability at scale","This practical guide to GitLab pipeline analytics helps self-managed users gain operational insights using Prometheus and Grafana.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1774465167/n5hlvrsrheadeccyr1oz.png","2026-04-28",[1480],"Paul Meresanu","how-to-build-ci-cd-observability-at-scale",{"promotions":1483},[1484,1498,1510,1522],{"id":1485,"categories":1486,"header":1488,"text":1489,"button":1490,"image":1495},"ai-modernization",[1487],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1491,"config":1492},"Get your AI maturity score",{"href":1493,"dataGaName":1494,"dataGaLocation":970},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1496},{"src":1497},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1499,"categories":1500,"header":1502,"text":1489,"button":1503,"image":1507},"devops-modernization",[1501,1306],"product","Are you just managing tools or shipping innovation?",{"text":1504,"config":1505},"Get your DevOps maturity score",{"href":1506,"dataGaName":1494,"dataGaLocation":970},"/assessments/devops-modernization-assessment/",{"config":1508},{"src":1509},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1511,"categories":1512,"header":1514,"text":1489,"button":1515,"image":1519},"security-modernization",[1513],"security","Are you trading speed for security?",{"text":1516,"config":1517},"Get your security maturity score",{"href":1518,"dataGaName":1494,"dataGaLocation":970},"/assessments/security-modernization-assessment/",{"config":1520},{"src":1521},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1523,"paths":1524,"header":1527,"text":1528,"button":1529,"image":1534},"github-azure-migration",[1525,1526],"migration-from-azure-devops-to-gitlab","integrating-azure-devops-scm-and-gitlab","Is your team ready for GitHub's Azure move?","GitHub is already rebuilding around Azure. Find out what it means for you.",{"text":1530,"config":1531},"See how GitLab compares to GitHub",{"href":1532,"dataGaName":1533,"dataGaLocation":970},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1535},{"src":1509},{"header":1537,"blurb":1538,"button":1539,"secondaryButton":1544},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1540,"config":1541},"Get your free trial",{"href":1542,"dataGaName":769,"dataGaLocation":1543},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1242,"config":1545},{"href":1094,"dataGaName":774,"dataGaLocation":1543},1786803776248]