diff --git a/app/assets/javascripts/pages/projects/ci/lints/ci_lint_editor.js b/app/assets/javascripts/pages/projects/ci/lints/ci_lint_editor.js deleted file mode 100644 index df635522e94..00000000000 --- a/app/assets/javascripts/pages/projects/ci/lints/ci_lint_editor.js +++ /dev/null @@ -1,32 +0,0 @@ -import EditorLite from '~/editor/editor_lite'; - -export default class CILintEditor { - constructor() { - this.clearYml = document.querySelector('.clear-yml'); - this.clearYml.addEventListener('click', this.clear.bind(this)); - - return this.initEditorLite(); - } - - clear() { - this.editor.setValue(''); - } - - initEditorLite() { - const editorEl = document.getElementById('editor'); - const fileContentEl = document.getElementById('content'); - const form = document.querySelector('.js-ci-lint-form'); - - const rootEditor = new EditorLite(); - - this.editor = rootEditor.createInstance({ - el: editorEl, - blobPath: '.gitlab-ci.yml', - blobContent: editorEl.innerText, - }); - - form.addEventListener('submit', () => { - fileContentEl.value = this.editor.getValue(); - }); - } -} diff --git a/app/assets/javascripts/pages/projects/ci/lints/new/index.js b/app/assets/javascripts/pages/projects/ci/lints/new/index.js deleted file mode 100644 index 5a0689b15f2..00000000000 --- a/app/assets/javascripts/pages/projects/ci/lints/new/index.js +++ /dev/null @@ -1,17 +0,0 @@ -import createFlash from '~/flash'; -import { __ } from '~/locale'; - -const ERROR = __('An error occurred while rendering the linter'); - -document.addEventListener('DOMContentLoaded', () => { - if (gon?.features?.ciLintVue) { - import(/* webpackChunkName: 'ciLintIndex' */ '~/ci_lint/index') - .then(module => module.default()) - .catch(() => createFlash({ message: ERROR })); - } else { - import(/* webpackChunkName: 'ciLintEditor' */ '../ci_lint_editor') - // eslint-disable-next-line new-cap - .then(module => new module.default()) - .catch(() => createFlash({ message: ERROR })); - } -}); diff --git a/app/assets/javascripts/pages/projects/ci/lints/show/index.js b/app/assets/javascripts/pages/projects/ci/lints/show/index.js index 5a0689b15f2..6e1cdf557b5 100644 --- a/app/assets/javascripts/pages/projects/ci/lints/show/index.js +++ b/app/assets/javascripts/pages/projects/ci/lints/show/index.js @@ -1,17 +1,3 @@ -import createFlash from '~/flash'; -import { __ } from '~/locale'; +import initCiLint from '~/ci_lint'; -const ERROR = __('An error occurred while rendering the linter'); - -document.addEventListener('DOMContentLoaded', () => { - if (gon?.features?.ciLintVue) { - import(/* webpackChunkName: 'ciLintIndex' */ '~/ci_lint/index') - .then(module => module.default()) - .catch(() => createFlash({ message: ERROR })); - } else { - import(/* webpackChunkName: 'ciLintEditor' */ '../ci_lint_editor') - // eslint-disable-next-line new-cap - .then(module => new module.default()) - .catch(() => createFlash({ message: ERROR })); - } -}); +initCiLint(); diff --git a/app/controllers/projects/ci/lints_controller.rb b/app/controllers/projects/ci/lints_controller.rb index 26797a4613c..9dc3194df85 100644 --- a/app/controllers/projects/ci/lints_controller.rb +++ b/app/controllers/projects/ci/lints_controller.rb @@ -2,28 +2,22 @@ class Projects::Ci::LintsController < Projects::ApplicationController before_action :authorize_create_pipeline! - before_action do - push_frontend_feature_flag(:ci_lint_vue, project, default_enabled: true) - end feature_category :pipeline_authoring + respond_to :json, only: [:create] + def show end def create - @content = params[:content] - @dry_run = params[:dry_run] + content = params[:content] + dry_run = params[:dry_run] - @result = Gitlab::Ci::Lint + result = Gitlab::Ci::Lint .new(project: @project, current_user: current_user) - .validate(@content, dry_run: @dry_run) + .validate(content, dry_run: dry_run) - respond_to do |format| - format.html { render :show } - format.json do - render json: ::Ci::Lint::ResultSerializer.new.represent(@result) - end - end + render json: ::Ci::Lint::ResultSerializer.new.represent(result) end end diff --git a/app/views/projects/ci/lints/_create.html.haml b/app/views/projects/ci/lints/_create.html.haml deleted file mode 100644 index 8afa5c220ba..00000000000 --- a/app/views/projects/ci/lints/_create.html.haml +++ /dev/null @@ -1,51 +0,0 @@ -- if @result.valid? - .bs-callout.bs-callout-success - %p - %b= _("Status:") - = _("syntax is correct") - - = render "projects/ci/lints/lint_warnings", warnings: @result.warnings - - .table-holder - %table.table.table-bordered - %thead - %tr - %th= _("Parameter") - %th= _("Value") - %tbody - - @result.jobs.each do |job| - %tr - %td #{job[:stage].capitalize} Job - #{job[:name]} - %td - %pre= job[:before_script].to_a.join('
') - %pre= job[:script].to_a.join('
') - %pre= job[:after_script].to_a.join('
') - %br - %b= _("Tag list:") - = job[:tag_list].to_a.join(", ") - - unless @dry_run - %br - %b= _("Only policy:") - = job[:only].to_a.join(", ") - %br - %b= _("Except policy:") - = job[:except].to_a.join(", ") - %br - %b= _("Environment:") - = job[:environment] - %br - %b= _("When:") - = job[:when] - - if job[:allow_failure] - %b= _("Allowed to fail") - -- else - .bs-callout.bs-callout-danger - %p - %b= _("Status:") - = _("syntax is incorrect") - %pre - - @result.errors.each do |message| - %p= message - - = render "projects/ci/lints/lint_warnings", warnings: @result.warnings diff --git a/app/views/projects/ci/lints/_lint_warnings.html.haml b/app/views/projects/ci/lints/_lint_warnings.html.haml deleted file mode 100644 index 90db65e6c27..00000000000 --- a/app/views/projects/ci/lints/_lint_warnings.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -- if warnings - - total_warnings = warnings.length - - message = warning_header(total_warnings) - - - if warnings.any? - .bs-callout.bs-callout-warning - %details - %summary.gl-mb-2= message - - warnings.each do |warning| - = markdown(warning) diff --git a/app/views/projects/ci/lints/show.html.haml b/app/views/projects/ci/lints/show.html.haml index 9eaaba0e909..1b1bef1f85c 100644 --- a/app/views/projects/ci/lints/show.html.haml +++ b/app/views/projects/ci/lints/show.html.haml @@ -3,32 +3,4 @@ %h2.pt-3.pb-3= _("Validate your GitLab CI configuration") -- if Feature.enabled?(:ci_lint_vue, @project, default_enabled: true) - #js-ci-lint{ data: { endpoint: project_ci_lint_path(@project), help_page_path: help_page_path('ci/lint', anchor: 'pipeline-simulation') } } - -- else - .project-ci-linter - = form_tag project_ci_lint_path(@project), method: :post, class: 'js-ci-lint-form' do - .row - .col-sm-12 - .file-holder - .js-file-title.file-title.clearfix - = _("Contents of .gitlab-ci.yml") - .file-editor.code - .js-edit-mode-pane.qa-editor#editor{ data: { 'editor-loading': true } }< - %pre.editor-loading-content= params[:content] - = text_area_tag(:content, @content, class: 'hidden form-control span1', rows: 7, require: true) - .col-sm-12 - .float-left.gl-mt-3 - = submit_tag(_('Validate'), class: 'gl-button btn btn-success submit-yml') - - if Gitlab::Ci::Features.lint_creates_pipeline_with_dry_run?(@project) - = check_box_tag(:dry_run, 'true', params[:dry_run]) - = label_tag(:dry_run, _('Simulate a pipeline created for the default branch')) - = link_to sprite_icon('question-o'), help_page_path('ci/lint', anchor: 'pipeline-simulation'), target: '_blank', rel: 'noopener noreferrer' - .float-right.prepend-top-10 - = button_tag(_('Clear'), type: 'button', class: 'gl-button btn btn-default clear-yml') - - .row.prepend-top-20 - .col-sm-12 - .results.project-ci-template - = render partial: 'create' if defined?(@result) +#js-ci-lint{ data: { endpoint: project_ci_lint_path(@project), help_page_path: help_page_path('ci/lint', anchor: 'pipeline-simulation') } } diff --git a/config/feature_flags/development/ci_lint_vue.yml b/config/feature_flags/development/ci_lint_vue.yml deleted file mode 100644 index 0997da761c0..00000000000 --- a/config/feature_flags/development/ci_lint_vue.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -name: ci_lint_vue -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42401 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/249661 -group: group::continuous integration -type: development -default_enabled: true diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 2a3d8c23e89..95c8e8ab658 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -3154,9 +3154,6 @@ msgstr "" msgid "An error occurred while rendering the editor" msgstr "" -msgid "An error occurred while rendering the linter" -msgstr "" - msgid "An error occurred while reordering issues." msgstr "" diff --git a/spec/controllers/projects/ci/lints_controller_spec.rb b/spec/controllers/projects/ci/lints_controller_spec.rb index 22f052e39b7..24048aea838 100644 --- a/spec/controllers/projects/ci/lints_controller_spec.rb +++ b/spec/controllers/projects/ci/lints_controller_spec.rb @@ -47,9 +47,9 @@ RSpec.describe Projects::Ci::LintsController do describe 'POST #create' do subject { post :create, params: params } - let(:format) { :html } - let(:params) { { namespace_id: project.namespace, project_id: project, content: content, format: format } } + let(:params) { { namespace_id: project.namespace, project_id: project, content: content, format: :json } } let(:remote_file_path) { 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' } + let(:parsed_body) { Gitlab::Json.parse(response.body) } let(:remote_file_content) do <<~HEREDOC @@ -72,17 +72,23 @@ RSpec.describe Projects::Ci::LintsController do HEREDOC end - shared_examples 'successful request with format json' do - context 'with format json' do - let(:format) { :json } - let(:parsed_body) { Gitlab::Json.parse(response.body) } + shared_examples 'returns a successful validation' do + before do + subject + end - it 'renders json' do - expect(response).to have_gitlab_http_status :ok - expect(response.content_type).to eq 'application/json' - expect(parsed_body).to include('errors', 'warnings', 'jobs', 'valid') - expect(parsed_body).to match_schema('entities/lint_result_entity') - end + it 'returns successfully' do + expect(response).to have_gitlab_http_status :ok + end + + it 'renders json' do + expect(response.content_type).to eq 'application/json' + expect(parsed_body).to include('errors', 'warnings', 'jobs', 'valid') + expect(parsed_body).to match_schema('entities/lint_result_entity') + end + + it 'retrieves project' do + expect(assigns(:project)).to eq(project) end end @@ -92,25 +98,7 @@ RSpec.describe Projects::Ci::LintsController do project.add_developer(user) end - shared_examples 'returns a successful validation' do - before do - subject - end - - it 'returns successfully' do - expect(response).to have_gitlab_http_status :ok - end - - it 'renders show page' do - expect(response).to render_template :show - end - - it 'retrieves project' do - expect(assigns(:project)).to eq(project) - end - - it_behaves_like 'successful request with format json' - end + it_behaves_like 'returns a successful validation' context 'using legacy validation (YamlProcessor)' do it_behaves_like 'returns a successful validation' @@ -166,27 +154,23 @@ RSpec.describe Projects::Ci::LintsController do subject end + it_behaves_like 'returns a successful validation' + it 'assigns result with errors' do - expect(assigns[:result].errors).to match_array([ + expect(parsed_body['errors']).to match_array([ 'jobs rubocop config should implement a script: or a trigger: keyword', 'jobs config should contain at least one visible job' ]) end - it 'render show page' do - expect(response).to render_template :show - end - - it_behaves_like 'successful request with format json' - context 'with dry_run mode' do subject { post :create, params: params.merge(dry_run: 'true') } it 'assigns result with errors' do - expect(assigns[:result].errors).to eq(['jobs rubocop config should implement a script: or a trigger: keyword']) + expect(parsed_body['errors']).to eq(['jobs rubocop config should implement a script: or a trigger: keyword']) end - it_behaves_like 'successful request with format json' + it_behaves_like 'returns a successful validation' end end @@ -200,14 +184,6 @@ RSpec.describe Projects::Ci::LintsController do it 'responds with 404' do expect(response).to have_gitlab_http_status(:not_found) end - - context 'with format json' do - let(:format) { :json } - - it 'responds with 404' do - expect(response).to have_gitlab_http_status :not_found - end - end end end end diff --git a/spec/features/projects/ci/lint_spec.rb b/spec/features/projects/ci/lint_spec.rb index eb2efb4357d..466c7ba215e 100644 --- a/spec/features/projects/ci/lint_spec.rb +++ b/spec/features/projects/ci/lint_spec.rb @@ -11,7 +11,6 @@ RSpec.describe 'CI Lint', :js do let(:content_selector) { '.content .view-lines' } before do - stub_feature_flags(ci_lint_vue: false) project.add_developer(user) sign_in(user) @@ -26,7 +25,6 @@ RSpec.describe 'CI Lint', :js do describe 'YAML parsing' do shared_examples 'validates the YAML' do before do - stub_feature_flags(ci_lint_vue: false) click_on 'Validate' end @@ -68,14 +66,6 @@ RSpec.describe 'CI Lint', :js do it_behaves_like 'validates the YAML' end - - describe 'YAML revalidate' do - let(:yaml_content) { 'my yaml content' } - - it 'loads previous YAML content after validation' do - expect(page).to have_field('content', with: 'my yaml content', visible: false, type: 'textarea') - end - end end describe 'YAML clearing' do @@ -89,7 +79,7 @@ RSpec.describe 'CI Lint', :js do end it 'YAML content is cleared' do - expect(page).to have_field('content', with: '', visible: false, type: 'textarea') + expect(page).to have_field(class: 'inputarea', with: '', visible: false, type: 'textarea') end end end diff --git a/spec/views/projects/ci/lints/show.html.haml_spec.rb b/spec/views/projects/ci/lints/show.html.haml_spec.rb deleted file mode 100644 index f59ad3f5f84..00000000000 --- a/spec/views/projects/ci/lints/show.html.haml_spec.rb +++ /dev/null @@ -1,127 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'projects/ci/lints/show' do - include Devise::Test::ControllerHelpers - let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, :repository) } - let(:lint) { Gitlab::Ci::Lint.new(project: project, current_user: user) } - let(:result) { lint.validate(YAML.dump(content)) } - - describe 'XSS protection' do - before do - assign(:project, project) - assign(:result, result) - stub_feature_flags(ci_lint_vue: false) - end - - context 'when builds attrbiutes contain HTML nodes' do - let(:content) do - { - rspec: { - script: '

rspec

', - stage: 'test' - } - } - end - - it 'does not render HTML elements' do - render - - expect(rendered).not_to have_css('h1', text: 'rspec') - end - end - - context 'when builds attributes do not contain HTML nodes' do - let(:content) do - { - rspec: { - script: 'rspec', - stage: 'test' - } - } - end - - it 'shows configuration in the table' do - render - - expect(rendered).to have_css('td pre', text: 'rspec') - end - end - end - - context 'when the content is valid' do - let(:content) do - { - build_template: { - script: './build.sh', - tags: ['dotnet'], - only: ['test@dude/repo'], - except: ['deploy'], - environment: 'testing' - } - } - end - - before do - assign(:project, project) - assign(:result, result) - stub_feature_flags(ci_lint_vue: false) - end - - it 'shows the correct values' do - render - - expect(rendered).to have_content('Status: syntax is correct') - expect(rendered).to have_content('Tag list: dotnet') - expect(rendered).to have_content('Only policy: refs, test@dude/repo') - expect(rendered).to have_content('Except policy: refs, deploy') - expect(rendered).to have_content('Environment: testing') - expect(rendered).to have_content('When: on_success') - end - - context 'when content has warnings' do - before do - allow(result).to receive(:warnings).and_return(['Warning 1', 'Warning 2']) - end - - it 'shows warning messages' do - render - - expect(rendered).to have_content('2 warning(s) found:') - expect(rendered).to have_content('Warning 1') - expect(rendered).to have_content('Warning 2') - end - end - end - - context 'when the content is invalid' do - let(:content) { double(:content) } - - before do - allow(result).to receive(:warnings).and_return(['Warning 1', 'Warning 2']) - allow(result).to receive(:errors).and_return(['Undefined error']) - - assign(:project, project) - assign(:result, result) - stub_feature_flags(ci_lint_vue: false) - end - - it 'shows error message' do - render - - expect(rendered).to have_content('Status: syntax is incorrect') - expect(rendered).to have_content('Undefined error') - expect(rendered).not_to have_content('Tag list:') - end - - it 'shows warning messages' do - render - - expect(rendered).to have_content('2 warning(s) found:') - expect(rendered).to have_content('Warning 1') - expect(rendered).to have_content('Warning 2') - end - end -end