[{"data":1,"prerenderedAt":2322},["ShallowReactive",2],{"/blog/empowering-modelops-and-hpc-workloads-with-gpu-enabled-runners":3,"navigation-en-us":1539,"banner-en-us":1966,"footer-en-us":1976,"blog-post-authors-en-us-Gabriel Engel":2220,"blog-related-posts-en-us-empowering-modelops-and-hpc-workloads-with-gpu-enabled-runners":2235,"blog-promotions-en-us":2260,"next-steps-en-us":2312},{"id":4,"title":5,"authors":6,"body":8,"category":1515,"date":1516,"description":1517,"extension":1518,"externalUrl":1519,"faq":1519,"featured":1520,"heroImage":1521,"meta":1522,"navigation":207,"path":1523,"seo":1524,"slug":1529,"stem":1530,"tags":1531,"template":1537,"updatedDate":1519,"__hash__":1538},"blogPosts/en-us/blog/empowering-modelops-and-hpc-workloads-with-gpu-enabled-runners.md","Empower ModelOps and HPC workloads with GPU-enabled runners integrated with CI/CD",[7],"Gabriel Engel",{"type":9,"value":10,"toc":1497},"minimark",[11,29,44,47,52,72,76,79,84,101,105,125,177,181,195,198,219,223,234,257,261,264,268,275,280,371,375,378,382,435,439,442,446,455,474,477,480,520,527,532,550,658,675,823,832,857,873,879,883,893,899,967,978,1035,1039,1042,1048,1133,1138,1144,1150,1154,1160,1225,1237,1243,1247,1256,1274,1279,1440,1446,1454,1463,1467,1470,1478,1493],[12,13,14],"p",{},[15,16,17,18,23,24,28],"em",{},"This blog post is the latest in an ongoing series about GitLab's journey to ",[19,20,22],"a",{"href":21},"/blog/ai-ml-in-devsecops-series/","build and integrate AI/ML into our DevSecOps platform",". Start with the first blog post: ",[19,25,27],{"href":26},"/blog/what-the-ml-ai/","What the ML is up with DevSecOps and AI?",". Throughout the series, we'll feature blogs from our product, engineering, and UX teams to showcase how we're infusing AI/ML into GitLab.",[12,30,31,32,37,38,43],{},"In today's fast-paced world, organizations are constantly looking to improve their ",[19,33,36],{"href":34,"rel":35},"https://docs.gitlab.com/user/project/ml/",[],"ModelOps"," and high-performance computing (HPC) capabilities. Leveraging powerful graphical processing units (",[19,39,42],{"href":40,"rel":41},"https://www.techtarget.com/searchvirtualdesktop/definition/GPU-graphics-processing-unit",[],"GPUs",") has become a game-changer for accelerating machine learning workflows and compute-intensive tasks. To help meet these evolving needs, we recently released our first GPU-enabled runners on GitLab.com.",[12,45,46],{},"Securely hosting a GitLab Runner environment for ModelOps and HPC is non-trivial and requires a lot of knowledge and time to set up and maintain. In this blog post, we'll look at some real-world examples of how you can harness the potential of GPU computing for ModelOps or HPC workloads while taking full advantage of a SaaS solution.",[48,49,51],"h2",{"id":50},"what-are-gpu-enabled-runners","What are GPU-enabled runners?",[12,53,54,55,60,61,65,66,71],{},"GPU-enabled runners are dedicated computing resources for the AI-powered DevSecOps platform. They provide accelerated processing power for ModelOps and HPC such as the training or deployment of large language models (",[19,56,59],{"href":57,"rel":58},"https://www.techtarget.com/whatis/definition/large-language-model-LLM",[],"LLMs",") as part of ModelOps workloads. In the first iteration of releasing GPU-enabled runners, GitLab.com SaaS offers the GCP ",[62,63,64],"code",{},"n1-standard-4"," machine type (4 vCPU, 15 GB memory) with 1 NVIDIA T4 (16 GB memory) attached. The runner behaves like a GitLab Runner on Linux, using the docker+machine ",[19,67,70],{"href":68,"rel":69},"https://docs.gitlab.com/runner/executors/",[],"executor",".",[48,73,75],{"id":74},"using-gpu-enabled-runners","Using GPU-enabled runners",[12,77,78],{},"To take advantage of GitLab GPU-enabled runners, follow these steps:",[80,81,83],"h3",{"id":82},"_1-have-a-project-on-gitlabcom","1. Have a project on GitLab.com",[12,85,86,87,90,91,94,95,100],{},"All projects on GitLab.com SaaS with a ",[62,88,89],{},"Premium"," or ",[62,92,93],{},"Ultimate"," ",[19,96,99],{"href":97,"rel":98},"https://about.gitlab.com/pricing/",[],"subscription"," have the GPU-enabled runners enabled by default - no additional configuration is required.",[80,102,104],{"id":103},"_2-create-a-job-running-on-gpu-enabled-runners","2. Create a job running on GPU-enabled runners",[12,106,107,108,111,112,120,121,124],{},"Create a job in your ",[62,109,110],{},".gitlab-ci.yml"," configuration file, and set the ",[19,113,116,117],{"href":114,"rel":115},"https://docs.gitlab.com/ci/runners/configure_runners/#use-tags-to-control-which-jobs-a-runner-can-run",[],"runner ",[62,118,119],{},"tag"," to the ",[62,122,123],{},"saas-linux-medium-amd64-gpu-standard"," value.",[126,127,132],"pre",{"className":128,"code":129,"language":130,"meta":131,"style":131},"language-yaml shiki shiki-themes github-light","gpu-job:\n  stage: build\n  tags:\n    - saas-linux-medium-amd64-gpu-standard\n\n","yaml","",[62,133,134,147,160,168],{"__ignoreMap":131},[135,136,139,143],"span",{"class":137,"line":138},"line",1,[135,140,142],{"class":141},"shJU0","gpu-job",[135,144,146],{"class":145},"sgsFI",":\n",[135,148,150,153,156],{"class":137,"line":149},2,[135,151,152],{"class":141},"  stage",[135,154,155],{"class":145},": ",[135,157,159],{"class":158},"sYBdl","build\n",[135,161,163,166],{"class":137,"line":162},3,[135,164,165],{"class":141},"  tags",[135,167,146],{"class":145},[135,169,171,174],{"class":137,"line":170},4,[135,172,173],{"class":145},"    - ",[135,175,176],{"class":158},"saas-linux-medium-amd64-gpu-standard\n",[80,178,180],{"id":179},"_3-select-a-docker-image-with-the-nvidia-cuda-driver","3. Select a Docker image with the Nvidia CUDA driver",[12,182,183,184,189,190,71],{},"The CI/CD job runs in an isolated virtual machine (VM) with a bring-your-own-image policy as with GitLab SaaS runners on Linux. GitLab mounts the GPU from the host VM into your isolated environment. You must use a Docker image with the GPU driver installed to use the GPU. For Nvidia GPUs, you can use the ",[19,185,188],{"href":186,"rel":187},"https://catalog.ngc.nvidia.com/orgs/nvidia/containers/cuda",[],"CUDA Toolkit"," directly, or third-party images with Nvidia drivers installed, such as the ",[19,191,194],{"href":192,"rel":193},"https://hub.docker.com/r/tensorflow/tensorflow/",[],"TensorFlow GPU image",[12,196,197],{},"The CI/CD job configuration for the Nvidia CUDA base Ubuntu image looks like this:",[126,199,201],{"className":128,"code":200,"language":130,"meta":131,"style":131},"\n  image: nvcr.io/nvidia/cuda:12.1.1-base-ubuntu22.04\n\n",[62,202,203,209],{"__ignoreMap":131},[135,204,205],{"class":137,"line":138},[135,206,208],{"emptyLinePlaceholder":207},true,"\n",[135,210,211,214,216],{"class":137,"line":149},[135,212,213],{"class":141},"  image",[135,215,155],{"class":145},[135,217,218],{"class":158},"nvcr.io/nvidia/cuda:12.1.1-base-ubuntu22.04\n",[80,220,222],{"id":221},"_4-verify-that-the-gpu-is-working","4. Verify that the GPU is working",[12,224,225,226,229,230,233],{},"To verify that the GPU drivers are working correctly, you can execute the ",[62,227,228],{},"nvidia-smi"," command in the CI/CD job ",[62,231,232],{},"script"," section.",[126,235,237],{"className":128,"code":236,"language":130,"meta":131,"style":131},"\n  script:\n    - nvidia-smi\n\n",[62,238,239,243,250],{"__ignoreMap":131},[135,240,241],{"class":137,"line":138},[135,242,208],{"emptyLinePlaceholder":207},[135,244,245,248],{"class":137,"line":149},[135,246,247],{"class":141},"  script",[135,249,146],{"class":145},[135,251,252,254],{"class":137,"line":162},[135,253,173],{"class":145},[135,255,256],{"class":158},"nvidia-smi\n",[48,258,260],{"id":259},"basic-usage-examples","Basic usage examples",[12,262,263],{},"Let's explore some basic scenarios where GPU-enabled runners can supercharge your ModelOps and HPC workloads:",[80,265,267],{"id":266},"example-1-modelops-with-python","Example 1: ModelOps with Python",[12,269,270,271,274],{},"In this example, we train a model on our GPU-enabled runner defined in the ",[62,272,273],{},"train.py"," file using the Nvidia CUDA base Ubuntu image mentioned earlier.",[12,276,277,279],{},[62,278,110],{}," file:",[126,281,283],{"className":128,"code":282,"language":130,"meta":131,"style":131},"model-training:\n  stage: build\n  tags:\n    - saas-linux-medium-amd64-gpu-standard\n  image: nvcr.io/nvidia/cuda:12.1.1-base-ubuntu22.04\n  script:\n    - apt update\n    - apt install -y --no-install-recommends python3 python3-pip \n    - pip3 install -r requirements.txt\n    - python3 --version\n    - python3 train.py\n\n",[62,284,285,292,300,306,312,321,328,336,347,355,363],{"__ignoreMap":131},[135,286,287,290],{"class":137,"line":138},[135,288,289],{"class":141},"model-training",[135,291,146],{"class":145},[135,293,294,296,298],{"class":137,"line":149},[135,295,152],{"class":141},[135,297,155],{"class":145},[135,299,159],{"class":158},[135,301,302,304],{"class":137,"line":162},[135,303,165],{"class":141},[135,305,146],{"class":145},[135,307,308,310],{"class":137,"line":170},[135,309,173],{"class":145},[135,311,176],{"class":158},[135,313,315,317,319],{"class":137,"line":314},5,[135,316,213],{"class":141},[135,318,155],{"class":145},[135,320,218],{"class":158},[135,322,324,326],{"class":137,"line":323},6,[135,325,247],{"class":141},[135,327,146],{"class":145},[135,329,331,333],{"class":137,"line":330},7,[135,332,173],{"class":145},[135,334,335],{"class":158},"apt update\n",[135,337,339,341,344],{"class":137,"line":338},8,[135,340,173],{"class":145},[135,342,343],{"class":158},"apt install -y --no-install-recommends python3 python3-pip",[135,345,346],{"class":145}," \n",[135,348,350,352],{"class":137,"line":349},9,[135,351,173],{"class":145},[135,353,354],{"class":158},"pip3 install -r requirements.txt\n",[135,356,358,360],{"class":137,"line":357},10,[135,359,173],{"class":145},[135,361,362],{"class":158},"python3 --version\n",[135,364,366,368],{"class":137,"line":365},11,[135,367,173],{"class":145},[135,369,370],{"class":158},"python3 train.py\n",[80,372,374],{"id":373},"example-2-scientific-simulations-and-hpc","Example 2: Scientific simulations and HPC",[12,376,377],{},"Complex scientific simulations require significant computing resources. GPU-enabled runners can accelerate these simulations, allowing you to get results in less time.",[12,379,380,279],{},[62,381,110],{},[126,383,385],{"className":128,"code":384,"language":130,"meta":131,"style":131},"simulation-run:\n  stage: build\n  tags:\n    - saas-linux-medium-amd64-gpu-standard\n  image: nvcr.io/nvidia/cuda:12.1.1-base-ubuntu22.04\n  script:\n    - ./run_simulation --input input_file.txt\n\n",[62,386,387,394,402,408,414,422,428],{"__ignoreMap":131},[135,388,389,392],{"class":137,"line":138},[135,390,391],{"class":141},"simulation-run",[135,393,146],{"class":145},[135,395,396,398,400],{"class":137,"line":149},[135,397,152],{"class":141},[135,399,155],{"class":145},[135,401,159],{"class":158},[135,403,404,406],{"class":137,"line":162},[135,405,165],{"class":141},[135,407,146],{"class":145},[135,409,410,412],{"class":137,"line":170},[135,411,173],{"class":145},[135,413,176],{"class":158},[135,415,416,418,420],{"class":137,"line":314},[135,417,213],{"class":141},[135,419,155],{"class":145},[135,421,218],{"class":158},[135,423,424,426],{"class":137,"line":323},[135,425,247],{"class":141},[135,427,146],{"class":145},[135,429,430,432],{"class":137,"line":330},[135,431,173],{"class":145},[135,433,434],{"class":158},"./run_simulation --input input_file.txt\n",[48,436,438],{"id":437},"advanced-usage-examples","Advanced usage examples",[12,440,441],{},"Let's go through some real-world scenarios of how we use GPU-enabled runners at GitLab.",[80,443,445],{"id":444},"example-3-python-model-training-with-a-custom-docker-image","Example 3: Python model training with a custom Docker image",[12,447,448,449,454],{},"For our third example, we will use this ",[19,450,453],{"href":451,"rel":452},"https://gitlab.com/gitlab-org/modelops/demos/handwritten-digit-recognition",[],"handwritten digit recognition model",". We are using this project as a demo to showcase or try out new ModelOps features.",[12,456,457,461,462,467,468,471,472,71],{},[19,458,460],{"href":451,"rel":459},[],"Open the project"," and fork it into your preferred namespace. You can follow the next steps using the ",[19,463,466],{"href":464,"rel":465},"https://docs.gitlab.com/user/project/web_ide/",[],"Web IDE"," in the browser, or clone the project locally to create and edit the files. Some of the next steps require you to override existing configuration in the ",[62,469,470],{},"Dockerfile"," and ",[62,473,110],{},[12,475,476],{},"As we need more pre-installed components and want to save installation time when training the model, we decided to create a custom Docker image with all dependencies pre-installed. This also gives us full control over the build environment we use and allows us to reuse it locally without relying on the `.gitlab-ci.yml' implementation.",[12,478,479],{},"In addition, we are using a more complete pipeline configuration with the following stages:",[126,481,483],{"className":128,"code":482,"language":130,"meta":131,"style":131},"stages:\n  - build\n  - test\n  - train\n  - publish\n\n",[62,484,485,492,499,506,513],{"__ignoreMap":131},[135,486,487,490],{"class":137,"line":138},[135,488,489],{"class":141},"stages",[135,491,146],{"class":145},[135,493,494,497],{"class":137,"line":149},[135,495,496],{"class":145},"  - ",[135,498,159],{"class":158},[135,500,501,503],{"class":137,"line":162},[135,502,496],{"class":145},[135,504,505],{"class":158},"test\n",[135,507,508,510],{"class":137,"line":170},[135,509,496],{"class":145},[135,511,512],{"class":158},"train\n",[135,514,515,517],{"class":137,"line":314},[135,516,496],{"class":145},[135,518,519],{"class":158},"publish\n",[12,521,522],{},[523,524],"img",{"alt":525,"src":526},"GPU pipeline overview","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397795/blog/Content%20Images/2023-07-06-gpu-enabled-runners-for-modelops/pipeline-overview.png",[528,529,531],"h4",{"id":530},"building-a-custom-docker-image","Building a custom Docker image",[12,533,534,535,537,538,541,542,545,546,549],{},"The first step is to define a ",[62,536,470],{},". In this example, we start with the Nvidia CUDA base Ubuntu image and then install ",[62,539,540],{},"Python3.10",". Using ",[62,543,544],{},"pip install",", we then add all the required libraries specified in a ",[62,547,548],{},"requirements.txt"," file.",[126,551,555],{"className":552,"code":553,"language":554,"meta":131,"style":131},"language-docker shiki shiki-themes github-light","FROM nvcr.io/nvidia/cuda:12.1.1-base-ubuntu22.04\n\n1. Update and install required packages\nRUN apt-get update && apt-get install -y \\\n    python3.10 \\\n    python3.10-dev \\\n    python3-pip \\\n    && rm -rf /var/lib/apt/lists/*\n\n2. Set Python 3.10 as the default Python version\nRUN ln -s /usr/bin/python3.10 /usr/bin/python\n\n3. Copy the requirements.txt file\nCOPY requirements.txt /tmp/requirements.txt\n\n4. Install Python dependencies\nRUN pip3 install --no-cache-dir -r /tmp/requirements.txt\n","docker",[62,556,557,566,570,575,583,588,593,598,603,607,612,619,624,630,639,644,650],{"__ignoreMap":131},[135,558,559,563],{"class":137,"line":138},[135,560,562],{"class":561},"sD7c4","FROM",[135,564,565],{"class":145}," nvcr.io/nvidia/cuda:12.1.1-base-ubuntu22.04\n",[135,567,568],{"class":137,"line":149},[135,569,208],{"emptyLinePlaceholder":207},[135,571,572],{"class":137,"line":162},[135,573,574],{"class":145},"1. Update and install required packages\n",[135,576,577,580],{"class":137,"line":170},[135,578,579],{"class":561},"RUN",[135,581,582],{"class":145}," apt-get update && apt-get install -y \\\n",[135,584,585],{"class":137,"line":314},[135,586,587],{"class":145},"    python3.10 \\\n",[135,589,590],{"class":137,"line":323},[135,591,592],{"class":145},"    python3.10-dev \\\n",[135,594,595],{"class":137,"line":330},[135,596,597],{"class":145},"    python3-pip \\\n",[135,599,600],{"class":137,"line":338},[135,601,602],{"class":145},"    && rm -rf /var/lib/apt/lists/*\n",[135,604,605],{"class":137,"line":349},[135,606,208],{"emptyLinePlaceholder":207},[135,608,609],{"class":137,"line":357},[135,610,611],{"class":145},"2. Set Python 3.10 as the default Python version\n",[135,613,614,616],{"class":137,"line":365},[135,615,579],{"class":561},[135,617,618],{"class":145}," ln -s /usr/bin/python3.10 /usr/bin/python\n",[135,620,622],{"class":137,"line":621},12,[135,623,208],{"emptyLinePlaceholder":207},[135,625,627],{"class":137,"line":626},13,[135,628,629],{"class":145},"3. Copy the requirements.txt file\n",[135,631,633,636],{"class":137,"line":632},14,[135,634,635],{"class":561},"COPY",[135,637,638],{"class":145}," requirements.txt /tmp/requirements.txt\n",[135,640,642],{"class":137,"line":641},15,[135,643,208],{"emptyLinePlaceholder":207},[135,645,647],{"class":137,"line":646},16,[135,648,649],{"class":145},"4. Install Python dependencies\n",[135,651,653,655],{"class":137,"line":652},17,[135,654,579],{"class":561},[135,656,657],{"class":145}," pip3 install --no-cache-dir -r /tmp/requirements.txt\n",[12,659,660,661,663,664,669,670,71],{},"In the ",[62,662,110],{}," file we use ",[19,665,668],{"href":666,"rel":667},"https://docs.gitlab.com/ci/docker/using_kaniko/",[],"Kaniko"," to build the Docker image and push it into the ",[19,671,674],{"href":672,"rel":673},"https://docs.gitlab.com/user/packages/container_registry/",[],"GitLab Container Registry",[126,676,678],{"className":128,"code":677,"language":130,"meta":131,"style":131},"variables:\n  IMAGE_PATH: \"${CI_REGISTRY_IMAGE}:latest\"\n  GIT_STRATEGY: fetch\n\ndocker-build:\n  stage: build\n  tags:\n    - saas-linux-medium-amd64\n  image:\n    name: gcr.io/kaniko-project/executor:v1.9.0-debug\n    entrypoint: [\"\"]\n  script:\n    - /kaniko/executor\n      --context \"${CI_PROJECT_DIR}\"\n      --dockerfile \"${CI_PROJECT_DIR}/Dockerfile\"\n      --destination \"${IMAGE_PATH}\"\n      --destination \"${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}\"\n  rules:\n    - if: $CI_COMMIT_TAG\n\n",[62,679,680,687,697,707,711,718,726,732,739,745,755,769,775,782,787,792,797,802,810],{"__ignoreMap":131},[135,681,682,685],{"class":137,"line":138},[135,683,684],{"class":141},"variables",[135,686,146],{"class":145},[135,688,689,692,694],{"class":137,"line":149},[135,690,691],{"class":141},"  IMAGE_PATH",[135,693,155],{"class":145},[135,695,696],{"class":158},"\"${CI_REGISTRY_IMAGE}:latest\"\n",[135,698,699,702,704],{"class":137,"line":162},[135,700,701],{"class":141},"  GIT_STRATEGY",[135,703,155],{"class":145},[135,705,706],{"class":158},"fetch\n",[135,708,709],{"class":137,"line":170},[135,710,208],{"emptyLinePlaceholder":207},[135,712,713,716],{"class":137,"line":314},[135,714,715],{"class":141},"docker-build",[135,717,146],{"class":145},[135,719,720,722,724],{"class":137,"line":323},[135,721,152],{"class":141},[135,723,155],{"class":145},[135,725,159],{"class":158},[135,727,728,730],{"class":137,"line":330},[135,729,165],{"class":141},[135,731,146],{"class":145},[135,733,734,736],{"class":137,"line":338},[135,735,173],{"class":145},[135,737,738],{"class":158},"saas-linux-medium-amd64\n",[135,740,741,743],{"class":137,"line":349},[135,742,213],{"class":141},[135,744,146],{"class":145},[135,746,747,750,752],{"class":137,"line":357},[135,748,749],{"class":141},"    name",[135,751,155],{"class":145},[135,753,754],{"class":158},"gcr.io/kaniko-project/executor:v1.9.0-debug\n",[135,756,757,760,763,766],{"class":137,"line":365},[135,758,759],{"class":141},"    entrypoint",[135,761,762],{"class":145},": [",[135,764,765],{"class":158},"\"\"",[135,767,768],{"class":145},"]\n",[135,770,771,773],{"class":137,"line":621},[135,772,247],{"class":141},[135,774,146],{"class":145},[135,776,777,779],{"class":137,"line":626},[135,778,173],{"class":145},[135,780,781],{"class":158},"/kaniko/executor\n",[135,783,784],{"class":137,"line":632},[135,785,786],{"class":158},"      --context \"${CI_PROJECT_DIR}\"\n",[135,788,789],{"class":137,"line":641},[135,790,791],{"class":158},"      --dockerfile \"${CI_PROJECT_DIR}/Dockerfile\"\n",[135,793,794],{"class":137,"line":646},[135,795,796],{"class":158},"      --destination \"${IMAGE_PATH}\"\n",[135,798,799],{"class":137,"line":652},[135,800,801],{"class":158},"      --destination \"${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}\"\n",[135,803,805,808],{"class":137,"line":804},18,[135,806,807],{"class":141},"  rules",[135,809,146],{"class":145},[135,811,813,815,818,820],{"class":137,"line":812},19,[135,814,173],{"class":145},[135,816,817],{"class":141},"if",[135,819,155],{"class":145},[135,821,822],{"class":158},"$CI_COMMIT_TAG\n",[12,824,825,826,831],{},"In ",[19,827,830],{"href":828,"rel":829},"https://docs.gitlab.com/ci/yaml/#rules",[],"rules"," we define to only trigger the Docker image build for a new git tag. The reason is simple - we don't want to run the image build process for every time we train the model.",[12,833,834,835,840,841,844,845,848,849,852,853,856],{},"To start the image build job ",[19,836,839],{"href":837,"rel":838},"https://docs.gitlab.com/user/project/repository/tags/#create-a-tag",[],"create a new Git tag",". You can either do this by using ",[62,842,843],{},"git tag -a v0.0.1"," command or via UI. Navigate into ",[62,846,847],{},"Code > Tags"," and click on ",[62,850,851],{},"New Tag",". As Tag name type ",[62,854,855],{},"v0.0.1"," to create a new Git tag and trigger the job.",[12,858,859,860,863,864,866,867,71],{},"Navigate to ",[62,861,862],{},"Build > Pipelines"," to verify the ",[62,865,715],{}," job status, and then locate the tagged image following ",[19,868,870],{"href":672,"rel":869},[],[62,871,872],{},"Deploy > Container Registry",[12,874,875],{},[523,876],{"alt":877,"src":878},"Docker image","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397795/blog/Content%20Images/2023-07-06-gpu-enabled-runners-for-modelops/gpu-docker-image.png",[528,880,882],{"id":881},"testing-the-docker-image","Testing the Docker image",[12,884,885,886,889,890,892],{},"To test the image, we will use the following ",[62,887,888],{},"test-image"," job and run ",[62,891,228],{}," and check that the GPU drivers are working correctly.",[12,894,895,896,898],{},"The job configuration in ",[62,897,110],{}," file looks as follows:",[126,900,902],{"className":128,"code":901,"language":130,"meta":131,"style":131},"test-image:\n  stage: test\n  tags:\n    - saas-linux-medium-amd64-gpu-standard\n  image: $IMAGE_PATH\n  script:\n    - nvidia-smi\n  rules:\n    - if: $CI_COMMIT_TAG\n\n",[62,903,904,910,918,924,930,939,945,951,957],{"__ignoreMap":131},[135,905,906,908],{"class":137,"line":138},[135,907,888],{"class":141},[135,909,146],{"class":145},[135,911,912,914,916],{"class":137,"line":149},[135,913,152],{"class":141},[135,915,155],{"class":145},[135,917,505],{"class":158},[135,919,920,922],{"class":137,"line":162},[135,921,165],{"class":141},[135,923,146],{"class":145},[135,925,926,928],{"class":137,"line":170},[135,927,173],{"class":145},[135,929,176],{"class":158},[135,931,932,934,936],{"class":137,"line":314},[135,933,213],{"class":141},[135,935,155],{"class":145},[135,937,938],{"class":158},"$IMAGE_PATH\n",[135,940,941,943],{"class":137,"line":323},[135,942,247],{"class":141},[135,944,146],{"class":145},[135,946,947,949],{"class":137,"line":330},[135,948,173],{"class":145},[135,950,256],{"class":158},[135,952,953,955],{"class":137,"line":338},[135,954,807],{"class":141},[135,956,146],{"class":145},[135,958,959,961,963,965],{"class":137,"line":349},[135,960,173],{"class":145},[135,962,817],{"class":141},[135,964,155],{"class":145},[135,966,822],{"class":158},[12,968,969,970,975,976,549],{},"We also include container scanning and more ",[19,971,974],{"href":972,"rel":973},"https://docs.gitlab.com/user/application_security/",[],"security scanning"," templates in the ",[62,977,110],{},[126,979,981],{"className":128,"code":980,"language":130,"meta":131,"style":131},"include:\n  - template: Security/Secret-Detection.gitlab-ci.yml\n  - template: Security/Container-Scanning.gitlab-ci.yml\n  - template: Jobs/Dependency-Scanning.gitlab-ci.yml\n  - template: Security/SAST.gitlab-ci.yml\n\n",[62,982,983,990,1002,1013,1024],{"__ignoreMap":131},[135,984,985,988],{"class":137,"line":138},[135,986,987],{"class":141},"include",[135,989,146],{"class":145},[135,991,992,994,997,999],{"class":137,"line":149},[135,993,496],{"class":145},[135,995,996],{"class":141},"template",[135,998,155],{"class":145},[135,1000,1001],{"class":158},"Security/Secret-Detection.gitlab-ci.yml\n",[135,1003,1004,1006,1008,1010],{"class":137,"line":162},[135,1005,496],{"class":145},[135,1007,996],{"class":141},[135,1009,155],{"class":145},[135,1011,1012],{"class":158},"Security/Container-Scanning.gitlab-ci.yml\n",[135,1014,1015,1017,1019,1021],{"class":137,"line":170},[135,1016,496],{"class":145},[135,1018,996],{"class":141},[135,1020,155],{"class":145},[135,1022,1023],{"class":158},"Jobs/Dependency-Scanning.gitlab-ci.yml\n",[135,1025,1026,1028,1030,1032],{"class":137,"line":314},[135,1027,496],{"class":145},[135,1029,996],{"class":141},[135,1031,155],{"class":145},[135,1033,1034],{"class":158},"Security/SAST.gitlab-ci.yml\n",[528,1036,1038],{"id":1037},"training-the-model-with-our-custom-docker-image","Training the model with our custom Docker image",[12,1040,1041],{},"Now that we have built our Custom docker image, we can train the model without installing any more dependencies in the job.",[12,1043,1044,1045,1047],{},"The train job in our ",[62,1046,110],{}," looks like this:",[126,1049,1051],{"className":128,"code":1050,"language":130,"meta":131,"style":131},"train:\n  stage: train\n  tags:\n    - saas-linux-medium-amd64-gpu-standard\n  image: $IMAGE_PATH\n  script:\n    - python train_digit_recognizer.py\n  artifacts:\n    paths:\n      - mnist.h5\n    expose_as: 'trained model'\n\n",[62,1052,1053,1060,1068,1074,1080,1088,1094,1101,1108,1115,1123],{"__ignoreMap":131},[135,1054,1055,1058],{"class":137,"line":138},[135,1056,1057],{"class":141},"train",[135,1059,146],{"class":145},[135,1061,1062,1064,1066],{"class":137,"line":149},[135,1063,152],{"class":141},[135,1065,155],{"class":145},[135,1067,512],{"class":158},[135,1069,1070,1072],{"class":137,"line":162},[135,1071,165],{"class":141},[135,1073,146],{"class":145},[135,1075,1076,1078],{"class":137,"line":170},[135,1077,173],{"class":145},[135,1079,176],{"class":158},[135,1081,1082,1084,1086],{"class":137,"line":314},[135,1083,213],{"class":141},[135,1085,155],{"class":145},[135,1087,938],{"class":158},[135,1089,1090,1092],{"class":137,"line":323},[135,1091,247],{"class":141},[135,1093,146],{"class":145},[135,1095,1096,1098],{"class":137,"line":330},[135,1097,173],{"class":145},[135,1099,1100],{"class":158},"python train_digit_recognizer.py\n",[135,1102,1103,1106],{"class":137,"line":338},[135,1104,1105],{"class":141},"  artifacts",[135,1107,146],{"class":145},[135,1109,1110,1113],{"class":137,"line":349},[135,1111,1112],{"class":141},"    paths",[135,1114,146],{"class":145},[135,1116,1117,1120],{"class":137,"line":357},[135,1118,1119],{"class":145},"      - ",[135,1121,1122],{"class":158},"mnist.h5\n",[135,1124,1125,1128,1130],{"class":137,"line":365},[135,1126,1127],{"class":141},"    expose_as",[135,1129,155],{"class":145},[135,1131,1132],{"class":158},"'trained model'\n",[12,1134,859,1135,1137],{},[62,1136,862],{}," to see the job logs.",[12,1139,1140],{},[523,1141],{"alt":1142,"src":1143},"Train job logs","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397796/blog/Content%20Images/2023-07-06-gpu-enabled-runners-for-modelops/train-job-log.png",[12,1145,1146,1147,1149],{},"From here, you can also inspect the ",[62,1148,1057],{}," job artifacts.",[528,1151,1153],{"id":1152},"publishing-the-model","Publishing the model",[12,1155,1156,1157,1159],{},"In the last step of our ",[62,1158,110],{}," file, we are going to publish the trained model.",[126,1161,1163],{"className":128,"code":1162,"language":130,"meta":131,"style":131},"publish:\n  stage: publish\n  when: manual\n  dependencies:\n    - train\n  image: curlimages/curl:latest\n  script:\n    - 'curl --header \"JOB-TOKEN: $CI_JOB_TOKEN\" --upload-file mnist.h5 \"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/MNIST-Model/${CI_COMMIT_TAG}/mnist.h5\"'\n\n",[62,1164,1165,1172,1180,1190,1197,1203,1212,1218],{"__ignoreMap":131},[135,1166,1167,1170],{"class":137,"line":138},[135,1168,1169],{"class":141},"publish",[135,1171,146],{"class":145},[135,1173,1174,1176,1178],{"class":137,"line":149},[135,1175,152],{"class":141},[135,1177,155],{"class":145},[135,1179,519],{"class":158},[135,1181,1182,1185,1187],{"class":137,"line":162},[135,1183,1184],{"class":141},"  when",[135,1186,155],{"class":145},[135,1188,1189],{"class":158},"manual\n",[135,1191,1192,1195],{"class":137,"line":170},[135,1193,1194],{"class":141},"  dependencies",[135,1196,146],{"class":145},[135,1198,1199,1201],{"class":137,"line":314},[135,1200,173],{"class":145},[135,1202,512],{"class":158},[135,1204,1205,1207,1209],{"class":137,"line":323},[135,1206,213],{"class":141},[135,1208,155],{"class":145},[135,1210,1211],{"class":158},"curlimages/curl:latest\n",[135,1213,1214,1216],{"class":137,"line":330},[135,1215,247],{"class":141},[135,1217,146],{"class":145},[135,1219,1220,1222],{"class":137,"line":338},[135,1221,173],{"class":145},[135,1223,1224],{"class":158},"'curl --header \"JOB-TOKEN: $CI_JOB_TOKEN\" --upload-file mnist.h5 \"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/MNIST-Model/${CI_COMMIT_TAG}/mnist.h5\"'\n",[12,1226,859,1227,1229,1230,1232,1233,1236],{},[62,1228,862],{}," and trigger the ",[62,1231,1169],{}," job manually. After that, navigate into ",[62,1234,1235],{},"Deploy > Package Registry"," to verify the uploaded trained model.",[12,1238,1239],{},[523,1240],{"alt":1241,"src":1242},"Package Registry","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397795/blog/Content%20Images/2023-07-06-gpu-enabled-runners-for-modelops/package-registry.png",[80,1244,1246],{"id":1245},"example-4-jupyter-notebook-model-training-for-ml-powered-gitlab-issue-triage","Example 4: Jupyter notebook model training for ML-powered GitLab Issue triage",[12,1248,1249,1250,1255],{},"In the last example, we are using our GPU-enabled runner to train the internal ",[19,1251,1254],{"href":1252,"rel":1253},"https://gitlab.com/gitlab-org/ml-ops/tanuki-stan/-/tree/using-gpu-enabled-runner",[],"GitLab model to triage issues",". We use this model at GitLab to determine and assign issues to the right team from the context of the issue description.",[12,1257,1258,1259,1267,1268,1273],{},"Different from the previous examples, we now use the ",[19,1260,1263,1266],{"href":1261,"rel":1262},"https://hub.docker.com/r/tensorflow/tensorflow",[],[62,1264,1265],{},"tensorflow-gpu"," container image"," and install the ",[19,1269,1272],{"href":1270,"rel":1271},"https://gitlab.com/gitlab-org/ml-ops/tanuki-stan/-/blob/using-gpu-enabled-runner/notebooks/requirements.tensorflow-gpu.txt",[],"requirements"," in the job itself.",[12,1275,1276,1278],{},[62,1277,110],{}," configuration:",[126,1280,1282],{"className":128,"code":1281,"language":130,"meta":131,"style":131},"train:\n  tags:\n    - saas-linux-medium-amd64-gpu-standard\n  image: tensorflow/tensorflow:2.4.1-gpu\n  script:\n    - nvidia-smi\n    - cd notebooks\n    - pip install -r requirements.tensorflow-gpu.txt\n    - jupyter nbconvert --to script classify_groups.ipynb\n    - apt-get install -y p7zip-full\n    - cd ../data\n    - 7z x -p${DATA_PASSWORD} gitlab-issues.7z\n    - cd ../notebooks\n    - python3 classify_groups.py\n  artifacts:\n    paths:\n      - models/\n  rules:\n    - if: $CI_PIPELINE_SOURCE == \"merge_request_event\" || $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH  \n      when: manual\n      allow_failure: true\n\n",[62,1283,1284,1290,1296,1302,1311,1317,1323,1330,1337,1344,1351,1358,1365,1372,1379,1385,1391,1398,1404,1418,1428],{"__ignoreMap":131},[135,1285,1286,1288],{"class":137,"line":138},[135,1287,1057],{"class":141},[135,1289,146],{"class":145},[135,1291,1292,1294],{"class":137,"line":149},[135,1293,165],{"class":141},[135,1295,146],{"class":145},[135,1297,1298,1300],{"class":137,"line":162},[135,1299,173],{"class":145},[135,1301,176],{"class":158},[135,1303,1304,1306,1308],{"class":137,"line":170},[135,1305,213],{"class":141},[135,1307,155],{"class":145},[135,1309,1310],{"class":158},"tensorflow/tensorflow:2.4.1-gpu\n",[135,1312,1313,1315],{"class":137,"line":314},[135,1314,247],{"class":141},[135,1316,146],{"class":145},[135,1318,1319,1321],{"class":137,"line":323},[135,1320,173],{"class":145},[135,1322,256],{"class":158},[135,1324,1325,1327],{"class":137,"line":330},[135,1326,173],{"class":145},[135,1328,1329],{"class":158},"cd notebooks\n",[135,1331,1332,1334],{"class":137,"line":338},[135,1333,173],{"class":145},[135,1335,1336],{"class":158},"pip install -r requirements.tensorflow-gpu.txt\n",[135,1338,1339,1341],{"class":137,"line":349},[135,1340,173],{"class":145},[135,1342,1343],{"class":158},"jupyter nbconvert --to script classify_groups.ipynb\n",[135,1345,1346,1348],{"class":137,"line":357},[135,1347,173],{"class":145},[135,1349,1350],{"class":158},"apt-get install -y p7zip-full\n",[135,1352,1353,1355],{"class":137,"line":365},[135,1354,173],{"class":145},[135,1356,1357],{"class":158},"cd ../data\n",[135,1359,1360,1362],{"class":137,"line":621},[135,1361,173],{"class":145},[135,1363,1364],{"class":158},"7z x -p${DATA_PASSWORD} gitlab-issues.7z\n",[135,1366,1367,1369],{"class":137,"line":626},[135,1368,173],{"class":145},[135,1370,1371],{"class":158},"cd ../notebooks\n",[135,1373,1374,1376],{"class":137,"line":632},[135,1375,173],{"class":145},[135,1377,1378],{"class":158},"python3 classify_groups.py\n",[135,1380,1381,1383],{"class":137,"line":641},[135,1382,1105],{"class":141},[135,1384,146],{"class":145},[135,1386,1387,1389],{"class":137,"line":646},[135,1388,1112],{"class":141},[135,1390,146],{"class":145},[135,1392,1393,1395],{"class":137,"line":652},[135,1394,1119],{"class":145},[135,1396,1397],{"class":158},"models/\n",[135,1399,1400,1402],{"class":137,"line":804},[135,1401,807],{"class":141},[135,1403,146],{"class":145},[135,1405,1406,1408,1410,1412,1415],{"class":137,"line":812},[135,1407,173],{"class":145},[135,1409,817],{"class":141},[135,1411,155],{"class":145},[135,1413,1414],{"class":158},"$CI_PIPELINE_SOURCE == \"merge_request_event\" || $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH",[135,1416,1417],{"class":145},"  \n",[135,1419,1421,1424,1426],{"class":137,"line":1420},20,[135,1422,1423],{"class":141},"      when",[135,1425,155],{"class":145},[135,1427,1189],{"class":158},[135,1429,1431,1434,1436],{"class":137,"line":1430},21,[135,1432,1433],{"class":141},"      allow_failure",[135,1435,155],{"class":145},[135,1437,1439],{"class":1438},"sYu0t","true\n",[12,1441,1442],{},[523,1443],{"alt":1444,"src":1445},"TensorFlow train","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397795/blog/Content%20Images/2023-07-06-gpu-enabled-runners-for-modelops/tensorflow-train.png",[12,1447,1448,1449,71],{},"If you are interested in another Jupyter notebook example, check out our recently published video on ",[19,1450,1453],{"href":1451,"rel":1452},"https://youtu.be/tElegG4NCZ0",[],"Training ML Models using GPU-enabled runner",[1455,1456],"iframe",{"width":1457,"height":1458,"src":1459,"title":1460,"frameBorder":1461,"allow":1462,"allowFullScreen":207},768,432,"https://www.youtube.com/embed/tElegG4NCZ0","YouTube video player","0","accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",[48,1464,1466],{"id":1465},"results","Results",[12,1468,1469],{},"The integration of GPU-enabled runners on GitLab.com SaaS opens up a new realm of possibilities for ModelOps and HPC workloads.\nBy harnessing the power of GPU-enabled runners, you can accelerate your machine learning workflows, enable faster data processing, and improve scientific simulations, all while taking full advantage of a SaaS solution and avoiding the hurdles of hosting and maintaining your own build hardware.",[12,1471,1472,1473,71],{},"When you try the GPU-enabled runners, please share your experience in our ",[19,1474,1477],{"href":1475,"rel":1476},"https://gitlab.com/gitlab-org/gitlab/-/issues/403008",[],"feedback issue",[12,1479,1480,1481,1486,1487,1492],{},"Compute-heavy workloads can take a long time. A known problem is timeouts after three hours because of the current ",[19,1482,1485],{"href":1483,"rel":1484},"https://docs.gitlab.com/ci/runners/#how-saas-runners-work",[],"configuration of GitLab SaaS runners",".\nWe plan to release more powerful compute for future iterations to handle heavier workloads faster. You can follow updates about GPU-enabled runners in the ",[19,1488,1491],{"href":1489,"rel":1490},"https://gitlab.com/groups/gitlab-org/-/epics/8648",[],"GPU-enabled runners epic"," and learn more in the GPU-enabled runners documentation.",[1494,1495,1496],"style",{},"html pre.shiki code .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}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 .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}",{"title":131,"searchDepth":149,"depth":149,"links":1498},[1499,1500,1506,1510,1514],{"id":50,"depth":149,"text":51},{"id":74,"depth":149,"text":75,"children":1501},[1502,1503,1504,1505],{"id":82,"depth":162,"text":83},{"id":103,"depth":162,"text":104},{"id":179,"depth":162,"text":180},{"id":221,"depth":162,"text":222},{"id":259,"depth":149,"text":260,"children":1507},[1508,1509],{"id":266,"depth":162,"text":267},{"id":373,"depth":162,"text":374},{"id":437,"depth":149,"text":438,"children":1511},[1512,1513],{"id":444,"depth":162,"text":445},{"id":1245,"depth":162,"text":1246},{"id":1465,"depth":149,"text":1466},"ai","2023-07-06","Learn how to leverage our GitLab-hosted GPU-enabled runners for ModelOps and high-performance computing workloads.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682702/Blog/Hero%20Images/gitlab-data-science-icon.png",{},"/en-us/blog/empowering-modelops-and-hpc-workloads-with-gpu-enabled-runners",{"title":1525,"description":1517,"ogTitle":1525,"ogDescription":1517,"noIndex":1520,"ogImage":1521,"ogUrl":1526,"ogSiteName":1527,"ogType":1528,"canonicalUrls":1526},"GPU-enabled runners for ModelOps and HPC workloads in CI/CD","https://about.gitlab.com/blog/empowering-modelops-and-hpc-workloads-with-gpu-enabled-runners","https://about.gitlab.com","article","empowering-modelops-and-hpc-workloads-with-gpu-enabled-runners","en-us/blog/empowering-modelops-and-hpc-workloads-with-gpu-enabled-runners",[1532,1533,1534,1535,1536],"DevSecOps","AI","CI/CD","product","features","BlogPost","1SHMqjZ1TPiZSe8cXS5N8GJqXN6bN9vrrj9rERsyy7k",{"logo":1540,"freeTrial":1545,"sales":1550,"login":1555,"items":1560,"search":1886,"minimal":1917,"duo":1936,"switchNav":1945,"pricingDeployment":1956},{"config":1541},{"href":1542,"dataGaName":1543,"dataGaLocation":1544},"/","gitlab logo","header",{"text":1546,"config":1547},"Get free trial",{"href":1548,"dataGaName":1549,"dataGaLocation":1544},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":1551,"config":1552},"Request a demo",{"href":1553,"dataGaName":1554,"dataGaLocation":1544},"/sales/?contact-topic=request-demo","sales",{"text":1556,"config":1557},"Sign in",{"href":1558,"dataGaName":1559,"dataGaLocation":1544},"https://gitlab.com/users/sign_in/","sign in",[1561,1590,1689,1694,1808,1864],{"text":1562,"config":1563,"menu":1565},"Platform",{"dataNavLevelOne":1564},"platform",{"type":1566,"columns":1567},"cards",[1568,1574,1582],{"title":1562,"description":1569,"link":1570},"The intelligent orchestration platform for DevSecOps",{"text":1571,"config":1572},"Explore our Platform",{"href":1573,"dataGaName":1564,"dataGaLocation":1544},"/platform/",{"title":1575,"description":1576,"link":1577},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":1578,"config":1579},"Meet GitLab Duo",{"href":1580,"dataGaName":1581,"dataGaLocation":1544},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":1583,"description":1584,"link":1585},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":1586,"config":1587},"Learn more",{"href":1588,"dataGaName":1589,"dataGaLocation":1544},"/why-gitlab/","why gitlab",{"text":1591,"left":207,"config":1592,"menu":1594},"Product",{"dataNavLevelOne":1593},"solutions",{"type":1595,"link":1596,"columns":1600,"feature":1668},"lists",{"text":1597,"config":1598},"View all Solutions",{"href":1599,"dataGaName":1593,"dataGaLocation":1544},"/solutions/",[1601,1624,1647],{"title":1602,"description":1603,"link":1604,"items":1609},"Automation","CI/CD and automation to accelerate deployment",{"config":1605},{"icon":1606,"href":1607,"dataGaName":1608,"dataGaLocation":1544},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[1610,1613,1616,1620],{"text":1534,"config":1611},{"href":1612,"dataGaLocation":1544,"dataGaName":1534},"/solutions/continuous-integration/",{"text":1575,"config":1614},{"href":1580,"dataGaLocation":1544,"dataGaName":1615},"gitlab duo agent platform - product menu",{"text":1617,"config":1618},"Source Code Management",{"href":1619,"dataGaLocation":1544,"dataGaName":1617},"/solutions/source-code-management/",{"text":1621,"config":1622},"Automated Software Delivery",{"href":1607,"dataGaLocation":1544,"dataGaName":1623},"Automated software delivery",{"title":1625,"description":1626,"link":1627,"items":1632},"Security","Deliver code faster without compromising security",{"config":1628},{"href":1629,"dataGaName":1630,"dataGaLocation":1544,"icon":1631},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[1633,1637,1642],{"text":1634,"config":1635},"Application Security Testing",{"href":1629,"dataGaName":1636,"dataGaLocation":1544},"Application security testing",{"text":1638,"config":1639},"Software Supply Chain Security",{"href":1640,"dataGaLocation":1544,"dataGaName":1641},"/solutions/supply-chain/","Software supply chain security",{"text":1643,"config":1644},"Software Compliance",{"href":1645,"dataGaName":1646,"dataGaLocation":1544},"/solutions/software-compliance/","software compliance",{"title":1648,"link":1649,"items":1654},"Measurement",{"config":1650},{"icon":1651,"href":1652,"dataGaName":1653,"dataGaLocation":1544},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[1655,1659,1663],{"text":1656,"config":1657},"Visibility & Measurement",{"href":1652,"dataGaLocation":1544,"dataGaName":1658},"Visibility and Measurement",{"text":1660,"config":1661},"Value Stream Management",{"href":1662,"dataGaLocation":1544,"dataGaName":1660},"/solutions/value-stream-management/",{"text":1664,"config":1665},"Analytics & Insights",{"href":1666,"dataGaLocation":1544,"dataGaName":1667},"/solutions/analytics-and-insights/","Analytics and insights",{"title":1669,"type":1595,"items":1670},"GitLab for",[1671,1677,1683],{"text":1672,"config":1673},"Enterprise",{"icon":1674,"href":1675,"dataGaLocation":1544,"dataGaName":1676},"Building","/enterprise/","enterprise",{"text":1678,"config":1679},"Small Business",{"icon":1680,"href":1681,"dataGaLocation":1544,"dataGaName":1682},"Work","/small-business/","small business",{"text":1684,"config":1685},"Public Sector",{"icon":1686,"href":1687,"dataGaLocation":1544,"dataGaName":1688},"Organization","/solutions/public-sector/","public sector",{"text":1690,"config":1691},"Pricing",{"href":1692,"dataGaName":1693,"dataGaLocation":1544,"dataNavLevelOne":1693},"/pricing/","pricing",{"text":1695,"config":1696,"menu":1698},"Resources",{"dataNavLevelOne":1697},"resources",{"type":1595,"link":1699,"columns":1703,"feature":1797},{"text":1700,"config":1701},"View all resources",{"href":1702,"dataGaName":1697,"dataGaLocation":1544},"/resources/",[1704,1737,1764],{"title":1705,"items":1706},"Getting started",[1707,1712,1717,1722,1727,1732],{"text":1708,"config":1709},"Install",{"href":1710,"dataGaName":1711,"dataGaLocation":1544},"/install/","install",{"text":1713,"config":1714},"Quick start guides",{"href":1715,"dataGaName":1716,"dataGaLocation":1544},"/get-started/","quick setup checklists",{"text":1718,"config":1719},"Learn",{"href":1720,"dataGaLocation":1544,"dataGaName":1721},"https://university.gitlab.com/","learn",{"text":1723,"config":1724},"Product documentation",{"href":1725,"dataGaName":1726,"dataGaLocation":1544},"https://docs.gitlab.com/","product documentation",{"text":1728,"config":1729},"Best practice videos",{"href":1730,"dataGaName":1731,"dataGaLocation":1544},"/getting-started-videos/","best practice videos",{"text":1733,"config":1734},"Integrations",{"href":1735,"dataGaName":1736,"dataGaLocation":1544},"/integrations/","integrations",{"title":1738,"items":1739},"Discover",[1740,1745,1750,1755,1759],{"text":1741,"config":1742},"Customer success stories",{"href":1743,"dataGaName":1744,"dataGaLocation":1544},"/customers/","customer success stories",{"text":1746,"config":1747},"Blog",{"href":1748,"dataGaName":1749,"dataGaLocation":1544},"/blog/","blog",{"text":1751,"config":1752},"Demo Hub",{"href":1753,"dataGaName":1754,"dataGaLocation":1544},"/demo-hub/","demo hub",{"text":1756,"config":1757},"The Source",{"href":1758,"dataGaName":1749,"dataGaLocation":1544},"/the-source/",{"text":1760,"config":1761},"Remote",{"href":1762,"dataGaName":1763,"dataGaLocation":1544},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":1765,"items":1766},"Connect",[1767,1772,1777,1782,1787,1792],{"text":1768,"config":1769},"GitLab Services",{"href":1770,"dataGaName":1771,"dataGaLocation":1544},"/services/","services",{"text":1773,"config":1774},"Contribute",{"href":1775,"dataGaName":1776,"dataGaLocation":1544},"https://contributors.gitlab.com","contribute",{"text":1778,"config":1779},"Community",{"href":1780,"dataGaName":1781,"dataGaLocation":1544},"/community/","community",{"text":1783,"config":1784},"Forum",{"href":1785,"dataGaName":1786,"dataGaLocation":1544},"https://forum.gitlab.com/","forum",{"text":1788,"config":1789},"Events",{"href":1790,"dataGaName":1791,"dataGaLocation":1544},"/events/","events",{"text":1793,"config":1794},"Partners",{"href":1795,"dataGaName":1796,"dataGaLocation":1544},"/partners/","partners",{"config":1798,"title":1801,"text":1802,"link":1803},{"background":1799,"textColor":1800},"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":1804,"config":1805},"Read the latest",{"href":1806,"dataGaName":1807,"dataGaLocation":1544},"/whats-new/","whats new",{"text":1809,"config":1810,"menu":1812},"Company",{"dataNavLevelOne":1811},"company",{"type":1595,"columns":1813},[1814],{"items":1815},[1816,1821,1827,1829,1834,1839,1844,1849,1854,1859],{"text":1817,"config":1818},"About",{"href":1819,"dataGaName":1820,"dataGaLocation":1544},"/company/","about",{"text":1822,"config":1823,"footerGa":1826},"Jobs",{"href":1824,"dataGaName":1825,"dataGaLocation":1544},"/jobs/","jobs",{"dataGaName":1825},{"text":1788,"config":1828},{"href":1790,"dataGaName":1791,"dataGaLocation":1544},{"text":1830,"config":1831},"Leadership",{"href":1832,"dataGaName":1833,"dataGaLocation":1544},"/company/team/e-group/","leadership",{"text":1835,"config":1836},"Handbook",{"href":1837,"dataGaName":1838,"dataGaLocation":1544},"https://handbook.gitlab.com/","handbook",{"text":1840,"config":1841},"Investor relations",{"href":1842,"dataGaName":1843,"dataGaLocation":1544},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1845,"config":1846},"Trust Center",{"href":1847,"dataGaName":1848,"dataGaLocation":1544},"/security/","trust center",{"text":1850,"config":1851},"AI Transparency Center",{"href":1852,"dataGaName":1853,"dataGaLocation":1544},"/ai-transparency-center/","ai transparency center",{"text":1855,"config":1856},"Newsletter",{"href":1857,"dataGaName":1858,"dataGaLocation":1544},"/company/contact/#contact-forms","newsletter",{"text":1860,"config":1861},"Press",{"href":1862,"dataGaName":1863,"dataGaLocation":1544},"/press/","press",{"text":1865,"config":1866,"menu":1867},"Contact us",{"dataNavLevelOne":1811},{"type":1595,"columns":1868},[1869],{"items":1870},[1871,1876,1881],{"text":1872,"config":1873},"Talk to sales",{"href":1874,"dataGaName":1875,"dataGaLocation":1544},"/sales/","talk to sales",{"text":1877,"config":1878},"Support portal",{"href":1879,"dataGaName":1880,"dataGaLocation":1544},"https://support.gitlab.com/hc/en-us","support portal",{"text":1882,"config":1883},"Customer portal",{"href":1884,"dataGaName":1885,"dataGaLocation":1544},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1887,"login":1888,"suggestions":1895},"Close",{"text":1889,"link":1890},"To search repositories and projects, login to",{"text":1891,"config":1892},"gitlab.com",{"href":1558,"dataGaName":1893,"dataGaLocation":1894},"search login","search",{"text":1896,"default":1897},"Suggestions",[1898,1900,1904,1906,1910,1914],{"text":1575,"config":1899},{"href":1580,"dataGaName":1575,"dataGaLocation":1894},{"text":1901,"config":1902},"Code Suggestions (AI)",{"href":1903,"dataGaName":1901,"dataGaLocation":1894},"/solutions/code-suggestions/",{"text":1534,"config":1905},{"href":1612,"dataGaName":1534,"dataGaLocation":1894},{"text":1907,"config":1908},"GitLab on AWS",{"href":1909,"dataGaName":1907,"dataGaLocation":1894},"/partners/technology-partners/aws/",{"text":1911,"config":1912},"GitLab on Google Cloud",{"href":1913,"dataGaName":1911,"dataGaLocation":1894},"/partners/technology-partners/google-cloud-platform/",{"text":1915,"config":1916},"Why GitLab?",{"href":1588,"dataGaName":1915,"dataGaLocation":1894},{"freeTrial":1918,"mobileIcon":1923,"desktopIcon":1928,"secondaryButton":1931},{"text":1919,"config":1920},"Start free trial",{"href":1921,"dataGaName":1549,"dataGaLocation":1922},"https://gitlab.com/-/trials/new/","nav",{"altText":1924,"config":1925},"Gitlab Icon",{"src":1926,"dataGaName":1927,"dataGaLocation":1922},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1924,"config":1929},{"src":1930,"dataGaName":1927,"dataGaLocation":1922},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1932,"config":1933},"Get Started",{"href":1934,"dataGaName":1935,"dataGaLocation":1922},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1937,"mobileIcon":1941,"desktopIcon":1943},{"text":1938,"config":1939},"Learn more about GitLab Duo",{"href":1580,"dataGaName":1940,"dataGaLocation":1922},"gitlab duo",{"altText":1924,"config":1942},{"src":1926,"dataGaName":1927,"dataGaLocation":1922},{"altText":1924,"config":1944},{"src":1930,"dataGaName":1927,"dataGaLocation":1922},{"button":1946,"mobileIcon":1951,"desktopIcon":1953},{"text":1947,"config":1948},"/switch",{"href":1949,"dataGaName":1950,"dataGaLocation":1922},"#contact","switch",{"altText":1924,"config":1952},{"src":1926,"dataGaName":1927,"dataGaLocation":1922},{"altText":1924,"config":1954},{"src":1955,"dataGaName":1927,"dataGaLocation":1922},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1957,"mobileIcon":1962,"desktopIcon":1964},{"text":1958,"config":1959},"Back to pricing",{"href":1692,"dataGaName":1960,"dataGaLocation":1922,"icon":1961},"back to pricing","GoBack",{"altText":1924,"config":1963},{"src":1926,"dataGaName":1927,"dataGaLocation":1922},{"altText":1924,"config":1965},{"src":1930,"dataGaName":1927,"dataGaLocation":1922},{"title":1967,"titleMobile":1968,"button":1969,"config":1974},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":1586,"config":1970},{"href":1971,"dataGaName":1972,"dataGaLocation":1973},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":1975,"disabled":1520},"release",{"data":1977},{"text":1978,"source":1979,"edit":1985,"contribute":1990,"config":1995,"items":2000,"minimal":2209},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1980,"config":1981},"View page source",{"href":1982,"dataGaName":1983,"dataGaLocation":1984},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1986,"config":1987},"Edit this page",{"href":1988,"dataGaName":1989,"dataGaLocation":1984},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1991,"config":1992},"Please contribute",{"href":1993,"dataGaName":1994,"dataGaLocation":1984},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1996,"facebook":1997,"youtube":1998,"linkedin":1999},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[2001,2048,2101,2145,2177],{"title":1690,"links":2002,"subMenu":2017},[2003,2007,2012],{"text":2004,"config":2005},"View plans",{"href":1692,"dataGaName":2006,"dataGaLocation":1984},"view plans",{"text":2008,"config":2009},"Why Premium?",{"href":2010,"dataGaName":2011,"dataGaLocation":1984},"/pricing/premium/","why premium",{"text":2013,"config":2014},"Why Ultimate?",{"href":2015,"dataGaName":2016,"dataGaLocation":1984},"/pricing/ultimate/","why ultimate",[2018],{"title":2019,"links":2020},"Contact Us",[2021,2024,2026,2028,2033,2038,2043],{"text":2022,"config":2023},"Contact sales",{"href":1874,"dataGaName":1554,"dataGaLocation":1984},{"text":1877,"config":2025},{"href":1879,"dataGaName":1880,"dataGaLocation":1984},{"text":1882,"config":2027},{"href":1884,"dataGaName":1885,"dataGaLocation":1984},{"text":2029,"config":2030},"Status",{"href":2031,"dataGaName":2032,"dataGaLocation":1984},"https://status.gitlab.com/","status",{"text":2034,"config":2035},"Terms of use",{"href":2036,"dataGaName":2037,"dataGaLocation":1984},"/terms/","terms of use",{"text":2039,"config":2040},"Privacy statement",{"href":2041,"dataGaName":2042,"dataGaLocation":1984},"/privacy/","privacy statement",{"text":2044,"config":2045},"Cookie preferences",{"dataGaName":2046,"dataGaLocation":1984,"id":2047,"isOneTrustButton":207},"cookie preferences","ot-sdk-btn",{"title":1591,"links":2049,"subMenu":2058},[2050,2054],{"text":2051,"config":2052},"DevSecOps platform",{"href":1573,"dataGaName":2053,"dataGaLocation":1984},"devsecops platform",{"text":2055,"config":2056},"AI-Assisted Development",{"href":1580,"dataGaName":2057,"dataGaLocation":1984},"ai-assisted development",[2059],{"title":2060,"links":2061},"Topics",[2062,2067,2072,2077,2082,2086,2091,2096],{"text":2063,"config":2064},"CICD",{"href":2065,"dataGaName":2066,"dataGaLocation":1984},"/topics/ci-cd/","cicd",{"text":2068,"config":2069},"GitOps",{"href":2070,"dataGaName":2071,"dataGaLocation":1984},"/topics/gitops/","gitops",{"text":2073,"config":2074},"DevOps",{"href":2075,"dataGaName":2076,"dataGaLocation":1984},"/topics/devops/","devops",{"text":2078,"config":2079},"Version Control",{"href":2080,"dataGaName":2081,"dataGaLocation":1984},"/topics/version-control/","version control",{"text":1532,"config":2083},{"href":2084,"dataGaName":2085,"dataGaLocation":1984},"/topics/devsecops/","devsecops",{"text":2087,"config":2088},"Cloud Native",{"href":2089,"dataGaName":2090,"dataGaLocation":1984},"/topics/cloud-native/","cloud native",{"text":2092,"config":2093},"AI for Coding",{"href":2094,"dataGaName":2095,"dataGaLocation":1984},"/topics/devops/ai-for-coding/","ai for coding",{"text":2097,"config":2098},"Agentic AI",{"href":2099,"dataGaName":2100,"dataGaLocation":1984},"/topics/agentic-ai/","agentic ai",{"title":2102,"links":2103},"Solutions",[2104,2106,2108,2113,2117,2120,2124,2127,2129,2132,2135,2140],{"text":1634,"config":2105},{"href":1629,"dataGaName":1634,"dataGaLocation":1984},{"text":1623,"config":2107},{"href":1607,"dataGaName":1608,"dataGaLocation":1984},{"text":2109,"config":2110},"Agile development",{"href":2111,"dataGaName":2112,"dataGaLocation":1984},"/solutions/agile-delivery/","agile delivery",{"text":2114,"config":2115},"SCM",{"href":1619,"dataGaName":2116,"dataGaLocation":1984},"source code management",{"text":2063,"config":2118},{"href":1612,"dataGaName":2119,"dataGaLocation":1984},"continuous integration & delivery",{"text":2121,"config":2122},"Value stream management",{"href":1662,"dataGaName":2123,"dataGaLocation":1984},"value stream management",{"text":2068,"config":2125},{"href":2126,"dataGaName":2071,"dataGaLocation":1984},"/solutions/gitops/",{"text":1672,"config":2128},{"href":1675,"dataGaName":1676,"dataGaLocation":1984},{"text":2130,"config":2131},"Small business",{"href":1681,"dataGaName":1682,"dataGaLocation":1984},{"text":2133,"config":2134},"Public sector",{"href":1687,"dataGaName":1688,"dataGaLocation":1984},{"text":2136,"config":2137},"Education",{"href":2138,"dataGaName":2139,"dataGaLocation":1984},"/solutions/education/","education",{"text":2141,"config":2142},"Financial services",{"href":2143,"dataGaName":2144,"dataGaLocation":1984},"/solutions/finance/","financial services",{"title":1695,"links":2146},[2147,2149,2151,2153,2156,2158,2161,2163,2165,2167,2169,2171,2173,2175],{"text":1708,"config":2148},{"href":1710,"dataGaName":1711,"dataGaLocation":1984},{"text":1713,"config":2150},{"href":1715,"dataGaName":1716,"dataGaLocation":1984},{"text":1718,"config":2152},{"href":1720,"dataGaName":1721,"dataGaLocation":1984},{"text":1723,"config":2154},{"href":1725,"dataGaName":2155,"dataGaLocation":1984},"docs",{"text":1746,"config":2157},{"href":1748,"dataGaName":1749,"dataGaLocation":1984},{"text":2159,"config":2160},"What's new",{"href":1806,"dataGaName":1807,"dataGaLocation":1984},{"text":1741,"config":2162},{"href":1743,"dataGaName":1744,"dataGaLocation":1984},{"text":1760,"config":2164},{"href":1762,"dataGaName":1763,"dataGaLocation":1984},{"text":1768,"config":2166},{"href":1770,"dataGaName":1771,"dataGaLocation":1984},{"text":1773,"config":2168},{"href":1775,"dataGaName":1776,"dataGaLocation":1984},{"text":1778,"config":2170},{"href":1780,"dataGaName":1781,"dataGaLocation":1984},{"text":1783,"config":2172},{"href":1785,"dataGaName":1786,"dataGaLocation":1984},{"text":1788,"config":2174},{"href":1790,"dataGaName":1791,"dataGaLocation":1984},{"text":1793,"config":2176},{"href":1795,"dataGaName":1796,"dataGaLocation":1984},{"title":1809,"links":2178},[2179,2181,2183,2185,2187,2189,2193,2198,2200,2202,2204],{"text":1817,"config":2180},{"href":1819,"dataGaName":1811,"dataGaLocation":1984},{"text":1822,"config":2182},{"href":1824,"dataGaName":1825,"dataGaLocation":1984},{"text":1830,"config":2184},{"href":1832,"dataGaName":1833,"dataGaLocation":1984},{"text":1835,"config":2186},{"href":1837,"dataGaName":1838,"dataGaLocation":1984},{"text":1840,"config":2188},{"href":1842,"dataGaName":1843,"dataGaLocation":1984},{"text":2190,"config":2191},"Sustainability",{"href":2192,"dataGaName":2190,"dataGaLocation":1984},"/sustainability/",{"text":2194,"config":2195},"Diversity, inclusion and belonging (DIB)",{"href":2196,"dataGaName":2197,"dataGaLocation":1984},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1845,"config":2199},{"href":1847,"dataGaName":1848,"dataGaLocation":1984},{"text":1855,"config":2201},{"href":1857,"dataGaName":1858,"dataGaLocation":1984},{"text":1860,"config":2203},{"href":1862,"dataGaName":1863,"dataGaLocation":1984},{"text":2205,"config":2206},"Modern Slavery Transparency Statement",{"href":2207,"dataGaName":2208,"dataGaLocation":1984},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":2210},[2211,2214,2217],{"text":2212,"config":2213},"Terms",{"href":2036,"dataGaName":2037,"dataGaLocation":1984},{"text":2215,"config":2216},"Cookies",{"dataGaName":2046,"dataGaLocation":1984,"id":2047,"isOneTrustButton":207},{"text":2218,"config":2219},"Privacy",{"href":2041,"dataGaName":2042,"dataGaLocation":1984},[2221],{"id":2222,"title":7,"body":1519,"config":2223,"content":2225,"description":1519,"extension":2229,"meta":2230,"navigation":207,"path":2231,"seo":2232,"stem":2233,"__hash__":2234},"blogAuthors/en-us/blog/authors/gabriel-engel.yml",{"template":2224},"BlogAuthor",{"name":7,"config":2226},{"headshot":2227,"ctfId":2228},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664747/Blog/Author%20Headshots/gabrielengel_gl-headshot.jpg","gabrielengelgl","yml",{},"/en-us/blog/authors/gabriel-engel",{},"en-us/blog/authors/gabriel-engel","iVkglJtikdZz4_wER91EaHRwdIt1ZjN3O1LGKFcDThM",[2236,2244,2252],{"title":2237,"description":2238,"heroImage":2239,"category":1515,"date":2240,"authors":2241,"slug":2243,"externalUrl":1519},"How I built a demo generator with GitLab Duo Agent Platform","Demos haven't always looked like this. Looking back over my career, here's how they have evolved. Follow the tutorial to build your own demo and agent.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1765809212/noh0mdfn9o94ry9ykura.png","2026-08-13",[2242],"Itzik Gan Baruch","agentic-click-through-demo",{"title":2245,"description":2246,"heroImage":2247,"category":1515,"date":2248,"authors":2249,"slug":2251,"externalUrl":1519},"How to govern agentic AI, MCPs, and AI code assistants","AI agents can write, push, and deploy without human review at each step. Learn a practical framework for controlling access, permissions, and audit trails.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1785337625/ifzlc2hyzaxhzmjgyymh.png","2026-07-31",[2250],"Julie Griffin","govern-agentic-ai-mcps-code-assistants",{"title":2253,"description":2254,"heroImage":2255,"category":1515,"date":2256,"authors":2257,"slug":2259,"externalUrl":1519},"Claude Opus 5 on GitLab: Reasoning built for the hard tasks","Anthropic’s Claude Opus 5 is now available on GitLab Duo Agent Platform, delivering deeper reasoning without sacrificing speed.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099203/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2820%29_2bJGC5ZP3WheoqzlLT05C5_1750099203484.png","2026-07-27",[2258],"Brittany Lutz","claude-opus-5-on-gitlab-duo-agent-platform",{"promotions":2261},[2262,2275,2286,2298],{"id":2263,"categories":2264,"header":2265,"text":2266,"button":2267,"image":2272},"ai-modernization",[1515],"Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":2268,"config":2269},"Get your AI maturity score",{"href":2270,"dataGaName":2271,"dataGaLocation":1749},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":2273},{"src":2274},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":2276,"categories":2277,"header":2278,"text":2266,"button":2279,"image":2283},"devops-modernization",[1535,2085],"Are you just managing tools or shipping innovation?",{"text":2280,"config":2281},"Get your DevOps maturity score",{"href":2282,"dataGaName":2271,"dataGaLocation":1749},"/assessments/devops-modernization-assessment/",{"config":2284},{"src":2285},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":2287,"categories":2288,"header":2290,"text":2266,"button":2291,"image":2295},"security-modernization",[2289],"security","Are you trading speed for security?",{"text":2292,"config":2293},"Get your security maturity score",{"href":2294,"dataGaName":2271,"dataGaLocation":1749},"/assessments/security-modernization-assessment/",{"config":2296},{"src":2297},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":2299,"paths":2300,"header":2303,"text":2304,"button":2305,"image":2310},"github-azure-migration",[2301,2302],"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":2306,"config":2307},"See how GitLab compares to GitHub",{"href":2308,"dataGaName":2309,"dataGaLocation":1749},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":2311},{"src":2285},{"header":2313,"blurb":2314,"button":2315,"secondaryButton":2320},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":2316,"config":2317},"Get your free trial",{"href":2318,"dataGaName":1549,"dataGaLocation":2319},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":2022,"config":2321},{"href":1874,"dataGaName":1554,"dataGaLocation":2319},1786803746803]