Skip to content
代码片段 群组 项目
未验证 提交 dcd7e4e1 编辑于 作者: Furkan Ayhan's avatar Furkan Ayhan 提交者: GitLab
浏览文件

Add `inputs` to `POST /projects/:id/trigger/pipeline`

This also adds the params conversion helper for inputs.
上级 63f71344
No related branches found
No related tags found
2 合并请求!3031Merge per-main-jh to main-jh by luzhiyuan,!3030Merge per-main-jh to main-jh
......@@ -31,7 +31,7 @@ def create_pipeline_from_trigger(trigger)
response = Ci::CreatePipelineService
.new(project, trigger.owner, ref: params[:ref], variables_attributes: variables)
.execute(:trigger, ignore_skip_ci: true) do |pipeline|
.execute(:trigger, ignore_skip_ci: true, inputs: inputs) do |pipeline|
pipeline.trigger = trigger
pipeline.trigger_requests.build(trigger: trigger, project_id: project.id)
end
......@@ -62,7 +62,7 @@ def create_pipeline_from_job(job)
response = Ci::CreatePipelineService
.new(project, job.user, ref: params[:ref], variables_attributes: variables)
.execute(:pipeline, ignore_skip_ci: true) do |pipeline|
.execute(:pipeline, ignore_skip_ci: true, inputs: inputs) do |pipeline|
source = job.sourced_pipelines.build(
source_pipeline: job.pipeline,
source_project: job.project,
......@@ -82,6 +82,10 @@ def job_from_token
end
end
def inputs
params[:inputs]
end
def variables
param_variables + [payload_variable]
end
......
......@@ -156,6 +156,13 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
## Trigger a pipeline with a token
{{< history >}}
- `inputs` attribute [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/519958) in GitLab 17.10
[with a flag](../administration/feature_flags.md) named `ci_inputs_for_pipelines`. Disabled by default.
{{< /history >}}
Trigger a pipeline by using a [pipeline trigger token](../ci/triggers/_index.md#create-a-pipeline-trigger-token)
or a [CI/CD job token](../ci/jobs/ci_job_token.md) for authentication.
......@@ -177,11 +184,26 @@ Supported attributes:
| `ref` | string | Yes | The branch or tag to run the pipeline on. |
| `token` | string | Yes | The trigger token or CI/CD job token. |
| `variables` | hash | No | A map of key-valued strings containing the pipeline variables. For example: `{ VAR1: "value1", VAR2: "value2" }`. |
| `inputs` | hash | No | A map of inputs, as key-value pairs, to use when creating the pipeline. Required feature flag: `ci_inputs_for_pipelines` |
Example request with [variables](../ci/variables/_index.md):
```shell
curl --request POST \
--form "variables[VAR1]=value1" \
--form "variables[VAR2]=value2" \
"https://gitlab.example.com/api/v4/projects/123/trigger/pipeline?token=2cb1840fb9dfc9fb0b7b1609cd29cb&ref=main"
```
Example request with [inputs](../ci/yaml/inputs.md):
Example request:
_Required [feature flag](feature_flags.md): `ci_inputs_for_pipelines`_
```shell
curl --request POST --form "variables[VAR1]=value1" --form "variables[VAR2]=value2" "https://gitlab.example.com/api/v4/projects/123/trigger/pipeline?token=2cb1840fb9dfc9fb0b7b1609cd29cb&ref=main"
curl --request POST \
--header "Content-Type: application/json" \
--data '{"inputs": {"environment": "environment", "scan_security": false, "level": 3}}' \
"https://gitlab.example.com/api/v4/projects/123/trigger/pipeline?token=2cb1840fb9dfc9fb0b7b1609cd29cb&ref=main"
```
Example response:
......
......@@ -31,6 +31,7 @@ class Triggers < ::API::Base
documentation: { example: '6d056f63e50fe6f8c5f8f4aa10edb7' }
optional :variables, type: Hash, desc: 'The list of variables to be injected into build',
documentation: { example: { VAR1: "value1", VAR2: "value2" } }
optional :inputs, type: Hash, desc: 'The list of inputs to be used to create the pipeline.'
end
post ":id/(ref/:ref/)trigger/pipeline", requirements: { ref: /.+/ } do
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20758')
......
# frozen_string_literal: true
module Ci
module PipelineCreation
module Inputs
def self.parse_params(params)
return params unless params.is_a?(Hash)
params.to_hash.transform_values do |value| # `to_hash` to avoid `ActiveSupport::HashWithIndifferentAccess`
next value unless value.is_a?(String)
begin
Gitlab::Json.parse(value) # convert to number, boolean, array
rescue JSON::ParserError
value # we treat the value as-is as it's likely a string like 'blue-green'.
end
end.deep_symbolize_keys # `deep_symbolize_keys` because Interpolator requires
end
end
end
end
......@@ -35,7 +35,7 @@ def pipeline_config
triggered_for_branch: @pipeline.branch?,
ref: @pipeline.ref,
pipeline_policy_context: @command.pipeline_policy_context,
inputs: @command.inputs
inputs: ::Ci::PipelineCreation::Inputs.parse_params(@command.inputs)
)
end
end
......
......@@ -61,7 +61,9 @@ def ci_yaml_include(config)
end
def include_inputs
{ 'inputs' => inputs }.compact_blank
{ inputs: inputs }
.compact_blank
.deep_stringify_keys # to avoid symbols in the YAML
end
end
end
......
# frozen_string_literal: true
require 'fast_spec_helper'
require 'oj'
require_relative Rails.root.join('lib/ci/pipeline_creation/inputs.rb')
RSpec.describe Ci::PipelineCreation::Inputs, feature_category: :pipeline_composition do
describe '.parse_params' do
let(:params) do
{
'string_param' => 'regular-string',
json_array: '[1, 2, 3]',
'json_object' => '{"key": "value"}',
'json_boolean' => 'true',
'json_number' => '42',
'nested' => { 'param' => 'value' }
}
end
subject(:parse_params) { described_class.parse_params(params) }
it 'transforms values' do
expect(parse_params).to include(
string_param: 'regular-string',
json_array: [1, 2, 3],
json_object: { key: 'value' },
json_boolean: true,
json_number: 42,
nested: { param: 'value' }
)
end
context 'when params are not a hash' do
let(:params) { 'not a hash' }
it 'returns the params as-is' do
expect(parse_params).to eq('not a hash')
end
end
end
end
......@@ -150,14 +150,26 @@
end
context 'when passing inputs' do
let(:inputs) { { 'foo' => 'bar' } }
let(:inputs) do
{
'string' => 'bar',
boolean: true,
'array' => [{ 'foo' => 'bar' }],
number: 1
}
end
let(:config_content_result) do
<<~CICONFIG
---
include:
- local: ".gitlab-ci.yml"
inputs:
foo: bar
string: bar
boolean: true
array:
- foo: bar
number: 1
CICONFIG
end
......@@ -168,6 +180,7 @@
expect(pipeline.pipeline_config.content).to eq(config_content_result)
expect(command.config_content).to eq(config_content_result)
expect(command.pipeline_config.internal_include_prepended?).to eq(true)
expect(command.pipeline_config.inputs_for_pipeline_creation).to eq({})
end
end
end
......@@ -217,7 +230,15 @@
end
context 'when passing inputs' do
let(:inputs) { { 'foo' => 'bar' } }
let(:content) do
<<~EOY
---
stages:
- $[[ inputs.stage ]]
EOY
end
let(:inputs) { { stage: 'bar' } }
it 'uses the parameter content with inputs' do
subject.perform!
......@@ -226,6 +247,7 @@
expect(pipeline.pipeline_config.content).to eq(content)
expect(command.config_content).to eq(content)
expect(command.pipeline_config.internal_include_prepended?).to eq(false)
expect(command.pipeline_config.inputs_for_pipeline_creation).to eq(inputs)
end
end
end
......
......@@ -181,6 +181,84 @@
expect(response).to have_gitlab_http_status(:forbidden)
end
end
context 'when using inputs' do
let(:inputs) do
{
deploy_strategy: 'blue-green',
job_stage: 'deploy',
test_script: ['echo "test"'],
parallel_jobs: 3,
allow_failure: true,
test_rules: [
{ if: '$CI_PIPELINE_SOURCE == "web"' }
]
}
end
before do
stub_ci_pipeline_yaml_file(
File.read(Rails.root.join('spec/lib/gitlab/ci/config/yaml/fixtures/complex-included-ci.yml'))
)
end
shared_examples 'sending request using inputs' do
shared_examples 'creating a succesful pipeline' do
it 'creates a pipeline using inputs' do
expect { post_request }.to change { Ci::Pipeline.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
pipeline = Ci::Pipeline.find(json_response['id'])
expect(pipeline.builds.map { |b| "#{b.name} #{b.allow_failure}" }).to contain_exactly(
'my-job-build 1/3 false', 'my-job-build 2/3 false', 'my-job-build 3/3 false',
'my-job-test true', 'my-job-deploy false'
)
end
end
context 'when passing parameters as JSON' do
let(:headers) do
{ 'Content-Type' => 'application/json' }
end
subject(:post_request) do
post api("/projects/#{project.id}/ref/master/trigger/pipeline?token=#{token}"),
headers: headers,
params: { ref: 'refs/heads/other-branch', inputs: inputs }.to_json
end
it_behaves_like 'creating a succesful pipeline'
end
context 'when passing parameters as form data' do
let(:headers) do
{ 'Content-Type' => 'application/x-www-form-urlencoded' }
end
subject(:post_request) do
post api("/projects/#{project.id}/ref/master/trigger/pipeline?token=#{token}"),
headers: headers,
params: { ref: 'refs/heads/other-branch', inputs: inputs.transform_values(&:to_json) }
end
it_behaves_like 'creating a succesful pipeline'
end
end
context 'when triggering a pipeline from a trigger token' do
let!(:token) { trigger_token }
it_behaves_like 'sending request using inputs'
end
context 'when triggered from another running job' do
let!(:token) { create(:ci_build, :running, project: project, user: user).token }
it_behaves_like 'sending request using inputs'
end
end
end
describe 'GET /projects/:id/triggers' do
......
......@@ -45,6 +45,33 @@
end
end
shared_examples 'accepting inputs' do
let(:inputs) do
{
deploy_strategy: 'blue-green',
job_stage: 'deploy',
test_script: ['echo "test"'],
test_rules: [
{ if: '$CI_PIPELINE_SOURCE == "web"' }
]
}
end
before do
stub_ci_pipeline_yaml_file(
File.read(Rails.root.join('spec/lib/gitlab/ci/config/yaml/fixtures/complex-included-ci.yml'))
)
end
it 'triggers a pipeline using inputs' do
expect { result }.to change { Ci::Pipeline.count }.by(1)
expect(result.payload[:pipeline].builds.map(&:name)).to contain_exactly(
'my-job-build 1/2', 'my-job-build 2/2', 'my-job-test', 'my-job-deploy'
)
end
end
context 'with a trigger token' do
let(:trigger) { create(:ci_trigger, project: project, owner: user) }
......@@ -150,6 +177,12 @@
expect(result).to be_nil
end
end
context 'when using inputs' do
let(:params) { { token: trigger.token, ref: 'master', inputs: inputs } }
it_behaves_like 'accepting inputs'
end
end
context 'with a pipeline job token' do
......@@ -253,6 +286,12 @@
expect(result).to be_nil
end
end
context 'when using inputs' do
let(:params) { { token: job.token, ref: 'master', inputs: inputs } }
it_behaves_like 'accepting inputs'
end
end
end
end
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册