2019-10-29 00:06:10 +00:00
# frozen_string_literal: true
2016-08-18 06:50:01 +00:00
require 'spec_helper'
2020-06-24 06:09:01 +00:00
RSpec . describe API :: Lint do
2016-08-29 13:07:19 +00:00
describe 'POST /ci/lint' do
2016-08-24 08:16:58 +00:00
context 'with valid .gitlab-ci.yaml content' do
2016-08-30 13:38:36 +00:00
let ( :yaml_content ) do
File . read ( Rails . root . join ( 'spec/support/gitlab_stubs/gitlab_ci.yml' ) )
end
2020-11-18 03:09:21 +00:00
it 'passes validation without warnings or errors' do
2018-12-17 22:52:17 +00:00
post api ( '/ci/lint' ) , params : { content : yaml_content }
2016-08-24 12:36:14 +00:00
2020-02-25 12:08:48 +00:00
expect ( response ) . to have_gitlab_http_status ( :ok )
2016-08-24 12:36:14 +00:00
expect ( json_response ) . to be_an Hash
expect ( json_response [ 'status' ] ) . to eq ( 'valid' )
2020-11-18 03:09:21 +00:00
expect ( json_response [ 'warnings' ] ) . to eq ( [ ] )
2016-08-30 11:03:29 +00:00
expect ( json_response [ 'errors' ] ) . to eq ( [ ] )
2016-08-18 06:50:01 +00:00
end
2020-09-25 18:09:46 +00:00
it 'outputs expanded yaml content' do
post api ( '/ci/lint' ) , params : { content : yaml_content , include_merged_yaml : true }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to have_key ( 'merged_yaml' )
end
2016-08-18 06:50:01 +00:00
end
2016-08-23 10:12:21 +00:00
2020-11-18 03:09:21 +00:00
context 'with valid .gitlab-ci.yaml with warnings' do
let ( :yaml_content ) { { job : { script : 'ls' , rules : [ { when : 'always' } ] } } . to_yaml }
it 'passes validation but returns warnings' do
post api ( '/ci/lint' ) , params : { content : yaml_content }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response [ 'status' ] ) . to eq ( 'valid' )
expect ( json_response [ 'warnings' ] ) . not_to be_empty
expect ( json_response [ 'status' ] ) . to eq ( 'valid' )
expect ( json_response [ 'errors' ] ) . to eq ( [ ] )
end
end
2016-08-26 10:49:59 +00:00
context 'with an invalid .gitlab_ci.yml' do
2020-09-25 18:09:46 +00:00
context 'with invalid syntax' do
let ( :yaml_content ) { 'invalid content' }
2016-08-23 10:12:21 +00:00
2020-09-25 18:09:46 +00:00
it 'responds with errors about invalid syntax' do
post api ( '/ci/lint' ) , params : { content : yaml_content }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response [ 'status' ] ) . to eq ( 'invalid' )
2020-11-18 03:09:21 +00:00
expect ( json_response [ 'warnings' ] ) . to eq ( [ ] )
2020-09-25 18:09:46 +00:00
expect ( json_response [ 'errors' ] ) . to eq ( [ 'Invalid configuration format' ] )
end
it 'outputs expanded yaml content' do
post api ( '/ci/lint' ) , params : { content : yaml_content , include_merged_yaml : true }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to have_key ( 'merged_yaml' )
end
2016-08-24 12:36:14 +00:00
end
2020-09-25 18:09:46 +00:00
context 'with invalid configuration' do
2021-01-19 09:10:32 +00:00
let ( :yaml_content ) { '{ image: "ruby:2.7", services: ["postgres"], invalid }' }
2016-08-24 12:36:14 +00:00
2020-09-25 18:09:46 +00:00
it 'responds with errors about invalid configuration' do
post api ( '/ci/lint' ) , params : { content : yaml_content }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response [ 'status' ] ) . to eq ( 'invalid' )
2020-11-18 03:09:21 +00:00
expect ( json_response [ 'warnings' ] ) . to eq ( [ ] )
2021-01-19 09:10:32 +00:00
expect ( json_response [ 'errors' ] ) . to eq ( [ 'jobs invalid config should implement a script: or a trigger: keyword' , 'jobs config should contain at least one visible job' ] )
2020-09-25 18:09:46 +00:00
end
it 'outputs expanded yaml content' do
post api ( '/ci/lint' ) , params : { content : yaml_content , include_merged_yaml : true }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to have_key ( 'merged_yaml' )
end
2016-08-23 10:12:21 +00:00
end
end
2016-08-26 10:49:59 +00:00
context 'without the content parameter' do
2016-08-29 13:07:19 +00:00
it 'responds with validation error about missing content' do
post api ( '/ci/lint' )
2016-08-23 10:12:21 +00:00
2020-02-25 12:08:48 +00:00
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2016-08-26 10:49:59 +00:00
expect ( json_response [ 'error' ] ) . to eq ( 'content is missing' )
2016-08-23 10:12:21 +00:00
end
end
2016-08-18 06:50:01 +00:00
end
2020-10-05 12:08:47 +00:00
describe 'GET /projects/:id/ci/lint' do
subject ( :ci_lint ) { get api ( " /projects/ #{ project . id } /ci/lint " , api_user ) , params : { dry_run : dry_run } }
let ( :project ) { create ( :project , :repository ) }
let ( :dry_run ) { nil }
2020-11-18 03:09:21 +00:00
RSpec . shared_examples 'valid config with warnings' do
it 'passes validation with warnings' do
ci_lint
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response [ 'valid' ] ) . to eq ( true )
expect ( json_response [ 'errors' ] ) . to eq ( [ ] )
expect ( json_response [ 'warnings' ] ) . not_to be_empty
end
end
RSpec . shared_examples 'valid config without warnings' do
2020-10-05 12:08:47 +00:00
it 'passes validation' do
ci_lint
included_config = YAML . safe_load ( included_content , [ Symbol ] )
root_config = YAML . safe_load ( yaml_content , [ Symbol ] )
expected_yaml = included_config . merge ( root_config ) . except ( :include ) . to_yaml
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to be_an Hash
expect ( json_response [ 'merged_yaml' ] ) . to eq ( expected_yaml )
expect ( json_response [ 'valid' ] ) . to eq ( true )
2020-11-18 03:09:21 +00:00
expect ( json_response [ 'warnings' ] ) . to eq ( [ ] )
2020-10-05 12:08:47 +00:00
expect ( json_response [ 'errors' ] ) . to eq ( [ ] )
end
end
RSpec . shared_examples 'invalid config' do
it 'responds with errors about invalid configuration' do
ci_lint
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response [ 'merged_yaml' ] ) . to eq ( yaml_content )
expect ( json_response [ 'valid' ] ) . to eq ( false )
2020-11-18 03:09:21 +00:00
expect ( json_response [ 'warnings' ] ) . to eq ( [ ] )
2020-10-05 12:08:47 +00:00
expect ( json_response [ 'errors' ] ) . to eq ( [ 'jobs config should contain at least one visible job' ] )
end
end
context 'when unauthenticated' do
2020-10-06 12:08:38 +00:00
let_it_be ( :api_user ) { nil }
2020-10-05 12:08:47 +00:00
it 'returns authentication error' do
ci_lint
expect ( response ) . to have_gitlab_http_status ( :not_found )
end
end
2020-10-06 12:08:38 +00:00
context 'when authenticated as non-member' do
let_it_be ( :api_user ) { create ( :user ) }
let ( :yaml_content ) do
{ include : { local : 'another-gitlab-ci.yml' } , test : { stage : 'test' , script : 'echo 1' } } . to_yaml
end
context 'when project is private' do
before do
project . update! ( visibility_level : Gitlab :: VisibilityLevel :: PRIVATE )
stub_ci_pipeline_yaml_file ( yaml_content )
end
it 'returns authentication error' do
ci_lint
expect ( response ) . to have_gitlab_http_status ( :not_found )
end
end
context 'when project is public' do
before do
project . update! ( visibility_level : Gitlab :: VisibilityLevel :: PUBLIC )
end
context 'when running as dry run' do
let ( :dry_run ) { true }
before do
stub_ci_pipeline_yaml_file ( yaml_content )
end
it 'returns pipeline creation error' do
ci_lint
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response [ 'merged_yaml' ] ) . to eq ( nil )
expect ( json_response [ 'valid' ] ) . to eq ( false )
2020-11-18 03:09:21 +00:00
expect ( json_response [ 'warnings' ] ) . to eq ( [ ] )
2020-10-06 12:08:38 +00:00
expect ( json_response [ 'errors' ] ) . to eq ( [ 'Insufficient permissions to create a new pipeline' ] )
end
end
context 'when running static validation' do
let ( :dry_run ) { false }
let ( :included_content ) do
{ another_test : { stage : 'test' , script : 'echo 1' } } . to_yaml
end
before do
project . repository . create_file (
project . creator ,
'.gitlab-ci.yml' ,
yaml_content ,
message : 'Automatically created .gitlab-ci.yml' ,
branch_name : 'master'
)
project . repository . create_file (
project . creator ,
'another-gitlab-ci.yml' ,
included_content ,
message : 'Automatically created another-gitlab-ci.yml' ,
branch_name : 'master'
)
end
2020-11-18 03:09:21 +00:00
it_behaves_like 'valid config without warnings'
2020-10-06 12:08:38 +00:00
end
end
end
context 'when authenticated as project guest' do
let_it_be ( :api_user ) { create ( :user ) }
before do
project . add_guest ( api_user )
end
it 'returns authentication error' do
ci_lint
expect ( response ) . to have_gitlab_http_status ( :forbidden )
end
end
context 'when authenticated as project developer' do
let_it_be ( :api_user ) { create ( :user ) }
2020-10-05 12:08:47 +00:00
before do
project . add_developer ( api_user )
end
context 'with valid .gitlab-ci.yml content' do
let ( :yaml_content ) do
{ include : { local : 'another-gitlab-ci.yml' } , test : { stage : 'test' , script : 'echo 1' } } . to_yaml
end
let ( :included_content ) do
{ another_test : { stage : 'test' , script : 'echo 1' } } . to_yaml
end
before do
project . repository . create_file (
project . creator ,
'.gitlab-ci.yml' ,
yaml_content ,
message : 'Automatically created .gitlab-ci.yml' ,
branch_name : 'master'
)
project . repository . create_file (
project . creator ,
'another-gitlab-ci.yml' ,
included_content ,
message : 'Automatically created another-gitlab-ci.yml' ,
branch_name : 'master'
)
end
context 'when running as dry run' do
let ( :dry_run ) { true }
2020-11-18 03:09:21 +00:00
it_behaves_like 'valid config without warnings'
2020-10-05 12:08:47 +00:00
end
context 'when running static validation' do
let ( :dry_run ) { false }
2020-11-18 03:09:21 +00:00
it_behaves_like 'valid config without warnings'
end
context 'With warnings' do
let ( :yaml_content ) { { job : { script : 'ls' , rules : [ { when : 'always' } ] } } . to_yaml }
it_behaves_like 'valid config with warnings'
2020-10-05 12:08:47 +00:00
end
end
context 'with invalid .gitlab-ci.yml content' do
let ( :yaml_content ) do
{ image : 'ruby:2.7' , services : [ 'postgres' ] } . to_yaml
end
before do
stub_ci_pipeline_yaml_file ( yaml_content )
end
context 'when running as dry run' do
let ( :dry_run ) { true }
it_behaves_like 'invalid config'
end
context 'when running static validation' do
let ( :dry_run ) { false }
it_behaves_like 'invalid config'
end
end
end
end
2020-11-11 15:08:46 +00:00
describe 'POST /projects/:id/ci/lint' do
subject ( :ci_lint ) { post api ( " /projects/ #{ project . id } /ci/lint " , api_user ) , params : { dry_run : dry_run , content : yaml_content } }
let ( :project ) { create ( :project , :repository ) }
let ( :dry_run ) { nil }
let_it_be ( :api_user ) { create ( :user ) }
let_it_be ( :yaml_content ) do
{ include : { local : 'another-gitlab-ci.yml' } , test : { stage : 'test' , script : 'echo 1' } } . to_yaml
end
let_it_be ( :included_content ) do
{ another_test : { stage : 'test' , script : 'echo 1' } } . to_yaml
end
RSpec . shared_examples 'valid project config' do
it 'passes validation' do
ci_lint
included_config = YAML . safe_load ( included_content , [ Symbol ] )
root_config = YAML . safe_load ( yaml_content , [ Symbol ] )
expected_yaml = included_config . merge ( root_config ) . except ( :include ) . to_yaml
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to be_an Hash
expect ( json_response [ 'merged_yaml' ] ) . to eq ( expected_yaml )
expect ( json_response [ 'valid' ] ) . to eq ( true )
expect ( json_response [ 'errors' ] ) . to eq ( [ ] )
end
end
RSpec . shared_examples 'invalid project config' do
it 'responds with errors about invalid configuration' do
ci_lint
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response [ 'merged_yaml' ] ) . to eq ( yaml_content )
expect ( json_response [ 'valid' ] ) . to eq ( false )
expect ( json_response [ 'errors' ] ) . to eq ( [ 'jobs config should contain at least one visible job' ] )
end
end
context 'when unauthenticated' do
let_it_be ( :api_user ) { nil }
it 'returns authentication error' do
ci_lint
expect ( response ) . to have_gitlab_http_status ( :not_found )
end
end
context 'when authenticated as non-member' do
context 'when project is private' do
before do
project . update! ( visibility_level : Gitlab :: VisibilityLevel :: PRIVATE )
end
it 'returns authentication error' do
ci_lint
expect ( response ) . to have_gitlab_http_status ( :not_found )
end
end
context 'when project is public' do
before do
project . update! ( visibility_level : Gitlab :: VisibilityLevel :: PUBLIC )
end
context 'when running as dry run' do
let ( :dry_run ) { true }
it 'returns pipeline creation error' do
ci_lint
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response [ 'merged_yaml' ] ) . to eq ( nil )
expect ( json_response [ 'valid' ] ) . to eq ( false )
expect ( json_response [ 'errors' ] ) . to eq ( [ 'Insufficient permissions to create a new pipeline' ] )
end
end
context 'when running static validation' do
let ( :dry_run ) { false }
before do
project . repository . create_file (
project . creator ,
'another-gitlab-ci.yml' ,
included_content ,
message : 'Automatically created another-gitlab-ci.yml' ,
branch_name : 'master'
)
end
it_behaves_like 'valid project config'
end
end
end
context 'when authenticated as project guest' do
before do
project . add_guest ( api_user )
end
it 'returns authentication error' do
ci_lint
expect ( response ) . to have_gitlab_http_status ( :forbidden )
end
end
context 'when authenticated as project developer' do
before do
project . add_developer ( api_user )
end
context 'with valid .gitlab-ci.yml content' do
before do
project . repository . create_file (
project . creator ,
'another-gitlab-ci.yml' ,
included_content ,
message : 'Automatically created another-gitlab-ci.yml' ,
branch_name : 'master'
)
end
context 'when running as dry run' do
let ( :dry_run ) { true }
it_behaves_like 'valid project config'
end
context 'when running static validation' do
let ( :dry_run ) { false }
it_behaves_like 'valid project config'
end
end
context 'with invalid .gitlab-ci.yml content' do
let ( :yaml_content ) do
{ image : 'ruby:2.7' , services : [ 'postgres' ] } . to_yaml
end
context 'when running as dry run' do
let ( :dry_run ) { true }
it_behaves_like 'invalid project config'
end
context 'when running static validation' do
let ( :dry_run ) { false }
it_behaves_like 'invalid project config'
end
end
end
end
2016-08-18 06:50:01 +00:00
end