From 3d5f2896630af6eade8bfcd2e6a2d0cc6dd2c270 Mon Sep 17 00:00:00 2001 From: Kouta Kumagai <4884802-kouta_kumagai@users.noreply.gitlab.com> Date: Tue, 25 Nov 2025 08:49:15 +0000 Subject: [PATCH 1/7] Add CI_UPSTREAM_PROJECT_ID to pipeline predefined variables Add CI_UPSTREAM_PROJECT_ID based on the cross-project upstream pipeline. This lets downstream pipelines in multi-project chains know which upstream project triggered them. --- .../ci/variables/downstream/generator.rb | 16 ++++++- .../ci/variables/downstream/generator_spec.rb | 43 ++++++++++++++++++- spec/models/ci/bridge_spec.rb | 41 +++++++++++++++--- 3 files changed, 91 insertions(+), 9 deletions(-) diff --git a/lib/gitlab/ci/variables/downstream/generator.rb b/lib/gitlab/ci/variables/downstream/generator.rb index 6b1824f49eb472..35eb808e8c322c 100644 --- a/lib/gitlab/ci/variables/downstream/generator.rb +++ b/lib/gitlab/ci/variables/downstream/generator.rb @@ -30,7 +30,8 @@ def calculate def calculate_downstream_variables # The order of this list refers to the priority of the variables # The variables added later takes priority. - downstream_yaml_variables + + downstream_predefined_variables + + downstream_yaml_variables + downstream_pipeline_dotenv_variables + downstream_pipeline_variables + downstream_pipeline_schedule_variables @@ -63,6 +64,19 @@ def downstream_pipeline_dotenv_variables build_downstream_variables_from(pipeline_dotenv_variables) end + def downstream_predefined_variables + variables = [] + + if bridge.triggers_cross_project_pipeline? + variables << { + key: 'CI_UPSTREAM_PROJECT_ID', + value: bridge.project.id.to_s + } + end + + variables + end + def build_downstream_variables_from(variables) Gitlab::Ci::Variables::Collection.fabricate(variables).flat_map do |item| if item.raw? diff --git a/spec/lib/gitlab/ci/variables/downstream/generator_spec.rb b/spec/lib/gitlab/ci/variables/downstream/generator_spec.rb index 8f7f19da5fbda4..f4ab08d6e00320 100644 --- a/spec/lib/gitlab/ci/variables/downstream/generator_spec.rb +++ b/spec/lib/gitlab/ci/variables/downstream/generator_spec.rb @@ -48,12 +48,16 @@ ] end + let_it_be(:project) { create(:project) } + let(:bridge) do instance_double( - 'Ci::Bridge', + Ci::Bridge, variables: bridge_variables, forward_yaml_variables?: true, forward_pipeline_variables?: true, + triggers_cross_project_pipeline?: false, + project: project, yaml_variables: yaml_variables, pipeline_variables: pipeline_variables, pipeline_schedule_variables: pipeline_schedule_variables, @@ -136,5 +140,42 @@ expect(generator.calculate).to contain_exactly(*expected) end end + + context 'with predefined variables' do + context 'when bridge triggers cross-project pipeline' do + before do + allow(bridge).to receive(:triggers_cross_project_pipeline?).and_return(true) + end + + subject(:ci_upstream_project_id) do + generator.calculate.find { |v| v[:key] == 'CI_UPSTREAM_PROJECT_ID' } + end + + it 'includes CI_UPSTREAM_PROJECT_ID variable' do + expect(ci_upstream_project_id) + .to eq({ key: 'CI_UPSTREAM_PROJECT_ID', value: project.id.to_s }) + end + + it 'includes CI_UPSTREAM_PROJECT_ID even when forward settings are disabled' do + allow(bridge).to receive_messages( + forward_yaml_variables?: false, + forward_pipeline_variables?: false + ) + + expect(ci_upstream_project_id) + .to eq({ key: 'CI_UPSTREAM_PROJECT_ID', value: project.id.to_s }) + end + end + + context 'when bridge does not trigger cross-project pipeline' do + subject(:ci_upstream_project_id) do + generator.calculate.find { |v| v[:key] == 'CI_UPSTREAM_PROJECT_ID' } + end + + it 'does not include CI_UPSTREAM_PROJECT_ID variable' do + expect(ci_upstream_project_id).to be_nil + end + end + end end end diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb index 3476b4c9cb8798..97445ddc701f07 100644 --- a/spec/models/ci/bridge_spec.rb +++ b/spec/models/ci/bridge_spec.rb @@ -108,7 +108,9 @@ source: :pipeline, target_revision: { ref: downstream_project.default_branch, - variables_attributes: [] + variables_attributes: [ + { key: 'CI_UPSTREAM_PROJECT_ID', value: bridge.project.id.to_s } + ] }, execute_params: { ignore_skip_ci: true, @@ -519,11 +521,18 @@ # return the new variables due to memoized results from previous tests. let(:pipeline) { create(:ci_pipeline, project: project) } + let(:upstream_project_id_variable) do + { key: 'CI_UPSTREAM_PROJECT_ID', value: bridge.pipeline.project.id.to_s } + end + subject(:downstream_variables) { bridge.downstream_variables } it 'returns variables that are going to be passed downstream' do expect(bridge.downstream_variables) - .to contain_exactly(key: 'BRIDGE', value: 'cross') + .to contain_exactly( + upstream_project_id_variable, + { key: 'BRIDGE', value: 'cross' } + ) end context 'when using variables interpolation' do @@ -581,6 +590,7 @@ it 'does not expand file variable and forwards the file variable' do expected_vars = [ + upstream_project_id_variable, { key: 'EXPANDED_FILE', value: '$TEST_FILE_VAR' }, { key: 'TEST_FILE_VAR', value: 'test-file-value', variable_type: :file } ] @@ -596,7 +606,10 @@ it 'does not expand variable recursively' do expect(bridge.downstream_variables) - .to contain_exactly(key: 'EXPANDED', value: '$EXPANDED') + .to contain_exactly( + upstream_project_id_variable, + { key: 'EXPANDED', value: '$EXPANDED' } + ) end end @@ -632,7 +645,8 @@ end it 'returns variables according to the forward value' do - expect(bridge.downstream_variables.map { |v| v[:key] }).to contain_exactly(*variables) + expected_keys = ['CI_UPSTREAM_PROJECT_ID'] + variables + expect(bridge.downstream_variables.map { |v| v[:key] }).to contain_exactly(*expected_keys) end end @@ -647,7 +661,10 @@ end it 'uses the pipeline variable' do - expect(bridge.downstream_variables).to contain_exactly({ key: 'SHARED_KEY', value: 'new value' }) + expect(bridge.downstream_variables).to contain_exactly( + upstream_project_id_variable, + { key: 'SHARED_KEY', value: 'new value' } + ) end end @@ -664,7 +681,10 @@ # The current behaviour forwards the file variable as an environment variable. # TODO: decide whether to forward as a file var in https://gitlab.com/gitlab-org/gitlab/-/issues/416334 it 'forwards the pipeline file variable' do - expect(bridge.downstream_variables).to contain_exactly({ key: 'FILE_VAR', value: 'new value' }) + expect(bridge.downstream_variables).to contain_exactly( + upstream_project_id_variable, + { key: 'FILE_VAR', value: 'new value' } + ) end end @@ -682,6 +702,7 @@ it 'does not expand the scoped file variable and forwards the file variable' do expected_vars = [ + upstream_project_id_variable, { key: 'FILE_VAR', value: '$PROJECT_FILE_VAR' }, { key: 'YAML_VAR', value: '$PROJECT_FILE_VAR' }, { key: 'PROJECT_FILE_VAR', value: 'project file', variable_type: :file } @@ -705,6 +726,7 @@ it 'adds the schedule variable' do expected_vars = [ + upstream_project_id_variable, { key: 'BRIDGE', value: 'cross' }, { key: 'schedule_var_key', value: 'schedule var value' } ] @@ -730,7 +752,10 @@ # The current behaviour forwards the file variable as an environment variable. # TODO: decide whether to forward as a file var in https://gitlab.com/gitlab-org/gitlab/-/issues/416334 it 'forwards the schedule file variable' do - expect(bridge.downstream_variables).to contain_exactly({ key: 'schedule_var_key', value: 'schedule var value' }) + expect(bridge.downstream_variables).to contain_exactly( + upstream_project_id_variable, + { key: 'schedule_var_key', value: 'schedule var value' } + ) end end @@ -750,6 +775,7 @@ it 'does not expand the scoped file variable and forwards the file variable' do expected_vars = [ + upstream_project_id_variable, { key: 'schedule_var_key', value: '$PROJECT_FILE_VAR' }, { key: 'PROJECT_FILE_VAR', value: 'project file', variable_type: :file } ] @@ -800,6 +826,7 @@ it 'expands variables according to their raw attributes' do expect(downstream_variables).to contain_exactly( + upstream_project_id_variable, { key: 'BRIDGE', value: 'cross' }, { key: 'VAR1', value: 'value1' }, { key: 'VAR2', value: 'value2 value1' }, -- GitLab From ff0a8c239c552ca622619e5e0d15b3ddeedef528 Mon Sep 17 00:00:00 2001 From: Kouta Kumagai <4884802-kouta_kumagai@users.noreply.gitlab.com> Date: Tue, 25 Nov 2025 14:40:05 +0000 Subject: [PATCH 2/7] Document CI_UPSTREAM_PROJECT_ID variable --- doc-locale/ja-jp/ci/variables/predefined_variables.md | 1 + doc/ci/variables/predefined_variables.md | 1 + 2 files changed, 2 insertions(+) diff --git a/doc-locale/ja-jp/ci/variables/predefined_variables.md b/doc-locale/ja-jp/ci/variables/predefined_variables.md index 5ca7d385d2030a..3896ed06463f66 100644 --- a/doc-locale/ja-jp/ci/variables/predefined_variables.md +++ b/doc-locale/ja-jp/ci/variables/predefined_variables.md @@ -104,6 +104,7 @@ title: 定義済みCI/CD変数のリファレンス | `CI_PIPELINE_CREATED_AT` | ジョブ専用 | パイプラインが作成された日時([ISO 8601](https://www.rfc-editor.org/rfc/rfc3339#appendix-A)形式)。例: `2022-01-31T16:47:55Z`。[デフォルトではUTC](../../administration/timezone.md)です。 | | `CI_PIPELINE_NAME` | プリパイプライン | [`workflow:name`](../yaml/_index.md#workflowname)で定義されたパイプライン名。GitLab 16.3で導入されました。 | | `CI_PIPELINE_SCHEDULE_DESCRIPTION` | プリパイプライン | パイプラインスケジュールの説明。スケジュールされたパイプラインでのみ使用できます。GitLab 17.8で導入されました。 | +| `CI_UPSTREAM_PROJECT_ID` | プリパイプライン | マルチプロジェクトパイプラインで、現在のパイプラインをトリガーしたアップストリームパイプラインのプロジェクトID。 | | `CI_PROJECT_DIR` | ジョブ専用 | リポジトリのクローン先であり、ジョブの実行起点となる場所のフルパス。GitLab Runnerの`builds_dir`パラメータが設定されている場合、この変数は`builds_dir`の値を基準に設定されます。詳細については、[GitLab Runnerの高度な設定](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section)を参照してください。 | | `CI_PROJECT_ID` | プリパイプライン | 現在のプロジェクトID。このIDは、GitLabインスタンス上のすべてのプロジェクトで一意です。 | | `CI_PROJECT_NAME` | プリパイプライン | プロジェクトのディレクトリ名。たとえば、プロジェクトのURLが`gitlab.example.com/group-name/project-1`の場合、`CI_PROJECT_NAME`は`project-1`になります。 | diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md index 54f9bebf49d65c..ae386991f1952e 100644 --- a/doc/ci/variables/predefined_variables.md +++ b/doc/ci/variables/predefined_variables.md @@ -111,6 +111,7 @@ Predefined variables become available at three different phases of pipeline exec | `CI_PIPELINE_CREATED_AT` | Job-only | The date and time when the pipeline was created, in [ISO 8601](https://www.rfc-editor.org/rfc/rfc3339#appendix-A) format. For example, `2022-01-31T16:47:55Z`. [UTC by default](../../administration/timezone.md). | | `CI_PIPELINE_NAME` | Pre-pipeline | The pipeline name defined in [`workflow:name`](../yaml/_index.md#workflowname). Introduced in GitLab 16.3. | | `CI_PIPELINE_SCHEDULE_DESCRIPTION` | Pre-pipeline | The description of the pipeline schedule. Only available in scheduled pipelines. Introduced in GitLab 17.8. | +| `CI_UPSTREAM_PROJECT_ID` | Pre-pipeline | ID of the upstream project that triggered the current pipeline in a multi-project pipeline. | | `CI_PROJECT_DIR` | Job-only | The full path the repository is cloned to, and where the job runs from. If the GitLab Runner `builds_dir` parameter is set, this variable is set relative to the value of `builds_dir`. For more information, see the [Advanced GitLab Runner configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section). | | `CI_PROJECT_ID` | Pre-pipeline | The ID of the current project. This ID is unique across all projects on the GitLab instance. | | `CI_PROJECT_NAME` | Pre-pipeline | The name of the directory for the project. For example if the project URL is `gitlab.example.com/group-name/project-1`, `CI_PROJECT_NAME` is `project-1`. | -- GitLab From abbe1ded2be562d074bf93732e3d40949ff1b2fd Mon Sep 17 00:00:00 2001 From: Kouta Kumagai <4884802-kouta_kumagai@users.noreply.gitlab.com> Date: Wed, 26 Nov 2025 19:56:55 +0900 Subject: [PATCH 3/7] Update CI_UPSTREAM_PROJECT_ID documentation - Remove manual changes to auto-generated Japanese docs - Add version information to CI_UPSTREAM_PROJECT_ID entry --- doc-locale/ja-jp/ci/variables/predefined_variables.md | 1 - doc/ci/variables/predefined_variables.md | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/doc-locale/ja-jp/ci/variables/predefined_variables.md b/doc-locale/ja-jp/ci/variables/predefined_variables.md index 3896ed06463f66..5ca7d385d2030a 100644 --- a/doc-locale/ja-jp/ci/variables/predefined_variables.md +++ b/doc-locale/ja-jp/ci/variables/predefined_variables.md @@ -104,7 +104,6 @@ title: 定義済みCI/CD変数のリファレンス | `CI_PIPELINE_CREATED_AT` | ジョブ専用 | パイプラインが作成された日時([ISO 8601](https://www.rfc-editor.org/rfc/rfc3339#appendix-A)形式)。例: `2022-01-31T16:47:55Z`。[デフォルトではUTC](../../administration/timezone.md)です。 | | `CI_PIPELINE_NAME` | プリパイプライン | [`workflow:name`](../yaml/_index.md#workflowname)で定義されたパイプライン名。GitLab 16.3で導入されました。 | | `CI_PIPELINE_SCHEDULE_DESCRIPTION` | プリパイプライン | パイプラインスケジュールの説明。スケジュールされたパイプラインでのみ使用できます。GitLab 17.8で導入されました。 | -| `CI_UPSTREAM_PROJECT_ID` | プリパイプライン | マルチプロジェクトパイプラインで、現在のパイプラインをトリガーしたアップストリームパイプラインのプロジェクトID。 | | `CI_PROJECT_DIR` | ジョブ専用 | リポジトリのクローン先であり、ジョブの実行起点となる場所のフルパス。GitLab Runnerの`builds_dir`パラメータが設定されている場合、この変数は`builds_dir`の値を基準に設定されます。詳細については、[GitLab Runnerの高度な設定](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section)を参照してください。 | | `CI_PROJECT_ID` | プリパイプライン | 現在のプロジェクトID。このIDは、GitLabインスタンス上のすべてのプロジェクトで一意です。 | | `CI_PROJECT_NAME` | プリパイプライン | プロジェクトのディレクトリ名。たとえば、プロジェクトのURLが`gitlab.example.com/group-name/project-1`の場合、`CI_PROJECT_NAME`は`project-1`になります。 | diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md index ae386991f1952e..9ef9db1dabbc9b 100644 --- a/doc/ci/variables/predefined_variables.md +++ b/doc/ci/variables/predefined_variables.md @@ -111,7 +111,7 @@ Predefined variables become available at three different phases of pipeline exec | `CI_PIPELINE_CREATED_AT` | Job-only | The date and time when the pipeline was created, in [ISO 8601](https://www.rfc-editor.org/rfc/rfc3339#appendix-A) format. For example, `2022-01-31T16:47:55Z`. [UTC by default](../../administration/timezone.md). | | `CI_PIPELINE_NAME` | Pre-pipeline | The pipeline name defined in [`workflow:name`](../yaml/_index.md#workflowname). Introduced in GitLab 16.3. | | `CI_PIPELINE_SCHEDULE_DESCRIPTION` | Pre-pipeline | The description of the pipeline schedule. Only available in scheduled pipelines. Introduced in GitLab 17.8. | -| `CI_UPSTREAM_PROJECT_ID` | Pre-pipeline | ID of the upstream project that triggered the current pipeline in a multi-project pipeline. | +| `CI_UPSTREAM_PROJECT_ID` | Pre-pipeline | ID of the upstream project that triggered the current pipeline in a multi-project pipeline. Introduced in GitLab 18.7. | | `CI_PROJECT_DIR` | Job-only | The full path the repository is cloned to, and where the job runs from. If the GitLab Runner `builds_dir` parameter is set, this variable is set relative to the value of `builds_dir`. For more information, see the [Advanced GitLab Runner configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section). | | `CI_PROJECT_ID` | Pre-pipeline | The ID of the current project. This ID is unique across all projects on the GitLab instance. | | `CI_PROJECT_NAME` | Pre-pipeline | The name of the directory for the project. For example if the project URL is `gitlab.example.com/group-name/project-1`, `CI_PROJECT_NAME` is `project-1`. | -- GitLab From 1e0503ee550263728f5fe76c9c8ad91f91a91917 Mon Sep 17 00:00:00 2001 From: Kouta Kumagai <4884802-kouta_kumagai@users.noreply.gitlab.com> Date: Thu, 11 Dec 2025 13:24:15 +0000 Subject: [PATCH 4/7] Remove predefined variable from generator Remove the CI_UPSTREAM_PROJECT_ID predefined variable from the generator. Defining this variable in the generator is no longer desired, as we plan to move its definition to the pipeline variables builder in a follow-up change. --- .../ci/variables/downstream/generator.rb | 16 +------- .../ci/variables/downstream/generator_spec.rb | 41 ------------------- 2 files changed, 1 insertion(+), 56 deletions(-) diff --git a/lib/gitlab/ci/variables/downstream/generator.rb b/lib/gitlab/ci/variables/downstream/generator.rb index 35eb808e8c322c..6b1824f49eb472 100644 --- a/lib/gitlab/ci/variables/downstream/generator.rb +++ b/lib/gitlab/ci/variables/downstream/generator.rb @@ -30,8 +30,7 @@ def calculate def calculate_downstream_variables # The order of this list refers to the priority of the variables # The variables added later takes priority. - downstream_predefined_variables + - downstream_yaml_variables + + downstream_yaml_variables + downstream_pipeline_dotenv_variables + downstream_pipeline_variables + downstream_pipeline_schedule_variables @@ -64,19 +63,6 @@ def downstream_pipeline_dotenv_variables build_downstream_variables_from(pipeline_dotenv_variables) end - def downstream_predefined_variables - variables = [] - - if bridge.triggers_cross_project_pipeline? - variables << { - key: 'CI_UPSTREAM_PROJECT_ID', - value: bridge.project.id.to_s - } - end - - variables - end - def build_downstream_variables_from(variables) Gitlab::Ci::Variables::Collection.fabricate(variables).flat_map do |item| if item.raw? diff --git a/spec/lib/gitlab/ci/variables/downstream/generator_spec.rb b/spec/lib/gitlab/ci/variables/downstream/generator_spec.rb index f4ab08d6e00320..9293c23fa4f5e1 100644 --- a/spec/lib/gitlab/ci/variables/downstream/generator_spec.rb +++ b/spec/lib/gitlab/ci/variables/downstream/generator_spec.rb @@ -48,16 +48,12 @@ ] end - let_it_be(:project) { create(:project) } - let(:bridge) do instance_double( Ci::Bridge, variables: bridge_variables, forward_yaml_variables?: true, forward_pipeline_variables?: true, - triggers_cross_project_pipeline?: false, - project: project, yaml_variables: yaml_variables, pipeline_variables: pipeline_variables, pipeline_schedule_variables: pipeline_schedule_variables, @@ -140,42 +136,5 @@ expect(generator.calculate).to contain_exactly(*expected) end end - - context 'with predefined variables' do - context 'when bridge triggers cross-project pipeline' do - before do - allow(bridge).to receive(:triggers_cross_project_pipeline?).and_return(true) - end - - subject(:ci_upstream_project_id) do - generator.calculate.find { |v| v[:key] == 'CI_UPSTREAM_PROJECT_ID' } - end - - it 'includes CI_UPSTREAM_PROJECT_ID variable' do - expect(ci_upstream_project_id) - .to eq({ key: 'CI_UPSTREAM_PROJECT_ID', value: project.id.to_s }) - end - - it 'includes CI_UPSTREAM_PROJECT_ID even when forward settings are disabled' do - allow(bridge).to receive_messages( - forward_yaml_variables?: false, - forward_pipeline_variables?: false - ) - - expect(ci_upstream_project_id) - .to eq({ key: 'CI_UPSTREAM_PROJECT_ID', value: project.id.to_s }) - end - end - - context 'when bridge does not trigger cross-project pipeline' do - subject(:ci_upstream_project_id) do - generator.calculate.find { |v| v[:key] == 'CI_UPSTREAM_PROJECT_ID' } - end - - it 'does not include CI_UPSTREAM_PROJECT_ID variable' do - expect(ci_upstream_project_id).to be_nil - end - end - end end end -- GitLab From c01725e3c4f150f72da3c81ca747058ebc547a5d Mon Sep 17 00:00:00 2001 From: Kouta Kumagai <4884802-kouta_kumagai@users.noreply.gitlab.com> Date: Thu, 11 Dec 2025 13:27:34 +0000 Subject: [PATCH 5/7] Add upstream pipeline variables to Builder::Pipeline Extend the pipeline variables builder to provide upstream pipeline context for downstream pipelines triggered by a bridge job. This change introduces three predefined variables: - CI_UPSTREAM_PROJECT_ID: upstream_pipeline.project_id - CI_UPSTREAM_PIPELINE_ID: upstream_pipeline.id - CI_UPSTREAM_JOB_ID: bridge.id --- lib/gitlab/ci/variables/builder/pipeline.rb | 14 ++++++++++++ .../ci/variables/builder/pipeline_spec.rb | 22 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/lib/gitlab/ci/variables/builder/pipeline.rb b/lib/gitlab/ci/variables/builder/pipeline.rb index d25c1a020d5e24..1aecb87381973b 100644 --- a/lib/gitlab/ci/variables/builder/pipeline.rb +++ b/lib/gitlab/ci/variables/builder/pipeline.rb @@ -35,6 +35,11 @@ def predefined_variables if pipeline.external_pull_request_event? && pipeline.external_pull_request variables.concat(pipeline.external_pull_request.predefined_variables) end + + if pipeline.source_pipeline&.source_bridge.present? && + pipeline.source_pipeline.source_bridge.triggers_cross_project_pipeline? + variables.concat(predefined_upstream_variables) + end end end @@ -106,6 +111,15 @@ def predefined_merge_request_variables end strong_memoize_attr :predefined_merge_request_variables + def predefined_upstream_variables + Gitlab::Ci::Variables::Collection.new.tap do |variables| + variables.append(key: 'CI_UPSTREAM_PIPELINE_ID', value: pipeline.source_pipeline.source_pipeline_id.to_s) + variables.append(key: 'CI_UPSTREAM_PROJECT_ID', value: pipeline.source_pipeline.source_project_id.to_s) + variables.append(key: 'CI_UPSTREAM_JOB_ID', value: pipeline.source_pipeline.source_job_id.to_s) + end + end + strong_memoize_attr :predefined_upstream_variables + def merge_request_diff pipeline.merge_request_diff end diff --git a/spec/lib/gitlab/ci/variables/builder/pipeline_spec.rb b/spec/lib/gitlab/ci/variables/builder/pipeline_spec.rb index c450f9d3df9627..a50abb6b8f9b97 100644 --- a/spec/lib/gitlab/ci/variables/builder/pipeline_spec.rb +++ b/spec/lib/gitlab/ci/variables/builder/pipeline_spec.rb @@ -379,6 +379,28 @@ end end + context 'when pipeline triggered by upstream project' do + let_it_be(:upstream_project) { create(:project) } + let(:upstream_pipeline) { create(:ci_pipeline, project: upstream_project) } + let(:pipeline) { create(:ci_pipeline, project: project) } + let(:bridge) do + create(:ci_bridge, pipeline: upstream_pipeline, downstream_pipeline: pipeline, downstream: project) + end + + before do + create(:ci_sources_pipeline, source_job: bridge, pipeline: pipeline) + end + + it 'exposes upstream pipeline variables' do + expect(subject.to_hash) + .to include( + 'CI_UPSTREAM_PROJECT_ID' => upstream_pipeline.project_id.to_s, + 'CI_UPSTREAM_PIPELINE_ID' => upstream_pipeline.id.to_s, + 'CI_UPSTREAM_JOB_ID' => bridge.id.to_s + ) + end + end + context 'when source is external pull request' do let(:pipeline) do create(:ci_pipeline, source: :external_pull_request_event, external_pull_request: pull_request) -- GitLab From 65df0c639167f7592fcfbb049c0ca1cf63a2e62e Mon Sep 17 00:00:00 2001 From: Kouta Kumagai <4884802-kouta_kumagai@users.noreply.gitlab.com> Date: Thu, 11 Dec 2025 13:43:59 +0000 Subject: [PATCH 6/7] Document upstream tracking variables for multi-project pipelines Add documentation for three new CI/CD predefined variables: - CI_UPSTREAM_JOB_ID - CI_UPSTREAM_PIPELINE_ID - CI_UPSTREAM_PROJECT_ID --- doc/ci/variables/predefined_variables.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md index 9ef9db1dabbc9b..e88854408184ca 100644 --- a/doc/ci/variables/predefined_variables.md +++ b/doc/ci/variables/predefined_variables.md @@ -111,7 +111,6 @@ Predefined variables become available at three different phases of pipeline exec | `CI_PIPELINE_CREATED_AT` | Job-only | The date and time when the pipeline was created, in [ISO 8601](https://www.rfc-editor.org/rfc/rfc3339#appendix-A) format. For example, `2022-01-31T16:47:55Z`. [UTC by default](../../administration/timezone.md). | | `CI_PIPELINE_NAME` | Pre-pipeline | The pipeline name defined in [`workflow:name`](../yaml/_index.md#workflowname). Introduced in GitLab 16.3. | | `CI_PIPELINE_SCHEDULE_DESCRIPTION` | Pre-pipeline | The description of the pipeline schedule. Only available in scheduled pipelines. Introduced in GitLab 17.8. | -| `CI_UPSTREAM_PROJECT_ID` | Pre-pipeline | ID of the upstream project that triggered the current pipeline in a multi-project pipeline. Introduced in GitLab 18.7. | | `CI_PROJECT_DIR` | Job-only | The full path the repository is cloned to, and where the job runs from. If the GitLab Runner `builds_dir` parameter is set, this variable is set relative to the value of `builds_dir`. For more information, see the [Advanced GitLab Runner configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section). | | `CI_PROJECT_ID` | Pre-pipeline | The ID of the current project. This ID is unique across all projects on the GitLab instance. | | `CI_PROJECT_NAME` | Pre-pipeline | The name of the directory for the project. For example if the project URL is `gitlab.example.com/group-name/project-1`, `CI_PROJECT_NAME` is `project-1`. | @@ -161,6 +160,9 @@ Predefined variables become available at three different phases of pipeline exec | `CI_SHARED_ENVIRONMENT` | Pipeline | Only available if the job is executed in a shared environment (something that is persisted across CI/CD invocations, like the `shell` or `ssh` executor). `true` when available. | | `CI_TEMPLATE_REGISTRY_HOST` | Pre-pipeline | The host of the registry used by CI/CD templates. Defaults to `registry.gitlab.com`. Introduced in GitLab 15.3. | | `CI_TRIGGER_SHORT_TOKEN` | Job-only | First 4 characters of the [trigger token](../triggers/_index.md#create-a-pipeline-trigger-token) of the current job. Only available if the pipeline was [triggered with a trigger token](../triggers/_index.md). For example, for a trigger token of `glptt-1234567890abcdefghij`, `CI_TRIGGER_SHORT_TOKEN` would be `1234`. Introduced in GitLab 17.0. | +| `CI_UPSTREAM_JOB_ID` | Pre-pipeline | ID of the upstream bridge job that triggered the current pipeline in a multi-project pipeline. Introduced in GitLab 18.7. | +| `CI_UPSTREAM_PIPELINE_ID` | Pre-pipeline | ID of the upstream pipeline that triggered the current pipeline in a multi-project pipeline. Introduced in GitLab 18.7. | +| `CI_UPSTREAM_PROJECT_ID` | Pre-pipeline | ID of the upstream project that triggered the current pipeline in a multi-project pipeline. Introduced in GitLab 18.7. | | `GITLAB_CI` | Pre-pipeline | Available for all jobs executed in CI/CD. `true` when available. | | `GITLAB_FEATURES` | Pre-pipeline | The comma-separated list of licensed features available for the GitLab instance and license. | | `GITLAB_USER_EMAIL` | Pipeline | The email of the user who started the pipeline, unless the job is a manual job. In manual jobs, the value is the email of the user who started the job. | -- GitLab From 36656a1c57db60d77e9ace92d39934b6062e1dcf Mon Sep 17 00:00:00 2001 From: Kouta Kumagai <4884802-kouta_kumagai@users.noreply.gitlab.com> Date: Sat, 13 Dec 2025 10:14:37 +0900 Subject: [PATCH 7/7] Use "trigger job" instead of "bridge job" in documentation --- doc/ci/variables/predefined_variables.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md index e88854408184ca..e1f23a9e391724 100644 --- a/doc/ci/variables/predefined_variables.md +++ b/doc/ci/variables/predefined_variables.md @@ -160,7 +160,7 @@ Predefined variables become available at three different phases of pipeline exec | `CI_SHARED_ENVIRONMENT` | Pipeline | Only available if the job is executed in a shared environment (something that is persisted across CI/CD invocations, like the `shell` or `ssh` executor). `true` when available. | | `CI_TEMPLATE_REGISTRY_HOST` | Pre-pipeline | The host of the registry used by CI/CD templates. Defaults to `registry.gitlab.com`. Introduced in GitLab 15.3. | | `CI_TRIGGER_SHORT_TOKEN` | Job-only | First 4 characters of the [trigger token](../triggers/_index.md#create-a-pipeline-trigger-token) of the current job. Only available if the pipeline was [triggered with a trigger token](../triggers/_index.md). For example, for a trigger token of `glptt-1234567890abcdefghij`, `CI_TRIGGER_SHORT_TOKEN` would be `1234`. Introduced in GitLab 17.0. | -| `CI_UPSTREAM_JOB_ID` | Pre-pipeline | ID of the upstream bridge job that triggered the current pipeline in a multi-project pipeline. Introduced in GitLab 18.7. | +| `CI_UPSTREAM_JOB_ID` | Pre-pipeline | ID of the upstream trigger job that triggered the current pipeline in a multi-project pipeline. Introduced in GitLab 18.7. | | `CI_UPSTREAM_PIPELINE_ID` | Pre-pipeline | ID of the upstream pipeline that triggered the current pipeline in a multi-project pipeline. Introduced in GitLab 18.7. | | `CI_UPSTREAM_PROJECT_ID` | Pre-pipeline | ID of the upstream project that triggered the current pipeline in a multi-project pipeline. Introduced in GitLab 18.7. | | `GITLAB_CI` | Pre-pipeline | Available for all jobs executed in CI/CD. `true` when available. | -- GitLab