[{"data":1,"prerenderedAt":4259},["ShallowReactive",2],{"/blog/variable-and-artifact-sharing-in-gitlab-parent-child-pipelines":3,"navigation-en-us":3466,"banner-en-us":3889,"footer-en-us":3899,"blog-post-authors-en-us-William Arias|Daniel Helfand":4142,"blog-related-posts-en-us-variable-and-artifact-sharing-in-gitlab-parent-child-pipelines":4169,"blog-promotions-en-us":4195,"next-steps-en-us":4249},{"id":4,"title":5,"authors":6,"body":9,"category":3447,"date":3448,"description":3449,"extension":3450,"externalUrl":3451,"faq":3451,"featured":127,"heroImage":3452,"meta":3453,"navigation":127,"path":3454,"seo":3455,"slug":3458,"stem":3459,"tags":3460,"template":3464,"updatedDate":3451,"__hash__":3465},"blogPosts/en-us/blog/variable-and-artifact-sharing-in-gitlab-parent-child-pipelines.md","Variable and artifact sharing in GitLab parent-child pipelines",[7,8],"William Arias","Daniel Helfand",{"type":10,"value":11,"toc":3439},"minimark",[12,21,31,34,39,42,45,52,61,64,80,83,88,103,111,246,256,266,290,302,331,337,402,416,453,470,481,500,507,513,519,526,536,566,569,574,577,746,749,755,758,762,768,775,885,896,937,947,951,958,1007,1010,1044,1050,1054,1061,1066,1072,1078,1085,1091,1100,1103,1287,1290,1626,1629,1633,1641,1644,1649,1958,1963,2129,2134,2634,2639,3103,3112,3117,3120,3124,3130,3133,3137,3140,3148,3151,3210,3217,3221,3224,3395,3405,3409,3412,3426,3435],[13,14,15,16,20],"p",{},"Software projects have different evolving needs and requirements. Some have\nsaid that ",[17,18,19],"em",{},"software is never finished, merely abandoned",". Some software\nprojects are small and others are large with complex integrations. Some have\ndependencies on external projects, while others are self-contained.\nRegardless of the size and complexity, the need to validate and ensure\nfunctionality remains paramount.",[13,22,23,24,30],{},"CI/CD pipelines can help with the challenge of building and validating software projects consistently, but, much like the software itself, these pipelines can become complex with many dependencies. This is where ideas like ",[25,26,29],"a",{"href":27,"rel":28},"https://docs.gitlab.com/ci/pipelines/downstream_pipelines/#parent-child-pipelines",[],"parent-child pipelines"," and data exchange in CI/CD setups become incredibly important.",[13,32,33],{},"In this article, we will cover common CI/CD data exchange challenges users may encounter with parent-child pipelines in GitLab — and how to solve them. You'll learn how to turn complex CI/CD processes into more manageable setups.",[35,36,38],"h2",{"id":37},"using-parent-child-pipelines","Using parent-child pipelines",[13,40,41],{},"The pipeline setup in the image below illustrates a scenario where a project could require a large, complex pipeline. The whole project resides in one repository and contains different modules. Each module requires its own set of build and test automation steps.",[13,43,44],{},"One approach to address the CI/CD configuration in a scenario like this is to break down the larger pipeline into smaller ones (i.e., child pipelines) and keep a common CI/CD process that is shared across all modules in charge of the whole orchestration (i.e., parent pipeline).",[13,46,47],{},[48,49],"img",{"alt":50,"src":51},"CI/CD configuration","https://res.cloudinary.com/about-gitlab-com/image/upload/v1760617772/hizwvhmgxn6exbmvsnrv.png",[13,53,54,55,60],{},"The parent-child pipeline pattern allows a single pipeline to orchestrate one or many downstream pipelines. Similar to how a single pipeline coordinates the execution of multiple ",[25,56,59],{"href":57,"rel":58},"https://docs.gitlab.com/ci/jobs/",[],"jobs",", the parent pipeline coordinates the running of full pipelines with one or more jobs.",[13,62,63],{},"This pattern has been shown to be helpful in a variety of use cases:",[65,66,67,71,74,77],"ul",{},[68,69,70],"li",{},"Breaking down large, complex pipelines into smaller, manageable pieces",[68,72,73],{},"Conditionally executing certain pipelines as part of a larger CI/CD process",[68,75,76],{},"Executing pipelines in parallel",[68,78,79],{},"Helping manage user permissions to access and run certain pipelines",[13,81,82],{},"GitLab’s current CI/CD structure supports this pattern and makes it simple to implement parent-child pipelines. While there are many benefits when using the parent-child pipeline pattern with GitLab, one question we often get is how to share data between the parent and child pipelines. In the next sections, we’ll go over how to make use of GitLab variables and artifacts to address this concern.",[84,85,87],"h3",{"id":86},"sharing-variables","Sharing variables",[13,89,90,91,96,97,102],{},"There are cases where it is necessary to pass the output from a parent pipeline job to a child pipeline. These outputs can be shared as variables, ",[25,92,95],{"href":93,"rel":94},"https://docs.gitlab.com/ci/jobs/job_artifacts/",[],"artifacts",", and ",[25,98,101],{"href":99,"rel":100},"https://docs.gitlab.com/ci/inputs/",[],"inputs",".",[13,104,105,106,110],{},"Consider a case where we create a custom variable ",[107,108,109],"code",{},"var_1"," during the runtime of a job:",[112,113,118],"pre",{"className":114,"code":115,"language":116,"meta":117,"style":117},"language-yaml shiki shiki-themes github-light","\nstages:\n  - build\n  - triggers\n\n# This job only creates a variable \n\ncreate_var_job:\n  stage: build\n  script:\n    - var_1=\"Hi, I'm a Parent pipeline variable\"\n    - echo \"var_1=$var_1\" >> var.env\n  artifacts:\n    reports:\n      dotenv: var.env\n","yaml","",[107,119,120,129,140,150,158,163,170,175,183,194,202,211,219,227,235],{"__ignoreMap":117},[121,122,125],"span",{"class":123,"line":124},"line",1,[121,126,128],{"emptyLinePlaceholder":127},true,"\n",[121,130,132,136],{"class":123,"line":131},2,[121,133,135],{"class":134},"shJU0","stages",[121,137,139],{"class":138},"sgsFI",":\n",[121,141,143,146],{"class":123,"line":142},3,[121,144,145],{"class":138},"  - ",[121,147,149],{"class":148},"sYBdl","build\n",[121,151,153,155],{"class":123,"line":152},4,[121,154,145],{"class":138},[121,156,157],{"class":148},"triggers\n",[121,159,161],{"class":123,"line":160},5,[121,162,128],{"emptyLinePlaceholder":127},[121,164,166],{"class":123,"line":165},6,[121,167,169],{"class":168},"sAwPA","# This job only creates a variable \n",[121,171,173],{"class":123,"line":172},7,[121,174,128],{"emptyLinePlaceholder":127},[121,176,178,181],{"class":123,"line":177},8,[121,179,180],{"class":134},"create_var_job",[121,182,139],{"class":138},[121,184,186,189,192],{"class":123,"line":185},9,[121,187,188],{"class":134},"  stage",[121,190,191],{"class":138},": ",[121,193,149],{"class":148},[121,195,197,200],{"class":123,"line":196},10,[121,198,199],{"class":134},"  script",[121,201,139],{"class":138},[121,203,205,208],{"class":123,"line":204},11,[121,206,207],{"class":138},"    - ",[121,209,210],{"class":148},"var_1=\"Hi, I'm a Parent pipeline variable\"\n",[121,212,214,216],{"class":123,"line":213},12,[121,215,207],{"class":138},[121,217,218],{"class":148},"echo \"var_1=$var_1\" >> var.env\n",[121,220,222,225],{"class":123,"line":221},13,[121,223,224],{"class":134},"  artifacts",[121,226,139],{"class":138},[121,228,230,233],{"class":123,"line":229},14,[121,231,232],{"class":134},"    reports",[121,234,139],{"class":138},[121,236,238,241,243],{"class":123,"line":237},15,[121,239,240],{"class":134},"      dotenv",[121,242,191],{"class":138},[121,244,245],{"class":148},"var.env\n",[13,247,248,249,252,253,255],{},"Notice that the variable is created as part of the script steps in the job (during runtime). In this example, we are using a simple string ",[107,250,251],{},"\"Hi, I'm a Parent pipeline variable\""," to illustrate the main syntax required to later share this variable with a child pipeline. Let's break down the ",[107,254,180],{},"  and analyze the main steps from this GitLab job",[13,257,258,259,261,262,265],{},"First, we need to save ",[107,260,109],{}," as ",[107,263,264],{},"dotenv",":",[112,267,269],{"className":114,"code":268,"language":116,"meta":117,"style":117},"  script:\n    - var_1=\"Hi, I'm a pipeline variable\"\n    - echo \"var_1=$var_1\" >> var.env\n",[107,270,271,277,284],{"__ignoreMap":117},[121,272,273,275],{"class":123,"line":124},[121,274,199],{"class":134},[121,276,139],{"class":138},[121,278,279,281],{"class":123,"line":131},[121,280,207],{"class":138},[121,282,283],{"class":148},"var_1=\"Hi, I'm a pipeline variable\"\n",[121,285,286,288],{"class":123,"line":142},[121,287,207],{"class":138},[121,289,218],{"class":148},[13,291,292,293,261,295,298,299,301],{},"After saving ",[107,294,109],{},[107,296,297],{},"var.env",", the next important step is to make this variable available as an artifact produced by the ",[107,300,180],{},". To do that, we use the following syntax:",[112,303,305],{"className":114,"code":304,"language":116,"meta":117,"style":117},"\nartifacts:\n    reports:\n      dotenv: var.env\n",[107,306,307,311,317,323],{"__ignoreMap":117},[121,308,309],{"class":123,"line":124},[121,310,128],{"emptyLinePlaceholder":127},[121,312,313,315],{"class":123,"line":131},[121,314,95],{"class":134},[121,316,139],{"class":138},[121,318,319,321],{"class":123,"line":142},[121,320,232],{"class":134},[121,322,139],{"class":138},[121,324,325,327,329],{"class":123,"line":152},[121,326,240],{"class":134},[121,328,191],{"class":138},[121,330,245],{"class":148},[13,332,333,334,336],{},"Up to this point, we have created a variable during runtime and saved it as a ",[107,335,264],{}," report. Now let's add the job that should trigger the child pipeline:",[112,338,340],{"className":114,"code":339,"language":116,"meta":117,"style":117},"\ntelco_service_a:\n  stage: triggers\n  trigger:\n    include: service_a/.gitlab-ci.yml\n  rules:\n    - changes:\n        - service_a/*\n",[107,341,342,346,353,361,368,378,385,394],{"__ignoreMap":117},[121,343,344],{"class":123,"line":124},[121,345,128],{"emptyLinePlaceholder":127},[121,347,348,351],{"class":123,"line":131},[121,349,350],{"class":134},"telco_service_a",[121,352,139],{"class":138},[121,354,355,357,359],{"class":123,"line":142},[121,356,188],{"class":134},[121,358,191],{"class":138},[121,360,157],{"class":148},[121,362,363,366],{"class":123,"line":152},[121,364,365],{"class":134},"  trigger",[121,367,139],{"class":138},[121,369,370,373,375],{"class":123,"line":160},[121,371,372],{"class":134},"    include",[121,374,191],{"class":138},[121,376,377],{"class":148},"service_a/.gitlab-ci.yml\n",[121,379,380,383],{"class":123,"line":165},[121,381,382],{"class":134},"  rules",[121,384,139],{"class":138},[121,386,387,389,392],{"class":123,"line":172},[121,388,207],{"class":138},[121,390,391],{"class":134},"changes",[121,393,139],{"class":138},[121,395,396,399],{"class":123,"line":177},[121,397,398],{"class":138},"        - ",[121,400,401],{"class":148},"service_a/*\n",[13,403,404,405,407,408,411,412,415],{},"The goal of ",[107,406,350],{},"  job is to find the ",[107,409,410],{},".gitlab-ci.yml"," configuration of the child pipeline,  which is defined in this case as ",[107,413,414],{},"service_a,"," and trigger its execution. Let's examine this job:",[112,417,419],{"className":114,"code":418,"language":116,"meta":117,"style":117},"\ntelco_service_a:\n  stage: triggers\n  trigger:\n    include: service_a/.gitlab-ci.yml\n",[107,420,421,425,431,439,445],{"__ignoreMap":117},[121,422,423],{"class":123,"line":124},[121,424,128],{"emptyLinePlaceholder":127},[121,426,427,429],{"class":123,"line":131},[121,428,350],{"class":134},[121,430,139],{"class":138},[121,432,433,435,437],{"class":123,"line":142},[121,434,188],{"class":134},[121,436,191],{"class":138},[121,438,157],{"class":148},[121,440,441,443],{"class":123,"line":152},[121,442,365],{"class":134},[121,444,139],{"class":138},[121,446,447,449,451],{"class":123,"line":160},[121,448,372],{"class":134},[121,450,191],{"class":138},[121,452,377],{"class":148},[13,454,455,456,459,460,463,464,466,467,469],{},"We see it belongs to another ",[107,457,458],{},"stage"," of the pipeline named ",[107,461,462],{},"triggers.","This job will run only after ",[107,465,180],{}," from the first stage successfully finishes and where the variable  ",[107,468,109],{}," we want to pass is created.",[13,471,472,473,476,477,480],{},"After defining the stage, we use the reserved words ",[107,474,475],{},"trigger"," and ",[107,478,479],{},"include"," to tell GitLab where to search for the child pipeline configuration, as illustrated in the YAML below:",[112,482,484],{"className":114,"code":483,"language":116,"meta":117,"style":117},"  trigger:\n    include: service_a/.gitlab-ci.yml\n",[107,485,486,492],{"__ignoreMap":117},[121,487,488,490],{"class":123,"line":124},[121,489,365],{"class":134},[121,491,139],{"class":138},[121,493,494,496,498],{"class":123,"line":131},[121,495,372],{"class":134},[121,497,191],{"class":138},[121,499,377],{"class":148},[13,501,502,503,506],{},"Our child-pipeline YAML configuration is under ",[107,504,505],{},"service_a/.gitlab-ci.yml"," folder in the GitLab repository, for this example.",[13,508,509],{},[48,510],{"alt":511,"src":512},"child-pipeline YAML configuration","https://res.cloudinary.com/about-gitlab-com/image/upload/v1760617772/ujkirpbifthpuujkcm6f.png",[514,515,516],"center",{},[17,517,518],{},"Child pipelines folders with configurations",[13,520,521,522,525],{},"Take into consideration that the repository structure depicted above can vary. What matters is properly pointing the  ",[107,523,524],{},"triggers: include"," properties at the location of your child-pipeline configuration in your repository.",[13,527,528,529,532,533,535],{},"Finally, we use ",[107,530,531],{},"rules: changes"," to indicate to GitLab that this child pipeline should be triggered only if there is any change in any file in the ",[107,534,505],{}," directory, as illustrated in the following code snippet:",[112,537,539],{"className":114,"code":538,"language":116,"meta":117,"style":117},"\nrules:\n    - changes:\n        - service_a/*\n",[107,540,541,545,552,560],{"__ignoreMap":117},[121,542,543],{"class":123,"line":124},[121,544,128],{"emptyLinePlaceholder":127},[121,546,547,550],{"class":123,"line":131},[121,548,549],{"class":134},"rules",[121,551,139],{"class":138},[121,553,554,556,558],{"class":123,"line":142},[121,555,207],{"class":138},[121,557,391],{"class":134},[121,559,139],{"class":138},[121,561,562,564],{"class":123,"line":152},[121,563,398],{"class":138},[121,565,401],{"class":148},[13,567,568],{},"Using this rule helps to optimize cost by triggering the child pipeline job only when necessary. This approach is particularly valuable in a monorepo architecture where specific modules contain numerous components, allowing us to avoid running their dedicated pipelines when no changes have been made to their respective codebases.",[570,571,573],"h4",{"id":572},"configuring-the-parent-pipeline","Configuring the parent pipeline",[13,575,576],{},"Up to this point, we have put together our parent pipeline. Here's the full code snippet for this segment:",[112,578,580],{"className":114,"code":579,"language":116,"meta":117,"style":117},"\n# Parent Pipeline Configuration\n\n# This pipeline creates a custom variable and triggers a child pipeline\n\n\nstages:\n  - build\n  - trigger\n\ncreate_var_job:\n  stage: build\n  script:\n    - var_1=\"Hi, I'm a Parent pipeline variable\"\n    - echo \"var_1=$var_1\" >> var.env\n  artifacts:\n    reports:\n      dotenv: var.env\n\ntelco_service_a:\n  stage: triggers\n  trigger:\n    include: service_a/.gitlab-ci.yml\n  rules:\n    - changes:\n        - service_a/*\n",[107,581,582,586,591,595,600,604,608,614,620,627,631,637,645,651,657,663,670,677,686,691,698,707,714,723,730,739],{"__ignoreMap":117},[121,583,584],{"class":123,"line":124},[121,585,128],{"emptyLinePlaceholder":127},[121,587,588],{"class":123,"line":131},[121,589,590],{"class":168},"# Parent Pipeline Configuration\n",[121,592,593],{"class":123,"line":142},[121,594,128],{"emptyLinePlaceholder":127},[121,596,597],{"class":123,"line":152},[121,598,599],{"class":168},"# This pipeline creates a custom variable and triggers a child pipeline\n",[121,601,602],{"class":123,"line":160},[121,603,128],{"emptyLinePlaceholder":127},[121,605,606],{"class":123,"line":165},[121,607,128],{"emptyLinePlaceholder":127},[121,609,610,612],{"class":123,"line":172},[121,611,135],{"class":134},[121,613,139],{"class":138},[121,615,616,618],{"class":123,"line":177},[121,617,145],{"class":138},[121,619,149],{"class":148},[121,621,622,624],{"class":123,"line":185},[121,623,145],{"class":138},[121,625,626],{"class":148},"trigger\n",[121,628,629],{"class":123,"line":196},[121,630,128],{"emptyLinePlaceholder":127},[121,632,633,635],{"class":123,"line":204},[121,634,180],{"class":134},[121,636,139],{"class":138},[121,638,639,641,643],{"class":123,"line":213},[121,640,188],{"class":134},[121,642,191],{"class":138},[121,644,149],{"class":148},[121,646,647,649],{"class":123,"line":221},[121,648,199],{"class":134},[121,650,139],{"class":138},[121,652,653,655],{"class":123,"line":229},[121,654,207],{"class":138},[121,656,210],{"class":148},[121,658,659,661],{"class":123,"line":237},[121,660,207],{"class":138},[121,662,218],{"class":148},[121,664,666,668],{"class":123,"line":665},16,[121,667,224],{"class":134},[121,669,139],{"class":138},[121,671,673,675],{"class":123,"line":672},17,[121,674,232],{"class":134},[121,676,139],{"class":138},[121,678,680,682,684],{"class":123,"line":679},18,[121,681,240],{"class":134},[121,683,191],{"class":138},[121,685,245],{"class":148},[121,687,689],{"class":123,"line":688},19,[121,690,128],{"emptyLinePlaceholder":127},[121,692,694,696],{"class":123,"line":693},20,[121,695,350],{"class":134},[121,697,139],{"class":138},[121,699,701,703,705],{"class":123,"line":700},21,[121,702,188],{"class":134},[121,704,191],{"class":138},[121,706,157],{"class":148},[121,708,710,712],{"class":123,"line":709},22,[121,711,365],{"class":134},[121,713,139],{"class":138},[121,715,717,719,721],{"class":123,"line":716},23,[121,718,372],{"class":134},[121,720,191],{"class":138},[121,722,377],{"class":148},[121,724,726,728],{"class":123,"line":725},24,[121,727,382],{"class":134},[121,729,139],{"class":138},[121,731,733,735,737],{"class":123,"line":732},25,[121,734,207],{"class":138},[121,736,391],{"class":134},[121,738,139],{"class":138},[121,740,742,744],{"class":123,"line":741},26,[121,743,398],{"class":138},[121,745,401],{"class":148},[13,747,748],{},"When GitLab executes the YAML configuration in the GitLab UI, the parent pipeline gets rendered as follows:",[13,750,751],{},[48,752],{"alt":753,"src":754},"parent pipeline rendering","https://res.cloudinary.com/about-gitlab-com/image/upload/v1760617771/e1azkkr0rnzd42dzkw1x.png",[13,756,757],{},"Notice the label \"trigger job,\" which indicates this job will start the execution of another pipeline configuration.",[570,759,761],{"id":760},"configuring-the-child-pipeline","Configuring the child pipeline",[13,763,764,765,767],{},"Moving forward, let's now focus on the child pipeline configuration, where we expect to inherit and print the value of the ",[107,766,109],{}," created in the parent pipeline.",[13,769,770,771,774],{},"The pipeline configuration in ",[107,772,773],{},"service_a/.gitlab_ci.yml"," has the following definition:",[112,776,778],{"className":114,"code":777,"language":116,"meta":117,"style":117},"\nstages:\n  - build\n\nbuild_a:\n  stage: build\n  script:\n    - echo \"this job inherits the variable from the Parent pipeline:\"\n    - echo $var_1\n  needs:\n    - project: gitlab-da/use-cases/7-4-parent-child-pipeline\n      job: create_var_job\n      ref: main\n      artifacts: true\n",[107,779,780,784,790,796,800,807,815,821,828,835,842,854,864,874],{"__ignoreMap":117},[121,781,782],{"class":123,"line":124},[121,783,128],{"emptyLinePlaceholder":127},[121,785,786,788],{"class":123,"line":131},[121,787,135],{"class":134},[121,789,139],{"class":138},[121,791,792,794],{"class":123,"line":142},[121,793,145],{"class":138},[121,795,149],{"class":148},[121,797,798],{"class":123,"line":152},[121,799,128],{"emptyLinePlaceholder":127},[121,801,802,805],{"class":123,"line":160},[121,803,804],{"class":134},"build_a",[121,806,139],{"class":138},[121,808,809,811,813],{"class":123,"line":165},[121,810,188],{"class":134},[121,812,191],{"class":138},[121,814,149],{"class":148},[121,816,817,819],{"class":123,"line":172},[121,818,199],{"class":134},[121,820,139],{"class":138},[121,822,823,825],{"class":123,"line":177},[121,824,207],{"class":138},[121,826,827],{"class":148},"echo \"this job inherits the variable from the Parent pipeline:\"\n",[121,829,830,832],{"class":123,"line":185},[121,831,207],{"class":138},[121,833,834],{"class":148},"echo $var_1\n",[121,836,837,840],{"class":123,"line":196},[121,838,839],{"class":134},"  needs",[121,841,139],{"class":138},[121,843,844,846,849,851],{"class":123,"line":204},[121,845,207],{"class":138},[121,847,848],{"class":134},"project",[121,850,191],{"class":138},[121,852,853],{"class":148},"gitlab-da/use-cases/7-4-parent-child-pipeline\n",[121,855,856,859,861],{"class":123,"line":213},[121,857,858],{"class":134},"      job",[121,860,191],{"class":138},[121,862,863],{"class":148},"create_var_job\n",[121,865,866,869,871],{"class":123,"line":221},[121,867,868],{"class":134},"      ref",[121,870,191],{"class":138},[121,872,873],{"class":148},"main\n",[121,875,876,879,881],{"class":123,"line":229},[121,877,878],{"class":134},"      artifacts",[121,880,191],{"class":138},[121,882,884],{"class":883},"sYu0t","true\n",[13,886,887,888,891,892,895],{},"Like before, let's break down this pipeline and highlight the main parts to achieve our goal. This pipeline only contains one stage (i.e., ",[107,889,890],{},"build)"," and one job (i.e., ",[107,893,894],{},"build_a)",". The script in the job contains two steps:",[112,897,899],{"className":114,"code":898,"language":116,"meta":117,"style":117},"\nbuild_a:\n  stage: build\n  script:\n    - echo \"this job inherits the variable from the Parent pipeline:\"\n    - echo $var_1\n",[107,900,901,905,911,919,925,931],{"__ignoreMap":117},[121,902,903],{"class":123,"line":124},[121,904,128],{"emptyLinePlaceholder":127},[121,906,907,909],{"class":123,"line":131},[121,908,804],{"class":134},[121,910,139],{"class":138},[121,912,913,915,917],{"class":123,"line":142},[121,914,188],{"class":134},[121,916,191],{"class":138},[121,918,149],{"class":148},[121,920,921,923],{"class":123,"line":152},[121,922,199],{"class":134},[121,924,139],{"class":138},[121,926,927,929],{"class":123,"line":160},[121,928,207],{"class":138},[121,930,827],{"class":148},[121,932,933,935],{"class":123,"line":165},[121,934,207],{"class":138},[121,936,834],{"class":148},[13,938,939,940,943,944],{},"These two steps print output during the execution. The most interesting one is the second step, ",[107,941,942],{},"echo $var_1",", where we expect to print the variable value inherited from the parent pipeline. Remember, this was a simple string with value: ",[107,945,946],{},"\"Hi, I'm a Parent pipeline variable.\"",[570,948,950],{"id":949},"inheriting-variables-using-needs","Inheriting variables using needs",[13,952,953,954,957],{},"To set and link this job to inherit variables from the parent pipeline, we use the reserved GitLab CI properties ",[107,955,956],{},"needs"," as depicted in the following snippet:",[112,959,961],{"className":114,"code":960,"language":116,"meta":117,"style":117},"\nneeds:\n    - project: gitlab-da/use-cases/7-4-parent-child-pipeline\n      job: create_var_job\n      ref: main\n      artifacts: true\n",[107,962,963,967,973,983,991,999],{"__ignoreMap":117},[121,964,965],{"class":123,"line":124},[121,966,128],{"emptyLinePlaceholder":127},[121,968,969,971],{"class":123,"line":131},[121,970,956],{"class":134},[121,972,139],{"class":138},[121,974,975,977,979,981],{"class":123,"line":142},[121,976,207],{"class":138},[121,978,848],{"class":134},[121,980,191],{"class":138},[121,982,853],{"class":148},[121,984,985,987,989],{"class":123,"line":152},[121,986,858],{"class":134},[121,988,191],{"class":138},[121,990,863],{"class":148},[121,992,993,995,997],{"class":123,"line":160},[121,994,868],{"class":134},[121,996,191],{"class":138},[121,998,873],{"class":148},[121,1000,1001,1003,1005],{"class":123,"line":165},[121,1002,878],{"class":134},[121,1004,191],{"class":138},[121,1006,884],{"class":883},[13,1008,1009],{},"Using the \"needs\" keyword, we define dependencies that must be completed before running this job. In this case, we pass four different values. Let's walk through each one  of them:",[65,1011,1012,1023,1029,1038],{},[68,1013,1014,1018,1019,1022],{},[1015,1016,1017],"strong",{},"Project:"," The complete namespace of the project where the main ",[107,1020,1021],{},"gitlab-ci.yml"," containing the parent pipeline YAML is located. Make sure to include the absolute path.",[68,1024,1025,1028],{},[1015,1026,1027],{},"Job:"," The specific job name in the parent pipeline from where we want to inherit the variable.",[68,1030,1031,1034,1035,1037],{},[1015,1032,1033],{},"Ref:"," The name of the branch where the main ",[107,1036,1021],{}," containing the parent pipeline YAML is located.",[68,1039,1040,1043],{},[1015,1041,1042],{},"Artifacts:"," Where we set a boolean value, indicating that artifacts from the parent pipeline job should be downloaded and made available to this child pipeline job.",[13,1045,1046,1049],{},[1015,1047,1048],{},"Note:"," This specific approach using the needs property is only available to GitLab Premium and Ultimate users. We will cover another example for GitLab community users later on.",[570,1051,1053],{"id":1052},"putting-it-all-together","Putting it all together",[13,1055,1056,1057,1060],{},"Now let's assume we make a change to any of the files under ",[107,1058,1059],{},"service_a"," folder and commit the changes to the repository. When GitLab detects the change, the rule we set up will trigger the child job pipeline execution. This gets displayed in the GitLab UI as follows:",[13,1062,1063],{},[48,1064],{"alt":1065,"src":754},"Rule triggering the child job pipeline execution",[13,1067,1068,1069,1071],{},"Clicking on the ",[107,1070,350],{},"  will take us to the jobs in the child pipeline:",[13,1073,1074],{},[48,1075],{"alt":1076,"src":1077},"Jobs in pipeline","https://res.cloudinary.com/about-gitlab-com/image/upload/v1760617773/vftjkg7ct2wqmew1e3yk.png",[13,1079,1080,1081,1084],{},"We can see the parent-child relationship, and finally, by clicking on the ",[107,1082,1083],{},"build_a job",", we can visually verify the variable inheritance in the job execution log:",[13,1086,1087],{},[48,1088],{"alt":1089,"src":1090},"Verifying the variable inheritance in the job execution log","https://res.cloudinary.com/about-gitlab-com/image/upload/v1760617758/hxfkfmev9hebbqhgcvoh.png",[13,1092,1093,1094,1096,1097,1099],{},"This output confirms the behavior we expected. The custom runtime variable ",[107,1095,109],{}," created in the parent job is inherited in the child job, unpacked from the ",[107,1098,264],{}," report, and its value accessible as can be confirmed in Line 26 above.",[13,1101,1102],{},"This use case illustrates how to share custom variables that can contain any value between pipelines. This example is intentionally simple and can be extrapolated to more realistic scenarios. Take, for instance, the following CI/CD configuration, where the custom variable we need to share is the tag of a Docker image:",[112,1104,1106],{"className":114,"code":1105,"language":116,"meta":117,"style":117},"\n# Pipeline \n\n\nbuild-prod-image:\n  tags: [ saas-linux-large-amd64 ]\n  image: docker:20.10.16\n  stage: build\n  services:\n    - docker:20.10.16-dind\n  \n  script:\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n    - docker build -t $PRODUCTION_IMAGE .\n    - docker push $PRODUCTION_IMAGE\n    - echo \"UPSTREAM_CONTAINER_IMAGE=$PRODUCTION_IMAGE\" >> prodimage.env\n\n  artifacts:\n    reports:\n      dotenv: prodimage.env\n\n  rules:\n      - if: '$CI_COMMIT_BRANCH == \"main\"'\n        when: always\n      - when: never\n",[107,1107,1108,1112,1117,1121,1125,1132,1146,1156,1164,1171,1178,1183,1189,1196,1203,1210,1217,1221,1227,1233,1242,1246,1252,1265,1275],{"__ignoreMap":117},[121,1109,1110],{"class":123,"line":124},[121,1111,128],{"emptyLinePlaceholder":127},[121,1113,1114],{"class":123,"line":131},[121,1115,1116],{"class":168},"# Pipeline \n",[121,1118,1119],{"class":123,"line":142},[121,1120,128],{"emptyLinePlaceholder":127},[121,1122,1123],{"class":123,"line":152},[121,1124,128],{"emptyLinePlaceholder":127},[121,1126,1127,1130],{"class":123,"line":160},[121,1128,1129],{"class":134},"build-prod-image",[121,1131,139],{"class":138},[121,1133,1134,1137,1140,1143],{"class":123,"line":165},[121,1135,1136],{"class":134},"  tags",[121,1138,1139],{"class":138},": [ ",[121,1141,1142],{"class":148},"saas-linux-large-amd64",[121,1144,1145],{"class":138}," ]\n",[121,1147,1148,1151,1153],{"class":123,"line":172},[121,1149,1150],{"class":134},"  image",[121,1152,191],{"class":138},[121,1154,1155],{"class":148},"docker:20.10.16\n",[121,1157,1158,1160,1162],{"class":123,"line":177},[121,1159,188],{"class":134},[121,1161,191],{"class":138},[121,1163,149],{"class":148},[121,1165,1166,1169],{"class":123,"line":185},[121,1167,1168],{"class":134},"  services",[121,1170,139],{"class":138},[121,1172,1173,1175],{"class":123,"line":196},[121,1174,207],{"class":138},[121,1176,1177],{"class":148},"docker:20.10.16-dind\n",[121,1179,1180],{"class":123,"line":204},[121,1181,1182],{"class":138},"  \n",[121,1184,1185,1187],{"class":123,"line":213},[121,1186,199],{"class":134},[121,1188,139],{"class":138},[121,1190,1191,1193],{"class":123,"line":221},[121,1192,207],{"class":138},[121,1194,1195],{"class":148},"docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n",[121,1197,1198,1200],{"class":123,"line":229},[121,1199,207],{"class":138},[121,1201,1202],{"class":148},"docker build -t $PRODUCTION_IMAGE .\n",[121,1204,1205,1207],{"class":123,"line":237},[121,1206,207],{"class":138},[121,1208,1209],{"class":148},"docker push $PRODUCTION_IMAGE\n",[121,1211,1212,1214],{"class":123,"line":665},[121,1213,207],{"class":138},[121,1215,1216],{"class":148},"echo \"UPSTREAM_CONTAINER_IMAGE=$PRODUCTION_IMAGE\" >> prodimage.env\n",[121,1218,1219],{"class":123,"line":672},[121,1220,128],{"emptyLinePlaceholder":127},[121,1222,1223,1225],{"class":123,"line":679},[121,1224,224],{"class":134},[121,1226,139],{"class":138},[121,1228,1229,1231],{"class":123,"line":688},[121,1230,232],{"class":134},[121,1232,139],{"class":138},[121,1234,1235,1237,1239],{"class":123,"line":693},[121,1236,240],{"class":134},[121,1238,191],{"class":138},[121,1240,1241],{"class":148},"prodimage.env\n",[121,1243,1244],{"class":123,"line":700},[121,1245,128],{"emptyLinePlaceholder":127},[121,1247,1248,1250],{"class":123,"line":709},[121,1249,382],{"class":134},[121,1251,139],{"class":138},[121,1253,1254,1257,1260,1262],{"class":123,"line":716},[121,1255,1256],{"class":138},"      - ",[121,1258,1259],{"class":134},"if",[121,1261,191],{"class":138},[121,1263,1264],{"class":148},"'$CI_COMMIT_BRANCH == \"main\"'\n",[121,1266,1267,1270,1272],{"class":123,"line":725},[121,1268,1269],{"class":134},"        when",[121,1271,191],{"class":138},[121,1273,1274],{"class":148},"always\n",[121,1276,1277,1279,1282,1284],{"class":123,"line":732},[121,1278,1256],{"class":138},[121,1280,1281],{"class":134},"when",[121,1283,191],{"class":138},[121,1285,1286],{"class":148},"never\n",[13,1288,1289],{},"And use the variable with the Docker image tag, in another job that updates a Helm manifest file:",[112,1291,1295],{"className":1292,"code":1293,"language":1294,"meta":117,"style":117},"language-sql shiki shiki-themes github-light","\nupdate-helm-values:\n    stage: update-manifests\n    image:\n        name: alpine:3.16\n        entrypoint: [\"\"]\n  \n    before_script:\n          - apk add --no-cache git curl bash yq\n          - git remote set-url origin https://${CI_USERNAME}:${GITOPS_USER}@${SERVER_PATH}/${PROJECT_PATH}\n          - git config --global user.email \"gitlab@gitlab.com\"\n          - git config --global user.name \"GitLab GitOps\"\n          - git pull origin main\n    script:\n          - cd src\n          - echo $UPSTREAM_CONTAINER_IMAGE\n          - yq eval -i \".spec.template.spec.containers[0].image |= \\\"$UPSTREAM_CONTAINER_IMAGE\\\"\" store-deployment.yaml\n          - cat store-deployment.yaml\n          - git pull origin main\n          - git checkout -B main\n          - git commit -am '[skip ci] prod image update'\n          - git push origin main\n    needs:\n      - project: gitlab-da/use-cases/devsecops-platform/simply-find/simply-find-front-end\n        job: build-prod-image\n        ref: main\n        artifacts: true\n","sql",[107,1296,1297,1301,1315,1325,1332,1348,1353,1357,1362,1376,1404,1414,1423,1430,1435,1442,1449,1484,1499,1505,1517,1535,1542,1547,1602,1615,1620],{"__ignoreMap":117},[121,1298,1299],{"class":123,"line":124},[121,1300,128],{"emptyLinePlaceholder":127},[121,1302,1303,1307,1310,1313],{"class":123,"line":131},[121,1304,1306],{"class":1305},"sD7c4","update-",[121,1308,1309],{"class":138},"helm",[121,1311,1312],{"class":1305},"-values",[121,1314,139],{"class":138},[121,1316,1317,1320,1322],{"class":123,"line":142},[121,1318,1319],{"class":138},"    stage: ",[121,1321,1306],{"class":1305},[121,1323,1324],{"class":138},"manifests\n",[121,1326,1327,1330],{"class":123,"line":152},[121,1328,1329],{"class":1305},"    image",[121,1331,139],{"class":138},[121,1333,1334,1337,1340,1343,1345],{"class":123,"line":160},[121,1335,1336],{"class":1305},"        name",[121,1338,1339],{"class":138},": alpine:",[121,1341,1342],{"class":883},"3",[121,1344,102],{"class":138},[121,1346,1347],{"class":883},"16\n",[121,1349,1350],{"class":123,"line":165},[121,1351,1352],{"class":138},"        entrypoint: [\"\"]\n",[121,1354,1355],{"class":123,"line":172},[121,1356,1182],{"class":138},[121,1358,1359],{"class":123,"line":177},[121,1360,1361],{"class":138},"    before_script:\n",[121,1363,1364,1367,1370,1373],{"class":123,"line":185},[121,1365,1366],{"class":1305},"          -",[121,1368,1369],{"class":138}," apk ",[121,1371,1372],{"class":1305},"add",[121,1374,1375],{"class":168}," --no-cache git curl bash yq\n",[121,1377,1378,1380,1383,1386,1389,1392,1395,1398,1401],{"class":123,"line":196},[121,1379,1366],{"class":1305},[121,1381,1382],{"class":138}," git ",[121,1384,1385],{"class":1305},"remote",[121,1387,1388],{"class":1305}," set-url",[121,1390,1391],{"class":138}," origin https:",[121,1393,1394],{"class":1305},"//",[121,1396,1397],{"class":138},"${CI_USERNAME}:${GITOPS_USER}@${SERVER_PATH}",[121,1399,1400],{"class":1305},"/",[121,1402,1403],{"class":138},"${PROJECT_PATH}\n",[121,1405,1406,1408,1411],{"class":123,"line":204},[121,1407,1366],{"class":1305},[121,1409,1410],{"class":138}," git config ",[121,1412,1413],{"class":168},"--global user.email \"gitlab@gitlab.com\"\n",[121,1415,1416,1418,1420],{"class":123,"line":213},[121,1417,1366],{"class":1305},[121,1419,1410],{"class":138},[121,1421,1422],{"class":168},"--global user.name \"GitLab GitOps\"\n",[121,1424,1425,1427],{"class":123,"line":221},[121,1426,1366],{"class":1305},[121,1428,1429],{"class":138}," git pull origin main\n",[121,1431,1432],{"class":123,"line":229},[121,1433,1434],{"class":138},"    script:\n",[121,1436,1437,1439],{"class":123,"line":237},[121,1438,1366],{"class":1305},[121,1440,1441],{"class":138}," cd src\n",[121,1443,1444,1446],{"class":123,"line":665},[121,1445,1366],{"class":1305},[121,1447,1448],{"class":138}," echo $UPSTREAM_CONTAINER_IMAGE\n",[121,1450,1451,1453,1456,1459,1462,1465,1468,1471,1474,1476,1479,1481],{"class":123,"line":672},[121,1452,1366],{"class":1305},[121,1454,1455],{"class":138}," yq eval ",[121,1457,1458],{"class":1305},"-",[121,1460,1461],{"class":138},"i ",[121,1463,1464],{"class":148},"\".spec.template.spec.containers[0].image |= \\\"",[121,1466,1467],{"class":138},"$UPSTREAM_CONTAINER_IMAGE\\",[121,1469,1470],{"class":148},"\"\"",[121,1472,1473],{"class":138}," store",[121,1475,1458],{"class":1305},[121,1477,1478],{"class":883},"deployment",[121,1480,102],{"class":138},[121,1482,1483],{"class":883},"yaml\n",[121,1485,1486,1488,1491,1493,1495,1497],{"class":123,"line":679},[121,1487,1366],{"class":1305},[121,1489,1490],{"class":138}," cat store",[121,1492,1458],{"class":1305},[121,1494,1478],{"class":883},[121,1496,102],{"class":138},[121,1498,1483],{"class":883},[121,1500,1501,1503],{"class":123,"line":688},[121,1502,1366],{"class":1305},[121,1504,1429],{"class":138},[121,1506,1507,1509,1512,1514],{"class":123,"line":693},[121,1508,1366],{"class":1305},[121,1510,1511],{"class":138}," git checkout ",[121,1513,1458],{"class":1305},[121,1515,1516],{"class":138},"B main\n",[121,1518,1519,1521,1523,1526,1529,1532],{"class":123,"line":700},[121,1520,1366],{"class":1305},[121,1522,1382],{"class":138},[121,1524,1525],{"class":1305},"commit",[121,1527,1528],{"class":1305}," -",[121,1530,1531],{"class":138},"am ",[121,1533,1534],{"class":148},"'[skip ci] prod image update'\n",[121,1536,1537,1539],{"class":123,"line":709},[121,1538,1366],{"class":1305},[121,1540,1541],{"class":138}," git push origin main\n",[121,1543,1544],{"class":123,"line":716},[121,1545,1546],{"class":138},"    needs:\n",[121,1548,1549,1552,1555,1557,1560,1563,1566,1568,1571,1573,1576,1578,1581,1583,1586,1588,1590,1592,1594,1596,1599],{"class":123,"line":725},[121,1550,1551],{"class":1305},"      -",[121,1553,1554],{"class":138}," project: gitlab",[121,1556,1458],{"class":1305},[121,1558,1559],{"class":138},"da",[121,1561,1562],{"class":1305},"/use-",[121,1564,1565],{"class":138},"cases",[121,1567,1400],{"class":1305},[121,1569,1570],{"class":138},"devsecops",[121,1572,1458],{"class":1305},[121,1574,1575],{"class":138},"platform",[121,1577,1400],{"class":1305},[121,1579,1580],{"class":138},"simply",[121,1582,1458],{"class":1305},[121,1584,1585],{"class":138},"find",[121,1587,1400],{"class":1305},[121,1589,1580],{"class":138},[121,1591,1458],{"class":1305},[121,1593,1585],{"class":138},[121,1595,1458],{"class":1305},[121,1597,1598],{"class":138},"front",[121,1600,1601],{"class":1305},"-end\n",[121,1603,1604,1607,1609,1612],{"class":123,"line":732},[121,1605,1606],{"class":138},"        job: build",[121,1608,1458],{"class":1305},[121,1610,1611],{"class":138},"prod",[121,1613,1614],{"class":1305},"-image\n",[121,1616,1617],{"class":123,"line":741},[121,1618,1619],{"class":138},"        ref: main\n",[121,1621,1623],{"class":123,"line":1622},27,[121,1624,1625],{"class":138},"        artifacts: true\n",[13,1627,1628],{},"Mastering how to share variables between pipelines while maintaining the relationship between them enables us to create more sophisticated workflow orchestration that can meet our software building needs.",[84,1630,1632],{"id":1631},"using-gitlab-package-registry-to-share-artifacts","Using GitLab Package Registry to share artifacts",[13,1634,1635,1636,102],{},"While the needs feature mentioned above works great for Premium and Ultimate users, GitLab also has features to help achieve similar results for Community Edition users. One suggested approach is to store artifacts in the ",[25,1637,1640],{"href":1638,"rel":1639},"https://docs.gitlab.com/user/packages/package_registry/",[],"GitLab Package Registry",[13,1642,1643],{},"Using a combination of the variables provided in GitLab CI/CD jobs and the GitLab API, you can upload artifacts to the GitLab Package Registry from a parent pipeline. In the child pipeline, you can then access the uploaded artifact from the package registry using the same variables and API to access the artifact. Let’s take a look at the example pipeline and some supplementary scripts that illustrate this:",[13,1645,1646],{},[1015,1647,1648],{},"gitlab-ci.yml (parent pipeline)",[112,1650,1652],{"className":114,"code":1651,"language":116,"meta":117,"style":117},"\n# Parent Pipeline Configuration\n\n# This pipeline creates an artifact, uploads it to Package Registry, and triggers a child pipeline\n\n\nstages:\n  - create-upload\n  - trigger\n\nvariables:\n  PACKAGE_NAME: \"pipeline-artifacts\"\n  PACKAGE_VERSION: \"$CI_PIPELINE_ID\"\n  ARTIFACT_FILE: \"artifact.txt\"\n\n# Job 1: Create and upload artifact to Package Registry\n\ncreate-and-upload-artifact:\n  stage: create-upload\n  image: alpine:latest\n  before_script:\n    - apk add --no-cache curl bash\n  script:\n    - bash scripts/create-artifact.sh\n    - bash scripts/upload-to-registry.sh\n  rules:\n    - if: $CI_PIPELINE_SOURCE == \"push\"\n\n# Job 2: Trigger child pipeline\n\ntrigger-child:\n  stage: trigger\n  trigger:\n    include: child-pipeline.yml\n    strategy: depend\n  variables:\n    PARENT_PIPELINE_ID: $CI_PIPELINE_ID\n    PACKAGE_NAME: $PACKAGE_NAME\n    PACKAGE_VERSION: $PACKAGE_VERSION\n    ARTIFACT_FILE: $ARTIFACT_FILE\n  rules:\n    - if: $CI_PIPELINE_SOURCE == \"push\"\n",[107,1653,1654,1658,1662,1666,1671,1675,1679,1685,1692,1698,1702,1709,1719,1729,1739,1743,1748,1752,1759,1767,1776,1783,1790,1796,1803,1810,1816,1827,1832,1838,1843,1851,1860,1867,1877,1888,1896,1907,1918,1929,1940,1947],{"__ignoreMap":117},[121,1655,1656],{"class":123,"line":124},[121,1657,128],{"emptyLinePlaceholder":127},[121,1659,1660],{"class":123,"line":131},[121,1661,590],{"class":168},[121,1663,1664],{"class":123,"line":142},[121,1665,128],{"emptyLinePlaceholder":127},[121,1667,1668],{"class":123,"line":152},[121,1669,1670],{"class":168},"# This pipeline creates an artifact, uploads it to Package Registry, and triggers a child pipeline\n",[121,1672,1673],{"class":123,"line":160},[121,1674,128],{"emptyLinePlaceholder":127},[121,1676,1677],{"class":123,"line":165},[121,1678,128],{"emptyLinePlaceholder":127},[121,1680,1681,1683],{"class":123,"line":172},[121,1682,135],{"class":134},[121,1684,139],{"class":138},[121,1686,1687,1689],{"class":123,"line":177},[121,1688,145],{"class":138},[121,1690,1691],{"class":148},"create-upload\n",[121,1693,1694,1696],{"class":123,"line":185},[121,1695,145],{"class":138},[121,1697,626],{"class":148},[121,1699,1700],{"class":123,"line":196},[121,1701,128],{"emptyLinePlaceholder":127},[121,1703,1704,1707],{"class":123,"line":204},[121,1705,1706],{"class":134},"variables",[121,1708,139],{"class":138},[121,1710,1711,1714,1716],{"class":123,"line":213},[121,1712,1713],{"class":134},"  PACKAGE_NAME",[121,1715,191],{"class":138},[121,1717,1718],{"class":148},"\"pipeline-artifacts\"\n",[121,1720,1721,1724,1726],{"class":123,"line":221},[121,1722,1723],{"class":134},"  PACKAGE_VERSION",[121,1725,191],{"class":138},[121,1727,1728],{"class":148},"\"$CI_PIPELINE_ID\"\n",[121,1730,1731,1734,1736],{"class":123,"line":229},[121,1732,1733],{"class":134},"  ARTIFACT_FILE",[121,1735,191],{"class":138},[121,1737,1738],{"class":148},"\"artifact.txt\"\n",[121,1740,1741],{"class":123,"line":237},[121,1742,128],{"emptyLinePlaceholder":127},[121,1744,1745],{"class":123,"line":665},[121,1746,1747],{"class":168},"# Job 1: Create and upload artifact to Package Registry\n",[121,1749,1750],{"class":123,"line":672},[121,1751,128],{"emptyLinePlaceholder":127},[121,1753,1754,1757],{"class":123,"line":679},[121,1755,1756],{"class":134},"create-and-upload-artifact",[121,1758,139],{"class":138},[121,1760,1761,1763,1765],{"class":123,"line":688},[121,1762,188],{"class":134},[121,1764,191],{"class":138},[121,1766,1691],{"class":148},[121,1768,1769,1771,1773],{"class":123,"line":693},[121,1770,1150],{"class":134},[121,1772,191],{"class":138},[121,1774,1775],{"class":148},"alpine:latest\n",[121,1777,1778,1781],{"class":123,"line":700},[121,1779,1780],{"class":134},"  before_script",[121,1782,139],{"class":138},[121,1784,1785,1787],{"class":123,"line":709},[121,1786,207],{"class":138},[121,1788,1789],{"class":148},"apk add --no-cache curl bash\n",[121,1791,1792,1794],{"class":123,"line":716},[121,1793,199],{"class":134},[121,1795,139],{"class":138},[121,1797,1798,1800],{"class":123,"line":725},[121,1799,207],{"class":138},[121,1801,1802],{"class":148},"bash scripts/create-artifact.sh\n",[121,1804,1805,1807],{"class":123,"line":732},[121,1806,207],{"class":138},[121,1808,1809],{"class":148},"bash scripts/upload-to-registry.sh\n",[121,1811,1812,1814],{"class":123,"line":741},[121,1813,382],{"class":134},[121,1815,139],{"class":138},[121,1817,1818,1820,1822,1824],{"class":123,"line":1622},[121,1819,207],{"class":138},[121,1821,1259],{"class":134},[121,1823,191],{"class":138},[121,1825,1826],{"class":148},"$CI_PIPELINE_SOURCE == \"push\"\n",[121,1828,1830],{"class":123,"line":1829},28,[121,1831,128],{"emptyLinePlaceholder":127},[121,1833,1835],{"class":123,"line":1834},29,[121,1836,1837],{"class":168},"# Job 2: Trigger child pipeline\n",[121,1839,1841],{"class":123,"line":1840},30,[121,1842,128],{"emptyLinePlaceholder":127},[121,1844,1846,1849],{"class":123,"line":1845},31,[121,1847,1848],{"class":134},"trigger-child",[121,1850,139],{"class":138},[121,1852,1854,1856,1858],{"class":123,"line":1853},32,[121,1855,188],{"class":134},[121,1857,191],{"class":138},[121,1859,626],{"class":148},[121,1861,1863,1865],{"class":123,"line":1862},33,[121,1864,365],{"class":134},[121,1866,139],{"class":138},[121,1868,1870,1872,1874],{"class":123,"line":1869},34,[121,1871,372],{"class":134},[121,1873,191],{"class":138},[121,1875,1876],{"class":148},"child-pipeline.yml\n",[121,1878,1880,1883,1885],{"class":123,"line":1879},35,[121,1881,1882],{"class":134},"    strategy",[121,1884,191],{"class":138},[121,1886,1887],{"class":148},"depend\n",[121,1889,1891,1894],{"class":123,"line":1890},36,[121,1892,1893],{"class":134},"  variables",[121,1895,139],{"class":138},[121,1897,1899,1902,1904],{"class":123,"line":1898},37,[121,1900,1901],{"class":134},"    PARENT_PIPELINE_ID",[121,1903,191],{"class":138},[121,1905,1906],{"class":148},"$CI_PIPELINE_ID\n",[121,1908,1910,1913,1915],{"class":123,"line":1909},38,[121,1911,1912],{"class":134},"    PACKAGE_NAME",[121,1914,191],{"class":138},[121,1916,1917],{"class":148},"$PACKAGE_NAME\n",[121,1919,1921,1924,1926],{"class":123,"line":1920},39,[121,1922,1923],{"class":134},"    PACKAGE_VERSION",[121,1925,191],{"class":138},[121,1927,1928],{"class":148},"$PACKAGE_VERSION\n",[121,1930,1932,1935,1937],{"class":123,"line":1931},40,[121,1933,1934],{"class":134},"    ARTIFACT_FILE",[121,1936,191],{"class":138},[121,1938,1939],{"class":148},"$ARTIFACT_FILE\n",[121,1941,1943,1945],{"class":123,"line":1942},41,[121,1944,382],{"class":134},[121,1946,139],{"class":138},[121,1948,1950,1952,1954,1956],{"class":123,"line":1949},42,[121,1951,207],{"class":138},[121,1953,1259],{"class":134},[121,1955,191],{"class":138},[121,1957,1826],{"class":148},[13,1959,1960],{},[1015,1961,1962],{},"child-pipeline.yml",[112,1964,1966],{"className":114,"code":1965,"language":116,"meta":117,"style":117},"\n# Child Pipeline Configuration\n\n# This pipeline downloads the artifact from Package Registry and processes it\n\n\nstages:\n  - download-process\n\nvariables:\n  # These variables are passed from the parent pipeline\n  PACKAGE_NAME: \"pipeline-artifacts\"\n  PACKAGE_VERSION: \"$PARENT_PIPELINE_ID\"\n  ARTIFACT_FILE: \"artifact.txt\"\n\n# Job 1: Download and process artifact from Package Registry\n\ndownload-and-process-artifact:\n  stage: download-process\n  image: alpine:latest\n  before_script:\n    - apk add --no-cache curl bash\n  script:\n    - bash scripts/download-from-registry.sh\n    - echo \"Processing downloaded artifact...\"\n    - cat $ARTIFACT_FILE\n    - echo \"Artifact processed successfully!\"\n",[107,1967,1968,1972,1977,1981,1986,1990,1994,2000,2007,2011,2017,2022,2030,2039,2047,2051,2056,2060,2067,2075,2083,2089,2095,2101,2108,2115,2122],{"__ignoreMap":117},[121,1969,1970],{"class":123,"line":124},[121,1971,128],{"emptyLinePlaceholder":127},[121,1973,1974],{"class":123,"line":131},[121,1975,1976],{"class":168},"# Child Pipeline Configuration\n",[121,1978,1979],{"class":123,"line":142},[121,1980,128],{"emptyLinePlaceholder":127},[121,1982,1983],{"class":123,"line":152},[121,1984,1985],{"class":168},"# This pipeline downloads the artifact from Package Registry and processes it\n",[121,1987,1988],{"class":123,"line":160},[121,1989,128],{"emptyLinePlaceholder":127},[121,1991,1992],{"class":123,"line":165},[121,1993,128],{"emptyLinePlaceholder":127},[121,1995,1996,1998],{"class":123,"line":172},[121,1997,135],{"class":134},[121,1999,139],{"class":138},[121,2001,2002,2004],{"class":123,"line":177},[121,2003,145],{"class":138},[121,2005,2006],{"class":148},"download-process\n",[121,2008,2009],{"class":123,"line":185},[121,2010,128],{"emptyLinePlaceholder":127},[121,2012,2013,2015],{"class":123,"line":196},[121,2014,1706],{"class":134},[121,2016,139],{"class":138},[121,2018,2019],{"class":123,"line":204},[121,2020,2021],{"class":168},"  # These variables are passed from the parent pipeline\n",[121,2023,2024,2026,2028],{"class":123,"line":213},[121,2025,1713],{"class":134},[121,2027,191],{"class":138},[121,2029,1718],{"class":148},[121,2031,2032,2034,2036],{"class":123,"line":221},[121,2033,1723],{"class":134},[121,2035,191],{"class":138},[121,2037,2038],{"class":148},"\"$PARENT_PIPELINE_ID\"\n",[121,2040,2041,2043,2045],{"class":123,"line":229},[121,2042,1733],{"class":134},[121,2044,191],{"class":138},[121,2046,1738],{"class":148},[121,2048,2049],{"class":123,"line":237},[121,2050,128],{"emptyLinePlaceholder":127},[121,2052,2053],{"class":123,"line":665},[121,2054,2055],{"class":168},"# Job 1: Download and process artifact from Package Registry\n",[121,2057,2058],{"class":123,"line":672},[121,2059,128],{"emptyLinePlaceholder":127},[121,2061,2062,2065],{"class":123,"line":679},[121,2063,2064],{"class":134},"download-and-process-artifact",[121,2066,139],{"class":138},[121,2068,2069,2071,2073],{"class":123,"line":688},[121,2070,188],{"class":134},[121,2072,191],{"class":138},[121,2074,2006],{"class":148},[121,2076,2077,2079,2081],{"class":123,"line":693},[121,2078,1150],{"class":134},[121,2080,191],{"class":138},[121,2082,1775],{"class":148},[121,2084,2085,2087],{"class":123,"line":700},[121,2086,1780],{"class":134},[121,2088,139],{"class":138},[121,2090,2091,2093],{"class":123,"line":709},[121,2092,207],{"class":138},[121,2094,1789],{"class":148},[121,2096,2097,2099],{"class":123,"line":716},[121,2098,199],{"class":134},[121,2100,139],{"class":138},[121,2102,2103,2105],{"class":123,"line":725},[121,2104,207],{"class":138},[121,2106,2107],{"class":148},"bash scripts/download-from-registry.sh\n",[121,2109,2110,2112],{"class":123,"line":732},[121,2111,207],{"class":138},[121,2113,2114],{"class":148},"echo \"Processing downloaded artifact...\"\n",[121,2116,2117,2119],{"class":123,"line":741},[121,2118,207],{"class":138},[121,2120,2121],{"class":148},"cat $ARTIFACT_FILE\n",[121,2123,2124,2126],{"class":123,"line":1622},[121,2125,207],{"class":138},[121,2127,2128],{"class":148},"echo \"Artifact processed successfully!\"\n",[13,2130,2131],{},[1015,2132,2133],{},"upload-to-registry.sh",[112,2135,2139],{"className":2136,"code":2137,"language":2138,"meta":117,"style":117},"language-bash shiki shiki-themes github-light","\n#!/bin/bash\n\nset -e\n\n# Configuration\n\nPACKAGE_NAME=\"${PACKAGE_NAME:-pipeline-artifacts}\"\n\nPACKAGE_VERSION=\"${PACKAGE_VERSION:-$CI_PIPELINE_ID}\"\n\nARTIFACT_FILE=\"${ARTIFACT_FILE:-artifact.txt}\"\n\n# Validate required variables\n\nif [ -z \"$CI_PROJECT_ID\" ]; then\n    echo \"Error: CI_PROJECT_ID is not set\"\n    exit 1\nfi\n\nif [ -z \"$CI_JOB_TOKEN\" ]; then\n    echo \"Error: CI_JOB_TOKEN is not set\"\n    exit 1\nfi\n\nif [ -z \"$CI_API_V4_URL\" ]; then\n    echo \"Error: CI_API_V4_URL is not set\"\n    exit 1\nfi\n\nif [ ! -f \"$ARTIFACT_FILE\" ]; then\n    echo \"Error: Artifact file '$ARTIFACT_FILE' not found\"\n    exit 1\nfi\n\n# Construct the upload URL\n\nUPLOAD_URL=\"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${PACKAGE_NAME}/${PACKAGE_VERSION}/${ARTIFACT_FILE}\"\n\n# Upload the file using curl\n\nresponse=$(curl -w \"%{http_code}\" -o /tmp/upload_response.json \\\n    --header \"JOB-TOKEN: $CI_JOB_TOKEN\" \\\n    --upload-file \"$ARTIFACT_FILE\" \\\n    \"$UPLOAD_URL\")\n\nif [ \"$response\" -eq 201 ]; then\n    echo \"Upload successful!\"\nelse\n    echo \"Upload failed with HTTP code: $response\"\n    exit 1\nfi\n\n","bash",[107,2140,2141,2145,2150,2154,2162,2166,2171,2175,2197,2201,2219,2223,2246,2250,2255,2259,2284,2292,2300,2305,2309,2328,2335,2341,2345,2349,2368,2375,2381,2385,2389,2412,2424,2430,2434,2438,2443,2447,2481,2485,2490,2494,2523,2538,2552,2566,2571,2595,2603,2609,2622,2629],{"__ignoreMap":117},[121,2142,2143],{"class":123,"line":124},[121,2144,128],{"emptyLinePlaceholder":127},[121,2146,2147],{"class":123,"line":131},[121,2148,2149],{"class":168},"#!/bin/bash\n",[121,2151,2152],{"class":123,"line":142},[121,2153,128],{"emptyLinePlaceholder":127},[121,2155,2156,2159],{"class":123,"line":152},[121,2157,2158],{"class":883},"set",[121,2160,2161],{"class":883}," -e\n",[121,2163,2164],{"class":123,"line":160},[121,2165,128],{"emptyLinePlaceholder":127},[121,2167,2168],{"class":123,"line":165},[121,2169,2170],{"class":168},"# Configuration\n",[121,2172,2173],{"class":123,"line":172},[121,2174,128],{"emptyLinePlaceholder":127},[121,2176,2177,2180,2183,2186,2188,2191,2194],{"class":123,"line":177},[121,2178,2179],{"class":138},"PACKAGE_NAME",[121,2181,2182],{"class":1305},"=",[121,2184,2185],{"class":148},"\"${",[121,2187,2179],{"class":138},[121,2189,2190],{"class":1305},":-",[121,2192,2193],{"class":138},"pipeline-artifacts",[121,2195,2196],{"class":148},"}\"\n",[121,2198,2199],{"class":123,"line":185},[121,2200,128],{"emptyLinePlaceholder":127},[121,2202,2203,2206,2208,2210,2212,2214,2217],{"class":123,"line":196},[121,2204,2205],{"class":138},"PACKAGE_VERSION",[121,2207,2182],{"class":1305},[121,2209,2185],{"class":148},[121,2211,2205],{"class":138},[121,2213,2190],{"class":1305},[121,2215,2216],{"class":138},"$CI_PIPELINE_ID",[121,2218,2196],{"class":148},[121,2220,2221],{"class":123,"line":204},[121,2222,128],{"emptyLinePlaceholder":127},[121,2224,2225,2228,2230,2232,2234,2236,2239,2241,2244],{"class":123,"line":213},[121,2226,2227],{"class":138},"ARTIFACT_FILE",[121,2229,2182],{"class":1305},[121,2231,2185],{"class":148},[121,2233,2227],{"class":138},[121,2235,2190],{"class":1305},[121,2237,2238],{"class":138},"artifact",[121,2240,102],{"class":148},[121,2242,2243],{"class":138},"txt",[121,2245,2196],{"class":148},[121,2247,2248],{"class":123,"line":221},[121,2249,128],{"emptyLinePlaceholder":127},[121,2251,2252],{"class":123,"line":229},[121,2253,2254],{"class":168},"# Validate required variables\n",[121,2256,2257],{"class":123,"line":237},[121,2258,128],{"emptyLinePlaceholder":127},[121,2260,2261,2263,2266,2269,2272,2275,2278,2281],{"class":123,"line":665},[121,2262,1259],{"class":1305},[121,2264,2265],{"class":138}," [ ",[121,2267,2268],{"class":1305},"-z",[121,2270,2271],{"class":148}," \"",[121,2273,2274],{"class":138},"$CI_PROJECT_ID",[121,2276,2277],{"class":148},"\"",[121,2279,2280],{"class":138}," ]; ",[121,2282,2283],{"class":1305},"then\n",[121,2285,2286,2289],{"class":123,"line":672},[121,2287,2288],{"class":883},"    echo",[121,2290,2291],{"class":148}," \"Error: CI_PROJECT_ID is not set\"\n",[121,2293,2294,2297],{"class":123,"line":679},[121,2295,2296],{"class":883},"    exit",[121,2298,2299],{"class":883}," 1\n",[121,2301,2302],{"class":123,"line":688},[121,2303,2304],{"class":1305},"fi\n",[121,2306,2307],{"class":123,"line":693},[121,2308,128],{"emptyLinePlaceholder":127},[121,2310,2311,2313,2315,2317,2319,2322,2324,2326],{"class":123,"line":700},[121,2312,1259],{"class":1305},[121,2314,2265],{"class":138},[121,2316,2268],{"class":1305},[121,2318,2271],{"class":148},[121,2320,2321],{"class":138},"$CI_JOB_TOKEN",[121,2323,2277],{"class":148},[121,2325,2280],{"class":138},[121,2327,2283],{"class":1305},[121,2329,2330,2332],{"class":123,"line":709},[121,2331,2288],{"class":883},[121,2333,2334],{"class":148}," \"Error: CI_JOB_TOKEN is not set\"\n",[121,2336,2337,2339],{"class":123,"line":716},[121,2338,2296],{"class":883},[121,2340,2299],{"class":883},[121,2342,2343],{"class":123,"line":725},[121,2344,2304],{"class":1305},[121,2346,2347],{"class":123,"line":732},[121,2348,128],{"emptyLinePlaceholder":127},[121,2350,2351,2353,2355,2357,2359,2362,2364,2366],{"class":123,"line":741},[121,2352,1259],{"class":1305},[121,2354,2265],{"class":138},[121,2356,2268],{"class":1305},[121,2358,2271],{"class":148},[121,2360,2361],{"class":138},"$CI_API_V4_URL",[121,2363,2277],{"class":148},[121,2365,2280],{"class":138},[121,2367,2283],{"class":1305},[121,2369,2370,2372],{"class":123,"line":1622},[121,2371,2288],{"class":883},[121,2373,2374],{"class":148}," \"Error: CI_API_V4_URL is not set\"\n",[121,2376,2377,2379],{"class":123,"line":1829},[121,2378,2296],{"class":883},[121,2380,2299],{"class":883},[121,2382,2383],{"class":123,"line":1834},[121,2384,2304],{"class":1305},[121,2386,2387],{"class":123,"line":1840},[121,2388,128],{"emptyLinePlaceholder":127},[121,2390,2391,2393,2395,2398,2401,2403,2406,2408,2410],{"class":123,"line":1845},[121,2392,1259],{"class":1305},[121,2394,2265],{"class":138},[121,2396,2397],{"class":1305},"!",[121,2399,2400],{"class":1305}," -f",[121,2402,2271],{"class":148},[121,2404,2405],{"class":138},"$ARTIFACT_FILE",[121,2407,2277],{"class":148},[121,2409,2280],{"class":138},[121,2411,2283],{"class":1305},[121,2413,2414,2416,2419,2421],{"class":123,"line":1853},[121,2415,2288],{"class":883},[121,2417,2418],{"class":148}," \"Error: Artifact file '",[121,2420,2405],{"class":138},[121,2422,2423],{"class":148},"' not found\"\n",[121,2425,2426,2428],{"class":123,"line":1862},[121,2427,2296],{"class":883},[121,2429,2299],{"class":883},[121,2431,2432],{"class":123,"line":1869},[121,2433,2304],{"class":1305},[121,2435,2436],{"class":123,"line":1879},[121,2437,128],{"emptyLinePlaceholder":127},[121,2439,2440],{"class":123,"line":1890},[121,2441,2442],{"class":168},"# Construct the upload URL\n",[121,2444,2445],{"class":123,"line":1898},[121,2446,128],{"emptyLinePlaceholder":127},[121,2448,2449,2452,2454,2456,2459,2462,2465,2468,2470,2473,2475,2477,2479],{"class":123,"line":1909},[121,2450,2451],{"class":138},"UPLOAD_URL",[121,2453,2182],{"class":1305},[121,2455,2185],{"class":148},[121,2457,2458],{"class":138},"CI_API_V4_URL",[121,2460,2461],{"class":148},"}/projects/${",[121,2463,2464],{"class":138},"CI_PROJECT_ID",[121,2466,2467],{"class":148},"}/packages/generic/${",[121,2469,2179],{"class":138},[121,2471,2472],{"class":148},"}/${",[121,2474,2205],{"class":138},[121,2476,2472],{"class":148},[121,2478,2227],{"class":138},[121,2480,2196],{"class":148},[121,2482,2483],{"class":123,"line":1920},[121,2484,128],{"emptyLinePlaceholder":127},[121,2486,2487],{"class":123,"line":1931},[121,2488,2489],{"class":168},"# Upload the file using curl\n",[121,2491,2492],{"class":123,"line":1942},[121,2493,128],{"emptyLinePlaceholder":127},[121,2495,2496,2499,2501,2504,2508,2511,2514,2517,2520],{"class":123,"line":1949},[121,2497,2498],{"class":138},"response",[121,2500,2182],{"class":1305},[121,2502,2503],{"class":138},"$(",[121,2505,2507],{"class":2506},"s7eDp","curl",[121,2509,2510],{"class":883}," -w",[121,2512,2513],{"class":148}," \"%{http_code}\"",[121,2515,2516],{"class":883}," -o",[121,2518,2519],{"class":148}," /tmp/upload_response.json",[121,2521,2522],{"class":883}," \\\n",[121,2524,2526,2529,2532,2534,2536],{"class":123,"line":2525},43,[121,2527,2528],{"class":883},"    --header",[121,2530,2531],{"class":148}," \"JOB-TOKEN: ",[121,2533,2321],{"class":138},[121,2535,2277],{"class":148},[121,2537,2522],{"class":883},[121,2539,2541,2544,2546,2548,2550],{"class":123,"line":2540},44,[121,2542,2543],{"class":883},"    --upload-file",[121,2545,2271],{"class":148},[121,2547,2405],{"class":138},[121,2549,2277],{"class":148},[121,2551,2522],{"class":883},[121,2553,2555,2558,2561,2563],{"class":123,"line":2554},45,[121,2556,2557],{"class":148},"    \"",[121,2559,2560],{"class":138},"$UPLOAD_URL",[121,2562,2277],{"class":148},[121,2564,2565],{"class":138},")\n",[121,2567,2569],{"class":123,"line":2568},46,[121,2570,128],{"emptyLinePlaceholder":127},[121,2572,2574,2576,2578,2580,2583,2585,2588,2591,2593],{"class":123,"line":2573},47,[121,2575,1259],{"class":1305},[121,2577,2265],{"class":138},[121,2579,2277],{"class":148},[121,2581,2582],{"class":138},"$response",[121,2584,2277],{"class":148},[121,2586,2587],{"class":1305}," -eq",[121,2589,2590],{"class":883}," 201",[121,2592,2280],{"class":138},[121,2594,2283],{"class":1305},[121,2596,2598,2600],{"class":123,"line":2597},48,[121,2599,2288],{"class":883},[121,2601,2602],{"class":148}," \"Upload successful!\"\n",[121,2604,2606],{"class":123,"line":2605},49,[121,2607,2608],{"class":1305},"else\n",[121,2610,2612,2614,2617,2619],{"class":123,"line":2611},50,[121,2613,2288],{"class":883},[121,2615,2616],{"class":148}," \"Upload failed with HTTP code: ",[121,2618,2582],{"class":138},[121,2620,2621],{"class":148},"\"\n",[121,2623,2625,2627],{"class":123,"line":2624},51,[121,2626,2296],{"class":883},[121,2628,2299],{"class":883},[121,2630,2632],{"class":123,"line":2631},52,[121,2633,2304],{"class":1305},[13,2635,2636],{},[1015,2637,2638],{},"download-from-regsitry.sh",[112,2640,2642],{"className":2136,"code":2641,"language":2138,"meta":117,"style":117},"\n#!/bin/bash\n\n\nset -e\n\n\n# Configuration\n\nPACKAGE_NAME=\"${PACKAGE_NAME:-pipeline-artifacts}\"\n\nPACKAGE_VERSION=\"${PACKAGE_VERSION:-$PARENT_PIPELINE_ID}\"\n\nARTIFACT_FILE=\"${ARTIFACT_FILE:-artifact.txt}\"\n\n\n# Validate required variables\n\nif [ -z \"$CI_PROJECT_ID\" ]; then\n    echo \"Error: CI_PROJECT_ID is not set\"\n    exit 1\nfi\n\n\nif [ -z \"$CI_JOB_TOKEN\" ]; then\n    echo \"Error: CI_JOB_TOKEN is not set\"\n    exit 1\nfi\n\n\nif [ -z \"$CI_API_V4_URL\" ]; then\n    echo \"Error: CI_API_V4_URL is not set\"\n    exit 1\nfi\n\n\nif [ -z \"$PACKAGE_VERSION\" ]; then\n    echo \"Error: PACKAGE_VERSION is not set\"\n    exit 1\nfi\n\n\n# Construct the download URL\n\nDOWNLOAD_URL=\"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${PACKAGE_NAME}/${PACKAGE_VERSION}/${ARTIFACT_FILE}\"\n\n\n# Download the file using curl\n\nresponse=$(curl -w \"%{http_code}\" -o \"$ARTIFACT_FILE\" \\\n    --header \"JOB-TOKEN: $CI_JOB_TOKEN\" \\\n    --fail-with-body \\\n    \"$DOWNLOAD_URL\")\n\nif [ \"$response\" -eq 200 ]; then\n    echo \"Download successful!\"\nelse\n    echo \"Download failed with HTTP code: $response\"\n    exit 1\nfi\n\n",[107,2643,2644,2648,2652,2656,2660,2666,2670,2674,2678,2682,2698,2702,2719,2723,2743,2747,2751,2755,2759,2777,2783,2789,2793,2797,2801,2819,2825,2831,2835,2839,2843,2861,2867,2873,2877,2881,2885,2904,2911,2917,2921,2925,2929,2934,2938,2967,2971,2975,2980,2984,3008,3020,3027,3039,3044,3066,3074,3079,3091,3098],{"__ignoreMap":117},[121,2645,2646],{"class":123,"line":124},[121,2647,128],{"emptyLinePlaceholder":127},[121,2649,2650],{"class":123,"line":131},[121,2651,2149],{"class":168},[121,2653,2654],{"class":123,"line":142},[121,2655,128],{"emptyLinePlaceholder":127},[121,2657,2658],{"class":123,"line":152},[121,2659,128],{"emptyLinePlaceholder":127},[121,2661,2662,2664],{"class":123,"line":160},[121,2663,2158],{"class":883},[121,2665,2161],{"class":883},[121,2667,2668],{"class":123,"line":165},[121,2669,128],{"emptyLinePlaceholder":127},[121,2671,2672],{"class":123,"line":172},[121,2673,128],{"emptyLinePlaceholder":127},[121,2675,2676],{"class":123,"line":177},[121,2677,2170],{"class":168},[121,2679,2680],{"class":123,"line":185},[121,2681,128],{"emptyLinePlaceholder":127},[121,2683,2684,2686,2688,2690,2692,2694,2696],{"class":123,"line":196},[121,2685,2179],{"class":138},[121,2687,2182],{"class":1305},[121,2689,2185],{"class":148},[121,2691,2179],{"class":138},[121,2693,2190],{"class":1305},[121,2695,2193],{"class":138},[121,2697,2196],{"class":148},[121,2699,2700],{"class":123,"line":204},[121,2701,128],{"emptyLinePlaceholder":127},[121,2703,2704,2706,2708,2710,2712,2714,2717],{"class":123,"line":213},[121,2705,2205],{"class":138},[121,2707,2182],{"class":1305},[121,2709,2185],{"class":148},[121,2711,2205],{"class":138},[121,2713,2190],{"class":1305},[121,2715,2716],{"class":138},"$PARENT_PIPELINE_ID",[121,2718,2196],{"class":148},[121,2720,2721],{"class":123,"line":221},[121,2722,128],{"emptyLinePlaceholder":127},[121,2724,2725,2727,2729,2731,2733,2735,2737,2739,2741],{"class":123,"line":229},[121,2726,2227],{"class":138},[121,2728,2182],{"class":1305},[121,2730,2185],{"class":148},[121,2732,2227],{"class":138},[121,2734,2190],{"class":1305},[121,2736,2238],{"class":138},[121,2738,102],{"class":148},[121,2740,2243],{"class":138},[121,2742,2196],{"class":148},[121,2744,2745],{"class":123,"line":237},[121,2746,128],{"emptyLinePlaceholder":127},[121,2748,2749],{"class":123,"line":665},[121,2750,128],{"emptyLinePlaceholder":127},[121,2752,2753],{"class":123,"line":672},[121,2754,2254],{"class":168},[121,2756,2757],{"class":123,"line":679},[121,2758,128],{"emptyLinePlaceholder":127},[121,2760,2761,2763,2765,2767,2769,2771,2773,2775],{"class":123,"line":688},[121,2762,1259],{"class":1305},[121,2764,2265],{"class":138},[121,2766,2268],{"class":1305},[121,2768,2271],{"class":148},[121,2770,2274],{"class":138},[121,2772,2277],{"class":148},[121,2774,2280],{"class":138},[121,2776,2283],{"class":1305},[121,2778,2779,2781],{"class":123,"line":693},[121,2780,2288],{"class":883},[121,2782,2291],{"class":148},[121,2784,2785,2787],{"class":123,"line":700},[121,2786,2296],{"class":883},[121,2788,2299],{"class":883},[121,2790,2791],{"class":123,"line":709},[121,2792,2304],{"class":1305},[121,2794,2795],{"class":123,"line":716},[121,2796,128],{"emptyLinePlaceholder":127},[121,2798,2799],{"class":123,"line":725},[121,2800,128],{"emptyLinePlaceholder":127},[121,2802,2803,2805,2807,2809,2811,2813,2815,2817],{"class":123,"line":732},[121,2804,1259],{"class":1305},[121,2806,2265],{"class":138},[121,2808,2268],{"class":1305},[121,2810,2271],{"class":148},[121,2812,2321],{"class":138},[121,2814,2277],{"class":148},[121,2816,2280],{"class":138},[121,2818,2283],{"class":1305},[121,2820,2821,2823],{"class":123,"line":741},[121,2822,2288],{"class":883},[121,2824,2334],{"class":148},[121,2826,2827,2829],{"class":123,"line":1622},[121,2828,2296],{"class":883},[121,2830,2299],{"class":883},[121,2832,2833],{"class":123,"line":1829},[121,2834,2304],{"class":1305},[121,2836,2837],{"class":123,"line":1834},[121,2838,128],{"emptyLinePlaceholder":127},[121,2840,2841],{"class":123,"line":1840},[121,2842,128],{"emptyLinePlaceholder":127},[121,2844,2845,2847,2849,2851,2853,2855,2857,2859],{"class":123,"line":1845},[121,2846,1259],{"class":1305},[121,2848,2265],{"class":138},[121,2850,2268],{"class":1305},[121,2852,2271],{"class":148},[121,2854,2361],{"class":138},[121,2856,2277],{"class":148},[121,2858,2280],{"class":138},[121,2860,2283],{"class":1305},[121,2862,2863,2865],{"class":123,"line":1853},[121,2864,2288],{"class":883},[121,2866,2374],{"class":148},[121,2868,2869,2871],{"class":123,"line":1862},[121,2870,2296],{"class":883},[121,2872,2299],{"class":883},[121,2874,2875],{"class":123,"line":1869},[121,2876,2304],{"class":1305},[121,2878,2879],{"class":123,"line":1879},[121,2880,128],{"emptyLinePlaceholder":127},[121,2882,2883],{"class":123,"line":1890},[121,2884,128],{"emptyLinePlaceholder":127},[121,2886,2887,2889,2891,2893,2895,2898,2900,2902],{"class":123,"line":1898},[121,2888,1259],{"class":1305},[121,2890,2265],{"class":138},[121,2892,2268],{"class":1305},[121,2894,2271],{"class":148},[121,2896,2897],{"class":138},"$PACKAGE_VERSION",[121,2899,2277],{"class":148},[121,2901,2280],{"class":138},[121,2903,2283],{"class":1305},[121,2905,2906,2908],{"class":123,"line":1909},[121,2907,2288],{"class":883},[121,2909,2910],{"class":148}," \"Error: PACKAGE_VERSION is not set\"\n",[121,2912,2913,2915],{"class":123,"line":1920},[121,2914,2296],{"class":883},[121,2916,2299],{"class":883},[121,2918,2919],{"class":123,"line":1931},[121,2920,2304],{"class":1305},[121,2922,2923],{"class":123,"line":1942},[121,2924,128],{"emptyLinePlaceholder":127},[121,2926,2927],{"class":123,"line":1949},[121,2928,128],{"emptyLinePlaceholder":127},[121,2930,2931],{"class":123,"line":2525},[121,2932,2933],{"class":168},"# Construct the download URL\n",[121,2935,2936],{"class":123,"line":2540},[121,2937,128],{"emptyLinePlaceholder":127},[121,2939,2940,2943,2945,2947,2949,2951,2953,2955,2957,2959,2961,2963,2965],{"class":123,"line":2554},[121,2941,2942],{"class":138},"DOWNLOAD_URL",[121,2944,2182],{"class":1305},[121,2946,2185],{"class":148},[121,2948,2458],{"class":138},[121,2950,2461],{"class":148},[121,2952,2464],{"class":138},[121,2954,2467],{"class":148},[121,2956,2179],{"class":138},[121,2958,2472],{"class":148},[121,2960,2205],{"class":138},[121,2962,2472],{"class":148},[121,2964,2227],{"class":138},[121,2966,2196],{"class":148},[121,2968,2969],{"class":123,"line":2568},[121,2970,128],{"emptyLinePlaceholder":127},[121,2972,2973],{"class":123,"line":2573},[121,2974,128],{"emptyLinePlaceholder":127},[121,2976,2977],{"class":123,"line":2597},[121,2978,2979],{"class":168},"# Download the file using curl\n",[121,2981,2982],{"class":123,"line":2605},[121,2983,128],{"emptyLinePlaceholder":127},[121,2985,2986,2988,2990,2992,2994,2996,2998,3000,3002,3004,3006],{"class":123,"line":2611},[121,2987,2498],{"class":138},[121,2989,2182],{"class":1305},[121,2991,2503],{"class":138},[121,2993,2507],{"class":2506},[121,2995,2510],{"class":883},[121,2997,2513],{"class":148},[121,2999,2516],{"class":883},[121,3001,2271],{"class":148},[121,3003,2405],{"class":138},[121,3005,2277],{"class":148},[121,3007,2522],{"class":883},[121,3009,3010,3012,3014,3016,3018],{"class":123,"line":2624},[121,3011,2528],{"class":883},[121,3013,2531],{"class":148},[121,3015,2321],{"class":138},[121,3017,2277],{"class":148},[121,3019,2522],{"class":883},[121,3021,3022,3025],{"class":123,"line":2631},[121,3023,3024],{"class":883},"    --fail-with-body",[121,3026,2522],{"class":883},[121,3028,3030,3032,3035,3037],{"class":123,"line":3029},53,[121,3031,2557],{"class":148},[121,3033,3034],{"class":138},"$DOWNLOAD_URL",[121,3036,2277],{"class":148},[121,3038,2565],{"class":138},[121,3040,3042],{"class":123,"line":3041},54,[121,3043,128],{"emptyLinePlaceholder":127},[121,3045,3047,3049,3051,3053,3055,3057,3059,3062,3064],{"class":123,"line":3046},55,[121,3048,1259],{"class":1305},[121,3050,2265],{"class":138},[121,3052,2277],{"class":148},[121,3054,2582],{"class":138},[121,3056,2277],{"class":148},[121,3058,2587],{"class":1305},[121,3060,3061],{"class":883}," 200",[121,3063,2280],{"class":138},[121,3065,2283],{"class":1305},[121,3067,3069,3071],{"class":123,"line":3068},56,[121,3070,2288],{"class":883},[121,3072,3073],{"class":148}," \"Download successful!\"\n",[121,3075,3077],{"class":123,"line":3076},57,[121,3078,2608],{"class":1305},[121,3080,3082,3084,3087,3089],{"class":123,"line":3081},58,[121,3083,2288],{"class":883},[121,3085,3086],{"class":148}," \"Download failed with HTTP code: ",[121,3088,2582],{"class":138},[121,3090,2621],{"class":148},[121,3092,3094,3096],{"class":123,"line":3093},59,[121,3095,2296],{"class":883},[121,3097,2299],{"class":883},[121,3099,3101],{"class":123,"line":3100},60,[121,3102,2304],{"class":1305},[13,3104,3105,3106,3108,3109,3111],{},"In this example, the parent pipeline uploads a file to the GitLab Package Registry by calling a script named ",[107,3107,2133],{},". The script gives the artifact a name and version and constructs the API call to upload the file to the package registry. The parent pipeline is able to authenticate using a ",[107,3110,2321],{}," to push the artifact.txt file to the registry.",[13,3113,3114,3115,102],{},"The child pipeline operates the same as the parent pipeline by using a script to construct the API call to download the artifact.txt file from the package registry. It also is able to authenticate to the registry using the ",[107,3116,2321],{},[13,3118,3119],{},"Since the GitLab Package Registry is available to all GitLab users, it helps to serve as a central location for storing and versioning artifacts. It is a great option for users working with many kinds of artifacts and needing to version artifacts for workflows even beyond CI/CD.",[84,3121,3123],{"id":3122},"using-inputs-to-pass-variables-to-a-child-pipeline","Using inputs to pass variables to a child pipeline",[13,3125,3126,3127,3129],{},"If you made it this far in this tutorial, and you have plans to start creating new pipeline configurations, you might want to start by evaluating if your use case can benefit from using ",[1015,3128,101],{}," to pass variables to other pipelines.",[13,3131,3132],{},"Using inputs is a recommended way to pass variables when you need to define specific values in a CI/CD job and have those values remain fixed during the pipeline run. Inputs might offer certain advantages over the method we implemented before. For example, with inputs, you can include data validation through options (i.e., values must be one of these: [‘staging', ‘prod’]), variable descriptions, type checking, and assign default values before the pipeline run.",[570,3134,3136],{"id":3135},"configuring-cicd-inputs","Configuring CI/CD inputs",[13,3138,3139],{},"Consider the following parent pipeline configuration:",[112,3141,3146],{"className":3142,"code":3144,"language":3145,"meta":117},[3143],"language-text","\n# .gitlab-ci.yml (main file)\n\nstages:\n  - trigger\n\ntrigger-staging:\n  stage: trigger\n  trigger:\n    include:\n      - local: service_a/.gitlab-ci.yml\n        inputs:\n          environment: staging\n          version: \"1.0.0\"\n","text",[107,3147,3144],{"__ignoreMap":117},[13,3149,3150],{},"Let's zoom in at the main difference between the code snippet above and the previous parent pipeline examples in this tutorial:",[112,3152,3154],{"className":114,"code":3153,"language":116,"meta":117,"style":117},"\ntrigger:\n    include:\n      - local: service_a/.gitlab-ci.yml\n        inputs:\n          environment: staging\n          version: \"1.0.0\"\n",[107,3155,3156,3160,3166,3172,3183,3190,3200],{"__ignoreMap":117},[121,3157,3158],{"class":123,"line":124},[121,3159,128],{"emptyLinePlaceholder":127},[121,3161,3162,3164],{"class":123,"line":131},[121,3163,475],{"class":134},[121,3165,139],{"class":138},[121,3167,3168,3170],{"class":123,"line":142},[121,3169,372],{"class":134},[121,3171,139],{"class":138},[121,3173,3174,3176,3179,3181],{"class":123,"line":152},[121,3175,1256],{"class":138},[121,3177,3178],{"class":134},"local",[121,3180,191],{"class":138},[121,3182,377],{"class":148},[121,3184,3185,3188],{"class":123,"line":160},[121,3186,3187],{"class":134},"        inputs",[121,3189,139],{"class":138},[121,3191,3192,3195,3197],{"class":123,"line":165},[121,3193,3194],{"class":134},"          environment",[121,3196,191],{"class":138},[121,3198,3199],{"class":148},"staging\n",[121,3201,3202,3205,3207],{"class":123,"line":172},[121,3203,3204],{"class":134},"          version",[121,3206,191],{"class":138},[121,3208,3209],{"class":148},"\"1.0.0\"\n",[13,3211,3212,3213,3216],{},"The main difference is using the reserved word \"inputs\". This part of the YAML configuration can be read in natural language as: “trigger the child pipeline defined in ",[107,3214,3215],{},"service_a.gitlab-ci.yml"," and make sure to pass ‘environment: staging’ and ‘version:1.0.0’ as input variables that the child pipeline will know how to use.",[570,3218,3220],{"id":3219},"reading-cicd-inputs-in-child-pipelines","Reading CI/CD inputs in child pipelines",[13,3222,3223],{},"Moving to the child pipeline, it must contain in its declaration a spec that defines the inputs it can take. For each input, it is possible to add a little description, a set of predefined options the input value can take, and the type of value it will take. This is illustrated as follows:",[112,3225,3227],{"className":114,"code":3226,"language":116,"meta":117,"style":117},"\n# target pipeline or child-pipeline in this case\n\n\nspec:\n  inputs:\n    environment:\n      description: \"Deployment environment\"\n      options: [staging, production]\n    version:\n      type: string\n      description: \"Application version\"\n\n\n---\n\n\nstages:\n  - deploy\n# Jobs that will use the inputs\n\ndeploy:\n  stage: deploy\n  script:\n      -  echo \"Deploying version $[[ inputs.version ]] to $[[ inputs.environment ]]\"\n\n",[107,3228,3229,3233,3238,3242,3246,3253,3260,3267,3277,3297,3304,3314,3323,3327,3331,3336,3340,3344,3350,3357,3362,3366,3373,3381,3387],{"__ignoreMap":117},[121,3230,3231],{"class":123,"line":124},[121,3232,128],{"emptyLinePlaceholder":127},[121,3234,3235],{"class":123,"line":131},[121,3236,3237],{"class":168},"# target pipeline or child-pipeline in this case\n",[121,3239,3240],{"class":123,"line":142},[121,3241,128],{"emptyLinePlaceholder":127},[121,3243,3244],{"class":123,"line":152},[121,3245,128],{"emptyLinePlaceholder":127},[121,3247,3248,3251],{"class":123,"line":160},[121,3249,3250],{"class":134},"spec",[121,3252,139],{"class":138},[121,3254,3255,3258],{"class":123,"line":165},[121,3256,3257],{"class":134},"  inputs",[121,3259,139],{"class":138},[121,3261,3262,3265],{"class":123,"line":172},[121,3263,3264],{"class":134},"    environment",[121,3266,139],{"class":138},[121,3268,3269,3272,3274],{"class":123,"line":177},[121,3270,3271],{"class":134},"      description",[121,3273,191],{"class":138},[121,3275,3276],{"class":148},"\"Deployment environment\"\n",[121,3278,3279,3282,3285,3288,3291,3294],{"class":123,"line":185},[121,3280,3281],{"class":134},"      options",[121,3283,3284],{"class":138},": [",[121,3286,3287],{"class":148},"staging",[121,3289,3290],{"class":138},", ",[121,3292,3293],{"class":148},"production",[121,3295,3296],{"class":138},"]\n",[121,3298,3299,3302],{"class":123,"line":196},[121,3300,3301],{"class":134},"    version",[121,3303,139],{"class":138},[121,3305,3306,3309,3311],{"class":123,"line":204},[121,3307,3308],{"class":134},"      type",[121,3310,191],{"class":138},[121,3312,3313],{"class":148},"string\n",[121,3315,3316,3318,3320],{"class":123,"line":213},[121,3317,3271],{"class":134},[121,3319,191],{"class":138},[121,3321,3322],{"class":148},"\"Application version\"\n",[121,3324,3325],{"class":123,"line":221},[121,3326,128],{"emptyLinePlaceholder":127},[121,3328,3329],{"class":123,"line":229},[121,3330,128],{"emptyLinePlaceholder":127},[121,3332,3333],{"class":123,"line":237},[121,3334,3335],{"class":2506},"---\n",[121,3337,3338],{"class":123,"line":665},[121,3339,128],{"emptyLinePlaceholder":127},[121,3341,3342],{"class":123,"line":672},[121,3343,128],{"emptyLinePlaceholder":127},[121,3345,3346,3348],{"class":123,"line":679},[121,3347,135],{"class":134},[121,3349,139],{"class":138},[121,3351,3352,3354],{"class":123,"line":688},[121,3353,145],{"class":138},[121,3355,3356],{"class":148},"deploy\n",[121,3358,3359],{"class":123,"line":693},[121,3360,3361],{"class":168},"# Jobs that will use the inputs\n",[121,3363,3364],{"class":123,"line":700},[121,3365,128],{"emptyLinePlaceholder":127},[121,3367,3368,3371],{"class":123,"line":709},[121,3369,3370],{"class":134},"deploy",[121,3372,139],{"class":138},[121,3374,3375,3377,3379],{"class":123,"line":716},[121,3376,188],{"class":134},[121,3378,191],{"class":138},[121,3380,3356],{"class":148},[121,3382,3383,3385],{"class":123,"line":725},[121,3384,199],{"class":134},[121,3386,139],{"class":138},[121,3388,3389,3392],{"class":123,"line":732},[121,3390,3391],{"class":138},"      -  ",[121,3393,3394],{"class":148},"echo \"Deploying version $[[ inputs.version ]] to $[[ inputs.environment ]]\"\n",[13,3396,3397,3398,476,3401,3404],{},"Notice from the code snippet that after defining the spec, there is a YAML document separator \"---\"  followed by the actual child pipeline definition where we access the variables ",[107,3399,3400],{},"$[[ inputs.version ]]",[107,3402,3403],{},"$[[ inputs.environment ]]\""," from the defined inputs using input interpolation.",[35,3406,3408],{"id":3407},"get-hands-on-with-parent-child-pipelines-artifacts-and-more","Get hands-on with parent-child pipelines, artifacts, and more",[13,3410,3411],{},"We hope this article has helped with navigating the challenge of sharing variables and artifacts in parent-child pipeline setups.",[13,3413,3414,3415,3420,3421,3425],{},"To try these examples for yourself, feel free to view or fork the ",[25,3416,3419],{"href":3417,"rel":3418},"https://gitlab.com/gitlab-da/use-cases/devsecops-platform/devops-platform-wave/scenarios/scenario7-deep-dive-into-build-automation-and-ci/7-4-parent-child-pipeline/-/tree/main",[],"Premium/Ultimate"," and the ",[25,3422,1640],{"href":3423,"rel":3424},"https://gitlab.com/gitlab-da/playground/dhelfand/parent-child-pipeline-with-package-registry-artifacts",[]," examples of sharing artifacts.",[13,3427,3428,3429,3434],{},"You can also sign up for a ",[25,3430,3433],{"href":3431,"rel":3432},"https://about.gitlab.com/free-trial/",[],"30-day free trial of GitLab Ultimate"," to experience all the features GitLab has to offer. Thanks for reading!",[3436,3437,3438],"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 pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}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}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}",{"title":117,"searchDepth":131,"depth":131,"links":3440},[3441,3446],{"id":37,"depth":131,"text":38,"children":3442},[3443,3444,3445],{"id":86,"depth":142,"text":87},{"id":1631,"depth":142,"text":1632},{"id":3122,"depth":142,"text":3123},{"id":3407,"depth":131,"text":3408},"engineering","2025-10-16","Learn how to simplify complex CI/CD pipelines with these best practices for sharing data in more modular pipeline setups. ","md",null,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664198/Blog/Hero%20Images/Self-Hosted_1800x945.png",{},"/en-us/blog/variable-and-artifact-sharing-in-gitlab-parent-child-pipelines",{"config":3456,"title":5,"description":3449},{"noIndex":3457},false,"variable-and-artifact-sharing-in-gitlab-parent-child-pipelines","en-us/blog/variable-and-artifact-sharing-in-gitlab-parent-child-pipelines",[3461,3462,3463],"CI/CD","DevSecOps","tutorial","BlogPost","e_bOqDpNwvRdZcSLAqe-b94T7_7uoPcTjPTl7dtFIMo",{"logo":3467,"freeTrial":3471,"sales":3476,"login":3481,"items":3486,"search":3809,"minimal":3840,"duo":3859,"switchNav":3868,"pricingDeployment":3879},{"config":3468},{"href":1400,"dataGaName":3469,"dataGaLocation":3470},"gitlab logo","header",{"text":3472,"config":3473},"Get free trial",{"href":3474,"dataGaName":3475,"dataGaLocation":3470},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":3477,"config":3478},"Request a demo",{"href":3479,"dataGaName":3480,"dataGaLocation":3470},"/sales/?contact-topic=request-demo","sales",{"text":3482,"config":3483},"Sign in",{"href":3484,"dataGaName":3485,"dataGaLocation":3470},"https://gitlab.com/users/sign_in/","sign in",[3487,3515,3614,3619,3732,3787],{"text":3488,"config":3489,"menu":3490},"Platform",{"dataNavLevelOne":1575},{"type":3491,"columns":3492},"cards",[3493,3499,3507],{"title":3488,"description":3494,"link":3495},"The intelligent orchestration platform for DevSecOps",{"text":3496,"config":3497},"Explore our Platform",{"href":3498,"dataGaName":1575,"dataGaLocation":3470},"/platform/",{"title":3500,"description":3501,"link":3502},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":3503,"config":3504},"Meet GitLab Duo",{"href":3505,"dataGaName":3506,"dataGaLocation":3470},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":3508,"description":3509,"link":3510},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":3511,"config":3512},"Learn more",{"href":3513,"dataGaName":3514,"dataGaLocation":3470},"/why-gitlab/","why gitlab",{"text":3516,"left":127,"config":3517,"menu":3519},"Product",{"dataNavLevelOne":3518},"solutions",{"type":3520,"link":3521,"columns":3525,"feature":3593},"lists",{"text":3522,"config":3523},"View all Solutions",{"href":3524,"dataGaName":3518,"dataGaLocation":3470},"/solutions/",[3526,3549,3572],{"title":3527,"description":3528,"link":3529,"items":3534},"Automation","CI/CD and automation to accelerate deployment",{"config":3530},{"icon":3531,"href":3532,"dataGaName":3533,"dataGaLocation":3470},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[3535,3538,3541,3545],{"text":3461,"config":3536},{"href":3537,"dataGaLocation":3470,"dataGaName":3461},"/solutions/continuous-integration/",{"text":3500,"config":3539},{"href":3505,"dataGaLocation":3470,"dataGaName":3540},"gitlab duo agent platform - product menu",{"text":3542,"config":3543},"Source Code Management",{"href":3544,"dataGaLocation":3470,"dataGaName":3542},"/solutions/source-code-management/",{"text":3546,"config":3547},"Automated Software Delivery",{"href":3532,"dataGaLocation":3470,"dataGaName":3548},"Automated software delivery",{"title":3550,"description":3551,"link":3552,"items":3557},"Security","Deliver code faster without compromising security",{"config":3553},{"href":3554,"dataGaName":3555,"dataGaLocation":3470,"icon":3556},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[3558,3562,3567],{"text":3559,"config":3560},"Application Security Testing",{"href":3554,"dataGaName":3561,"dataGaLocation":3470},"Application security testing",{"text":3563,"config":3564},"Software Supply Chain Security",{"href":3565,"dataGaLocation":3470,"dataGaName":3566},"/solutions/supply-chain/","Software supply chain security",{"text":3568,"config":3569},"Software Compliance",{"href":3570,"dataGaName":3571,"dataGaLocation":3470},"/solutions/software-compliance/","software compliance",{"title":3573,"link":3574,"items":3579},"Measurement",{"config":3575},{"icon":3576,"href":3577,"dataGaName":3578,"dataGaLocation":3470},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[3580,3584,3588],{"text":3581,"config":3582},"Visibility & Measurement",{"href":3577,"dataGaLocation":3470,"dataGaName":3583},"Visibility and Measurement",{"text":3585,"config":3586},"Value Stream Management",{"href":3587,"dataGaLocation":3470,"dataGaName":3585},"/solutions/value-stream-management/",{"text":3589,"config":3590},"Analytics & Insights",{"href":3591,"dataGaLocation":3470,"dataGaName":3592},"/solutions/analytics-and-insights/","Analytics and insights",{"title":3594,"type":3520,"items":3595},"GitLab for",[3596,3602,3608],{"text":3597,"config":3598},"Enterprise",{"icon":3599,"href":3600,"dataGaLocation":3470,"dataGaName":3601},"Building","/enterprise/","enterprise",{"text":3603,"config":3604},"Small Business",{"icon":3605,"href":3606,"dataGaLocation":3470,"dataGaName":3607},"Work","/small-business/","small business",{"text":3609,"config":3610},"Public Sector",{"icon":3611,"href":3612,"dataGaLocation":3470,"dataGaName":3613},"Organization","/solutions/public-sector/","public sector",{"text":3615,"config":3616},"Pricing",{"href":3617,"dataGaName":3618,"dataGaLocation":3470,"dataNavLevelOne":3618},"/pricing/","pricing",{"text":3620,"config":3621,"menu":3623},"Resources",{"dataNavLevelOne":3622},"resources",{"type":3520,"link":3624,"columns":3628,"feature":3721},{"text":3625,"config":3626},"View all resources",{"href":3627,"dataGaName":3622,"dataGaLocation":3470},"/resources/",[3629,3662,3688],{"title":3630,"items":3631},"Getting started",[3632,3637,3642,3647,3652,3657],{"text":3633,"config":3634},"Install",{"href":3635,"dataGaName":3636,"dataGaLocation":3470},"/install/","install",{"text":3638,"config":3639},"Quick start guides",{"href":3640,"dataGaName":3641,"dataGaLocation":3470},"/get-started/","quick setup checklists",{"text":3643,"config":3644},"Learn",{"href":3645,"dataGaLocation":3470,"dataGaName":3646},"https://university.gitlab.com/","learn",{"text":3648,"config":3649},"Product documentation",{"href":3650,"dataGaName":3651,"dataGaLocation":3470},"https://docs.gitlab.com/","product documentation",{"text":3653,"config":3654},"Best practice videos",{"href":3655,"dataGaName":3656,"dataGaLocation":3470},"/getting-started-videos/","best practice videos",{"text":3658,"config":3659},"Integrations",{"href":3660,"dataGaName":3661,"dataGaLocation":3470},"/integrations/","integrations",{"title":3663,"items":3664},"Discover",[3665,3670,3675,3680,3684],{"text":3666,"config":3667},"Customer success stories",{"href":3668,"dataGaName":3669,"dataGaLocation":3470},"/customers/","customer success stories",{"text":3671,"config":3672},"Blog",{"href":3673,"dataGaName":3674,"dataGaLocation":3470},"/blog/","blog",{"text":3676,"config":3677},"Demo Hub",{"href":3678,"dataGaName":3679,"dataGaLocation":3470},"/demo-hub/","demo hub",{"text":3681,"config":3682},"The Source",{"href":3683,"dataGaName":3674,"dataGaLocation":3470},"/the-source/",{"text":3685,"config":3686},"Remote",{"href":3687,"dataGaName":1385,"dataGaLocation":3470},"https://handbook.gitlab.com/handbook/company/culture/all-remote/",{"title":3689,"items":3690},"Connect",[3691,3696,3701,3706,3711,3716],{"text":3692,"config":3693},"GitLab Services",{"href":3694,"dataGaName":3695,"dataGaLocation":3470},"/services/","services",{"text":3697,"config":3698},"Contribute",{"href":3699,"dataGaName":3700,"dataGaLocation":3470},"https://contributors.gitlab.com","contribute",{"text":3702,"config":3703},"Community",{"href":3704,"dataGaName":3705,"dataGaLocation":3470},"/community/","community",{"text":3707,"config":3708},"Forum",{"href":3709,"dataGaName":3710,"dataGaLocation":3470},"https://forum.gitlab.com/","forum",{"text":3712,"config":3713},"Events",{"href":3714,"dataGaName":3715,"dataGaLocation":3470},"/events/","events",{"text":3717,"config":3718},"Partners",{"href":3719,"dataGaName":3720,"dataGaLocation":3470},"/partners/","partners",{"config":3722,"title":3725,"text":3726,"link":3727},{"background":3723,"textColor":3724},"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":3728,"config":3729},"Read the latest",{"href":3730,"dataGaName":3731,"dataGaLocation":3470},"/whats-new/","whats new",{"text":3733,"config":3734,"menu":3736},"Company",{"dataNavLevelOne":3735},"company",{"type":3520,"columns":3737},[3738],{"items":3739},[3740,3745,3750,3752,3757,3762,3767,3772,3777,3782],{"text":3741,"config":3742},"About",{"href":3743,"dataGaName":3744,"dataGaLocation":3470},"/company/","about",{"text":3746,"config":3747,"footerGa":3749},"Jobs",{"href":3748,"dataGaName":59,"dataGaLocation":3470},"/jobs/",{"dataGaName":59},{"text":3712,"config":3751},{"href":3714,"dataGaName":3715,"dataGaLocation":3470},{"text":3753,"config":3754},"Leadership",{"href":3755,"dataGaName":3756,"dataGaLocation":3470},"/company/team/e-group/","leadership",{"text":3758,"config":3759},"Handbook",{"href":3760,"dataGaName":3761,"dataGaLocation":3470},"https://handbook.gitlab.com/","handbook",{"text":3763,"config":3764},"Investor relations",{"href":3765,"dataGaName":3766,"dataGaLocation":3470},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":3768,"config":3769},"Trust Center",{"href":3770,"dataGaName":3771,"dataGaLocation":3470},"/security/","trust center",{"text":3773,"config":3774},"AI Transparency Center",{"href":3775,"dataGaName":3776,"dataGaLocation":3470},"/ai-transparency-center/","ai transparency center",{"text":3778,"config":3779},"Newsletter",{"href":3780,"dataGaName":3781,"dataGaLocation":3470},"/company/contact/#contact-forms","newsletter",{"text":3783,"config":3784},"Press",{"href":3785,"dataGaName":3786,"dataGaLocation":3470},"/press/","press",{"text":3788,"config":3789,"menu":3790},"Contact us",{"dataNavLevelOne":3735},{"type":3520,"columns":3791},[3792],{"items":3793},[3794,3799,3804],{"text":3795,"config":3796},"Talk to sales",{"href":3797,"dataGaName":3798,"dataGaLocation":3470},"/sales/","talk to sales",{"text":3800,"config":3801},"Support portal",{"href":3802,"dataGaName":3803,"dataGaLocation":3470},"https://support.gitlab.com/hc/en-us","support portal",{"text":3805,"config":3806},"Customer portal",{"href":3807,"dataGaName":3808,"dataGaLocation":3470},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":3810,"login":3811,"suggestions":3818},"Close",{"text":3812,"link":3813},"To search repositories and projects, login to",{"text":3814,"config":3815},"gitlab.com",{"href":3484,"dataGaName":3816,"dataGaLocation":3817},"search login","search",{"text":3819,"default":3820},"Suggestions",[3821,3823,3827,3829,3833,3837],{"text":3500,"config":3822},{"href":3505,"dataGaName":3500,"dataGaLocation":3817},{"text":3824,"config":3825},"Code Suggestions (AI)",{"href":3826,"dataGaName":3824,"dataGaLocation":3817},"/solutions/code-suggestions/",{"text":3461,"config":3828},{"href":3537,"dataGaName":3461,"dataGaLocation":3817},{"text":3830,"config":3831},"GitLab on AWS",{"href":3832,"dataGaName":3830,"dataGaLocation":3817},"/partners/technology-partners/aws/",{"text":3834,"config":3835},"GitLab on Google Cloud",{"href":3836,"dataGaName":3834,"dataGaLocation":3817},"/partners/technology-partners/google-cloud-platform/",{"text":3838,"config":3839},"Why GitLab?",{"href":3513,"dataGaName":3838,"dataGaLocation":3817},{"freeTrial":3841,"mobileIcon":3846,"desktopIcon":3851,"secondaryButton":3854},{"text":3842,"config":3843},"Start free trial",{"href":3844,"dataGaName":3475,"dataGaLocation":3845},"https://gitlab.com/-/trials/new/","nav",{"altText":3847,"config":3848},"Gitlab Icon",{"src":3849,"dataGaName":3850,"dataGaLocation":3845},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":3847,"config":3852},{"src":3853,"dataGaName":3850,"dataGaLocation":3845},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":3855,"config":3856},"Get Started",{"href":3857,"dataGaName":3858,"dataGaLocation":3845},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":3860,"mobileIcon":3864,"desktopIcon":3866},{"text":3861,"config":3862},"Learn more about GitLab Duo",{"href":3505,"dataGaName":3863,"dataGaLocation":3845},"gitlab duo",{"altText":3847,"config":3865},{"src":3849,"dataGaName":3850,"dataGaLocation":3845},{"altText":3847,"config":3867},{"src":3853,"dataGaName":3850,"dataGaLocation":3845},{"button":3869,"mobileIcon":3874,"desktopIcon":3876},{"text":3870,"config":3871},"/switch",{"href":3872,"dataGaName":3873,"dataGaLocation":3845},"#contact","switch",{"altText":3847,"config":3875},{"src":3849,"dataGaName":3850,"dataGaLocation":3845},{"altText":3847,"config":3877},{"src":3878,"dataGaName":3850,"dataGaLocation":3845},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":3880,"mobileIcon":3885,"desktopIcon":3887},{"text":3881,"config":3882},"Back to pricing",{"href":3617,"dataGaName":3883,"dataGaLocation":3845,"icon":3884},"back to pricing","GoBack",{"altText":3847,"config":3886},{"src":3849,"dataGaName":3850,"dataGaLocation":3845},{"altText":3847,"config":3888},{"src":3853,"dataGaName":3850,"dataGaLocation":3845},{"title":3890,"titleMobile":3891,"button":3892,"config":3897},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":3511,"config":3893},{"href":3894,"dataGaName":3895,"dataGaLocation":3896},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":3898,"disabled":3457},"release",{"data":3900},{"text":3901,"source":3902,"edit":3908,"contribute":3913,"config":3918,"items":3923,"minimal":4131},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":3903,"config":3904},"View page source",{"href":3905,"dataGaName":3906,"dataGaLocation":3907},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":3909,"config":3910},"Edit this page",{"href":3911,"dataGaName":3912,"dataGaLocation":3907},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":3914,"config":3915},"Please contribute",{"href":3916,"dataGaName":3917,"dataGaLocation":3907},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":3919,"facebook":3920,"youtube":3921,"linkedin":3922},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[3924,3971,4023,4067,4099],{"title":3615,"links":3925,"subMenu":3940},[3926,3930,3935],{"text":3927,"config":3928},"View plans",{"href":3617,"dataGaName":3929,"dataGaLocation":3907},"view plans",{"text":3931,"config":3932},"Why Premium?",{"href":3933,"dataGaName":3934,"dataGaLocation":3907},"/pricing/premium/","why premium",{"text":3936,"config":3937},"Why Ultimate?",{"href":3938,"dataGaName":3939,"dataGaLocation":3907},"/pricing/ultimate/","why ultimate",[3941],{"title":3942,"links":3943},"Contact Us",[3944,3947,3949,3951,3956,3961,3966],{"text":3945,"config":3946},"Contact sales",{"href":3797,"dataGaName":3480,"dataGaLocation":3907},{"text":3800,"config":3948},{"href":3802,"dataGaName":3803,"dataGaLocation":3907},{"text":3805,"config":3950},{"href":3807,"dataGaName":3808,"dataGaLocation":3907},{"text":3952,"config":3953},"Status",{"href":3954,"dataGaName":3955,"dataGaLocation":3907},"https://status.gitlab.com/","status",{"text":3957,"config":3958},"Terms of use",{"href":3959,"dataGaName":3960,"dataGaLocation":3907},"/terms/","terms of use",{"text":3962,"config":3963},"Privacy statement",{"href":3964,"dataGaName":3965,"dataGaLocation":3907},"/privacy/","privacy statement",{"text":3967,"config":3968},"Cookie preferences",{"dataGaName":3969,"dataGaLocation":3907,"id":3970,"isOneTrustButton":127},"cookie preferences","ot-sdk-btn",{"title":3516,"links":3972,"subMenu":3981},[3973,3977],{"text":3974,"config":3975},"DevSecOps platform",{"href":3498,"dataGaName":3976,"dataGaLocation":3907},"devsecops platform",{"text":3978,"config":3979},"AI-Assisted Development",{"href":3505,"dataGaName":3980,"dataGaLocation":3907},"ai-assisted development",[3982],{"title":3983,"links":3984},"Topics",[3985,3990,3995,4000,4005,4008,4013,4018],{"text":3986,"config":3987},"CICD",{"href":3988,"dataGaName":3989,"dataGaLocation":3907},"/topics/ci-cd/","cicd",{"text":3991,"config":3992},"GitOps",{"href":3993,"dataGaName":3994,"dataGaLocation":3907},"/topics/gitops/","gitops",{"text":3996,"config":3997},"DevOps",{"href":3998,"dataGaName":3999,"dataGaLocation":3907},"/topics/devops/","devops",{"text":4001,"config":4002},"Version Control",{"href":4003,"dataGaName":4004,"dataGaLocation":3907},"/topics/version-control/","version control",{"text":3462,"config":4006},{"href":4007,"dataGaName":1570,"dataGaLocation":3907},"/topics/devsecops/",{"text":4009,"config":4010},"Cloud Native",{"href":4011,"dataGaName":4012,"dataGaLocation":3907},"/topics/cloud-native/","cloud native",{"text":4014,"config":4015},"AI for Coding",{"href":4016,"dataGaName":4017,"dataGaLocation":3907},"/topics/devops/ai-for-coding/","ai for coding",{"text":4019,"config":4020},"Agentic AI",{"href":4021,"dataGaName":4022,"dataGaLocation":3907},"/topics/agentic-ai/","agentic ai",{"title":4024,"links":4025},"Solutions",[4026,4028,4030,4035,4039,4042,4046,4049,4051,4054,4057,4062],{"text":3559,"config":4027},{"href":3554,"dataGaName":3559,"dataGaLocation":3907},{"text":3548,"config":4029},{"href":3532,"dataGaName":3533,"dataGaLocation":3907},{"text":4031,"config":4032},"Agile development",{"href":4033,"dataGaName":4034,"dataGaLocation":3907},"/solutions/agile-delivery/","agile delivery",{"text":4036,"config":4037},"SCM",{"href":3544,"dataGaName":4038,"dataGaLocation":3907},"source code management",{"text":3986,"config":4040},{"href":3537,"dataGaName":4041,"dataGaLocation":3907},"continuous integration & delivery",{"text":4043,"config":4044},"Value stream management",{"href":3587,"dataGaName":4045,"dataGaLocation":3907},"value stream management",{"text":3991,"config":4047},{"href":4048,"dataGaName":3994,"dataGaLocation":3907},"/solutions/gitops/",{"text":3597,"config":4050},{"href":3600,"dataGaName":3601,"dataGaLocation":3907},{"text":4052,"config":4053},"Small business",{"href":3606,"dataGaName":3607,"dataGaLocation":3907},{"text":4055,"config":4056},"Public sector",{"href":3612,"dataGaName":3613,"dataGaLocation":3907},{"text":4058,"config":4059},"Education",{"href":4060,"dataGaName":4061,"dataGaLocation":3907},"/solutions/education/","education",{"text":4063,"config":4064},"Financial services",{"href":4065,"dataGaName":4066,"dataGaLocation":3907},"/solutions/finance/","financial services",{"title":3620,"links":4068},[4069,4071,4073,4075,4078,4080,4083,4085,4087,4089,4091,4093,4095,4097],{"text":3633,"config":4070},{"href":3635,"dataGaName":3636,"dataGaLocation":3907},{"text":3638,"config":4072},{"href":3640,"dataGaName":3641,"dataGaLocation":3907},{"text":3643,"config":4074},{"href":3645,"dataGaName":3646,"dataGaLocation":3907},{"text":3648,"config":4076},{"href":3650,"dataGaName":4077,"dataGaLocation":3907},"docs",{"text":3671,"config":4079},{"href":3673,"dataGaName":3674,"dataGaLocation":3907},{"text":4081,"config":4082},"What's new",{"href":3730,"dataGaName":3731,"dataGaLocation":3907},{"text":3666,"config":4084},{"href":3668,"dataGaName":3669,"dataGaLocation":3907},{"text":3685,"config":4086},{"href":3687,"dataGaName":1385,"dataGaLocation":3907},{"text":3692,"config":4088},{"href":3694,"dataGaName":3695,"dataGaLocation":3907},{"text":3697,"config":4090},{"href":3699,"dataGaName":3700,"dataGaLocation":3907},{"text":3702,"config":4092},{"href":3704,"dataGaName":3705,"dataGaLocation":3907},{"text":3707,"config":4094},{"href":3709,"dataGaName":3710,"dataGaLocation":3907},{"text":3712,"config":4096},{"href":3714,"dataGaName":3715,"dataGaLocation":3907},{"text":3717,"config":4098},{"href":3719,"dataGaName":3720,"dataGaLocation":3907},{"title":3733,"links":4100},[4101,4103,4105,4107,4109,4111,4115,4120,4122,4124,4126],{"text":3741,"config":4102},{"href":3743,"dataGaName":3735,"dataGaLocation":3907},{"text":3746,"config":4104},{"href":3748,"dataGaName":59,"dataGaLocation":3907},{"text":3753,"config":4106},{"href":3755,"dataGaName":3756,"dataGaLocation":3907},{"text":3758,"config":4108},{"href":3760,"dataGaName":3761,"dataGaLocation":3907},{"text":3763,"config":4110},{"href":3765,"dataGaName":3766,"dataGaLocation":3907},{"text":4112,"config":4113},"Sustainability",{"href":4114,"dataGaName":4112,"dataGaLocation":3907},"/sustainability/",{"text":4116,"config":4117},"Diversity, inclusion and belonging (DIB)",{"href":4118,"dataGaName":4119,"dataGaLocation":3907},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":3768,"config":4121},{"href":3770,"dataGaName":3771,"dataGaLocation":3907},{"text":3778,"config":4123},{"href":3780,"dataGaName":3781,"dataGaLocation":3907},{"text":3783,"config":4125},{"href":3785,"dataGaName":3786,"dataGaLocation":3907},{"text":4127,"config":4128},"Modern Slavery Transparency Statement",{"href":4129,"dataGaName":4130,"dataGaLocation":3907},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":4132},[4133,4136,4139],{"text":4134,"config":4135},"Terms",{"href":3959,"dataGaName":3960,"dataGaLocation":3907},{"text":4137,"config":4138},"Cookies",{"dataGaName":3969,"dataGaLocation":3907,"id":3970,"isOneTrustButton":127},{"text":4140,"config":4141},"Privacy",{"href":3964,"dataGaName":3965,"dataGaLocation":3907},[4143,4157],{"id":4144,"title":7,"body":3451,"config":4145,"content":4147,"description":3451,"extension":4151,"meta":4152,"navigation":127,"path":4153,"seo":4154,"stem":4155,"__hash__":4156},"blogAuthors/en-us/blog/authors/william-arias.yml",{"template":4146},"BlogAuthor",{"name":7,"config":4148},{"headshot":4149,"ctfId":4150},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667549/Blog/Author%20Headshots/warias-headshot.jpg","warias","yml",{},"/en-us/blog/authors/william-arias",{},"en-us/blog/authors/william-arias","1h59SugLZ7hePm0SChSE5WG0Z3uurYxGrujcXoxs4tA",{"id":4158,"title":8,"body":3451,"config":4159,"content":4160,"description":3451,"extension":4151,"meta":4164,"navigation":127,"path":4165,"seo":4166,"stem":4167,"__hash__":4168},"blogAuthors/en-us/blog/authors/daniel-helfand.yml",{"template":4146},{"name":8,"config":4161},{"headshot":4162,"ctfId":4163},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662418/Blog/Author%20Headshots/dhelfand.png","b9sRP0HJhdPsOEruWUfih",{},"/en-us/blog/authors/daniel-helfand",{},"en-us/blog/authors/daniel-helfand","U_csW5bNItyLp5wX6zV8xvC4yi-USG4wFxbnBMasIFw",[4170,4179,4187],{"title":4171,"description":4172,"heroImage":4173,"category":3447,"date":4174,"authors":4175,"slug":4178,"externalUrl":3451},"Confidential AI for GitLab Self-Hosted","Give developers AI coding agents in GitLab Duo without source code leaving a hardware-encrypted boundary — no GPUs needed.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1773866173/vte9qh8rriznvyclhkes.png","2026-08-06",[4176,4177],"Mathias Ewald","Martin Paloncy, Edgeless Systems","confidential-ai-for-gitlab-self-hosted",{"title":4180,"description":4181,"heroImage":4182,"category":3447,"date":4183,"authors":4184,"slug":4186,"externalUrl":3451},"Green DevOps: Why carbon measurement belongs in your CI/CD pipeline","CI/CD pipelines have a hidden carbon cost. Here's why measuring it matters, and how you can get started with Eco CI and Carmen in GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1765809212/noh0mdfn9o94ry9ykura.png","2026-07-09",[4185],"Lysanne Pinto","green-devops-carbon-measurement-cicd-pipeline",{"title":4188,"description":4189,"heroImage":4190,"category":3447,"date":4191,"authors":4192,"slug":4194,"externalUrl":3451},"How to build CI/CD observability at scale","This practical guide to GitLab pipeline analytics helps self-managed users gain operational insights using Prometheus and Grafana.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1774465167/n5hlvrsrheadeccyr1oz.png","2026-04-28",[4193],"Paul Meresanu","how-to-build-ci-cd-observability-at-scale",{"promotions":4196},[4197,4211,4223,4235],{"id":4198,"categories":4199,"header":4201,"text":4202,"button":4203,"image":4208},"ai-modernization",[4200],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":4204,"config":4205},"Get your AI maturity score",{"href":4206,"dataGaName":4207,"dataGaLocation":3674},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":4209},{"src":4210},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":4212,"categories":4213,"header":4215,"text":4202,"button":4216,"image":4220},"devops-modernization",[4214,1570],"product","Are you just managing tools or shipping innovation?",{"text":4217,"config":4218},"Get your DevOps maturity score",{"href":4219,"dataGaName":4207,"dataGaLocation":3674},"/assessments/devops-modernization-assessment/",{"config":4221},{"src":4222},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":4224,"categories":4225,"header":4227,"text":4202,"button":4228,"image":4232},"security-modernization",[4226],"security","Are you trading speed for security?",{"text":4229,"config":4230},"Get your security maturity score",{"href":4231,"dataGaName":4207,"dataGaLocation":3674},"/assessments/security-modernization-assessment/",{"config":4233},{"src":4234},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":4236,"paths":4237,"header":4240,"text":4241,"button":4242,"image":4247},"github-azure-migration",[4238,4239],"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":4243,"config":4244},"See how GitLab compares to GitHub",{"href":4245,"dataGaName":4246,"dataGaLocation":3674},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":4248},{"src":4222},{"header":4250,"blurb":4251,"button":4252,"secondaryButton":4257},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":4253,"config":4254},"Get your free trial",{"href":4255,"dataGaName":3475,"dataGaLocation":4256},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":3945,"config":4258},{"href":3797,"dataGaName":3480,"dataGaLocation":4256},1786803774768]