summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue25
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue8
-rw-r--r--app/services/quick_actions/interpret_service.rb2
-rw-r--r--data/whats_new/202202210001_14_08.yml92
-rw-r--r--lib/backup/files.rb38
-rw-r--r--spec/factories/users.rb4
-rw-r--r--spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb22
-rw-r--r--spec/features/merge_request/user_sees_pipelines_spec.rb6
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb2
-rw-r--r--spec/frontend/pipelines/mock_data.js175
-rw-r--r--spec/frontend/pipelines/pipeline_url_spec.js37
-rw-r--r--spec/frontend/vue_shared/components/markdown/header_spec.js7
-rw-r--r--spec/lib/backup/artifacts_spec.rb14
-rw-r--r--spec/lib/backup/lfs_spec.rb1
-rw-r--r--spec/lib/backup/manager_spec.rb5
-rw-r--r--spec/lib/backup/object_backup_spec.rb1
-rw-r--r--spec/lib/backup/pages_spec.rb6
-rw-r--r--spec/lib/backup/uploads_spec.rb16
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb32
19 files changed, 180 insertions, 313 deletions
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
index 52da4d01468..7c78abae77f 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
@@ -136,8 +136,8 @@ export default {
return __('Branch');
}
},
- commitTitleText() {
- return this.pipeline?.commit?.title || __("Can't find HEAD commit for this branch");
+ commitTitle() {
+ return this.pipeline?.commit?.title;
},
hasAuthor() {
return (
@@ -159,22 +159,27 @@ export default {
<div class="pipeline-tags" data-testid="pipeline-url-table-cell">
<template v-if="rearrangePipelinesTable">
<div class="commit-title gl-mb-2" data-testid="commit-title-container">
- <span class="gl-display-flex">
- <tooltip-on-truncate :title="commitTitleText" class="flex-truncate-child gl-flex-grow-1">
+ <span v-if="commitTitle" class="gl-display-flex">
+ <tooltip-on-truncate :title="commitTitle" class="flex-truncate-child gl-flex-grow-1">
<gl-link
- :href="pipeline.path"
- class="commit-row-message gl-text-blue-600!"
+ :href="commitUrl"
+ class="commit-row-message gl-text-gray-900"
data-testid="commit-title"
- data-qa-selector="pipeline_url_link"
- >{{ commitTitleText }}</gl-link
+ >{{ commitTitle }}</gl-link
>
</tooltip-on-truncate>
</span>
+ <span v-else>{{ __("Can't find HEAD commit for this branch") }}</span>
</div>
<div class="gl-mb-2">
- <span class="gl-font-weight-bold gl-text-gray-500" data-testid="pipeline-identifier">
+ <gl-link
+ :href="pipeline.path"
+ class="gl-text-decoration-underline gl-text-blue-600!"
+ data-testid="pipeline-url-link"
+ data-qa-selector="pipeline_url_link"
+ >
#{{ pipeline[pipelineKey] }}
- </span>
+ </gl-link>
<!--Commit row-->
<div class="icon-container gl-display-inline-block">
<gl-icon
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index e2b6579a841..3b99afa9e3d 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -171,8 +171,12 @@ export default {
@click="previewMarkdownTab($event)"
/>
- <template v-if="!previewMarkdown" #tabs-end>
- <div class="md-header-toolbar gl-ml-auto gl-pb-3 gl-justify-content-center">
+ <template #tabs-end>
+ <div
+ data-testid="md-header-toolbar"
+ :class="{ 'gl-display-none': previewMarkdown }"
+ class="md-header-toolbar gl-ml-auto gl-pb-3 gl-justify-content-center"
+ >
<toolbar-button
tag="**"
:button-title="
diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb
index 906c4b98f56..1baa4ddf0eb 100644
--- a/app/services/quick_actions/interpret_service.rb
+++ b/app/services/quick_actions/interpret_service.rb
@@ -79,7 +79,7 @@ module QuickActions
# using a user-style reference, which is not in scope here.
args = params.split(/\s|,/).select(&:present?).uniq - ['and']
usernames = (args - ['me']).map { _1.delete_prefix('@') }
- found = User.by_username(usernames).to_a.select { can?(:read_user_profile, _1) }
+ found = User.by_username(usernames).to_a.select { can?(:read_user, _1) }
found_names = found.map(&:username).to_set
missing = args.reject { |arg| arg == 'me' || found_names.include?(arg.delete_prefix('@')) }.map { "'#{_1}'" }
diff --git a/data/whats_new/202202210001_14_08.yml b/data/whats_new/202202210001_14_08.yml
new file mode 100644
index 00000000000..116eb889bbe
--- /dev/null
+++ b/data/whats_new/202202210001_14_08.yml
@@ -0,0 +1,92 @@
+- title: "Support for ecdsa-sk and ed25519-sk SSH keys"
+ body: |
+ [OpenSSH 8.2](https://www.openssh.com/releasenotes.html#8.2) added support for FIDO/U2F hardware authenticators with new
+ ecdsa-sk and ed25519-sk key types.
+
+ GitLab now supports these key types, allowing users to take advantage of hardware-backed SSH authentication.
+ stage: manage
+ self-managed: true
+ gitlab-com: true
+ packages: [Free, Premium, Ultimate]
+ url: 'https://docs.gitlab.com/ee/ssh/#generate-an-ssh-key-pair-for-a-fidou2f-hardware-security-key'
+ image_url: 'https://about.gitlab.com/images/14_8/ssh_key.png'
+ published_at: 2022-02-22
+ release: 14.8
+- title: "Auto-completion of keywords in the Pipeline Editor"
+ body: |
+ Writing a valid GitLab CI/CD pipeline can be difficult regardless of whether you're a novice or more advanced user. Syntax structure should be accurate and even a small typo or misconfiguration could cause your pipeline to be invalid, introducing more work to find the source of the problem. In this release, we've added auto-completion of CI/CD keywords to the pipeline editor, which will greatly increase your efficiency when writing and debugging pipelines. You'll be more confident that your pipeline will run the way you want it the very first time it runs.
+ stage: verify
+ self-managed: true
+ gitlab-com: true
+ packages: [Free, Premium, Ultimate]
+ url: 'https://docs.gitlab.com/ee/ci/pipeline_editor/index.html#validate-ci-configuration'
+ image_url: 'https://about.gitlab.com/images/growth/verify.png'
+ published_at: 2022-02-22
+ release: 14.8
+- title: "Security approval policies"
+ body: |
+ GitLab now supports flexible security approvals as the replacement for the deprecated Vulnerability-Check feature. Security approvals are similar to Vulnerability-Check in that both can require approvals for MRs that contain security vulnerabilities. However, security approvals improve the previous experience in several ways:
+
+ - Users can choose who is allowed to edit security approval rules. An independent security or compliance team can therefore manage rules in a way that prevents development project maintainers from modifying the rules.
+ - Multiple rules can be created and chained together to allow for filtering on different severity thresholds for each scanner type.
+ - A two-step approval process can be enforced for any desired changes to security approval rules.
+ - A single set of security policies can be applied to multiple development projects to allow for ease in maintaining a single, centralized ruleset.
+
+ Security approval policies can be used alongside the existing Vulnerability-Check feature, as the two policies are additive and don't conflict. However, we encourage users to migrate their Vulnerability-Check rules over to security approval policies. Vulnerability-Check rules are now [deprecated](https://docs.gitlab.com/ee/update/deprecations.html#vulnerability-check), and are scheduled for removal in GitLab 15.0. Self managed users will need to enable the `scan_result_policy` feature flag prior to using this feature. To get started, navigate to **Security & Compliance > Policies** and create a new Scan Result type policy.
+ stage: protect
+ self-managed: true
+ gitlab-com: true
+ packages: [Ultimate]
+ url: 'https://docs.gitlab.com/ee/user/application_security/policies/scan-result-policies'
+ image_url: 'https://about.gitlab.com/images/14_8/protect-security-approval-policies.png'
+ published_at: 2022-02-22
+ release: 14.8
+- title: "On-demand security scan index view"
+ body: |
+ Find all your on-demand DAST and DAST API scans on a single page. We have introduced a new index page for on-demand scans that shows your in-progress scans, previously run scans, saved scans, and scheduled scans. From this index page, you can find specific scans easily or re-run scans that have already finished. In previous versions of GitLab, to see on-demand scans that were in-progress or had finished, you needed to search through the pipelines page to find the right pipeline. Saved on-demand scans were located in the Security & Compliance configuration section. To find scheduled scans, you needed to look at each saved scan individually to see their schedule. All of those activities are now rolled into one page to make it easier to run on-demand security testing outside of CI/CD builds, MRs, or pipelines.
+ stage: secure
+ self-managed: true
+ gitlab-com: true
+ packages: [Ultimate]
+ url: 'https://docs.gitlab.com/ee/user/application_security/dast/#view-on-demand-dast-scans'
+ image_url: 'https://about.gitlab.com/images/14_8/dast-on-demand-index-page.png'
+ published_at: 2022-02-22
+ release: 14.8
+- title: "User impersonation audit events for groups"
+ body: |
+ GitLab now provides audit events on the group audit events page for
+ [user impersonation](https://docs.gitlab.com/ee/user/admin_area/#user-impersonation) starting and stopping. This was previously
+ only available on a page unavailable to GitLab SaaS customers. We are excited to bring
+ it to the group page which allows both self-managed and SaaS users to view these events!
+
+ These events are helpful to understand if an administrator impersonated a user in your group and any actions that the
+ administrator took as the impersonated user. You can correlate:
+
+ - Any actions a user took.
+ - When impersonation was happening.
+
+ This can help you understand if it was actually the user performing certain actions or an administrator impersonating them. The
+ absence of impersonation events in the audit log is also a way to be confident that a given user actually performed given
+ actions, rather than someone impersonating them.
+ stage: manage
+ self-managed: true
+ gitlab-com: true
+ packages: [Premium, Ultimate]
+ url: 'https://docs.gitlab.com/ee/administration/audit_events.html#group-events'
+ image_url: 'https://about.gitlab.com/images/14_8/impersonation_audit_event.png'
+ published_at: 2022-02-22
+ release: 14.8
+- title: "Additional display options for roadmaps"
+ body: |
+ In this release, we have introduced additional progress tracking capabilities to roadmaps. You can now view the percentage of completed epics based on issue count instead of issue weight. This functionality is useful for organizations that are using Kanban or other methodologies that don't require their teams to set a weight on issues.
+
+ You can now also customize the level of milestones to include in your roadmap, allowing you to tailor your view to meet the needs of your audience.
+ stage: plan
+ self-managed: true
+ gitlab-com: true
+ packages: [Premium, Ultimate]
+ url: 'https://docs.gitlab.com/ee/user/group/roadmap/index.html#roadmap-settings'
+ image_url: 'https://about.gitlab.com/images/14_8/rp_roadmap_settings.png'
+ published_at: 2022-02-22
+ release: 14.8
+ \ No newline at end of file
diff --git a/lib/backup/files.rb b/lib/backup/files.rb
index 880522bc0f5..db6278360a3 100644
--- a/lib/backup/files.rb
+++ b/lib/backup/files.rb
@@ -9,13 +9,11 @@ module Backup
DEFAULT_EXCLUDE = 'lost+found'
- attr_reader :name, :app_files_dir, :backup_tarball, :excludes, :files_parent_dir
+ attr_reader :name, :backup_tarball, :excludes
def initialize(name, app_files_dir, excludes: [])
@name = name
- @app_files_dir = File.realpath(app_files_dir)
- @files_parent_dir = File.realpath(File.join(@app_files_dir, '..'))
- @backup_files_dir = File.join(Gitlab.config.backup.path, File.basename(@app_files_dir) )
+ @app_files_dir = app_files_dir
@backup_tarball = File.join(Gitlab.config.backup.path, name + '.tar.gz')
@excludes = [DEFAULT_EXCLUDE].concat(excludes)
end
@@ -26,7 +24,7 @@ module Backup
FileUtils.rm_f(backup_tarball)
if ENV['STRATEGY'] == 'copy'
- cmd = [%w[rsync -a --delete], exclude_dirs(:rsync), %W[#{app_files_dir} #{Gitlab.config.backup.path}]].flatten
+ cmd = [%w[rsync -a --delete], exclude_dirs(:rsync), %W[#{app_files_realpath} #{Gitlab.config.backup.path}]].flatten
output, status = Gitlab::Popen.popen(cmd)
# Retry if rsync source files vanish
@@ -40,11 +38,11 @@ module Backup
raise_custom_error
end
- tar_cmd = [tar, exclude_dirs(:tar), %W[-C #{@backup_files_dir} -cf - .]].flatten
+ tar_cmd = [tar, exclude_dirs(:tar), %W[-C #{backup_files_realpath} -cf - .]].flatten
status_list, output = run_pipeline!([tar_cmd, gzip_cmd], out: [backup_tarball, 'w', 0600])
- FileUtils.rm_rf(@backup_files_dir)
+ FileUtils.rm_rf(backup_files_realpath)
else
- tar_cmd = [tar, exclude_dirs(:tar), %W[-C #{app_files_dir} -cf - .]].flatten
+ tar_cmd = [tar, exclude_dirs(:tar), %W[-C #{app_files_realpath} -cf - .]].flatten
status_list, output = run_pipeline!([tar_cmd, gzip_cmd], out: [backup_tarball, 'w', 0600])
end
@@ -56,7 +54,7 @@ module Backup
def restore
backup_existing_files_dir
- cmd_list = [%w[gzip -cd], %W[#{tar} --unlink-first --recursive-unlink -C #{app_files_dir} -xf -]]
+ cmd_list = [%w[gzip -cd], %W[#{tar} --unlink-first --recursive-unlink -C #{app_files_realpath} -xf -]]
status_list, output = run_pipeline!(cmd_list, in: backup_tarball)
unless pipeline_succeeded?(gzip_status: status_list[0], tar_status: status_list[1], output: output)
raise Backup::Error, "Restore operation failed: #{output}"
@@ -78,17 +76,17 @@ module Backup
def backup_existing_files_dir
timestamped_files_path = File.join(Gitlab.config.backup.path, "tmp", "#{name}.#{Time.now.to_i}")
- if File.exist?(app_files_dir)
+ if File.exist?(app_files_realpath)
# Move all files in the existing repos directory except . and .. to
# repositories.old.<timestamp> directory
FileUtils.mkdir_p(timestamped_files_path, mode: 0700)
- files = Dir.glob(File.join(app_files_dir, "*"), File::FNM_DOTMATCH) - [File.join(app_files_dir, "."), File.join(app_files_dir, "..")]
+ files = Dir.glob(File.join(app_files_realpath, "*"), File::FNM_DOTMATCH) - [File.join(app_files_realpath, "."), File.join(app_files_realpath, "..")]
begin
FileUtils.mv(files, timestamped_files_path)
rescue Errno::EACCES
- access_denied_error(app_files_dir)
+ access_denied_error(app_files_realpath)
rescue Errno::EBUSY
- resource_busy_error(app_files_dir)
+ resource_busy_error(app_files_realpath)
end
end
end
@@ -141,7 +139,7 @@ module Backup
if s == DEFAULT_EXCLUDE
'--exclude=' + s
elsif fmt == :rsync
- '--exclude=/' + File.join(File.basename(app_files_dir), s)
+ '--exclude=/' + File.join(File.basename(app_files_realpath), s)
elsif fmt == :tar
'--exclude=./' + s
end
@@ -149,7 +147,17 @@ module Backup
end
def raise_custom_error
- raise FileBackupError.new(app_files_dir, backup_tarball)
+ raise FileBackupError.new(app_files_realpath, backup_tarball)
+ end
+
+ private
+
+ def app_files_realpath
+ @app_files_realpath ||= File.realpath(@app_files_dir)
+ end
+
+ def backup_files_realpath
+ @backup_files_realpath ||= File.join(Gitlab.config.backup.path, File.basename(@app_files_dir) )
end
end
end
diff --git a/spec/factories/users.rb b/spec/factories/users.rb
index 5f325717ec5..8764ac90af8 100644
--- a/spec/factories/users.rb
+++ b/spec/factories/users.rb
@@ -19,6 +19,10 @@ FactoryBot.define do
public_email { email }
end
+ trait :private_profile do
+ private_profile { true }
+ end
+
trait :blocked do
after(:build) { |user, _| user.block! }
end
diff --git a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
index b77b3d69fc1..2a49109d360 100644
--- a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
@@ -64,7 +64,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'sees branch pipelines and detached merge request pipelines in correct order' do
page.within('.ci-table') do
expect(page).to have_selector('.ci-created', count: 2)
- expect(first('[data-testid="pipeline-identifier"]')).to have_content("##{detached_merge_request_pipeline.id}")
+ expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{detached_merge_request_pipeline.id}")
end
end
@@ -101,16 +101,16 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
page.within('.ci-table') do
expect(page).to have_selector('.ci-pending', count: 4)
- expect(all('[data-testid="pipeline-identifier"]')[0])
+ expect(all('[data-testid="pipeline-url-link"]')[0])
.to have_content("##{detached_merge_request_pipeline_2.id}")
- expect(all('[data-testid="pipeline-identifier"]')[1])
+ expect(all('[data-testid="pipeline-url-link"]')[1])
.to have_content("##{detached_merge_request_pipeline.id}")
- expect(all('[data-testid="pipeline-identifier"]')[2])
+ expect(all('[data-testid="pipeline-url-link"]')[2])
.to have_content("##{push_pipeline_2.id}")
- expect(all('[data-testid="pipeline-identifier"]')[3])
+ expect(all('[data-testid="pipeline-url-link"]')[3])
.to have_content("##{push_pipeline.id}")
end
end
@@ -201,7 +201,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'sees a branch pipeline in pipeline tab' do
page.within('.ci-table') do
expect(page).to have_selector('.ci-created', count: 1)
- expect(first('[data-testid="pipeline-identifier"]')).to have_content("##{push_pipeline.id}")
+ expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{push_pipeline.id}")
end
end
@@ -252,7 +252,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'sees branch pipelines and detached merge request pipelines in correct order' do
page.within('.ci-table') do
expect(page).to have_selector('.ci-pending', count: 2)
- expect(first('[data-testid="pipeline-identifier"]')).to have_content("##{detached_merge_request_pipeline.id}")
+ expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{detached_merge_request_pipeline.id}")
end
end
@@ -295,16 +295,16 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
page.within('.ci-table') do
expect(page).to have_selector('.ci-pending', count: 4)
- expect(all('[data-testid="pipeline-identifier"]')[0])
+ expect(all('[data-testid="pipeline-url-link"]')[0])
.to have_content("##{detached_merge_request_pipeline_2.id}")
- expect(all('[data-testid="pipeline-identifier"]')[1])
+ expect(all('[data-testid="pipeline-url-link"]')[1])
.to have_content("##{detached_merge_request_pipeline.id}")
- expect(all('[data-testid="pipeline-identifier"]')[2])
+ expect(all('[data-testid="pipeline-url-link"]')[2])
.to have_content("##{push_pipeline_2.id}")
- expect(all('[data-testid="pipeline-identifier"]')[3])
+ expect(all('[data-testid="pipeline-url-link"]')[3])
.to have_content("##{push_pipeline.id}")
end
end
diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb
index a356dd50898..266ae0d8c37 100644
--- a/spec/features/merge_request/user_sees_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_pipelines_spec.rb
@@ -134,7 +134,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
create_merge_request_pipeline
act_on_security_warning(action: 'Run pipeline')
- check_pipeline(expected_project: parent_project, link_selector: 'pipeline-url-link')
+ check_pipeline(expected_project: parent_project)
check_head_pipeline(expected_project: parent_project)
end
@@ -179,13 +179,13 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
click_button('Run pipeline')
end
- def check_pipeline(expected_project:, link_selector: 'commit-title')
+ def check_pipeline(expected_project:)
page.within('.ci-table') do
expect(page).to have_selector('.commit', count: 2)
page.within(first('.commit')) do
page.within('.pipeline-tags') do
- expect(page.find("[data-testid=#{link_selector}]")[:href]).to include(expected_project.full_path)
+ expect(page.find('[data-testid="pipeline-url-link"]')[:href]).to include(expected_project.full_path)
expect(page).to have_content('detached')
end
page.within('.pipeline-triggerer') do
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index d5b470194a2..37ac5a9d5a2 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -711,7 +711,7 @@ RSpec.describe 'Pipelines', :js do
end
expect(page.find('[data-testid="pipeline-th"]')).to have_content 'Pipeline'
- expect(page.find('[data-testid="pipeline-identifier"]')).to have_content "##{pipeline.iid}"
+ expect(page.find('[data-testid="pipeline-url-link"]')).to have_content "##{pipeline.iid}"
end
end
end
diff --git a/spec/frontend/pipelines/mock_data.js b/spec/frontend/pipelines/mock_data.js
index 8cb6cf3bed6..59d4e808b32 100644
--- a/spec/frontend/pipelines/mock_data.js
+++ b/spec/frontend/pipelines/mock_data.js
@@ -676,7 +676,7 @@ export const mockPipeline = (projectPath) => {
short_id: 'fd6df5b3',
created_at: '2021-10-19T21:17:12.000+00:00',
parent_ids: ['7147906b84306e83cb3fec6582a25390b75713c6'],
- title: 'Commit Title',
+ title: 'Commit',
message: 'Commit',
author_name: 'Administrator',
author_email: 'admin@example.com',
@@ -1141,176 +1141,3 @@ export const mockPipelineBranch = () => {
viewType: 'root',
};
};
-
-export const mockPipelineNoCommit = () => {
- return {
- pipeline: {
- id: 268,
- iid: 34,
- user: {
- id: 1,
- username: 'root',
- name: 'Administrator',
- state: 'active',
- avatar_url:
- 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
- web_url: 'http://gdk.test:3000/root',
- show_status: false,
- path: '/root',
- },
- active: false,
- source: 'push',
- created_at: '2022-01-14T17:40:27.866Z',
- updated_at: '2022-01-14T18:02:35.850Z',
- path: '/root/mr-widgets/-/pipelines/268',
- flags: {
- stuck: false,
- auto_devops: false,
- merge_request: false,
- yaml_errors: false,
- retryable: true,
- cancelable: false,
- failure_reason: false,
- detached_merge_request_pipeline: false,
- merge_request_pipeline: false,
- merge_train_pipeline: false,
- latest: true,
- },
- details: {
- status: {
- icon: 'status_warning',
- text: 'passed',
- label: 'passed with warnings',
- group: 'success-with-warnings',
- tooltip: 'passed',
- has_details: true,
- details_path: '/root/mr-widgets/-/pipelines/268',
- illustration: null,
- favicon:
- '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
- },
- stages: [
- {
- name: 'validate',
- title: 'validate: passed with warnings',
- status: {
- icon: 'status_warning',
- text: 'passed',
- label: 'passed with warnings',
- group: 'success-with-warnings',
- tooltip: 'passed',
- has_details: true,
- details_path: '/root/mr-widgets/-/pipelines/268#validate',
- illustration: null,
- favicon:
- '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
- },
- path: '/root/mr-widgets/-/pipelines/268#validate',
- dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=validate',
- },
- {
- name: 'test',
- title: 'test: passed',
- status: {
- icon: 'status_success',
- text: 'passed',
- label: 'passed',
- group: 'success',
- tooltip: 'passed',
- has_details: true,
- details_path: '/root/mr-widgets/-/pipelines/268#test',
- illustration: null,
- favicon:
- '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
- },
- path: '/root/mr-widgets/-/pipelines/268#test',
- dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=test',
- },
- {
- name: 'build',
- title: 'build: passed',
- status: {
- icon: 'status_success',
- text: 'passed',
- label: 'passed',
- group: 'success',
- tooltip: 'passed',
- has_details: true,
- details_path: '/root/mr-widgets/-/pipelines/268#build',
- illustration: null,
- favicon:
- '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
- },
- path: '/root/mr-widgets/-/pipelines/268#build',
- dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=build',
- },
- ],
- duration: 75,
- finished_at: '2022-01-14T18:02:35.842Z',
- name: 'Pipeline',
- manual_actions: [],
- scheduled_actions: [],
- },
- ref: {
- name: 'update-ci',
- path: '/root/mr-widgets/-/commits/update-ci',
- tag: false,
- branch: true,
- merge_request: false,
- },
- retry_path: '/root/mr-widgets/-/pipelines/268/retry',
- delete_path: '/root/mr-widgets/-/pipelines/268',
- failed_builds: [
- {
- id: 1260,
- name: 'fmt',
- started: '2022-01-14T17:40:36.435Z',
- complete: true,
- archived: false,
- build_path: '/root/mr-widgets/-/jobs/1260',
- retry_path: '/root/mr-widgets/-/jobs/1260/retry',
- playable: false,
- scheduled: false,
- created_at: '2022-01-14T17:40:27.879Z',
- updated_at: '2022-01-14T17:40:42.129Z',
- status: {
- icon: 'status_warning',
- text: 'failed',
- label: 'failed (allowed to fail)',
- group: 'failed-with-warnings',
- tooltip: 'failed - (script failure) (allowed to fail)',
- has_details: true,
- details_path: '/root/mr-widgets/-/jobs/1260',
- illustration: {
- image:
- '/assets/illustrations/skipped-job_empty-29a8a37d8a61d1b6f68cf3484f9024e53cd6eb95e28eae3554f8011a1146bf27.svg',
- size: 'svg-430',
- title: 'This job does not have a trace.',
- },
- favicon:
- '/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png',
- action: {
- icon: 'retry',
- title: 'Retry',
- path: '/root/mr-widgets/-/jobs/1260/retry',
- method: 'post',
- button_title: 'Retry this job',
- },
- },
- recoverable: false,
- },
- ],
- project: {
- id: 23,
- name: 'mr-widgets',
- full_path: '/root/mr-widgets',
- full_name: 'Administrator / mr-widgets',
- },
- triggered_by: null,
- triggered: [],
- },
- pipelineScheduleUrl: 'foo',
- pipelineKey: 'id',
- viewType: 'root',
- };
-};
diff --git a/spec/frontend/pipelines/pipeline_url_spec.js b/spec/frontend/pipelines/pipeline_url_spec.js
index b24e2e09ea8..2f083faaaa6 100644
--- a/spec/frontend/pipelines/pipeline_url_spec.js
+++ b/spec/frontend/pipelines/pipeline_url_spec.js
@@ -1,12 +1,7 @@
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { trimText } from 'helpers/text_helper';
import PipelineUrlComponent from '~/pipelines/components/pipelines_list/pipeline_url.vue';
-import {
- mockPipeline,
- mockPipelineBranch,
- mockPipelineTag,
- mockPipelineNoCommit,
-} from './mock_data';
+import { mockPipeline, mockPipelineBranch, mockPipelineTag } from './mock_data';
const projectPath = 'test/test';
@@ -31,7 +26,7 @@ describe('Pipeline Url Component', () => {
const findCommitIconType = () => wrapper.findByTestId('commit-icon-type');
const findCommitTitleContainer = () => wrapper.findByTestId('commit-title-container');
- const findCommitTitle = () => wrapper.findByTestId('commit-title');
+ const findCommitTitle = (commitWrapper) => commitWrapper.find('[data-testid="commit-title"]');
const defaultProps = mockPipeline(projectPath);
@@ -237,33 +232,5 @@ describe('Pipeline Url Component', () => {
expect(findCommitIconType().attributes('title')).toBe(expectedTitle);
},
);
-
- describe('with commit', () => {
- beforeEach(() => {
- createComponent({}, true);
- });
-
- it('displays commit title with link to pipeline', () => {
- expect(findCommitTitle().attributes('href')).toBe(defaultProps.pipeline.path);
- });
-
- it('displays commit title text', () => {
- expect(findCommitTitle().text()).toBe(defaultProps.pipeline.commit.title);
- });
- });
-
- describe('without commit', () => {
- beforeEach(() => {
- createComponent(mockPipelineNoCommit(), true);
- });
-
- it('displays cant find head commit text', () => {
- expect(findCommitTitle().text()).toBe("Can't find HEAD commit for this branch");
- });
-
- it('displays link to pipeline', () => {
- expect(findCommitTitle().attributes('href')).toBe(mockPipelineNoCommit().pipeline.path);
- });
- });
});
});
diff --git a/spec/frontend/vue_shared/components/markdown/header_spec.js b/spec/frontend/vue_shared/components/markdown/header_spec.js
index 93ce3935fab..700ec75fcee 100644
--- a/spec/frontend/vue_shared/components/markdown/header_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/header_spec.js
@@ -20,6 +20,7 @@ describe('Markdown field header component', () => {
const findWriteTab = () => wrapper.findByTestId('write-tab');
const findPreviewTab = () => wrapper.findByTestId('preview-tab');
+ const findToolbar = () => wrapper.findByTestId('md-header-toolbar');
const findToolbarButtons = () => wrapper.findAll(ToolbarButton);
const findToolbarButtonByProp = (prop, value) =>
findToolbarButtons()
@@ -90,6 +91,12 @@ describe('Markdown field header component', () => {
expect(findPreviewTab().attributes('active')).toBe('true');
});
+ it('hides toolbar in preview mode', () => {
+ createWrapper({ previewMarkdown: true });
+
+ expect(findToolbar().classes().includes('gl-display-none')).toBe(true);
+ });
+
it('emits toggle markdown event when clicking preview tab', async () => {
const eventData = { target: {} };
findPreviewTab().vm.$emit('click', eventData);
diff --git a/spec/lib/backup/artifacts_spec.rb b/spec/lib/backup/artifacts_spec.rb
index 102d787a5e1..e65dc79b65b 100644
--- a/spec/lib/backup/artifacts_spec.rb
+++ b/spec/lib/backup/artifacts_spec.rb
@@ -7,16 +7,6 @@ RSpec.describe Backup::Artifacts do
subject(:backup) { described_class.new(progress) }
- describe '#initialize' do
- it 'uses the correct upload dir' do
- Dir.mktmpdir do |tmpdir|
- allow(JobArtifactUploader).to receive(:root) { "#{tmpdir}" }
-
- expect(backup.app_files_dir).to eq("#{File.realpath(tmpdir)}")
- end
- end
- end
-
describe '#dump' do
before do
allow(File).to receive(:realpath).with('/var/gitlab-artifacts').and_return('/var/gitlab-artifacts')
@@ -24,10 +14,6 @@ RSpec.describe Backup::Artifacts do
allow(JobArtifactUploader).to receive(:root) { '/var/gitlab-artifacts' }
end
- it 'uses the correct artifact dir' do
- expect(backup.app_files_dir).to eq('/var/gitlab-artifacts')
- end
-
it 'excludes tmp from backup tar' do
expect(backup).to receive(:tar).and_return('blabla-tar')
expect(backup).to receive(:run_pipeline!).with([%w(blabla-tar --exclude=lost+found --exclude=./tmp -C /var/gitlab-artifacts -cf - .), 'gzip -c -1'], any_args).and_return([[true, true], ''])
diff --git a/spec/lib/backup/lfs_spec.rb b/spec/lib/backup/lfs_spec.rb
index fdc1c0c885d..6525019d9ac 100644
--- a/spec/lib/backup/lfs_spec.rb
+++ b/spec/lib/backup/lfs_spec.rb
@@ -16,7 +16,6 @@ RSpec.describe Backup::Lfs do
end
it 'uses the correct lfs dir in tar command', :aggregate_failures do
- expect(backup.app_files_dir).to eq('/var/lfs-objects')
expect(backup).to receive(:tar).and_return('blabla-tar')
expect(backup).to receive(:run_pipeline!).with([%w(blabla-tar --exclude=lost+found -C /var/lfs-objects -cf - .), 'gzip -c -1'], any_args).and_return([[true, true], ''])
expect(backup).to receive(:pipeline_succeeded?).and_return(true)
diff --git a/spec/lib/backup/manager_spec.rb b/spec/lib/backup/manager_spec.rb
index ac693ad8b98..9c186205067 100644
--- a/spec/lib/backup/manager_spec.rb
+++ b/spec/lib/backup/manager_spec.rb
@@ -12,11 +12,6 @@ RSpec.describe Backup::Manager do
before do
allow(progress).to receive(:puts)
allow(progress).to receive(:print)
- FileUtils.mkdir_p('tmp/tests/public/uploads')
- end
-
- after do
- FileUtils.rm_rf('tmp/tests/public/uploads', secure: true)
end
describe '#pack' do
diff --git a/spec/lib/backup/object_backup_spec.rb b/spec/lib/backup/object_backup_spec.rb
index 6192b5c3482..4d34dc0ade7 100644
--- a/spec/lib/backup/object_backup_spec.rb
+++ b/spec/lib/backup/object_backup_spec.rb
@@ -17,7 +17,6 @@ RSpec.shared_examples 'backup object' do |setting|
end
it 'uses the correct storage dir in tar command and excludes tmp', :aggregate_failures do
- expect(backup.app_files_dir).to eq(backup_path)
expect(backup).to receive(:tar).and_return('blabla-tar')
expect(backup).to receive(:run_pipeline!).with([%W(blabla-tar --exclude=lost+found --exclude=./tmp -C #{backup_path} -cf - .), 'gzip -c -1'], any_args).and_return([[true, true], ''])
expect(backup).to receive(:pipeline_succeeded?).and_return(true)
diff --git a/spec/lib/backup/pages_spec.rb b/spec/lib/backup/pages_spec.rb
index 551d2df8f30..f9ee4bbdc41 100644
--- a/spec/lib/backup/pages_spec.rb
+++ b/spec/lib/backup/pages_spec.rb
@@ -13,12 +13,6 @@ RSpec.describe Backup::Pages do
end
describe '#dump' do
- it 'uses the correct pages dir' do
- allow(Gitlab.config.pages).to receive(:path) { '/var/gitlab-pages' }
-
- expect(subject.app_files_dir).to eq('/var/gitlab-pages')
- end
-
it 'excludes tmp from backup tar' do
allow(Gitlab.config.pages).to receive(:path) { '/var/gitlab-pages' }
diff --git a/spec/lib/backup/uploads_spec.rb b/spec/lib/backup/uploads_spec.rb
index c173916fe91..25ad0c0d3f7 100644
--- a/spec/lib/backup/uploads_spec.rb
+++ b/spec/lib/backup/uploads_spec.rb
@@ -7,18 +7,6 @@ RSpec.describe Backup::Uploads do
subject(:backup) { described_class.new(progress) }
- describe '#initialize' do
- it 'uses the correct upload dir' do
- Dir.mktmpdir do |tmpdir|
- FileUtils.mkdir_p("#{tmpdir}/uploads")
-
- allow(Gitlab.config.uploads).to receive(:storage_path) { tmpdir }
-
- expect(backup.app_files_dir).to eq("#{File.realpath(tmpdir)}/uploads")
- end
- end
- end
-
describe '#dump' do
before do
allow(File).to receive(:realpath).and_call_original
@@ -27,10 +15,6 @@ RSpec.describe Backup::Uploads do
allow(Gitlab.config.uploads).to receive(:storage_path) { '/var' }
end
- it 'uses the correct upload dir' do
- expect(backup.app_files_dir).to eq('/var/uploads')
- end
-
it 'excludes tmp from backup tar' do
expect(backup).to receive(:tar).and_return('blabla-tar')
expect(backup).to receive(:run_pipeline!).with([%w(blabla-tar --exclude=lost+found --exclude=./tmp -C /var/uploads -cf - .), 'gzip -c -1'], any_args).and_return([[true, true], ''])
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index ca3ae437540..afeb95a3ca3 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -682,6 +682,20 @@ RSpec.describe QuickActions::InterpretService do
expect(message).to eq("Assigned #{developer.to_reference}.")
end
+
+ context 'when the user has a private profile' do
+ let(:user) { create(:user, :private_profile) }
+ let(:content) { "/assign #{user.to_reference}" }
+
+ it 'assigns to the user' do
+ issuable.project.add_developer(user)
+
+ _, updates, message = service.execute(content, issuable)
+
+ expect(updates).to eq(assignee_ids: [user.id])
+ expect(message).to eq("Assigned #{user.to_reference}.")
+ end
+ end
end
shared_examples 'assign_reviewer command' do
@@ -971,24 +985,6 @@ RSpec.describe QuickActions::InterpretService do
it_behaves_like 'assign_reviewer command'
end
- context 'with a private user' do
- let(:ref) { create(:user, :unconfirmed).to_reference }
- let(:content) { "/assign_reviewer #{ref}" }
-
- it_behaves_like 'failed command', 'a parse error' do
- let(:match_msg) { eq "Could not apply assign_reviewer command. Failed to find users for '#{ref}'." }
- end
- end
-
- context 'with a private user, bare username' do
- let(:ref) { create(:user, :unconfirmed).username }
- let(:content) { "/assign_reviewer #{ref}" }
-
- it_behaves_like 'failed command', 'a parse error' do
- let(:match_msg) { eq "Could not apply assign_reviewer command. Failed to find users for '#{ref}'." }
- end
- end
-
context 'with @all' do
let(:content) { "/assign_reviewer @all" }