diff options
Diffstat (limited to 'spec/requests/api/ci')
-rw-r--r-- | spec/requests/api/ci/job_artifacts_spec.rb | 15 | ||||
-rw-r--r-- | spec/requests/api/ci/jobs_spec.rb | 24 | ||||
-rw-r--r-- | spec/requests/api/ci/resource_groups_spec.rb | 30 | ||||
-rw-r--r-- | spec/requests/api/ci/runner/jobs_artifacts_spec.rb | 160 | ||||
-rw-r--r-- | spec/requests/api/ci/runner/jobs_request_post_spec.rb | 14 | ||||
-rw-r--r-- | spec/requests/api/ci/runner/jobs_trace_spec.rb | 2 | ||||
-rw-r--r-- | spec/requests/api/ci/runners_spec.rb | 11 | ||||
-rw-r--r-- | spec/requests/api/ci/secure_files_spec.rb | 22 |
8 files changed, 198 insertions, 80 deletions
diff --git a/spec/requests/api/ci/job_artifacts_spec.rb b/spec/requests/api/ci/job_artifacts_spec.rb index 68b44bb89e0..1dd1ca4e115 100644 --- a/spec/requests/api/ci/job_artifacts_spec.rb +++ b/spec/requests/api/ci/job_artifacts_spec.rb @@ -263,6 +263,9 @@ RSpec.describe API::Ci::JobArtifacts do 'Content-Disposition' => %q(attachment; filename="ci_build_artifacts.zip"; filename*=UTF-8''ci_build_artifacts.zip) } end + let(:expected_params) { { artifact_size: job.artifacts_file.size } } + let(:subject_proc) { proc { subject } } + it 'returns specific job artifacts' do subject @@ -270,6 +273,9 @@ RSpec.describe API::Ci::JobArtifacts do expect(response.headers.to_h).to include(download_headers) expect(response.body).to match_file(job.artifacts_file.file.file) end + + it_behaves_like 'storing arguments in the application context' + it_behaves_like 'not executing any extra queries for the application context' end context 'normal authentication' do @@ -558,7 +564,8 @@ RSpec.describe API::Ci::JobArtifacts do expect(response).to have_gitlab_http_status(:ok) expect(response.headers.to_h) .to include('Content-Type' => 'application/json', - 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/) + 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/, + 'Gitlab-Workhorse-Detect-Content-Type' => 'true') end end @@ -628,7 +635,8 @@ RSpec.describe API::Ci::JobArtifacts do expect(response).to have_gitlab_http_status(:ok) expect(response.headers.to_h) .to include('Content-Type' => 'application/json', - 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/) + 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/, + 'Gitlab-Workhorse-Detect-Content-Type' => 'true') expect(response.parsed_body).to be_empty end end @@ -646,7 +654,8 @@ RSpec.describe API::Ci::JobArtifacts do expect(response).to have_gitlab_http_status(:ok) expect(response.headers.to_h) .to include('Content-Type' => 'application/json', - 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/) + 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/, + 'Gitlab-Workhorse-Detect-Content-Type' => 'true') end end diff --git a/spec/requests/api/ci/jobs_spec.rb b/spec/requests/api/ci/jobs_spec.rb index d3820e4948e..4bd9f81fd1d 100644 --- a/spec/requests/api/ci/jobs_spec.rb +++ b/spec/requests/api/ci/jobs_spec.rb @@ -471,7 +471,7 @@ RSpec.describe API::Ci::Jobs do end context 'authorized user' do - context 'when trace is in ObjectStorage' do + context 'when log is in ObjectStorage' do let!(:job) { create(:ci_build, :trace_artifact, pipeline: pipeline) } let(:url) { 'http://object-storage/trace' } let(:file_path) { expand_fixture_path('trace/sample_trace') } @@ -485,49 +485,49 @@ RSpec.describe API::Ci::Jobs do end end - it 'returns specific job trace' do + it 'returns specific job logs' do expect(response).to have_gitlab_http_status(:ok) expect(response.body).to eq(job.trace.raw) end end - context 'when trace is artifact' do + context 'when log is artifact' do let(:job) { create(:ci_build, :trace_artifact, pipeline: pipeline) } - it 'returns specific job trace' do + it 'returns specific job log' do expect(response).to have_gitlab_http_status(:ok) expect(response.body).to eq(job.trace.raw) end end - context 'when live trace and uploadless trace artifact' do + context 'when incremental logging and uploadless log artifact' do let(:job) { create(:ci_build, :trace_live, :unarchived_trace_artifact, pipeline: pipeline) } - it 'returns specific job trace' do + it 'returns specific job log' do expect(response).to have_gitlab_http_status(:ok) expect(response.body).to eq(job.trace.raw) end end - context 'when trace is live' do + context 'when log is incremental' do let(:job) { create(:ci_build, :trace_live, pipeline: pipeline) } - it 'returns specific job trace' do + it 'returns specific job log' do expect(response).to have_gitlab_http_status(:ok) expect(response.body).to eq(job.trace.raw) end end - context 'when no trace' do + context 'when no log' do let(:job) { create(:ci_build, pipeline: pipeline) } - it 'returns empty trace' do + it 'returns empty log' do expect(response).to have_gitlab_http_status(:ok) expect(response.body).to be_empty end end - context 'when trace artifact record exists with no stored file' do + context 'when log artifact record exists with no stored file' do let(:job) { create(:ci_build, pipeline: pipeline) } before do @@ -544,7 +544,7 @@ RSpec.describe API::Ci::Jobs do context 'unauthorized user' do let(:api_user) { nil } - it 'does not return specific job trace' do + it 'does not return specific job log' do expect(response).to have_gitlab_http_status(:unauthorized) end end diff --git a/spec/requests/api/ci/resource_groups_spec.rb b/spec/requests/api/ci/resource_groups_spec.rb index f5b68557a0d..864c363e6d3 100644 --- a/spec/requests/api/ci/resource_groups_spec.rb +++ b/spec/requests/api/ci/resource_groups_spec.rb @@ -9,6 +9,36 @@ RSpec.describe API::Ci::ResourceGroups do let(:user) { developer } + describe 'GET /projects/:id/resource_groups' do + subject { get api("/projects/#{project.id}/resource_groups", user) } + + let!(:resource_groups) { create_list(:ci_resource_group, 3, project: project) } + + it 'returns all resource groups for this project', :aggregate_failures do + subject + + expect(response).to have_gitlab_http_status(:ok) + expect(response).to include_pagination_headers + resource_groups.each_index do |i| + expect(json_response[i]['id']).to eq(resource_groups[i].id) + expect(json_response[i]['key']).to eq(resource_groups[i].key) + expect(json_response[i]['process_mode']).to eq(resource_groups[i].process_mode) + expect(Time.parse(json_response[i]['created_at'])).to be_like_time(resource_groups[i].created_at) + expect(Time.parse(json_response[i]['updated_at'])).to be_like_time(resource_groups[i].updated_at) + end + end + + context 'when user is reporter' do + let(:user) { reporter } + + it 'returns forbidden' do + subject + + expect(response).to have_gitlab_http_status(:forbidden) + end + end + end + describe 'GET /projects/:id/resource_groups/:key' do subject { get api("/projects/#{project.id}/resource_groups/#{key}", user) } diff --git a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb index f627f207d98..5767fa4326e 100644 --- a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb +++ b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb @@ -7,8 +7,20 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do include RedisHelpers include WorkhorseHelpers + let_it_be_with_reload(:parent_group) { create(:group) } + let_it_be_with_reload(:group) { create(:group, parent: parent_group) } + let_it_be_with_reload(:project) { create(:project, namespace: group, shared_runners_enabled: false) } + + let_it_be(:pipeline) { create(:ci_pipeline, project: project, ref: 'master') } + let_it_be(:runner) { create(:ci_runner, :project, projects: [project]) } + let_it_be(:user) { create(:user) } + let(:registration_token) { 'abcdefg123456' } + before_all do + project.add_developer(user) + end + before do stub_feature_flags(ci_enable_live_trace: true) stub_gitlab_calls @@ -17,12 +29,6 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do end describe '/api/v4/jobs' do - let(:parent_group) { create(:group) } - let(:group) { create(:group, parent: parent_group) } - let(:project) { create(:project, namespace: group, shared_runners_enabled: false) } - let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master') } - let(:runner) { create(:ci_runner, :project, projects: [project]) } - let(:user) { create(:user) } let(:job) do create(:ci_build, :artifacts, :extended_options, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) @@ -571,14 +577,21 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do context 'when artifact_type is archive' do context 'when artifact_format is zip' do + subject(:request) { upload_artifacts(file_upload, headers_with_token, params) } + let(:params) { { artifact_type: :archive, artifact_format: :zip } } + let(:expected_params) { { artifact_size: job.reload.artifacts_size } } + let(:subject_proc) { proc { subject } } it 'stores junit test report' do - upload_artifacts(file_upload, headers_with_token, params) + subject expect(response).to have_gitlab_http_status(:created) expect(job.reload.job_artifacts_archive).not_to be_nil end + + it_behaves_like 'storing arguments in the application context' + it_behaves_like 'not executing any extra queries for the application context' end context 'when artifact_format is gzip' do @@ -817,25 +830,23 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do end context 'when job has artifacts' do - let(:job) { create(:ci_build) } + let(:job) { create(:ci_build, pipeline: pipeline, user: user) } let(:store) { JobArtifactUploader::Store::LOCAL } before do create(:ci_job_artifact, :archive, file_store: store, job: job) end - context 'when using job token' do + shared_examples 'successful artifact download' do context 'when artifacts are stored locally' do let(:download_headers) do { 'Content-Transfer-Encoding' => 'binary', 'Content-Disposition' => %q(attachment; filename="ci_build_artifacts.zip"; filename*=UTF-8''ci_build_artifacts.zip) } end - before do + it 'downloads artifacts' do download_artifact - end - it 'download artifacts' do expect(response).to have_gitlab_http_status(:ok) expect(response.headers.to_h).to include download_headers end @@ -843,26 +854,20 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do context 'when artifacts are stored remotely' do let(:store) { JobArtifactUploader::Store::REMOTE } - let!(:job) { create(:ci_build) } context 'when proxy download is being used' do - before do + it 'uses workhorse send-url' do download_artifact(direct_download: false) - end - it 'uses workhorse send-url' do expect(response).to have_gitlab_http_status(:ok) - expect(response.headers.to_h).to include( - 'Gitlab-Workhorse-Send-Data' => /send-url:/) + expect(response.headers.to_h).to include('Gitlab-Workhorse-Send-Data' => /send-url:/) end end context 'when direct download is being used' do - before do + it 'receives redirect for downloading artifacts' do download_artifact(direct_download: true) - end - it 'receive redirect for downloading artifacts' do expect(response).to have_gitlab_http_status(:found) expect(response.headers).to include('Location') end @@ -870,16 +875,119 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do end end - context 'when using runnners token' do - let(:token) { job.project.runners_token } + shared_examples 'forbidden request' do + it 'responds with forbidden' do + download_artifact + + expect(response).to have_gitlab_http_status(:forbidden) + end + end + + context 'when using job token' do + let(:token) { job.token } + + it_behaves_like 'successful artifact download' + + context 'when the job is no longer running' do + before do + job.success! + end + + it_behaves_like 'successful artifact download' + end + end + + context 'when using token belonging to the dependent job' do + let!(:dependent_job) { create(:ci_build, :running, :dependent, user: user, pipeline: pipeline) } + let!(:job) { dependent_job.all_dependencies.first } + + let(:token) { dependent_job.token } + + it_behaves_like 'successful artifact download' + + context 'when the dependent job is no longer running' do + before do + dependent_job.success! + end + + it_behaves_like 'forbidden request' + end + end + + context 'when using token belonging to another job created by another project member' do + let!(:ci_build) { create(:ci_build, :running, :dependent, user: user, pipeline: pipeline) } + let!(:job) { ci_build.all_dependencies.first } + + let!(:another_dev) { create(:user) } + + let(:token) { ci_build.token } before do - download_artifact + project.add_developer(another_dev) + ci_build.update!(user: another_dev) end - it 'responds with forbidden' do - expect(response).to have_gitlab_http_status(:forbidden) + it_behaves_like 'successful artifact download' + end + + context 'when using token belonging to a pending dependent job' do + let!(:ci_build) { create(:ci_build, :pending, :dependent, user: user, project: project, pipeline: pipeline) } + let!(:job) { ci_build.all_dependencies.first } + + let(:token) { ci_build.token } + + it_behaves_like 'forbidden request' + end + + context 'when using a token from a cross pipeline build' do + let!(:ci_build) { create(:ci_build, :pending, :dependent, user: user, project: project, pipeline: pipeline) } + let!(:job) { ci_build.all_dependencies.first } + + let!(:options) do + { + cross_dependencies: [ + { + pipeline: pipeline.id, + job: job.name, + artifacts: true + } + ] + + } end + + let!(:cross_pipeline) { create(:ci_pipeline, project: project, child_of: pipeline) } + let!(:cross_pipeline_build) { create(:ci_build, :running, project: project, user: user, options: options, pipeline: cross_pipeline) } + + let(:token) { cross_pipeline_build.token } + + before do + job.success! + end + + it_behaves_like 'successful artifact download' + end + + context 'when using a token from an unrelated project' do + let!(:ci_build) { create(:ci_build, :running, :dependent, user: user, project: project, pipeline: pipeline) } + let!(:job) { ci_build.all_dependencies.first } + + let!(:unrelated_ci_build) { create(:ci_build, :running, user: create(:user)) } + let(:token) { unrelated_ci_build.token } + + it_behaves_like 'forbidden request' + end + + context 'when using runnners token' do + let(:token) { job.project.runners_token } + + it_behaves_like 'forbidden request' + end + + context 'when using an invalid token' do + let(:token) { 'invalid-token' } + + it_behaves_like 'forbidden request' end end diff --git a/spec/requests/api/ci/runner/jobs_request_post_spec.rb b/spec/requests/api/ci/runner/jobs_request_post_spec.rb index a662c77e5a2..dbc5f0e74e2 100644 --- a/spec/requests/api/ci/runner/jobs_request_post_spec.rb +++ b/spec/requests/api/ci/runner/jobs_request_post_spec.rb @@ -496,15 +496,15 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do job2.success end - it 'returns dependent jobs' do + it 'returns dependent jobs with the token of the test job' do request_job expect(response).to have_gitlab_http_status(:created) expect(json_response['id']).to eq(test_job.id) expect(json_response['dependencies'].count).to eq(2) expect(json_response['dependencies']).to include( - { 'id' => job.id, 'name' => job.name, 'token' => job.token }, - { 'id' => job2.id, 'name' => job2.name, 'token' => job2.token }) + { 'id' => job.id, 'name' => job.name, 'token' => test_job.token }, + { 'id' => job2.id, 'name' => job2.name, 'token' => test_job.token }) end describe 'preloading job_artifacts_archive' do @@ -526,14 +526,14 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do job.success end - it 'returns dependent jobs' do + it 'returns dependent jobs with the token of the test job' do request_job expect(response).to have_gitlab_http_status(:created) expect(json_response['id']).to eq(test_job.id) expect(json_response['dependencies'].count).to eq(1) expect(json_response['dependencies']).to include( - { 'id' => job.id, 'name' => job.name, 'token' => job.token, + { 'id' => job.id, 'name' => job.name, 'token' => test_job.token, 'artifacts_file' => { 'filename' => 'ci_build_artifacts.zip', 'size' => 107464 } }) end end @@ -552,13 +552,13 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do job2.success end - it 'returns dependent jobs' do + it 'returns dependent jobs with the token of the test job' do request_job expect(response).to have_gitlab_http_status(:created) expect(json_response['id']).to eq(test_job.id) expect(json_response['dependencies'].count).to eq(1) - expect(json_response['dependencies'][0]).to include('id' => job2.id, 'name' => job2.name, 'token' => job2.token) + expect(json_response['dependencies'][0]).to include('id' => job2.id, 'name' => job2.name, 'token' => test_job.token) end end diff --git a/spec/requests/api/ci/runner/jobs_trace_spec.rb b/spec/requests/api/ci/runner/jobs_trace_spec.rb index d6928969beb..c3c074d80d9 100644 --- a/spec/requests/api/ci/runner/jobs_trace_spec.rb +++ b/spec/requests/api/ci/runner/jobs_trace_spec.rb @@ -272,7 +272,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_trace_chunks do it { expect(response).to have_gitlab_http_status(:forbidden) } end - context 'when the job trace is too big' do + context 'when the job log is too big' do before do project.actual_limits.update!(ci_jobs_trace_size_limit: 1) end diff --git a/spec/requests/api/ci/runners_spec.rb b/spec/requests/api/ci/runners_spec.rb index d6ebc197ab0..3000bdc2ce7 100644 --- a/spec/requests/api/ci/runners_spec.rb +++ b/spec/requests/api/ci/runners_spec.rb @@ -274,7 +274,7 @@ RSpec.describe API::Ci::Runners do expect(response).to have_gitlab_http_status(:ok) expect(json_response['description']).to eq(shared_runner.description) expect(json_response['maximum_timeout']).to be_nil - expect(json_response['status']).to eq("not_connected") + expect(json_response['status']).to eq('never_contacted') expect(json_response['active']).to eq(true) expect(json_response['paused']).to eq(false) end @@ -1216,15 +1216,6 @@ RSpec.describe API::Ci::Runners do end end end - - it 'enables a instance type runner' do - expect do - post api("/projects/#{project.id}/runners", admin), params: { runner_id: shared_runner.id } - end.to change { project.runners.count }.by(1) - - expect(shared_runner.reload).not_to be_instance_type - expect(response).to have_gitlab_http_status(:created) - end end it 'raises an error when no runner_id param is provided' do diff --git a/spec/requests/api/ci/secure_files_spec.rb b/spec/requests/api/ci/secure_files_spec.rb index 6de6d1ef222..6f16fe5460b 100644 --- a/spec/requests/api/ci/secure_files_spec.rb +++ b/spec/requests/api/ci/secure_files_spec.rb @@ -143,7 +143,6 @@ RSpec.describe API::Ci::SecureFiles do expect(response).to have_gitlab_http_status(:ok) expect(json_response['name']).to eq(secure_file.name) - expect(json_response['permissions']).to eq(secure_file.permissions) end it 'responds with 404 Not Found if requesting non-existing secure file' do @@ -159,7 +158,6 @@ RSpec.describe API::Ci::SecureFiles do expect(response).to have_gitlab_http_status(:ok) expect(json_response['name']).to eq(secure_file.name) - expect(json_response['permissions']).to eq(secure_file.permissions) end end @@ -250,12 +248,11 @@ RSpec.describe API::Ci::SecureFiles do context 'authenticated user with admin permissions' do it 'creates a secure file' do expect do - post api("/projects/#{project.id}/secure_files", maintainer), params: file_params.merge(permissions: 'execute') + post api("/projects/#{project.id}/secure_files", maintainer), params: file_params end.to change {project.secure_files.count}.by(1) expect(response).to have_gitlab_http_status(:created) expect(json_response['name']).to eq('upload-keystore.jks') - expect(json_response['permissions']).to eq('execute') expect(json_response['checksum']).to eq(secure_file.checksum) expect(json_response['checksum_algorithm']).to eq('sha256') @@ -267,14 +264,6 @@ RSpec.describe API::Ci::SecureFiles do expect(Time.parse(json_response['created_at'])).to be_like_time(secure_file.created_at) end - it 'creates a secure file with read_only permissions by default' do - expect do - post api("/projects/#{project.id}/secure_files", maintainer), params: file_params - end.to change {project.secure_files.count}.by(1) - - expect(json_response['permissions']).to eq('read_only') - end - it 'uploads and downloads a secure file' do post api("/projects/#{project.id}/secure_files", maintainer), params: file_params @@ -327,15 +316,6 @@ RSpec.describe API::Ci::SecureFiles do expect(json_response['message']['name']).to include('has already been taken') end - it 'returns an error when an unexpected permission is supplied' do - expect do - post api("/projects/#{project.id}/secure_files", maintainer), params: file_params.merge(permissions: 'foo') - end.not_to change { project.secure_files.count } - - expect(response).to have_gitlab_http_status(:bad_request) - expect(json_response['error']).to eq('permissions does not have a valid value') - end - it 'returns an error when an unexpected validation failure happens' do allow_next_instance_of(Ci::SecureFile) do |instance| allow(instance).to receive(:valid?).and_return(false) |