diff --git a/app/assets/javascripts/pages/ci/lints/ci_lint_editor.js b/app/assets/javascripts/pages/projects/ci/lints/ci_lint_editor.js similarity index 100% rename from app/assets/javascripts/pages/ci/lints/ci_lint_editor.js rename to app/assets/javascripts/pages/projects/ci/lints/ci_lint_editor.js diff --git a/app/assets/javascripts/pages/ci/lints/show/index.js b/app/assets/javascripts/pages/projects/ci/lints/create/index.js similarity index 100% rename from app/assets/javascripts/pages/ci/lints/show/index.js rename to app/assets/javascripts/pages/projects/ci/lints/create/index.js diff --git a/app/assets/javascripts/pages/projects/ci/lints/show/index.js b/app/assets/javascripts/pages/projects/ci/lints/show/index.js new file mode 100644 index 00000000000..8e8a843da0b --- /dev/null +++ b/app/assets/javascripts/pages/projects/ci/lints/show/index.js @@ -0,0 +1,3 @@ +import CILintEditor from '../ci_lint_editor'; + +document.addEventListener('DOMContentLoaded', () => new CILintEditor()); diff --git a/app/controllers/ci/lints_controller.rb b/app/controllers/ci/lints_controller.rb index e9bd1689a1e..738a6a5173e 100644 --- a/app/controllers/ci/lints_controller.rb +++ b/app/controllers/ci/lints_controller.rb @@ -4,20 +4,5 @@ module Ci def show end - - def create - @content = params[:content] - @error = Gitlab::Ci::YamlProcessor.validation_message(@content) - @status = @error.blank? - - if @error.blank? - @config_processor = Gitlab::Ci::YamlProcessor.new(@content) - @stages = @config_processor.stages - @builds = @config_processor.builds - @jobs = @config_processor.jobs - end - - render :show - end end end diff --git a/app/controllers/projects/ci/lints_controller.rb b/app/controllers/projects/ci/lints_controller.rb new file mode 100644 index 00000000000..47328504cd5 --- /dev/null +++ b/app/controllers/projects/ci/lints_controller.rb @@ -0,0 +1,31 @@ +class Projects::Ci::LintsController < Projects::ApplicationController + before_action :ensure_user_access + + def show + end + + def create + @content = params[:content] + @error = Gitlab::Ci::YamlProcessor.validation_message(@content, yaml_processor_options) + @status = @error.blank? + + if @error.blank? + @config_processor = Gitlab::Ci::YamlProcessor.new(@content, yaml_processor_options) + @stages = @config_processor.stages + @builds = @config_processor.builds + @jobs = @config_processor.jobs + end + + render :show + end + + private + + def yaml_processor_options + { project: @project, sha: project.repository.commit.sha } + end + + def ensure_user_access + return access_denied! unless can?(current_user, :create_pipeline, @project) + end +end diff --git a/app/views/ci/lints/show.html.haml b/app/views/ci/lints/show.html.haml index 3c0881caa06..2f8387dc762 100644 --- a/app/views/ci/lints/show.html.haml +++ b/app/views/ci/lints/show.html.haml @@ -1,27 +1,6 @@ - page_title "CI Lint" -- page_description "Validate your GitLab CI configuration file" -- content_for :library_javascripts do - = page_specific_javascript_tag('lib/ace.js') -%h2 Check your .gitlab-ci.yml - -.ci-linter - .row - = form_tag ci_lint_path, method: :post do - .form-group - .col-sm-12 - .file-holder - .js-file-title.file-title.clearfix - Content of .gitlab-ci.yml - #ci-editor.ci-editor= @content - = text_area_tag(:content, @content, class: 'hidden form-control span1', rows: 7, require: true) - .col-sm-12 - .pull-left.prepend-top-10 - = submit_tag('Validate', class: 'btn btn-success submit-yml') - .pull-right.prepend-top-10 - = button_tag('Clear', type: 'button', class: 'btn btn-default clear-yml') - - .row.prepend-top-20 - .col-sm-12 - .results.ci-template - = render partial: 'create' if defined?(@status) +.center + = image_tag 'illustrations/feature_moved.svg' + %h3 GitLab CI Linter has been moved + %p To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the "CI Lint" button. diff --git a/app/views/ci/lints/_create.html.haml b/app/views/projects/ci/lints/_create.html.haml similarity index 100% rename from app/views/ci/lints/_create.html.haml rename to app/views/projects/ci/lints/_create.html.haml diff --git a/app/views/projects/ci/lints/show.html.haml b/app/views/projects/ci/lints/show.html.haml new file mode 100644 index 00000000000..cf2a25ce844 --- /dev/null +++ b/app/views/projects/ci/lints/show.html.haml @@ -0,0 +1,27 @@ +- page_title "CI Lint" +- page_description "Validate your GitLab CI configuration file" +- content_for :library_javascripts do + = page_specific_javascript_tag('lib/ace.js') + +%h2 Check your .gitlab-ci.yml + +.ci-linter + .row + = form_tag project_ci_lint_path(@project), method: :post do + .form-group + .col-sm-12 + .file-holder + .js-file-title.file-title.clearfix + Content of .gitlab-ci.yml + #ci-editor.ci-editor= @content + = text_area_tag(:content, @content, class: 'hidden form-control span1', rows: 7, require: true) + .col-sm-12 + .pull-left.prepend-top-10 + = submit_tag('Validate', class: 'btn btn-success submit-yml') + .pull-right.prepend-top-10 + = button_tag('Clear', type: 'button', class: 'btn btn-default clear-yml') + + .row.prepend-top-20 + .col-sm-12 + .results.ci-template + = render partial: 'create' if defined?(@status) diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 3e6b3346787..c0ee81fe28d 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -10,6 +10,6 @@ "no-pipelines-svg-path" => image_path('illustrations/pipelines_pending.svg'), "can-create-pipeline" => can?(current_user, :create_pipeline, @project).to_s, "new-pipeline-path" => can?(current_user, :create_pipeline, @project) && new_project_pipeline_path(@project), - "ci-lint-path" => can?(current_user, :create_pipeline, @project) && ci_lint_path, + "ci-lint-path" => can?(current_user, :create_pipeline, @project) && project_ci_lint_path(@project), "reset-cache-path" => can?(current_user, :admin_pipeline, @project) && reset_cache_project_settings_ci_cd_path(@project) , "has-gitlab-ci" => (@project.has_ci? && @project.builds_enabled?).to_s } } diff --git a/changelogs/unreleased/43603-ci-lint-support.yml b/changelogs/unreleased/43603-ci-lint-support.yml new file mode 100644 index 00000000000..8e4a92c0287 --- /dev/null +++ b/changelogs/unreleased/43603-ci-lint-support.yml @@ -0,0 +1,5 @@ +--- +title: Move ci/lint under project's namespace +merge_request: 17729 +author: +type: added diff --git a/config/routes/ci.rb b/config/routes/ci.rb index 60c1724bc05..ebd321ed097 100644 --- a/config/routes/ci.rb +++ b/config/routes/ci.rb @@ -1,5 +1,5 @@ namespace :ci do - resource :lint, only: [:show, :create] + resource :lint, only: :show root to: redirect('') end diff --git a/config/routes/project.rb b/config/routes/project.rb index f50b9aded8d..656ba6834f2 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -423,6 +423,10 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do resource :repository, only: [:show], controller: :repository end + namespace :ci do + resource :lint, only: [:show, :create] + end + # Since both wiki and repository routing contains wildcard characters # its preferable to keep it below all other project routes draw :wiki diff --git a/lib/gitlab/ci/config.rb b/lib/gitlab/ci/config.rb index f7ff7ea212e..1c2e86cd1cb 100644 --- a/lib/gitlab/ci/config.rb +++ b/lib/gitlab/ci/config.rb @@ -4,7 +4,7 @@ module Gitlab # Base GitLab CI Configuration facade # class Config - def initialize(config) + def initialize(config, opts = {}) @config = Loader.new(config).load! @global = Entry::Global.new(@config) diff --git a/lib/gitlab/ci/yaml_processor.rb b/lib/gitlab/ci/yaml_processor.rb index bc2a6f98dae..e829f2a95f8 100644 --- a/lib/gitlab/ci/yaml_processor.rb +++ b/lib/gitlab/ci/yaml_processor.rb @@ -7,8 +7,8 @@ module Gitlab attr_reader :cache, :stages, :jobs - def initialize(config) - @ci_config = Gitlab::Ci::Config.new(config) + def initialize(config, opts = {}) + @ci_config = Gitlab::Ci::Config.new(config, opts) @config = @ci_config.to_hash unless @ci_config.valid? @@ -73,11 +73,11 @@ module Gitlab end end - def self.validation_message(content) + def self.validation_message(content, opts = {}) return 'Please provide content of .gitlab-ci.yml' if content.blank? begin - Gitlab::Ci::YamlProcessor.new(content) + Gitlab::Ci::YamlProcessor.new(content, opts) nil rescue ValidationError => e e.message diff --git a/spec/controllers/projects/ci/lints_controller_spec.rb b/spec/controllers/projects/ci/lints_controller_spec.rb new file mode 100644 index 00000000000..1249a5528a9 --- /dev/null +++ b/spec/controllers/projects/ci/lints_controller_spec.rb @@ -0,0 +1,123 @@ +require 'spec_helper' + +describe Projects::Ci::LintsController do + let(:project) { create(:project, :repository) } + let(:user) { create(:user) } + + before do + sign_in(user) + end + + describe 'GET #show' do + context 'with enough privileges' do + before do + project.add_developer(user) + + get :show, namespace_id: project.namespace, project_id: project + end + + it 'should be success' do + expect(response).to be_success + end + + it 'should render show page' do + expect(response).to render_template :show + end + + it 'should retrieve project' do + expect(assigns(:project)).to eq(project) + end + end + + context 'without enough privileges' do + before do + project.add_guest(user) + + get :show, namespace_id: project.namespace, project_id: project + end + + it 'should respond with 404' do + expect(response).to have_gitlab_http_status(404) + end + end + end + + describe 'POST #create' do + let(:remote_file_path) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' } + + let(:remote_file_content) do + <<~HEREDOC + before_script: + - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs + - ruby -v + - which ruby + - gem install bundler --no-ri --no-rdoc + - bundle install --jobs $(nproc) "${FLAGS[@]}" + HEREDOC + end + + let(:content) do + <<~HEREDOC + include: + - #{remote_file_path} + + rubocop: + script: + - bundle exec rubocop + HEREDOC + end + + context 'with a valid gitlab-ci.yml' do + before do + WebMock.stub_request(:get, remote_file_path).to_return(body: remote_file_content) + project.add_developer(user) + + post :create, namespace_id: project.namespace, project_id: project, content: content + end + + it 'should be success' do + expect(response).to be_success + end + + it 'render show page' do + expect(response).to render_template :show + end + + it 'should retrieve project' do + expect(assigns(:project)).to eq(project) + end + end + + context 'with an invalid gitlab-ci.yml' do + let(:content) do + <<~HEREDOC + rubocop: + scriptt: + - bundle exec rubocop + HEREDOC + end + + before do + project.add_developer(user) + + post :create, namespace_id: project.namespace, project_id: project, content: content + end + + it 'should assign errors' do + expect(assigns[:error]).to eq('jobs:rubocop config contains unknown keys: scriptt') + end + end + + context 'without enough privileges' do + before do + project.add_guest(user) + + post :create, namespace_id: project.namespace, project_id: project, content: content + end + + it 'should respond with 404' do + expect(response).to have_gitlab_http_status(404) + end + end + end +end diff --git a/spec/features/ci_lint_spec.rb b/spec/features/projects/ci/lint_spec.rb similarity index 91% rename from spec/features/ci_lint_spec.rb rename to spec/features/projects/ci/lint_spec.rb index 220b934154e..313950072e7 100644 --- a/spec/features/ci_lint_spec.rb +++ b/spec/features/projects/ci/lint_spec.rb @@ -1,10 +1,14 @@ require 'spec_helper' describe 'CI Lint', :js do - before do - sign_in(create(:user)) + let(:project) { create(:project, :repository) } + let(:user) { create(:user) } - visit ci_lint_path + before do + project.add_developer(user) + sign_in(user) + + visit project_ci_lint_path(project) find('#ci-editor') execute_script("ace.edit('ci-editor').setValue(#{yaml_content.to_json});") diff --git a/spec/views/ci/lints/show.html.haml_spec.rb b/spec/views/projects/ci/lints/show.html.haml_spec.rb similarity index 92% rename from spec/views/ci/lints/show.html.haml_spec.rb rename to spec/views/projects/ci/lints/show.html.haml_spec.rb index ded320793ea..b50acc54276 100644 --- a/spec/views/ci/lints/show.html.haml_spec.rb +++ b/spec/views/projects/ci/lints/show.html.haml_spec.rb @@ -1,12 +1,14 @@ require 'spec_helper' -describe 'ci/lints/show' do +describe 'projects/ci/lints/show' do include Devise::Test::ControllerHelpers + let(:project) { create(:project, :repository) } describe 'XSS protection' do let(:config_processor) { Gitlab::Ci::YamlProcessor.new(YAML.dump(content)) } before do + assign(:project, project) assign(:status, true) assign(:builds, config_processor.builds) assign(:stages, config_processor.stages) @@ -64,6 +66,7 @@ describe 'ci/lints/show' do context 'when the content is valid' do before do + assign(:project, project) assign(:status, true) assign(:builds, config_processor.builds) assign(:stages, config_processor.stages) @@ -83,6 +86,7 @@ describe 'ci/lints/show' do context 'when the content is invalid' do before do + assign(:project, project) assign(:status, false) assign(:error, 'Undefined error') end