[{"data":1,"prerenderedAt":721},["ShallowReactive",2],{"/en-us/blog/how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery/":3,"navigation-en-us":39,"banner-en-us":467,"footer-en-us":484,"Daniel Helfand":693,"next-steps-en-us":706},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":29,"_id":32,"_type":33,"title":34,"_source":35,"_file":36,"_stem":37,"_extension":38},"/en-us/blog/how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"How to use OCI images as the source of truth for continuous delivery","Discover the benefits of using Open Container Initiative images as part of GitOps workflows and the many features GitLab offers to simplify deployments to Kubernetes.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097601/Blog/Hero%20Images/Blog/Hero%20Images/REFERENCE%20-%20Use%20this%20page%20as%20a%20reference%20for%20thumbnail%20sizes_76Tn5jFmEHY5LFj8RdDjNY_1750097600692.png","https://about.gitlab.com/blog/how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to use OCI images as the source of truth for continuous delivery\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Daniel Helfand\"}],\n        \"datePublished\": \"2025-02-19\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22},[18],"Daniel Helfand","2025-02-19","Is [GitOps](https://about.gitlab.com/topics/gitops/) still GitOps if you are\nnot using a git repository as your deployment artifact? While git remains\ncentral to GitOps workflows, storing infrastructure definitions as Open\nContainer Initiative (OCI) artifacts in container registries has seen a rise\nin adoption as the source for GitOps deployments. In this article, we will\ndive deeper into the ideas behind this trend and how GitLab features support\nthis enhancement to GitOps workflows.\n\n\n## What is GitOps?\n\n\nThe [OpenGitOps](https://opengitops.dev/) project has defined [four\nprinciples](https://opengitops.dev/#principles) for the practice of GitOps:\n\n- A [system managed by\nGitOps](https://github.com/open-gitops/documents/blob/v1.0.0/GLOSSARY.md#software-system)\nmust have its [desired state expressed\ndeclaratively](https://github.com/open-gitops/documents/blob/v1.0.0/GLOSSARY.md#declarative-description).\n\n- Desired state is stored in a way that enforces immutability and\nversioning, and retains a complete version history.\n\n- Software agents automatically pull the desired state declarations from the\nsource.\n\n- Software agents\n[continuously](https://github.com/open-gitops/documents/blob/v1.0.0/GLOSSARY.md#continuous)\nobserve actual system state and [attempt to apply the desired\nstate](https://github.com/open-gitops/documents/blob/v1.0.0/GLOSSARY.md#reconciliation).\n\n\nAn example of GitOps is storing the Kubernetes manifests for a microservice\nin a GitLab project. Those Kubernetes resources are then continuously\nreconciled by a\n[controller](https://kubernetes.io/docs/concepts/architecture/controller/)\nrunning on the Kubernetes cluster where the microservice is deployed to.\nThis allows engineers to manage infrastructure using the same workflows as\nworking with regular code, such as opening merge requests to make and review\nchanges and versioning changes. GitOps also has operational benefits such as\n[preventing configuration\ndrift](https://about.gitlab.com/topics/gitops/#cicd) and helps engineers\naudit what changes led to certain outcomes with deployments.\n\n\n## Benefits and limitations of git in GitOps workflows\n\n\nWhile git is an essential piece of GitOps workflows, git repositories were\nnot designed to be deployed by GitOps controllers. Git does provide the\nability for engineers to collaborate on infrastructure changes and audit\nthese changes later on, but controllers do not need to download an entire\ngit repository for a successful deployment. GitOps controllers simply need\nthe infrastructure defined for a particular environment.\n\n\nAdditionally, an important piece of the deployment process is to [sign and\nverify\ndeployments](https://docs.sigstore.dev/about/overview/#why-cryptographic-signing)\nto assure deployment changes to an environment are coming from a trusted\nsource. While git commits can be signed and verified by GitOps controllers,\ncommits may also capture other details not related to the deployment itself\n(e.g., documentation changes, updates to other environments, and git\nrepository restructuring) or not enough of the deployment picture as a\ndeployment may consist of multiple commits. This again feels like a case\nthis git feature wasn’t designed for.\n\n\nAnother challenging aspect of git in GitOps workflows is that it can\nsometimes lead to more automation than expected. Soon after merging a change\nto the watched branch, it will be deployed. There are no controls in the\nprocess outside of git. How can you make sure that nothing gets deployed on\na Friday late afternoon? What if teams responsible for deployment do not\nhave permissions to merge changes in certain GitLab projects? Using OCI\nimages adds a pipeline into the process, including all the delivery control\nfeatures, like [approvals or deploy\nfreezes](https://docs.gitlab.com/ee/ci/environments/protected_environments.html).\n\n\n## OCI images\n\n\nThe [Open Container Initiative](https://opencontainers.org/) has helped to\ndefine standards around container formats. While most engineers are familiar\nwith building Dockerfiles into container images, many may not be as familiar\nwith storing Kubernetes manifests in a container registry. Because [GitLab’s\nContainer\nRegistry](https://docs.gitlab.com/ee/user/packages/container_registry/) is\nOCI compliant, it allows for users to push Kubernetes manifests for a\nparticular environment to a container registry. GitOps controllers, such as\n[Flux\nCD](https://about.gitlab.com/blog/why-did-we-choose-to-integrate-fluxcd-with-gitlab/),\ncan use the manifests stored in this OCI artifact instead of needing to\nclone an entire git repository.\n\n\nOften in GitOps workflows, a git repository can include the infrastructure\ndefinitions for all environments that a microservice will be deployed to. By\npackaging the Kubernetes manifests for only a specific environment, Flux CD\ncan download the minimum files needed to carry out a deployment to a\nspecific environment.\n\n\n### Security benefits of using OCI artifacts\n\n\nAs mentioned previously, signing and verifying the artifacts to be deployed\nto an environment adds an additional layer of security for software\nprojects. After Kubernetes manifests are pushed to a container registry, a\ntool like [Sigstore\nCosign](https://docs.sigstore.dev/quickstart/quickstart-cosign/) can be used\nto sign the OCI image with a private key that can be securely stored in a\nGitLab project as a [CI/CD\nvariable](https://docs.gitlab.com/ee/ci/variables/). Flux CD can then use a\npublic key stored on a Kubernetes cluster to verify that a deployment is\ncoming from a trusted source.\n\n\n## Using GitLab to push and sign OCI images\n\n\nGitLab offers many features that help simplify the process of packaging,\nsigning, and deploying OCI images. A common way to structure GitLab projects\nwith GitOps workflows is to have separate GitLab projects for microservices’\ncode and a single infrastructure repository for all microservices. If an\napplication is composed of `n` microservices, this would require having `n\n+1` GitLab projects for an application.\n\n\nThe artifact produced by a code project is usually a container image that\nwill be used to package the application. The infrastructure or delivery\nproject will contain the Kubernetes manifests defining all the resources\nrequired to scale and serve traffic to each microservice. The artifact\nproduced by this project is usually an OCI image used to deploy the\napplication and other manifests to Kubernetes.\n\n\nIn this setup, separation of environments is handled by defining Kubernetes\nmanifests in separate folders. These folders represent environments (e.g.,\ndevelopment, staging, and production) that will host the application. When\nchanges are made to the code project and a new container image is pushed,\nall that needs to be done to deploy these changes via GitLab’s integration\nwith Flux CD is to edit the manifests under the environment folder to\ninclude the new image reference and open a merge request. Once that merge\nrequest is reviewed, approved, and merged, the delivery project’s CI/CD job\nwill push a new OCI image that Flux CD will pick up and deploy to the new\nenvironment.\n\n\n![OCI images - flow\nchart](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097611/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097611046.png)\n\n\nSigning an OCI image is as simple as including Cosign in your project’s\nCI/CD job. You can simply generate a new public and private key with Cosign\nby running the commands below locally. Just make sure to log in to your\nGitLab instance with the [glab\nCLI](https://gitlab.com/gitlab-org/cli/#installation) and replace the\n[`PROJECT_ID`] for the Cosign command with your [delivery project’s\nID](https://docs.gitlab.com/ee/user/project/working_with_projects.html#access-a-project-by-using-the-project-id).\n\n\n```\n\nglab auth login\n\ncosign generate-key-pair gitlab://[PROJECT_ID]\n\n```\n\n\nOnce the cosign command runs successfully, you can see the Cosign keys added\nto your project under the CI/CD variables section under the key names\n`COSIGN_PUBLIC_KEY` and `COSIGN_PRIVATE_KEY`.\n\n\n### Example CI/CD job\n\n\nA GitLab CI/CD job for pushing an OCI image will look something like the\nfollowing:\n\n\n```yaml\n\nfrontend-deploy:\n  rules:\n  - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    changes:\n      paths:\n      - manifests/dev/frontend-dev.yaml\n  trigger:\n    include:\n      - component: gitlab.com/components/fluxcd/oci-artifact@0.3.1\n        inputs:\n          version: 0.3.1\n          kubernetes_agent_reference: gitlab-da/projects/tanuki-bank/flux-config:dev\n          registry_image_url: \"oci://$CI_REGISTRY_IMAGE/frontend\"\n          image_tag: dev\n          manifest_path: ./manifests/dev/frontend-dev.yaml\n          flux_oci_repo_name: frontend\n          flux_oci_namespace_name: frontend-dev\n          signing_private_key: \"$COSIGN_PRIVATE_KEY\"\n```\n\n\nThe [GitLab CI/CD\nCatalog](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/)\noffers a GitLab-maintained [CI/CD component for working with OCI artifacts\nand Flux CD](https://gitlab.com/explore/catalog/components/fluxcd). This\ncomponent allows development teams to push Kubernetes manifests as OCI\nimages to GitLab’s Container Registry or an external container registry,\nsign the OCI image using Cosign, and immediately reconcile the newly pushed\nimage via Flux CD.\n\n\nIn the example above, the Flux CD `component` is included in a\n`.gitlab-ci.yml` file of a GitLab project. Using the component’s `inputs`,\nusers can define what registry to push the image to (i.e.,\n`registry_image_url` and `image tag`), the file path to Kubernetes manifests\nthat will be pushed (i.e., `manifest_path`), the cosign private key used to\nsign images (i.e., `signing_private_key`), and the Kubernetes namespace and\nFlux CD\n[OCIRepository](https://fluxcd.io/flux/components/source/ocirepositories/)\nname needed to sync updates to an environment (i.e.,\n`flux_oci_namespace_name` and `flux_oci_repo_name`).\n\n\nThe `kubernetes_agent_reference` allows GitLab CI/CD jobs to inherit the\n`kubeconfig` needed to access a Kubernetes cluster without needing to store\na `kubeconfig` CI/CD variable in each GitLab project. By setting up the\n[GitLab agent for\nKubernetes](https://docs.gitlab.com/ee/user/clusters/agent/), you can\nconfigure all GitLab projects’ CI/CD jobs in a [GitLab\ngroup](https://docs.gitlab.com/ee/user/group/) to inherit permissions to\ndeploy to the Kubernetes cluster.\n\n\nThe agent for Kubernetes context is typically configured wherever you\nconfigure the GitLab Agent for Kubernetes in your GitLab group. It is\ntypically recommended that this be done in the project where Flux CD is\nmanaged. More information on configuring the agent for CI/CD access can be\nfound in our [CI/CD workflow\ndocumentation](https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html).\n\n\nThe variables `$COSIGN_PRIVATE_KEY`, `$FLUX_OCI_REPO_NAME`, and\n`$FRONTEND_DEV_NAMESPACE` are values stored as CI/CD variables to easily\naccess and mask these sensitive pieces of data in CI/CD logs. The\n`$CI_REGISTRY_IMAGE` is a variable that GitLab jobs have available by\ndefault that specifies the GitLab project’s container registry.\n\n\n### Deploy OCI images\n\n\nUsing [Flux CD with your GitLab\nprojects](https://docs.gitlab.com/ee/user/clusters/agent/gitops/flux_tutorial.html),\nyou can automate deployments and signing verification for your\nmicroservice’s environments. Once Flux CD is configured to sync from a\nGitLab project, you could add the following Kubernetes [custom resource\ndefinitions](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/)\nto your project to sync your pushed OCI image.\n\n\n```yaml\n\napiVersion: v1\n\nkind: Namespace\n\nmetadata:\n  name: frontend-dev\n  labels:\n    name: frontend-dev\n---\n\napiVersion: bitnami.com/v1alpha1\n\nkind: SealedSecret\n\nmetadata:\n  name: cosign-public-key\n  namespace: frontend-dev\nspec:\n  encryptedData:\n    cosign.pub: AgAKgLf4VbVzJOmr6++k81LlFayx88AELaUQFNOaXmBF4G+fBfBYeABl0skNvMAa1UrPVNSfMIHgFoYHoO96g576a+epk6V6glOI+++XvYbfsygof3GGxe0nL5Qh2b3ge0fNpyd0kTPSjTj0YUhRhKtMGMRSRw1jrwhNcGxCHK+Byibs52v8Np49KsIkeZKbzLdgYABkrv+k0j7hQM+jR180NpG+2UiRvaXpPuogxkbj61FEqWGrJHk8IVyfl3eh+YhoXxOHGDqko6SUC+bUZPDBlU6yKegO0/8Zq3hwulrSEsEjzRZNK+RFVMOLWWuC6h+WGpYhAMcsZPwjjJ/y29KLNa/YeqkN/cdk488QyEFc6ehCxzhH67HxIn2PDa+KkEOTv2TuycGF+Q00jKIizXF+IwLx/oRb3pTCF0AoAY8D8N3Ey+KfkOjsBON7gGID8GbQiJqX2IgIZxFMk0JRzxbRKOEqn+guLd5Shj7CD1a1Mkk0DxBdbqrGv2XNYUaFPI7xd3rZXUJZlnv+fsmwswsiGWRuXwim45HScWzQnfgLAe7tv3spVEGeaO5apl6d89uN21PBQnfE/zyugB//7ZW9tSp6+CSMyc5HynxI8diafqiwKPgvzLmVWRnkvxJijoXicRr3sCo5RudZPSlnjfd7CKdhwEVvLl7dRR4e/XBMdxCzk1p52Pl+3/kJR+LJii5+iwOpYrpVltSZdzc/3qRd19yMpc9PWpXYi7HxTb24EOQ25i21eDJY1ceplDN6bRtop2quzkjlwVeE2i4cEsX/YG8QBtQbop/3fjiAjKaED3QH3Ul0PECS9ARTScSkcOL3I00Xpp8DyD+xH0/i9wCBRDmH3yKX18C8VrMq02ALSnlP7WCVVjCPzubqKx2LPZRxK9EG0fylwv/vWQzTUUwfbPQZsd4c75bSTsTvxqp/UcFaXA==\n  template:\n    metadata:\n      name: cosign-public-key\n      namespace: frontend-dev\n---\n\napiVersion: source.toolkit.fluxcd.io/v1beta2\n\nkind: OCIRepository\n\nmetadata:\n    name: frontend\n    namespace: frontend-dev\nspec:\n    interval: 1m\n    url: oci://registry.gitlab.com/gitlab-da/projects/tanuki-bank/tanuki-bank-delivery/frontend\n    ref:\n        tag: dev\n    verify:\n      provider: cosign\n      secretRef:\n        name: cosign-public-key\n---\n\napiVersion: kustomize.toolkit.fluxcd.io/v1\n\nkind: Kustomization\n\nmetadata:\n    name: frontend\n    namespace: frontend-dev\nspec:\n    interval: 1m\n    targetNamespace: frontend-dev\n    path: \".\"\n    sourceRef:\n        kind: OCIRepository\n        name: frontend\n    prune: true\n```\n\n\nThe\n[`Kustomization`](https://fluxcd.io/flux/components/kustomize/kustomizations/)\nresource allows for further customization of Kubernetes manifests and also\nspecifies which namespace to deploy resources to. The `OCIRepository`\nresource for Flux CD allows users to specify the OCI image repository\nreference and tag to regularly sync from. Additionally, you will notice the\n`verify.provider` and `verify.secretRef` properties. These fields allow you\nto verify that the OCI image deployed to the cluster was signed by the\ncorresponding Cosign private key used in the earlier CI/CD job.\n\n\nThe public key needs to be stored in a [Kubernetes\nsecret](https://kubernetes.io/docs/concepts/configuration/secret/) that will\nneed to be present in the same namespace as the `OCIRepository` resource. To\nhave this secret managed by Flux CD and not store the secret in plain text,\nyou can consider using\n[SealedSecrets](https://fluxcd.io/flux/guides/sealed-secrets/) to encrypt\nthe value and have it be decrypted cluster side by a controller.\n\n\nFor a simpler approach not requiring SealedSecrets, you can [deploy the\nsecret via a GitLab\nCI/CD](https://docs.gitlab.com/ee/user/clusters/agent/getting_started_deployments.html)\njob using the [`kubectl\nCLI`](https://kubernetes.io/docs/reference/kubectl/). In the non-sealed\nsecret approach, you would simply remove the SealedSecret included above and\nrun the job to deploy the public key secret before running the job to push\nthe new OCI image. This will make sure the secret is stored securely in\nGitLab and make sure the secret can be accessed on the cluster by the\nOCIRepository. While this approach is a bit simpler, just note this is not a\nsuitable approach for managing secrets in production.\n\n\n## The benefits of OCI, GitLab, and GitOps\n\n\nOCI artifacts allow for GitOps teams to take deployments even further with\nadded security benefits and allowing for deployments to be minimal. Users\nstill gain all the benefits offered by git as far as having a source of\ntruth for infrastructure and collaborating on projects. OCI images add a\npackaging approach that improves the deployment aspect of GitOps.\n\n\nGitLab continues to learn from our customers and the cloud native community\non building experiences that help simplify GitOps workflows. To get started\nusing some of the features mentioned in this blog, you can sign up for a\n[free trial of GitLab\nUltimate](https://about.gitlab.com/free-trial/). We would also love to hear\nfrom users about their experiences with these tools, and you can provide\nfeedback in the [community\nforum](https://forum.gitlab.com/t/oci-images-as-source-of-truth-for-gitops-with-gitlab/120965).\n","open-source",[23,24,25,26,27,28],"CI/CD","open source","kubernetes","GitOps","git","tutorial",{"slug":30,"featured":6,"template":31},"how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery","BlogPost","content:en-us:blog:how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery.yml","yaml","How To Use Oci Images As The Source Of Truth For Continuous Delivery","content","en-us/blog/how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery.yml","en-us/blog/how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery","yml",{"_path":40,"_dir":41,"_draft":6,"_partial":6,"_locale":7,"data":42,"_id":463,"_type":33,"title":464,"_source":35,"_file":465,"_stem":466,"_extension":38},"/shared/en-us/main-navigation","en-us",{"logo":43,"freeTrial":48,"sales":53,"login":58,"items":63,"search":394,"minimal":425,"duo":444,"pricingDeployment":453},{"config":44},{"href":45,"dataGaName":46,"dataGaLocation":47},"/","gitlab logo","header",{"text":49,"config":50},"Get free trial",{"href":51,"dataGaName":52,"dataGaLocation":47},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":54,"config":55},"Talk to sales",{"href":56,"dataGaName":57,"dataGaLocation":47},"/sales/","sales",{"text":59,"config":60},"Sign in",{"href":61,"dataGaName":62,"dataGaLocation":47},"https://gitlab.com/users/sign_in/","sign in",[64,108,205,210,315,375],{"text":65,"config":66,"cards":68,"footer":91},"Platform",{"dataNavLevelOne":67},"platform",[69,75,83],{"title":65,"description":70,"link":71},"The most comprehensive AI-powered DevSecOps Platform",{"text":72,"config":73},"Explore our Platform",{"href":74,"dataGaName":67,"dataGaLocation":47},"/platform/",{"title":76,"description":77,"link":78},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":79,"config":80},"Meet GitLab Duo",{"href":81,"dataGaName":82,"dataGaLocation":47},"/gitlab-duo/","gitlab duo ai",{"title":84,"description":85,"link":86},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":87,"config":88},"Learn more",{"href":89,"dataGaName":90,"dataGaLocation":47},"/why-gitlab/","why gitlab",{"title":92,"items":93},"Get started with",[94,99,104],{"text":95,"config":96},"Platform Engineering",{"href":97,"dataGaName":98,"dataGaLocation":47},"/solutions/platform-engineering/","platform engineering",{"text":100,"config":101},"Developer Experience",{"href":102,"dataGaName":103,"dataGaLocation":47},"/developer-experience/","Developer experience",{"text":105,"config":106},"MLOps",{"href":107,"dataGaName":105,"dataGaLocation":47},"/topics/devops/the-role-of-ai-in-devops/",{"text":109,"left":110,"config":111,"link":113,"lists":117,"footer":187},"Product",true,{"dataNavLevelOne":112},"solutions",{"text":114,"config":115},"View all Solutions",{"href":116,"dataGaName":112,"dataGaLocation":47},"/solutions/",[118,142,166],{"title":119,"description":120,"link":121,"items":126},"Automation","CI/CD and automation to accelerate deployment",{"config":122},{"icon":123,"href":124,"dataGaName":125,"dataGaLocation":47},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[127,130,134,138],{"text":23,"config":128},{"href":129,"dataGaLocation":47,"dataGaName":23},"/solutions/continuous-integration/",{"text":131,"config":132},"AI-Assisted Development",{"href":81,"dataGaLocation":47,"dataGaName":133},"AI assisted development",{"text":135,"config":136},"Source Code Management",{"href":137,"dataGaLocation":47,"dataGaName":135},"/solutions/source-code-management/",{"text":139,"config":140},"Automated Software Delivery",{"href":124,"dataGaLocation":47,"dataGaName":141},"Automated software delivery",{"title":143,"description":144,"link":145,"items":150},"Security","Deliver code faster without compromising security",{"config":146},{"href":147,"dataGaName":148,"dataGaLocation":47,"icon":149},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[151,156,161],{"text":152,"config":153},"Application Security Testing",{"href":154,"dataGaName":155,"dataGaLocation":47},"/solutions/application-security-testing/","Application security testing",{"text":157,"config":158},"Software Supply Chain Security",{"href":159,"dataGaLocation":47,"dataGaName":160},"/solutions/supply-chain/","Software supply chain security",{"text":162,"config":163},"Software Compliance",{"href":164,"dataGaName":165,"dataGaLocation":47},"/solutions/software-compliance/","software compliance",{"title":167,"link":168,"items":173},"Measurement",{"config":169},{"icon":170,"href":171,"dataGaName":172,"dataGaLocation":47},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[174,178,182],{"text":175,"config":176},"Visibility & Measurement",{"href":171,"dataGaLocation":47,"dataGaName":177},"Visibility and Measurement",{"text":179,"config":180},"Value Stream Management",{"href":181,"dataGaLocation":47,"dataGaName":179},"/solutions/value-stream-management/",{"text":183,"config":184},"Analytics & Insights",{"href":185,"dataGaLocation":47,"dataGaName":186},"/solutions/analytics-and-insights/","Analytics and insights",{"title":188,"items":189},"GitLab for",[190,195,200],{"text":191,"config":192},"Enterprise",{"href":193,"dataGaLocation":47,"dataGaName":194},"/enterprise/","enterprise",{"text":196,"config":197},"Small Business",{"href":198,"dataGaLocation":47,"dataGaName":199},"/small-business/","small business",{"text":201,"config":202},"Public Sector",{"href":203,"dataGaLocation":47,"dataGaName":204},"/solutions/public-sector/","public sector",{"text":206,"config":207},"Pricing",{"href":208,"dataGaName":209,"dataGaLocation":47,"dataNavLevelOne":209},"/pricing/","pricing",{"text":211,"config":212,"link":214,"lists":218,"feature":302},"Resources",{"dataNavLevelOne":213},"resources",{"text":215,"config":216},"View all resources",{"href":217,"dataGaName":213,"dataGaLocation":47},"/resources/",[219,252,274],{"title":220,"items":221},"Getting started",[222,227,232,237,242,247],{"text":223,"config":224},"Install",{"href":225,"dataGaName":226,"dataGaLocation":47},"/install/","install",{"text":228,"config":229},"Quick start guides",{"href":230,"dataGaName":231,"dataGaLocation":47},"/get-started/","quick setup checklists",{"text":233,"config":234},"Learn",{"href":235,"dataGaLocation":47,"dataGaName":236},"https://university.gitlab.com/","learn",{"text":238,"config":239},"Product documentation",{"href":240,"dataGaName":241,"dataGaLocation":47},"https://docs.gitlab.com/","product documentation",{"text":243,"config":244},"Best practice videos",{"href":245,"dataGaName":246,"dataGaLocation":47},"/getting-started-videos/","best practice videos",{"text":248,"config":249},"Integrations",{"href":250,"dataGaName":251,"dataGaLocation":47},"/integrations/","integrations",{"title":253,"items":254},"Discover",[255,260,264,269],{"text":256,"config":257},"Customer success stories",{"href":258,"dataGaName":259,"dataGaLocation":47},"/customers/","customer success stories",{"text":261,"config":262},"Blog",{"href":263,"dataGaName":5,"dataGaLocation":47},"/blog/",{"text":265,"config":266},"Remote",{"href":267,"dataGaName":268,"dataGaLocation":47},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":270,"config":271},"TeamOps",{"href":272,"dataGaName":273,"dataGaLocation":47},"/teamops/","teamops",{"title":275,"items":276},"Connect",[277,282,287,292,297],{"text":278,"config":279},"GitLab Services",{"href":280,"dataGaName":281,"dataGaLocation":47},"/services/","services",{"text":283,"config":284},"Community",{"href":285,"dataGaName":286,"dataGaLocation":47},"/community/","community",{"text":288,"config":289},"Forum",{"href":290,"dataGaName":291,"dataGaLocation":47},"https://forum.gitlab.com/","forum",{"text":293,"config":294},"Events",{"href":295,"dataGaName":296,"dataGaLocation":47},"/events/","events",{"text":298,"config":299},"Partners",{"href":300,"dataGaName":301,"dataGaLocation":47},"/partners/","partners",{"backgroundColor":303,"textColor":304,"text":305,"image":306,"link":310},"#2f2a6b","#fff","Insights for the future of software development",{"altText":307,"config":308},"the source promo card",{"src":309},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":311,"config":312},"Read the latest",{"href":313,"dataGaName":314,"dataGaLocation":47},"/the-source/","the source",{"text":316,"config":317,"lists":319},"Company",{"dataNavLevelOne":318},"company",[320],{"items":321},[322,327,333,335,340,345,350,355,360,365,370],{"text":323,"config":324},"About",{"href":325,"dataGaName":326,"dataGaLocation":47},"/company/","about",{"text":328,"config":329,"footerGa":332},"Jobs",{"href":330,"dataGaName":331,"dataGaLocation":47},"/jobs/","jobs",{"dataGaName":331},{"text":293,"config":334},{"href":295,"dataGaName":296,"dataGaLocation":47},{"text":336,"config":337},"Leadership",{"href":338,"dataGaName":339,"dataGaLocation":47},"/company/team/e-group/","leadership",{"text":341,"config":342},"Team",{"href":343,"dataGaName":344,"dataGaLocation":47},"/company/team/","team",{"text":346,"config":347},"Handbook",{"href":348,"dataGaName":349,"dataGaLocation":47},"https://handbook.gitlab.com/","handbook",{"text":351,"config":352},"Investor relations",{"href":353,"dataGaName":354,"dataGaLocation":47},"https://ir.gitlab.com/","investor relations",{"text":356,"config":357},"Trust Center",{"href":358,"dataGaName":359,"dataGaLocation":47},"/security/","trust center",{"text":361,"config":362},"AI Transparency Center",{"href":363,"dataGaName":364,"dataGaLocation":47},"/ai-transparency-center/","ai transparency center",{"text":366,"config":367},"Newsletter",{"href":368,"dataGaName":369,"dataGaLocation":47},"/company/contact/","newsletter",{"text":371,"config":372},"Press",{"href":373,"dataGaName":374,"dataGaLocation":47},"/press/","press",{"text":376,"config":377,"lists":378},"Contact us",{"dataNavLevelOne":318},[379],{"items":380},[381,384,389],{"text":54,"config":382},{"href":56,"dataGaName":383,"dataGaLocation":47},"talk to sales",{"text":385,"config":386},"Get help",{"href":387,"dataGaName":388,"dataGaLocation":47},"/support/","get help",{"text":390,"config":391},"Customer portal",{"href":392,"dataGaName":393,"dataGaLocation":47},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":395,"login":396,"suggestions":403},"Close",{"text":397,"link":398},"To search repositories and projects, login to",{"text":399,"config":400},"gitlab.com",{"href":61,"dataGaName":401,"dataGaLocation":402},"search login","search",{"text":404,"default":405},"Suggestions",[406,408,412,414,418,422],{"text":76,"config":407},{"href":81,"dataGaName":76,"dataGaLocation":402},{"text":409,"config":410},"Code Suggestions (AI)",{"href":411,"dataGaName":409,"dataGaLocation":402},"/solutions/code-suggestions/",{"text":23,"config":413},{"href":129,"dataGaName":23,"dataGaLocation":402},{"text":415,"config":416},"GitLab on AWS",{"href":417,"dataGaName":415,"dataGaLocation":402},"/partners/technology-partners/aws/",{"text":419,"config":420},"GitLab on Google Cloud",{"href":421,"dataGaName":419,"dataGaLocation":402},"/partners/technology-partners/google-cloud-platform/",{"text":423,"config":424},"Why GitLab?",{"href":89,"dataGaName":423,"dataGaLocation":402},{"freeTrial":426,"mobileIcon":431,"desktopIcon":436,"secondaryButton":439},{"text":427,"config":428},"Start free trial",{"href":429,"dataGaName":52,"dataGaLocation":430},"https://gitlab.com/-/trials/new/","nav",{"altText":432,"config":433},"Gitlab Icon",{"src":434,"dataGaName":435,"dataGaLocation":430},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":432,"config":437},{"src":438,"dataGaName":435,"dataGaLocation":430},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":440,"config":441},"Get Started",{"href":442,"dataGaName":443,"dataGaLocation":430},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":445,"mobileIcon":449,"desktopIcon":451},{"text":446,"config":447},"Learn more about GitLab Duo",{"href":81,"dataGaName":448,"dataGaLocation":430},"gitlab duo",{"altText":432,"config":450},{"src":434,"dataGaName":435,"dataGaLocation":430},{"altText":432,"config":452},{"src":438,"dataGaName":435,"dataGaLocation":430},{"freeTrial":454,"mobileIcon":459,"desktopIcon":461},{"text":455,"config":456},"Back to pricing",{"href":208,"dataGaName":457,"dataGaLocation":430,"icon":458},"back to pricing","GoBack",{"altText":432,"config":460},{"src":434,"dataGaName":435,"dataGaLocation":430},{"altText":432,"config":462},{"src":438,"dataGaName":435,"dataGaLocation":430},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":468,"_dir":41,"_draft":6,"_partial":6,"_locale":7,"title":469,"button":470,"image":475,"config":479,"_id":481,"_type":33,"_source":35,"_file":482,"_stem":483,"_extension":38},"/shared/en-us/banner","is now in public beta!",{"text":471,"config":472},"Try the Beta",{"href":473,"dataGaName":474,"dataGaLocation":47},"/gitlab-duo/agent-platform/","duo banner",{"altText":476,"config":477},"GitLab Duo Agent Platform",{"src":478},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":480},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":485,"_dir":41,"_draft":6,"_partial":6,"_locale":7,"data":486,"_id":689,"_type":33,"title":690,"_source":35,"_file":691,"_stem":692,"_extension":38},"/shared/en-us/main-footer",{"text":487,"source":488,"edit":494,"contribute":499,"config":504,"items":509,"minimal":681},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":489,"config":490},"View page source",{"href":491,"dataGaName":492,"dataGaLocation":493},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":495,"config":496},"Edit this page",{"href":497,"dataGaName":498,"dataGaLocation":493},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":500,"config":501},"Please contribute",{"href":502,"dataGaName":503,"dataGaLocation":493},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":505,"facebook":506,"youtube":507,"linkedin":508},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[510,533,588,617,651],{"title":65,"links":511,"subMenu":516},[512],{"text":513,"config":514},"DevSecOps platform",{"href":74,"dataGaName":515,"dataGaLocation":493},"devsecops platform",[517],{"title":206,"links":518},[519,523,528],{"text":520,"config":521},"View plans",{"href":208,"dataGaName":522,"dataGaLocation":493},"view plans",{"text":524,"config":525},"Why Premium?",{"href":526,"dataGaName":527,"dataGaLocation":493},"/pricing/premium/","why premium",{"text":529,"config":530},"Why Ultimate?",{"href":531,"dataGaName":532,"dataGaLocation":493},"/pricing/ultimate/","why ultimate",{"title":534,"links":535},"Solutions",[536,541,543,545,550,555,559,562,566,570,572,575,578,583],{"text":537,"config":538},"Digital transformation",{"href":539,"dataGaName":540,"dataGaLocation":493},"/topics/digital-transformation/","digital transformation",{"text":152,"config":542},{"href":154,"dataGaName":152,"dataGaLocation":493},{"text":141,"config":544},{"href":124,"dataGaName":125,"dataGaLocation":493},{"text":546,"config":547},"Agile development",{"href":548,"dataGaName":549,"dataGaLocation":493},"/solutions/agile-delivery/","agile delivery",{"text":551,"config":552},"Cloud transformation",{"href":553,"dataGaName":554,"dataGaLocation":493},"/topics/cloud-native/","cloud transformation",{"text":556,"config":557},"SCM",{"href":137,"dataGaName":558,"dataGaLocation":493},"source code management",{"text":23,"config":560},{"href":129,"dataGaName":561,"dataGaLocation":493},"continuous integration & delivery",{"text":563,"config":564},"Value stream management",{"href":181,"dataGaName":565,"dataGaLocation":493},"value stream management",{"text":26,"config":567},{"href":568,"dataGaName":569,"dataGaLocation":493},"/solutions/gitops/","gitops",{"text":191,"config":571},{"href":193,"dataGaName":194,"dataGaLocation":493},{"text":573,"config":574},"Small business",{"href":198,"dataGaName":199,"dataGaLocation":493},{"text":576,"config":577},"Public sector",{"href":203,"dataGaName":204,"dataGaLocation":493},{"text":579,"config":580},"Education",{"href":581,"dataGaName":582,"dataGaLocation":493},"/solutions/education/","education",{"text":584,"config":585},"Financial services",{"href":586,"dataGaName":587,"dataGaLocation":493},"/solutions/finance/","financial services",{"title":211,"links":589},[590,592,594,596,599,601,603,605,607,609,611,613,615],{"text":223,"config":591},{"href":225,"dataGaName":226,"dataGaLocation":493},{"text":228,"config":593},{"href":230,"dataGaName":231,"dataGaLocation":493},{"text":233,"config":595},{"href":235,"dataGaName":236,"dataGaLocation":493},{"text":238,"config":597},{"href":240,"dataGaName":598,"dataGaLocation":493},"docs",{"text":261,"config":600},{"href":263,"dataGaName":5,"dataGaLocation":493},{"text":256,"config":602},{"href":258,"dataGaName":259,"dataGaLocation":493},{"text":265,"config":604},{"href":267,"dataGaName":268,"dataGaLocation":493},{"text":278,"config":606},{"href":280,"dataGaName":281,"dataGaLocation":493},{"text":270,"config":608},{"href":272,"dataGaName":273,"dataGaLocation":493},{"text":283,"config":610},{"href":285,"dataGaName":286,"dataGaLocation":493},{"text":288,"config":612},{"href":290,"dataGaName":291,"dataGaLocation":493},{"text":293,"config":614},{"href":295,"dataGaName":296,"dataGaLocation":493},{"text":298,"config":616},{"href":300,"dataGaName":301,"dataGaLocation":493},{"title":316,"links":618},[619,621,623,625,627,629,631,635,640,642,644,646],{"text":323,"config":620},{"href":325,"dataGaName":318,"dataGaLocation":493},{"text":328,"config":622},{"href":330,"dataGaName":331,"dataGaLocation":493},{"text":336,"config":624},{"href":338,"dataGaName":339,"dataGaLocation":493},{"text":341,"config":626},{"href":343,"dataGaName":344,"dataGaLocation":493},{"text":346,"config":628},{"href":348,"dataGaName":349,"dataGaLocation":493},{"text":351,"config":630},{"href":353,"dataGaName":354,"dataGaLocation":493},{"text":632,"config":633},"Sustainability",{"href":634,"dataGaName":632,"dataGaLocation":493},"/sustainability/",{"text":636,"config":637},"Diversity, inclusion and belonging (DIB)",{"href":638,"dataGaName":639,"dataGaLocation":493},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":356,"config":641},{"href":358,"dataGaName":359,"dataGaLocation":493},{"text":366,"config":643},{"href":368,"dataGaName":369,"dataGaLocation":493},{"text":371,"config":645},{"href":373,"dataGaName":374,"dataGaLocation":493},{"text":647,"config":648},"Modern Slavery Transparency Statement",{"href":649,"dataGaName":650,"dataGaLocation":493},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":652,"links":653},"Contact Us",[654,657,659,661,666,671,676],{"text":655,"config":656},"Contact an expert",{"href":56,"dataGaName":57,"dataGaLocation":493},{"text":385,"config":658},{"href":387,"dataGaName":388,"dataGaLocation":493},{"text":390,"config":660},{"href":392,"dataGaName":393,"dataGaLocation":493},{"text":662,"config":663},"Status",{"href":664,"dataGaName":665,"dataGaLocation":493},"https://status.gitlab.com/","status",{"text":667,"config":668},"Terms of use",{"href":669,"dataGaName":670,"dataGaLocation":493},"/terms/","terms of use",{"text":672,"config":673},"Privacy statement",{"href":674,"dataGaName":675,"dataGaLocation":493},"/privacy/","privacy statement",{"text":677,"config":678},"Cookie preferences",{"dataGaName":679,"dataGaLocation":493,"id":680,"isOneTrustButton":110},"cookie preferences","ot-sdk-btn",{"items":682},[683,685,687],{"text":667,"config":684},{"href":669,"dataGaName":670,"dataGaLocation":493},{"text":672,"config":686},{"href":674,"dataGaName":675,"dataGaLocation":493},{"text":677,"config":688},{"dataGaName":679,"dataGaLocation":493,"id":680,"isOneTrustButton":110},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[694],{"_path":695,"_dir":696,"_draft":6,"_partial":6,"_locale":7,"content":697,"config":701,"_id":703,"_type":33,"title":18,"_source":35,"_file":704,"_stem":705,"_extension":38},"/en-us/blog/authors/daniel-helfand","authors",{"name":18,"config":698},{"headshot":699,"ctfId":700},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662418/Blog/Author%20Headshots/dhelfand.png","b9sRP0HJhdPsOEruWUfih",{"template":702},"BlogAuthor","content:en-us:blog:authors:daniel-helfand.yml","en-us/blog/authors/daniel-helfand.yml","en-us/blog/authors/daniel-helfand",{"_path":707,"_dir":41,"_draft":6,"_partial":6,"_locale":7,"header":708,"eyebrow":709,"blurb":710,"button":711,"secondaryButton":715,"_id":717,"_type":33,"title":718,"_source":35,"_file":719,"_stem":720,"_extension":38},"/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":49,"config":712},{"href":713,"dataGaName":52,"dataGaLocation":714},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":54,"config":716},{"href":56,"dataGaName":57,"dataGaLocation":714},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1758662335448]