diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-22 06:10:15 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-22 06:10:15 +0300 |
commit | 1e69e818f0f6d3598efb67104c39ec9408570b0f (patch) | |
tree | 1dbb70f80d2a63e1a1aa2f282e8ab8e08edaee89 | |
parent | 0bdb61ade7f12067dd524463af4f83994f1baa37 (diff) |
Add latest changes from gitlab-org/gitlab@master
-rw-r--r-- | app/assets/javascripts/repository/index.js | 2 | ||||
-rw-r--r-- | app/assets/javascripts/repository/router.js | 3 | ||||
-rw-r--r-- | app/models/repository.rb | 2 | ||||
-rw-r--r-- | app/views/projects/blob/show.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/buttons/_compare.html.haml | 8 | ||||
-rw-r--r-- | app/views/projects/tree/_tree_header.html.haml | 1 | ||||
-rw-r--r-- | doc/api/lint.md | 10 | ||||
-rw-r--r-- | doc/user/application_security/dependency_scanning/index.md | 4 | ||||
-rw-r--r-- | doc/user/packages/terraform_module_registry/index.md | 2 | ||||
-rw-r--r-- | lib/api/lint.rb | 17 | ||||
-rw-r--r-- | lib/extracts_ref.rb | 4 | ||||
-rw-r--r-- | locale/gitlab.pot | 3 | ||||
-rw-r--r-- | spec/features/projects/project_overview_spec.rb | 59 | ||||
-rw-r--r-- | spec/lib/extracts_ref_spec.rb | 6 | ||||
-rw-r--r-- | spec/presenters/tree_entry_presenter_spec.rb | 15 | ||||
-rw-r--r-- | spec/requests/api/lint_spec.rb | 99 | ||||
-rw-r--r-- | spec/views/projects/tree/show.html.haml_spec.rb | 22 |
17 files changed, 234 insertions, 25 deletions
diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js index 9753173ac30..74ef678c558 100644 --- a/app/assets/javascripts/repository/index.js +++ b/app/assets/javascripts/repository/index.js @@ -122,7 +122,7 @@ export default function setupVueRepositoryList() { return h(LastCommit, { props: { currentPath: this.$route.params.path, - refType: this.$route.query.ref_type, + refType: this.$route.meta.refType || this.$route.query.ref_type, }, }); }, diff --git a/app/assets/javascripts/repository/router.js b/app/assets/javascripts/repository/router.js index 5f73912ed2b..31bafab742d 100644 --- a/app/assets/javascripts/repository/router.js +++ b/app/assets/javascripts/repository/router.js @@ -63,6 +63,9 @@ export default function createRouter(base, baseRef) { props: { refType: 'HEADS', }, + meta: { + refType: 'HEADS', + }, }, ], }); diff --git a/app/models/repository.rb b/app/models/repository.rb index 1c27a7a64cf..18dcc7fb840 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -688,7 +688,7 @@ class Repository def head_tree(skip_flat_paths: true) return if empty? || root_ref.nil? - @head_tree ||= Tree.new(self, root_ref, nil, skip_flat_paths: skip_flat_paths) + @head_tree ||= Tree.new(self, root_ref, nil, skip_flat_paths: skip_flat_paths, ref_type: 'heads') end def tree(sha = :head, path = nil, recursive: false, skip_flat_paths: true, pagination_params: nil, ref_type: nil, rescue_not_found: true) diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml index 9ec824f64d4..82f517e8a84 100644 --- a/app/views/projects/blob/show.html.haml +++ b/app/views/projects/blob/show.html.haml @@ -4,7 +4,7 @@ - signatures_path = namespace_project_signatures_path(namespace_id: @project.namespace.full_path, project_id: @project.path, id: @last_commit, limit: 1) - content_for :prefetch_asset_tags do - webpack_preload_asset_tag('monaco', prefetch: true) -- add_page_startup_graphql_call('repository/blob_info', { projectPath: @project.full_path, ref: current_ref, refType: @ref_type.to_s, filePath: @blob.path, shouldFetchRawText: @blob.rendered_as_text? && !@blob.rich_viewer }) +- add_page_startup_graphql_call('repository/blob_info', { projectPath: @project.full_path, ref: current_ref, refType: @ref_type.to_s.upcase, filePath: @blob.path, shouldFetchRawText: @blob.rendered_as_text? && !@blob.rich_viewer }) .js-signature-container{ data: { 'signatures-path': signatures_path } } diff --git a/app/views/projects/buttons/_compare.html.haml b/app/views/projects/buttons/_compare.html.haml new file mode 100644 index 00000000000..82b1b837fbb --- /dev/null +++ b/app/views/projects/buttons/_compare.html.haml @@ -0,0 +1,8 @@ +- project = local_assigns.fetch(:project) +- ref = local_assigns.fetch(:ref, nil) +- root_ref = local_assigns.fetch(:root_ref, nil) +- unless ref.blank? || root_ref == ref + - compare_path = project_compare_index_path(project, from: root_ref, to: ref) + + = link_button_to compare_path, class: 'shortcuts-compare', rel: 'nofollow' do + = _('Compare') diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml index a4ed19c2fc9..dad6480706d 100644 --- a/app/views/projects/tree/_tree_header.html.haml +++ b/app/views/projects/tree/_tree_header.html.haml @@ -10,6 +10,7 @@ = render_if_exists 'projects/tree/lock_link' #js-tree-history-link{ data: { history_link: project_commits_path(@project, @ref) } } + = render 'projects/buttons/compare', project: @project, ref: @ref, root_ref: @repository&.root_ref = render 'projects/find_file_link' = render 'shared/web_ide_button', blob: nil = render 'projects/buttons/download', project: @project, ref: @ref diff --git a/doc/api/lint.md b/doc/api/lint.md index 9e29e8dccb4..7b288c34343 100644 --- a/doc/api/lint.md +++ b/doc/api/lint.md @@ -56,9 +56,12 @@ Example responses: ## Validate a project's CI configuration -Checks if a project's latest (`HEAD` of the project's default branch) -`.gitlab-ci.yml` configuration is valid. This endpoint uses all namespace -specific data available, including variables and local includes. +> `sha` attribute [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/369212) in GitLab 16.5. + +Checks if a project’s `.gitlab-ci.yml` configuration in a given commit +(by default `HEAD` of the project’s default branch) is valid. This +endpoint uses all namespace specific data available, including variables +and local includes. ```plaintext GET /projects/:id/ci/lint @@ -69,6 +72,7 @@ GET /projects/:id/ci/lint | `dry_run` | boolean | No | Run pipeline creation simulation, or only do static check. | | `include_jobs` | boolean | No | If the list of jobs that would exist in a static check or pipeline simulation should be included in the response. Default: `false`. | | `ref` | string | No | When `dry_run` is `true`, sets the branch or tag to use. Defaults to the project's default branch when not set. | +| `sha` | string | No | The commit SHA of a branch or tag. Defaults to the SHA of the head of the project's default branch when not set. | Example request: diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md index f8bd5b99cb6..532d9506270 100644 --- a/doc/user/application_security/dependency_scanning/index.md +++ b/doc/user/application_security/dependency_scanning/index.md @@ -126,7 +126,7 @@ table.supported-languages ul { 8 LTS, 11 LTS, 17 LTS, - or 21 EA<sup><b><a href="#notes-regarding-supported-languages-and-package-managers-2">2</a></b></sup> + or 21 LTS<sup><b><a href="#notes-regarding-supported-languages-and-package-managers-2">2</a></b></sup> </td> <td><a href="https://gradle.org/">Gradle</a><sup><b><a href="#notes-regarding-supported-languages-and-package-managers-3">3</a></b></sup></td> <td> @@ -236,7 +236,7 @@ table.supported-languages ul { <li> <a id="notes-regarding-supported-languages-and-package-managers-2"></a> <p> - Java 21 EA is only available when using <a href="https://maven.apache.org/">Maven</a> and is not supported when + Java 21 LTS is only available when using <a href="https://maven.apache.org/">Maven</a> and is not supported when <a href="https://docs.gitlab.com/ee/development/fips_compliance.html#enable-fips-mode">FIPS mode</a> is enabled. </p> </li> diff --git a/doc/user/packages/terraform_module_registry/index.md b/doc/user/packages/terraform_module_registry/index.md index cb0516bdc4a..5c4105f8e00 100644 --- a/doc/user/packages/terraform_module_registry/index.md +++ b/doc/user/packages/terraform_module_registry/index.md @@ -204,7 +204,7 @@ For example, if: - The project is `gitlab.example.com/parent-group/sub-group/my-project`. - The Terraform module is `my-infra-package`. -The project name must be unique in all projects in all groups under `parent-group`. +The module name must be unique in all projects in all groups under `parent-group`. ## Delete a Terraform module diff --git a/lib/api/lint.rb b/lib/api/lint.rb index 71965fc05c9..26619e6924f 100644 --- a/lib/api/lint.rb +++ b/lib/api/lint.rb @@ -6,12 +6,16 @@ module API resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do desc 'Validates a CI YAML configuration with a namespace' do - detail 'Checks if a project’s latest (HEAD of the project’s default branch) .gitlab-ci.yml configuration is - valid' + detail 'Checks if a project’s .gitlab-ci.yml configuration in a given commit (by default HEAD of the + project’s default branch) is valid' success Entities::Ci::Lint::Result tags %w[ci_lint] + failure [ + { code: 404, message: 'Not found' } + ] end params do + optional :sha, type: String, desc: 'The commit hash or name of a repository branch or tag. Defaults to the HEAD of the project’s default branch' optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check. This is false by default' optional :include_jobs, type: Boolean, desc: 'If the list of jobs that would exist in a static check or pipeline simulation should be included in the response. This is false by default' @@ -21,12 +25,13 @@ module API get ':id/ci/lint', urgency: :low do authorize_read_code! - if user_project.commit.present? - content = user_project.repository.gitlab_ci_yml_for(user_project.commit.id, user_project.ci_config_path_or_default) - end + sha = params[:sha] || user_project.repository.root_ref_sha + not_found! 'Commit' unless user_project.commit(sha).present? + + content = user_project.repository.gitlab_ci_yml_for(sha, user_project.ci_config_path_or_default) result = Gitlab::Ci::Lint - .new(project: user_project, current_user: current_user) + .new(project: user_project, current_user: current_user, sha: sha) .validate(content, dry_run: params[:dry_run], ref: params[:ref] || user_project.default_branch) present result, with: Entities::Ci::Lint::Result, current_user: current_user, include_jobs: params[:include_jobs] diff --git a/lib/extracts_ref.rb b/lib/extracts_ref.rb index 49ec564eb8d..fa3c1fe7307 100644 --- a/lib/extracts_ref.rb +++ b/lib/extracts_ref.rb @@ -10,9 +10,9 @@ module ExtractsRef REF_TYPES = [BRANCH_REF_TYPE, TAG_REF_TYPE].freeze def self.ref_type(type) - return unless REF_TYPES.include?(type) + return unless REF_TYPES.include?(type&.downcase) - type + type.downcase end def self.qualify_ref(ref, type) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index f98cb46dd78..6dfb78db9ba 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -42622,6 +42622,9 @@ msgstr "" msgid "SecurityOrchestration|This is a project-level policy" msgstr "" +msgid "SecurityOrchestration|This policy is inherited" +msgstr "" + msgid "SecurityOrchestration|This policy is inherited from %{namespace}" msgstr "" diff --git a/spec/features/projects/project_overview_spec.rb b/spec/features/projects/project_overview_spec.rb new file mode 100644 index 00000000000..e563b03c22a --- /dev/null +++ b/spec/features/projects/project_overview_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "Project overview when default branch collides with tag", :js, feature_category: :source_code_management do + let_it_be(:project) { create(:project, :empty_repo) } + let(:user) { project.first_owner } + + before_all do + # Create a branch called main that does not contain a readme (this will be the default branch) + project.repository.create_file( + project.creator, + 'NOTREADME.md', + '', + message: "Initial commit", + branch_name: 'main' + ) + + # Create a branch called readme_branch that contains a readme + project.repository.create_file( + project.creator, + 'README.md', + 'readme', + message: "Add README.md", + branch_name: 'readme_branch' + ) + + # Create a tag called main pointing to readme_branch + project.repository.add_tag( + project.creator, + 'main', + 'readme_branch' + ) + end + + before do + sign_in(user) + visit project_path(project) + end + + it "shows last commit" do + page.within(".commit-detail") do + expect(page).to have_content('Initial commit') + end + + page.execute_script(%{ + document.getElementsByClassName('tree-content-holder')[0].scrollIntoView()} + ) + wait_for_all_requests + + page.within(".tree-content-holder") do + expect(page).to have_content('Initial commit') + end + end + + it 'has a button to button to add readme' do + expect(page).to have_link 'Add README' + end +end diff --git a/spec/lib/extracts_ref_spec.rb b/spec/lib/extracts_ref_spec.rb index ac403ad642a..bf33c8b95f1 100644 --- a/spec/lib/extracts_ref_spec.rb +++ b/spec/lib/extracts_ref_spec.rb @@ -87,6 +87,12 @@ RSpec.describe ExtractsRef do it { is_expected.to eq('tags') } end + context 'when case does not match' do + let(:ref_type) { 'tAgS' } + + it { is_expected.to(eq('tags')) } + end + context 'when ref_type is invalid' do let(:ref_type) { 'invalid' } diff --git a/spec/presenters/tree_entry_presenter_spec.rb b/spec/presenters/tree_entry_presenter_spec.rb index 0abf372b704..359ffbcb140 100644 --- a/spec/presenters/tree_entry_presenter_spec.rb +++ b/spec/presenters/tree_entry_presenter_spec.rb @@ -7,29 +7,32 @@ RSpec.describe TreeEntryPresenter do let(:project) { create(:project, :repository) } let(:repository) { project.repository } - let(:tree) { Gitlab::Graphql::Representation::TreeEntry.new(repository.tree.trees.first, repository) } + let(:tree) { Gitlab::Graphql::Representation::TreeEntry.new(repository.tree(ref).trees.first, repository) } let(:presenter) { described_class.new(tree) } + let(:ref) { 'master' } describe '.web_url' do - it { expect(presenter.web_url).to eq("http://localhost/#{project.full_path}/-/tree/#{tree.commit_id}/#{tree.path}") } + it { + expect(presenter.web_url).to eq("http://localhost/#{project.full_path}/-/tree/#{ref}/#{tree.path}") + } end describe '#web_path' do - it { expect(presenter.web_path).to eq("/#{project.full_path}/-/tree/#{tree.commit_id}/#{tree.path}") } + it { expect(presenter.web_path).to eq("/#{project.full_path}/-/tree/#{ref}/#{tree.path}") } end - context 'when blob has ref_type' do + context 'when tree has ref_type' do before do tree.ref_type = 'heads' end describe '.web_url' do - it { expect(presenter.web_url).to eq("http://localhost/#{project.full_path}/-/tree/#{tree.commit_id}/#{tree.path}?ref_type=heads") } + it { expect(presenter.web_url).to eq("http://localhost/#{project.full_path}/-/tree/#{ref}/#{tree.path}?ref_type=heads") } end describe '#web_path' do it { - expect(presenter.web_path).to eq("/#{project.full_path}/-/tree/#{tree.commit_id}/#{tree.path}?ref_type=heads") + expect(presenter.web_path).to eq("/#{project.full_path}/-/tree/#{ref}/#{tree.path}?ref_type=heads") } end end diff --git a/spec/requests/api/lint_spec.rb b/spec/requests/api/lint_spec.rb index 7fe17760220..5842bd1c716 100644 --- a/spec/requests/api/lint_spec.rb +++ b/spec/requests/api/lint_spec.rb @@ -4,9 +4,10 @@ require 'spec_helper' RSpec.describe API::Lint, feature_category: :pipeline_composition do describe 'GET /projects/:id/ci/lint' do - subject(:ci_lint) { get api("/projects/#{project.id}/ci/lint", api_user), params: { dry_run: dry_run, include_jobs: include_jobs } } + subject(:ci_lint) { get api("/projects/#{project.id}/ci/lint", api_user), params: { sha: sha, dry_run: dry_run, include_jobs: include_jobs } } let(:project) { create(:project, :repository) } + let(:sha) { nil } let(:dry_run) { nil } let(:include_jobs) { nil } @@ -291,6 +292,102 @@ RSpec.describe API::Lint, feature_category: :pipeline_composition do end end end + + context 'with different sha values' do + let(:original_content) do + { test: { stage: 'test', script: 'echo 1' } }.deep_stringify_keys.to_yaml + end + + let(:first_edit) do + { image: 'image:1.0', services: ['postgres'] }.deep_stringify_keys.to_yaml + end + + let(:second_edit) do + { new_test: { stage: 'test', script: 'echo 0' } }.deep_stringify_keys.to_yaml + end + + before do + project.repository.create_file( + project.creator, + '.gitlab-ci.yml', + original_content, + message: 'Automatically created .gitlab-ci.yml', + branch_name: 'master' + ) + + project.repository.update_file( + project.creator, + '.gitlab-ci.yml', + first_edit, + message: 'Automatically edited .gitlab-ci.yml', + branch_name: 'master' + ) + + project.repository.update_file( + project.creator, + '.gitlab-ci.yml', + second_edit, + message: 'Automatically edited .gitlab-ci.yml again', + branch_name: 'master' + ) + end + + context 'when latest .gitlab-ci.yml is valid' do + # check with explicit sha + let(:sha) { project.repository.commit.sha } + + it 'passes validation' do + ci_lint + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to be_an Hash + expect(json_response['merged_yaml']).to eq(second_edit) + expect(json_response['valid']).to eq(true) + expect(json_response['warnings']).to eq([]) + expect(json_response['errors']).to eq([]) + end + end + + context 'when previous .gitlab-ci.yml is invalid' do + let(:sha) { project.repository.commit.parent.sha } + + it 'fails validation' do + ci_lint + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to be_an Hash + expect(json_response['merged_yaml']).to eq(first_edit) + expect(json_response['valid']).to eq(false) + expect(json_response['warnings']).to eq([]) + expect(json_response['errors']).to eq(["jobs config should contain at least one visible job"]) + end + end + + context 'when first .gitlab-ci.yml is valid' do + let(:sha) { project.repository.commit.parent.parent.sha } + + it 'passes validation' do + ci_lint + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to be_an Hash + expect(json_response['merged_yaml']).to eq(original_content) + expect(json_response['valid']).to eq(true) + expect(json_response['warnings']).to eq([]) + expect(json_response['errors']).to eq([]) + end + end + + context 'when sha is not found' do + let(:sha) { "unknown" } + + it 'returns 404 response' do + ci_lint + + expect(response).to have_gitlab_http_status(:not_found) + end + end + end end end diff --git a/spec/views/projects/tree/show.html.haml_spec.rb b/spec/views/projects/tree/show.html.haml_spec.rb index 5a1ae715f8f..942c352c6b6 100644 --- a/spec/views/projects/tree/show.html.haml_spec.rb +++ b/spec/views/projects/tree/show.html.haml_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe 'projects/tree/show' do include Devise::Test::ControllerHelpers - let(:project) { create(:project, :repository) } + let_it_be(:project) { create(:project, :repository, create_branch: 'bar') } let(:repository) { project.repository } let(:ref) { 'master' } let(:commit) { repository.commit(ref) } @@ -38,4 +38,24 @@ RSpec.describe 'projects/tree/show' do expect(rendered).to have_css('#js-tree-ref-switcher') end end + + context 'when on root ref' do + let(:ref) { repository.root_ref } + + it 'hides compare button' do + render + + expect(rendered).not_to include('Compare') + end + end + + context 'when not on root ref' do + let(:ref) { 'bar' } + + it 'shows a compare button' do + render + + expect(rendered).to include('Compare') + end + end end |