Commit b669e48a authored by Avielle Wolfe's avatar Avielle Wolfe Committed by Sean McGivern

Add job_variables_attributes to play build API

This will allow users to define custom variables when triggering manual
jobs via the REST API, in the same way that they can do so when
triggering manual jobs in the UI.

Changelog: added
parent 8449e79f
...@@ -822,16 +822,38 @@ Triggers a manual action to start a job. ...@@ -822,16 +822,38 @@ Triggers a manual action to start a job.
POST /projects/:id/jobs/:job_id/play POST /projects/:id/jobs/:job_id/play
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
|-----------|----------------|------------------------|-------------| |----------------------------|-----------------|------------------------|-------------|
| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `job_id` | integer | **{check-circle}** Yes | ID of a job. | | `job_id` | integer | **{check-circle}** Yes | ID of a job. |
| `job_variables_attributes` | array of hashes | **{dotted-circle}** No | An array containing the custom variables available to the job. [Introduced in](https://gitlab.com/gitlab-org/gitlab/-/issues/37267) GitLab 14.9. |
Example request:
```shell ```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/1/play" curl --request POST "https://gitlab.example.com/api/v4/projects/1/jobs/1/play
--header "PRIVATE-TOKEN: <your_access_token>"
--data @variables.json
``` ```
Example of response `@variables.json` is structured like:
```json
{
"job_variables_attributes": [
{
"key": "TEST_VAR_1",
"value": "test1"
},
{
"key": "TEST_VAR_2",
"value": "test2"
}
]
}
```
Example response:
```json ```json
{ {
......
...@@ -144,6 +144,11 @@ module API ...@@ -144,6 +144,11 @@ module API
end end
params do params do
requires :job_id, type: Integer, desc: 'The ID of a Job' requires :job_id, type: Integer, desc: 'The ID of a Job'
optional :job_variables_attributes, type: Array,
desc: 'User defined variables that will be included when running the job' do
requires :key, type: String, desc: 'The name of the variable'
requires :value, type: String, desc: 'The value of the variable'
end
end end
post ':id/jobs/:job_id/play', urgency: :low, feature_category: :continuous_integration do post ':id/jobs/:job_id/play', urgency: :low, feature_category: :continuous_integration do
...@@ -155,7 +160,7 @@ module API ...@@ -155,7 +160,7 @@ module API
bad_request!("Unplayable Job") unless job.playable? bad_request!("Unplayable Job") unless job.playable?
job.play(current_user) job.play(current_user, params[:job_variables_attributes])
status 200 status 200
......
...@@ -707,12 +707,14 @@ RSpec.describe API::Ci::Jobs do ...@@ -707,12 +707,14 @@ RSpec.describe API::Ci::Jobs do
end end
describe 'POST /projects/:id/jobs/:job_id/play' do describe 'POST /projects/:id/jobs/:job_id/play' do
let(:params) { {} }
before do before do
post api("/projects/#{project.id}/jobs/#{job.id}/play", api_user) post api("/projects/#{project.id}/jobs/#{job.id}/play", api_user), params: params
end end
context 'on a playable job' do context 'on a playable job' do
let_it_be(:job) { create(:ci_bridge, :playable, pipeline: pipeline, downstream: project) } let_it_be(:job) { create(:ci_build, :manual, project: project, pipeline: pipeline) }
before do before do
project.add_developer(user) project.add_developer(user)
...@@ -720,6 +722,8 @@ RSpec.describe API::Ci::Jobs do ...@@ -720,6 +722,8 @@ RSpec.describe API::Ci::Jobs do
context 'when user is authorized to trigger a manual action' do context 'when user is authorized to trigger a manual action' do
context 'that is a bridge' do context 'that is a bridge' do
let_it_be(:job) { create(:ci_bridge, :playable, pipeline: pipeline, downstream: project) }
it 'plays the job' do it 'plays the job' do
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(json_response['user']['id']).to eq(user.id) expect(json_response['user']['id']).to eq(user.id)
...@@ -729,8 +733,6 @@ RSpec.describe API::Ci::Jobs do ...@@ -729,8 +733,6 @@ RSpec.describe API::Ci::Jobs do
end end
context 'that is a build' do context 'that is a build' do
let_it_be(:job) { create(:ci_build, :manual, project: project, pipeline: pipeline) }
it 'plays the job' do it 'plays the job' do
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(json_response['user']['id']).to eq(user.id) expect(json_response['user']['id']).to eq(user.id)
...@@ -738,6 +740,47 @@ RSpec.describe API::Ci::Jobs do ...@@ -738,6 +740,47 @@ RSpec.describe API::Ci::Jobs do
expect(job.reload).to be_pending expect(job.reload).to be_pending
end end
end end
context 'when the user provides valid custom variables' do
let(:params) { { job_variables_attributes: [{ key: 'TEST_VAR', value: 'test' }] } }
it 'applies the variables to the job' do
expect(response).to have_gitlab_http_status(:ok)
expect(job.reload).to be_pending
expect(job.job_variables.map(&:key)).to contain_exactly('TEST_VAR')
expect(job.job_variables.map(&:value)).to contain_exactly('test')
end
end
context 'when the user provides a variable without a key' do
let(:params) { { job_variables_attributes: [{ value: 'test' }] } }
it 'reports that the key is missing' do
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('job_variables_attributes[0][key] is missing')
expect(job.reload).to be_manual
end
end
context 'when the user provides a variable without a value' do
let(:params) { { job_variables_attributes: [{ key: 'TEST_VAR' }] } }
it 'reports that the value is missing' do
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('job_variables_attributes[0][value] is missing')
expect(job.reload).to be_manual
end
end
context 'when the user provides both valid and invalid variables' do
let(:params) { { job_variables_attributes: [{ key: 'TEST_VAR', value: 'test' }, { value: 'test2' }] } }
it 'reports the invalid variables and does not run the job' do
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('job_variables_attributes[1][key] is missing')
expect(job.reload).to be_manual
end
end
end end
context 'when user is not authorized to trigger a manual action' do context 'when user is not authorized to trigger a manual action' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment