[{"data":1,"prerenderedAt":718},["ShallowReactive",2],{"/en-us/blog/dependency-proxy-updates/":3,"navigation-en-us":35,"banner-en-us":463,"footer-en-us":480,"Steve Abrams":690,"next-steps-en-us":703},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":25,"_id":28,"_type":29,"title":30,"_source":31,"_file":32,"_stem":33,"_extension":34},"/en-us/blog/dependency-proxy-updates","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Using the Dependency Proxy to improve your pipelines","The Dependency Proxy helps make pipelines faster and mitigates Docker Hub rate limits.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681815/Blog/Hero%20Images/dependency_proxy_header.jpg","https://about.gitlab.com/blog/dependency-proxy-updates","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Using the Dependency Proxy to improve your pipelines\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Steve Abrams\"}],\n        \"datePublished\": \"2020-12-15\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22},[18],"Steve Abrams","2020-12-15","{::options parse_block_html=\"true\" /}\n\n\n\n\nHi! I'm Steve, a backend engineer at GitLab. I work on the Package stage,\nwhich includes the Dependency Proxy.\n\n\nIn versions 13.6 and 13.7, we improved the [Dependency\nProxy](https://docs.gitlab.com/ee/user/packages/dependency_proxy/) so it's\nno longer an [MVC\nfeature](https://handbook.gitlab.com/handbook/product/product-principles/#the-minimal-viable-change-mvc).\nBefore, the Dependency Proxy was only available to paid users who may have\nbeen wary to use it, because they did not want to be forced to use a public\ngroup. Now the Dependency Proxy is a robust free feature that can really\nprovide value for free and paid users alike.\n\n\nIf you haven't tried the feature out before, now is a great time to take a\nlook. If you have previously tried the Dependency Proxy and found it was not\nquite the solution you were looking for, I invite you to take a look at the\nnew functionality detailed here. The Dependency Proxy is more available,\nmore secure, and easier to use than ever. These updates also come right as\nDocker Hub has rolled out rate limits on image pulls, which the Dependency\nProxy can help alleviate.\n\n\nYou can also watch a demo of most of these features in this video:\n\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/Nc4nUo7Pq08\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\u003C!-- blank line -->\n\n\n## Move to Core\n\n\nIn 13.6, we moved the [Dependency Proxy to\nCore](/releases/2020/11/22/gitlab-13-6-released/#the-dependency-proxy-is-now-open-source).\nThe ability to speed up pipelines and create a safety net behind Docker Hub\nseemed like functionality that everyone should benefit from.\n\n\n## Support for private groups\n\n\nStarting in 13.7, you can now use the Dependency Proxy with all groups. Each\ngroup and subgroup can have its own space to cache images.\n\n\n![Dependency Proxy\ninterface](https://about.gitlab.com/images/blogimages/dependency_proxy_interface.png)\n\n\n## Authentication\n\n\n[Authentication](https://docs.gitlab.com/ee/user/packages/dependency_proxy/#authenticate-with-the-dependency-proxy)\nis also new in 13.7. If you had previously used the Dependency Proxy, you\nwill need to update your CI scripts or workflow to make sure that you are\nnow logged in.\n\n\nAuthentication was not only necessary to enable the ability to support\nprivate groups with the Dependency Proxy, but it's also a security upgrade.\nThe Dependency Proxy caches image data in your group's storage, so without\nauthentication, public groups could easily be abused to store images that\nyour group might not even be using.\n\n\n### How does it work\n\n\nThe Dependency Proxy is a proxy, so from the perspective of the Docker\nclient, it is just another registry to authenticate with:\n\n\n```shell\n\ndocker login --username stanley --password tanuki gitlab.com\n\n```\n\n\nWhen Docker makes a request to a registry it first asks:\n\n\n```shell\n\nGET gitlab.com/v2 # are you a registry?\n\n```\n\n\nTo which GitLab responds:\n\n\n```shell\n\n401 Unauthorized\n\n\nWWW-Authenticate: Bearer realm=https://gitlab.com/auth/jwt,\nservice=dependency_proxy\n\n# Yes! But you have to get permission to access me.\n\n# Please request a token from this other URL first.\n\n```\n\n\nThen Docker requests a token using the username and password you supplied,\nand if things check out, GitLab returns a JWT. Docker uses it to make its\nnext request, which in the case of the Dependency Proxy is the image pull.\nIf things don't check out, you'll likely see a `403 Forbidden` error.\n\n\n## Docker Hub rate limiting\n\n\nIn November 2020, Docker Hub began rate limiting image pulls. The Dependency\nProxy was already caching the image layers (blobs), so it made sense that\n[the Dependency Proxy should help mitigate this problem for\nusers](https://docs.gitlab.com/ee/user/packages/dependency_proxy/#docker-hub-rate-limits-and-the-dependency-proxy).\n\n\nIt is not uncommon for a project's pipeline to run every time a user pushes\na commit. In an active project or group, this could happen many times in an\nhour. If your CI script starts with something as simple as:\n\n\n```yaml\n\nimage: node:latest\n\n```\n\n\nEvery time your pipeline runs, even though you are using the same image\nevery time, Docker will count an additional image pull against your account.\n\n\nAn image consists of many different files, and a `docker pull` command will\nmake several requests. So what counts as one image pull?\n\n\nThere are two types of files that make up an image. First is the manifest.\nYou can think of it as a table of contents for an image. It contains\ninformation about what layers, or blobs, the image is made of. Once the\nDocker client has received the manifest, it will make a request for each\nblob described in the manifest.\n\n\nDocker uses the [manifest requests to count the image\npulls](https://docs.docker.com/docker-hub/download-rate-limit/). This means\nthat if the Dependency Proxy is going to help mitigate the rate limiting, it\nneeds to store the manifest in addition to the blobs. This presents a small\nproblem: a manifest is usually requested by tag name, which is a mutable\nreference. If I request `node:latest` this week, it might be different than\nthe `node:latest` I requested last week. Each manifest contains a digest, or\nhash signature, that can be used to tell if it has changed. You can see this\ndigest when you pull the image:\n\n\n```shell\n\n$ docker pull alpine:latest\n\n\nlatest: Pulling from library/alpine\n\nDigest:\nsha256:a126728cb7db157f0deb377bcba3c5e473e612d7bafc27f6bb4e5e083f9f08c2\n\nStatus: Image is up to date for alpine:latest\n\ndocker.io/library/alpine:latest\n\n```\n\n\nDocker has allowed HEAD requests to be made for a manifest for free. The\nHEAD request response contains the digest of the underlying manifest. So we\ncan make a HEAD request to determine if the manifest we have cached in the\nDependency Proxy is up to date.\n\n\n```shell\n\ncurl --head -H \"Authorization: Bearer $TOKEN\"\nhttps://registry-1.docker.io/v2/library/alpine/manifests/latest\n\n\nHTTP/1.1 200 OK\n\nContent-Length: 2782\n\nContent-Type: application/vnd.docker.distribution.manifest.v1+prettyjws\n\nDocker-Content-Digest:\nsha256:a126728cb7db157f0deb377bcba3c5e473e612d7bafc27f6bb4e5e083f9f08c2\n\nDocker-Distribution-Api-Version: registry/2.0\n\nEtag:\n\"sha256:a126728cb7db157f0deb377bcba3c5e473e612d7bafc27f6bb4e5e083f9f08c2\"\n\nDate: Wed, 15 Dec 2020 03:34:24 GMT\n\nStrict-Transport-Security: max-age=31536000\n\nRateLimit-Limit: 100;w=21600\n\nRateLimit-Remaining: 72;w=21600\n\n```\n\n\nThe response even contains information telling us how many requests we have\nremaining within our rate limit. In this example, we see we have 72 out of\n100 remaining.\n\n\nWhen the Dependency Proxy first receives a request for the manifest, it\ndecides whether or not it needs to pull an image from Docker Hub based on a\nfew rules:\n\n\n![Dependency Proxy manifest\ncaching](https://about.gitlab.com/images/blogimages/dependency_proxy_flow_chart.png)\n\n\nThe really great thing about the Dependency Proxy is that you don't have to\ndo anything special to take advantage of these abilities. If you simply\nupdate your CI script with your Dependency Proxy image prefix to something\nlike:\n\n\n```yaml\n\nimage:\ngitlab.com/super-awesome-group/dependency_proxy/containers/node:latest\n\n```\n\n\nThen you will automatically bypass Docker Hub rate limiting and your cache\nwill have the most up-to-date version of each image tag.\n\n\n## CI/CD\n\n\nThe Dependency Proxy makes the most sense as a compliment to CI/CD\npipelines. Rather than pulling directly from Docker Hub, you can use the\nDependency Proxy to speed up your pipelines, avoid rate limiting, and create\nsecurity in case of an upstream outage.\n\n\nAs of 13.9, runners log in to the Dependency Proxy automatically, so you\ndon't need to explicitly log in unless you want to for reasons like using\nspecific tokens.\n\n\nTo make the Dependency Proxy easier to use, we have added a few predefined\nenvironment variables you can use in your `.gitlab-ci.yml` files.\n\n\n- `CI_DEPENDENCY_PROXY_USER`: A CI user for logging in to the Dependency\nProxy.\n\n- `CI_DEPENDENCY_PROXY_PASSWORD`: A CI password for logging in to the\nDependency Proxy.\n\n- `CI_DEPENDENCY_PROXY_SERVER`: The server for logging in to the Dependency\nProxy.\n\n- `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX`: The image prefix for pulling\nimages through the Dependency Proxy. This pulls through the top-level group.\n\n- `CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX` (starting in version\n14.3): An alternative image prefix for pulling images through the Dependency\nProxy. This pulls through the subgroup, or direct group the project exists\nin.\n\n\nDepending on how your scripts and pipelines look you can use these variables\nin a variety of ways. If you are manually pulling images in the script using\n`docker pull`, you can log in and pull like this:\n\n\n```yaml\n\n# .gitlab-ci.yml\n\n\ndependency-proxy-pull-master:\n  # Official docker image.\n  image: docker:latest\n  stage: build\n  services:\n    - docker:dind\n  before_script:\n    - docker login -u \"$CI_DEPENDENCY_PROXY_USER\" -p \"$CI_DEPENDENCY_PROXY_PASSWORD\" \"$CI_DEPENDENCY_PROXY_SERVER\"\n  script:\n    - docker pull \"$CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX\"/alpine:latest\n```\n\n\nIf you want to use the Dependency Proxy to pull images defined as `image`\nyaml attributes (the base images of the script), you can [create a custom\nenvironment\nvariable](https://docs.gitlab.com/ee/ci/variables/#custom-cicd-variables)\nnamed `DOCKER_AUTH_CONFIG` with a value of:\n\n\n```yaml\n\n{\n    \"auths\": {\n        \"https://gitlab.com:443\": { # if you are using $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX, you should explicitely include the port here.\n            \"auth\": \"(Base64 of username:password)\"\n        }\n    }\n}\n\n```\n\n\nYou will need to calculate the base64 value of your credentials. You can do\nthis from the command line:\n\n\n```shell\n\n# The use of \"-n\" - prevents encoding a newline in the password.\n\necho -n \"my_username:my_password\" | base64\n\n\n# Example output to copy\n\nbXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ==\n\n\n# A personal access token also works!\n\necho -n \"my_username:personal_access_token\" | base64\n\n```\n\n\nOnce you have the custom environment variable defined, you can use the\nDependency Proxy without having to manually log in within your CI script:\n\n\n```yaml\n\n# This is a working script that would publish an NPM package to the GitLab\npackage registry\n\n# if a properly formatted package.json file exists in the project root.\n\nimage: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/node:latest\n\n\nstages:\n  - deploy\n\ndeploy:\n  stage: deploy\n  script:\n    - echo \"//gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}\">.npmrc\n    - npm publish\n```\n\n\n## Support when Docker Hub is offline\n\n\nBy caching all files that make up an image, we also now have the ability to\nkeep pipelines green even if Docker Hub experiences an outage. As long as\nthe Dependency Proxy has the image you are using cached, when it makes the\nHEAD request to check if the cached image is stale or not, if the HEAD\nrequest fails, we will just fall back to the cached image.\n\n\nThanks for reading! If you haven't used the Dependency Proxy yet, [get\nstarted using it\ntoday](https://docs.gitlab.com/ee/user/packages/dependency_proxy/)!\n\n\n## Updates\n\n\nSince this was published in December 2020, there have been many additional\nimprovements and changes to the Dependency Proxy. As a result, some of the\nsuggested approaches in this post have been improved or have become\noutdated. I suggest looking through [the most recent\ndocumentation](https://docs.gitlab.com/ee/user/packages/dependency_proxy/)\nto learn more.\n","unfiltered",[23,24],"CI/CD","features",{"slug":26,"featured":6,"template":27},"dependency-proxy-updates","BlogPost","content:en-us:blog:dependency-proxy-updates.yml","yaml","Dependency Proxy Updates","content","en-us/blog/dependency-proxy-updates.yml","en-us/blog/dependency-proxy-updates","yml",{"_path":36,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"data":38,"_id":459,"_type":29,"title":460,"_source":31,"_file":461,"_stem":462,"_extension":34},"/shared/en-us/main-navigation","en-us",{"logo":39,"freeTrial":44,"sales":49,"login":54,"items":59,"search":390,"minimal":421,"duo":440,"pricingDeployment":449},{"config":40},{"href":41,"dataGaName":42,"dataGaLocation":43},"/","gitlab logo","header",{"text":45,"config":46},"Get free trial",{"href":47,"dataGaName":48,"dataGaLocation":43},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":50,"config":51},"Talk to sales",{"href":52,"dataGaName":53,"dataGaLocation":43},"/sales/","sales",{"text":55,"config":56},"Sign in",{"href":57,"dataGaName":58,"dataGaLocation":43},"https://gitlab.com/users/sign_in/","sign in",[60,104,201,206,311,371],{"text":61,"config":62,"cards":64,"footer":87},"Platform",{"dataNavLevelOne":63},"platform",[65,71,79],{"title":61,"description":66,"link":67},"The most comprehensive AI-powered DevSecOps Platform",{"text":68,"config":69},"Explore our Platform",{"href":70,"dataGaName":63,"dataGaLocation":43},"/platform/",{"title":72,"description":73,"link":74},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":75,"config":76},"Meet GitLab Duo",{"href":77,"dataGaName":78,"dataGaLocation":43},"/gitlab-duo/","gitlab duo ai",{"title":80,"description":81,"link":82},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":83,"config":84},"Learn more",{"href":85,"dataGaName":86,"dataGaLocation":43},"/why-gitlab/","why gitlab",{"title":88,"items":89},"Get started with",[90,95,100],{"text":91,"config":92},"Platform Engineering",{"href":93,"dataGaName":94,"dataGaLocation":43},"/solutions/platform-engineering/","platform engineering",{"text":96,"config":97},"Developer Experience",{"href":98,"dataGaName":99,"dataGaLocation":43},"/developer-experience/","Developer experience",{"text":101,"config":102},"MLOps",{"href":103,"dataGaName":101,"dataGaLocation":43},"/topics/devops/the-role-of-ai-in-devops/",{"text":105,"left":106,"config":107,"link":109,"lists":113,"footer":183},"Product",true,{"dataNavLevelOne":108},"solutions",{"text":110,"config":111},"View all Solutions",{"href":112,"dataGaName":108,"dataGaLocation":43},"/solutions/",[114,138,162],{"title":115,"description":116,"link":117,"items":122},"Automation","CI/CD and automation to accelerate deployment",{"config":118},{"icon":119,"href":120,"dataGaName":121,"dataGaLocation":43},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[123,126,130,134],{"text":23,"config":124},{"href":125,"dataGaLocation":43,"dataGaName":23},"/solutions/continuous-integration/",{"text":127,"config":128},"AI-Assisted Development",{"href":77,"dataGaLocation":43,"dataGaName":129},"AI assisted development",{"text":131,"config":132},"Source Code Management",{"href":133,"dataGaLocation":43,"dataGaName":131},"/solutions/source-code-management/",{"text":135,"config":136},"Automated Software Delivery",{"href":120,"dataGaLocation":43,"dataGaName":137},"Automated software delivery",{"title":139,"description":140,"link":141,"items":146},"Security","Deliver code faster without compromising security",{"config":142},{"href":143,"dataGaName":144,"dataGaLocation":43,"icon":145},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[147,152,157],{"text":148,"config":149},"Application Security Testing",{"href":150,"dataGaName":151,"dataGaLocation":43},"/solutions/application-security-testing/","Application security testing",{"text":153,"config":154},"Software Supply Chain Security",{"href":155,"dataGaLocation":43,"dataGaName":156},"/solutions/supply-chain/","Software supply chain security",{"text":158,"config":159},"Software Compliance",{"href":160,"dataGaName":161,"dataGaLocation":43},"/solutions/software-compliance/","software compliance",{"title":163,"link":164,"items":169},"Measurement",{"config":165},{"icon":166,"href":167,"dataGaName":168,"dataGaLocation":43},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[170,174,178],{"text":171,"config":172},"Visibility & Measurement",{"href":167,"dataGaLocation":43,"dataGaName":173},"Visibility and Measurement",{"text":175,"config":176},"Value Stream Management",{"href":177,"dataGaLocation":43,"dataGaName":175},"/solutions/value-stream-management/",{"text":179,"config":180},"Analytics & Insights",{"href":181,"dataGaLocation":43,"dataGaName":182},"/solutions/analytics-and-insights/","Analytics and insights",{"title":184,"items":185},"GitLab for",[186,191,196],{"text":187,"config":188},"Enterprise",{"href":189,"dataGaLocation":43,"dataGaName":190},"/enterprise/","enterprise",{"text":192,"config":193},"Small Business",{"href":194,"dataGaLocation":43,"dataGaName":195},"/small-business/","small business",{"text":197,"config":198},"Public Sector",{"href":199,"dataGaLocation":43,"dataGaName":200},"/solutions/public-sector/","public sector",{"text":202,"config":203},"Pricing",{"href":204,"dataGaName":205,"dataGaLocation":43,"dataNavLevelOne":205},"/pricing/","pricing",{"text":207,"config":208,"link":210,"lists":214,"feature":298},"Resources",{"dataNavLevelOne":209},"resources",{"text":211,"config":212},"View all resources",{"href":213,"dataGaName":209,"dataGaLocation":43},"/resources/",[215,248,270],{"title":216,"items":217},"Getting started",[218,223,228,233,238,243],{"text":219,"config":220},"Install",{"href":221,"dataGaName":222,"dataGaLocation":43},"/install/","install",{"text":224,"config":225},"Quick start guides",{"href":226,"dataGaName":227,"dataGaLocation":43},"/get-started/","quick setup checklists",{"text":229,"config":230},"Learn",{"href":231,"dataGaLocation":43,"dataGaName":232},"https://university.gitlab.com/","learn",{"text":234,"config":235},"Product documentation",{"href":236,"dataGaName":237,"dataGaLocation":43},"https://docs.gitlab.com/","product documentation",{"text":239,"config":240},"Best practice videos",{"href":241,"dataGaName":242,"dataGaLocation":43},"/getting-started-videos/","best practice videos",{"text":244,"config":245},"Integrations",{"href":246,"dataGaName":247,"dataGaLocation":43},"/integrations/","integrations",{"title":249,"items":250},"Discover",[251,256,260,265],{"text":252,"config":253},"Customer success stories",{"href":254,"dataGaName":255,"dataGaLocation":43},"/customers/","customer success stories",{"text":257,"config":258},"Blog",{"href":259,"dataGaName":5,"dataGaLocation":43},"/blog/",{"text":261,"config":262},"Remote",{"href":263,"dataGaName":264,"dataGaLocation":43},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":266,"config":267},"TeamOps",{"href":268,"dataGaName":269,"dataGaLocation":43},"/teamops/","teamops",{"title":271,"items":272},"Connect",[273,278,283,288,293],{"text":274,"config":275},"GitLab Services",{"href":276,"dataGaName":277,"dataGaLocation":43},"/services/","services",{"text":279,"config":280},"Community",{"href":281,"dataGaName":282,"dataGaLocation":43},"/community/","community",{"text":284,"config":285},"Forum",{"href":286,"dataGaName":287,"dataGaLocation":43},"https://forum.gitlab.com/","forum",{"text":289,"config":290},"Events",{"href":291,"dataGaName":292,"dataGaLocation":43},"/events/","events",{"text":294,"config":295},"Partners",{"href":296,"dataGaName":297,"dataGaLocation":43},"/partners/","partners",{"backgroundColor":299,"textColor":300,"text":301,"image":302,"link":306},"#2f2a6b","#fff","Insights for the future of software development",{"altText":303,"config":304},"the source promo card",{"src":305},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":307,"config":308},"Read the latest",{"href":309,"dataGaName":310,"dataGaLocation":43},"/the-source/","the source",{"text":312,"config":313,"lists":315},"Company",{"dataNavLevelOne":314},"company",[316],{"items":317},[318,323,329,331,336,341,346,351,356,361,366],{"text":319,"config":320},"About",{"href":321,"dataGaName":322,"dataGaLocation":43},"/company/","about",{"text":324,"config":325,"footerGa":328},"Jobs",{"href":326,"dataGaName":327,"dataGaLocation":43},"/jobs/","jobs",{"dataGaName":327},{"text":289,"config":330},{"href":291,"dataGaName":292,"dataGaLocation":43},{"text":332,"config":333},"Leadership",{"href":334,"dataGaName":335,"dataGaLocation":43},"/company/team/e-group/","leadership",{"text":337,"config":338},"Team",{"href":339,"dataGaName":340,"dataGaLocation":43},"/company/team/","team",{"text":342,"config":343},"Handbook",{"href":344,"dataGaName":345,"dataGaLocation":43},"https://handbook.gitlab.com/","handbook",{"text":347,"config":348},"Investor relations",{"href":349,"dataGaName":350,"dataGaLocation":43},"https://ir.gitlab.com/","investor relations",{"text":352,"config":353},"Trust Center",{"href":354,"dataGaName":355,"dataGaLocation":43},"/security/","trust center",{"text":357,"config":358},"AI Transparency Center",{"href":359,"dataGaName":360,"dataGaLocation":43},"/ai-transparency-center/","ai transparency center",{"text":362,"config":363},"Newsletter",{"href":364,"dataGaName":365,"dataGaLocation":43},"/company/contact/","newsletter",{"text":367,"config":368},"Press",{"href":369,"dataGaName":370,"dataGaLocation":43},"/press/","press",{"text":372,"config":373,"lists":374},"Contact us",{"dataNavLevelOne":314},[375],{"items":376},[377,380,385],{"text":50,"config":378},{"href":52,"dataGaName":379,"dataGaLocation":43},"talk to sales",{"text":381,"config":382},"Get help",{"href":383,"dataGaName":384,"dataGaLocation":43},"/support/","get help",{"text":386,"config":387},"Customer portal",{"href":388,"dataGaName":389,"dataGaLocation":43},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":391,"login":392,"suggestions":399},"Close",{"text":393,"link":394},"To search repositories and projects, login to",{"text":395,"config":396},"gitlab.com",{"href":57,"dataGaName":397,"dataGaLocation":398},"search login","search",{"text":400,"default":401},"Suggestions",[402,404,408,410,414,418],{"text":72,"config":403},{"href":77,"dataGaName":72,"dataGaLocation":398},{"text":405,"config":406},"Code Suggestions (AI)",{"href":407,"dataGaName":405,"dataGaLocation":398},"/solutions/code-suggestions/",{"text":23,"config":409},{"href":125,"dataGaName":23,"dataGaLocation":398},{"text":411,"config":412},"GitLab on AWS",{"href":413,"dataGaName":411,"dataGaLocation":398},"/partners/technology-partners/aws/",{"text":415,"config":416},"GitLab on Google Cloud",{"href":417,"dataGaName":415,"dataGaLocation":398},"/partners/technology-partners/google-cloud-platform/",{"text":419,"config":420},"Why GitLab?",{"href":85,"dataGaName":419,"dataGaLocation":398},{"freeTrial":422,"mobileIcon":427,"desktopIcon":432,"secondaryButton":435},{"text":423,"config":424},"Start free trial",{"href":425,"dataGaName":48,"dataGaLocation":426},"https://gitlab.com/-/trials/new/","nav",{"altText":428,"config":429},"Gitlab Icon",{"src":430,"dataGaName":431,"dataGaLocation":426},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":428,"config":433},{"src":434,"dataGaName":431,"dataGaLocation":426},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":436,"config":437},"Get Started",{"href":438,"dataGaName":439,"dataGaLocation":426},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":441,"mobileIcon":445,"desktopIcon":447},{"text":442,"config":443},"Learn more about GitLab Duo",{"href":77,"dataGaName":444,"dataGaLocation":426},"gitlab duo",{"altText":428,"config":446},{"src":430,"dataGaName":431,"dataGaLocation":426},{"altText":428,"config":448},{"src":434,"dataGaName":431,"dataGaLocation":426},{"freeTrial":450,"mobileIcon":455,"desktopIcon":457},{"text":451,"config":452},"Back to pricing",{"href":204,"dataGaName":453,"dataGaLocation":426,"icon":454},"back to pricing","GoBack",{"altText":428,"config":456},{"src":430,"dataGaName":431,"dataGaLocation":426},{"altText":428,"config":458},{"src":434,"dataGaName":431,"dataGaLocation":426},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":464,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"title":465,"button":466,"image":471,"config":475,"_id":477,"_type":29,"_source":31,"_file":478,"_stem":479,"_extension":34},"/shared/en-us/banner","is now in public beta!",{"text":467,"config":468},"Try the Beta",{"href":469,"dataGaName":470,"dataGaLocation":43},"/gitlab-duo/agent-platform/","duo banner",{"altText":472,"config":473},"GitLab Duo Agent Platform",{"src":474},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":476},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":481,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"data":482,"_id":686,"_type":29,"title":687,"_source":31,"_file":688,"_stem":689,"_extension":34},"/shared/en-us/main-footer",{"text":483,"source":484,"edit":490,"contribute":495,"config":500,"items":505,"minimal":678},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":485,"config":486},"View page source",{"href":487,"dataGaName":488,"dataGaLocation":489},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":491,"config":492},"Edit this page",{"href":493,"dataGaName":494,"dataGaLocation":489},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":496,"config":497},"Please contribute",{"href":498,"dataGaName":499,"dataGaLocation":489},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":501,"facebook":502,"youtube":503,"linkedin":504},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[506,529,585,614,648],{"title":61,"links":507,"subMenu":512},[508],{"text":509,"config":510},"DevSecOps platform",{"href":70,"dataGaName":511,"dataGaLocation":489},"devsecops platform",[513],{"title":202,"links":514},[515,519,524],{"text":516,"config":517},"View plans",{"href":204,"dataGaName":518,"dataGaLocation":489},"view plans",{"text":520,"config":521},"Why Premium?",{"href":522,"dataGaName":523,"dataGaLocation":489},"/pricing/premium/","why premium",{"text":525,"config":526},"Why Ultimate?",{"href":527,"dataGaName":528,"dataGaLocation":489},"/pricing/ultimate/","why ultimate",{"title":530,"links":531},"Solutions",[532,537,539,541,546,551,555,558,562,567,569,572,575,580],{"text":533,"config":534},"Digital transformation",{"href":535,"dataGaName":536,"dataGaLocation":489},"/topics/digital-transformation/","digital transformation",{"text":148,"config":538},{"href":150,"dataGaName":148,"dataGaLocation":489},{"text":137,"config":540},{"href":120,"dataGaName":121,"dataGaLocation":489},{"text":542,"config":543},"Agile development",{"href":544,"dataGaName":545,"dataGaLocation":489},"/solutions/agile-delivery/","agile delivery",{"text":547,"config":548},"Cloud transformation",{"href":549,"dataGaName":550,"dataGaLocation":489},"/topics/cloud-native/","cloud transformation",{"text":552,"config":553},"SCM",{"href":133,"dataGaName":554,"dataGaLocation":489},"source code management",{"text":23,"config":556},{"href":125,"dataGaName":557,"dataGaLocation":489},"continuous integration & delivery",{"text":559,"config":560},"Value stream management",{"href":177,"dataGaName":561,"dataGaLocation":489},"value stream management",{"text":563,"config":564},"GitOps",{"href":565,"dataGaName":566,"dataGaLocation":489},"/solutions/gitops/","gitops",{"text":187,"config":568},{"href":189,"dataGaName":190,"dataGaLocation":489},{"text":570,"config":571},"Small business",{"href":194,"dataGaName":195,"dataGaLocation":489},{"text":573,"config":574},"Public sector",{"href":199,"dataGaName":200,"dataGaLocation":489},{"text":576,"config":577},"Education",{"href":578,"dataGaName":579,"dataGaLocation":489},"/solutions/education/","education",{"text":581,"config":582},"Financial services",{"href":583,"dataGaName":584,"dataGaLocation":489},"/solutions/finance/","financial services",{"title":207,"links":586},[587,589,591,593,596,598,600,602,604,606,608,610,612],{"text":219,"config":588},{"href":221,"dataGaName":222,"dataGaLocation":489},{"text":224,"config":590},{"href":226,"dataGaName":227,"dataGaLocation":489},{"text":229,"config":592},{"href":231,"dataGaName":232,"dataGaLocation":489},{"text":234,"config":594},{"href":236,"dataGaName":595,"dataGaLocation":489},"docs",{"text":257,"config":597},{"href":259,"dataGaName":5,"dataGaLocation":489},{"text":252,"config":599},{"href":254,"dataGaName":255,"dataGaLocation":489},{"text":261,"config":601},{"href":263,"dataGaName":264,"dataGaLocation":489},{"text":274,"config":603},{"href":276,"dataGaName":277,"dataGaLocation":489},{"text":266,"config":605},{"href":268,"dataGaName":269,"dataGaLocation":489},{"text":279,"config":607},{"href":281,"dataGaName":282,"dataGaLocation":489},{"text":284,"config":609},{"href":286,"dataGaName":287,"dataGaLocation":489},{"text":289,"config":611},{"href":291,"dataGaName":292,"dataGaLocation":489},{"text":294,"config":613},{"href":296,"dataGaName":297,"dataGaLocation":489},{"title":312,"links":615},[616,618,620,622,624,626,628,632,637,639,641,643],{"text":319,"config":617},{"href":321,"dataGaName":314,"dataGaLocation":489},{"text":324,"config":619},{"href":326,"dataGaName":327,"dataGaLocation":489},{"text":332,"config":621},{"href":334,"dataGaName":335,"dataGaLocation":489},{"text":337,"config":623},{"href":339,"dataGaName":340,"dataGaLocation":489},{"text":342,"config":625},{"href":344,"dataGaName":345,"dataGaLocation":489},{"text":347,"config":627},{"href":349,"dataGaName":350,"dataGaLocation":489},{"text":629,"config":630},"Sustainability",{"href":631,"dataGaName":629,"dataGaLocation":489},"/sustainability/",{"text":633,"config":634},"Diversity, inclusion and belonging (DIB)",{"href":635,"dataGaName":636,"dataGaLocation":489},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":352,"config":638},{"href":354,"dataGaName":355,"dataGaLocation":489},{"text":362,"config":640},{"href":364,"dataGaName":365,"dataGaLocation":489},{"text":367,"config":642},{"href":369,"dataGaName":370,"dataGaLocation":489},{"text":644,"config":645},"Modern Slavery Transparency Statement",{"href":646,"dataGaName":647,"dataGaLocation":489},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":649,"links":650},"Contact Us",[651,654,656,658,663,668,673],{"text":652,"config":653},"Contact an expert",{"href":52,"dataGaName":53,"dataGaLocation":489},{"text":381,"config":655},{"href":383,"dataGaName":384,"dataGaLocation":489},{"text":386,"config":657},{"href":388,"dataGaName":389,"dataGaLocation":489},{"text":659,"config":660},"Status",{"href":661,"dataGaName":662,"dataGaLocation":489},"https://status.gitlab.com/","status",{"text":664,"config":665},"Terms of use",{"href":666,"dataGaName":667,"dataGaLocation":489},"/terms/","terms of use",{"text":669,"config":670},"Privacy statement",{"href":671,"dataGaName":672,"dataGaLocation":489},"/privacy/","privacy statement",{"text":674,"config":675},"Cookie preferences",{"dataGaName":676,"dataGaLocation":489,"id":677,"isOneTrustButton":106},"cookie preferences","ot-sdk-btn",{"items":679},[680,682,684],{"text":664,"config":681},{"href":666,"dataGaName":667,"dataGaLocation":489},{"text":669,"config":683},{"href":671,"dataGaName":672,"dataGaLocation":489},{"text":674,"config":685},{"dataGaName":676,"dataGaLocation":489,"id":677,"isOneTrustButton":106},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[691],{"_path":692,"_dir":693,"_draft":6,"_partial":6,"_locale":7,"content":694,"config":698,"_id":700,"_type":29,"title":18,"_source":31,"_file":701,"_stem":702,"_extension":34},"/en-us/blog/authors/steve-abrams","authors",{"name":18,"config":695},{"headshot":696,"ctfId":697},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681809/Blog/Author%20Headshots/sabrams-headshot.png","sabrams",{"template":699},"BlogAuthor","content:en-us:blog:authors:steve-abrams.yml","en-us/blog/authors/steve-abrams.yml","en-us/blog/authors/steve-abrams",{"_path":704,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"header":705,"eyebrow":706,"blurb":707,"button":708,"secondaryButton":712,"_id":714,"_type":29,"title":715,"_source":31,"_file":716,"_stem":717,"_extension":34},"/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":45,"config":709},{"href":710,"dataGaName":48,"dataGaLocation":711},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":50,"config":713},{"href":52,"dataGaName":53,"dataGaLocation":711},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1758326230671]