summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/project_find_file.js2
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss4
-rw-r--r--app/controllers/projects/artifacts_controller.rb38
-rw-r--r--app/finders/artifacts_finder.rb24
-rw-r--r--app/helpers/sorting_helper.rb20
-rw-r--r--app/models/ci/job_artifact.rb5
-rw-r--r--app/models/project.rb1
-rw-r--r--app/models/protected_branch.rb5
-rw-r--r--app/models/release.rb1
-rw-r--r--config/routes/project.rb2
-rw-r--r--db/post_migrate/20190827102026_migrate_code_owner_approval_status_to_protected_branches_in_batches.rb46
-rw-r--r--locale/gitlab.pot14
-rw-r--r--package.json6
-rw-r--r--spec/controllers/projects/artifacts_controller_spec.rb111
-rw-r--r--spec/finders/artifacts_finder_spec.rb31
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml1
-rw-r--r--spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb63
-rw-r--r--spec/models/release_spec.rb1
-rw-r--r--yarn.lock31
19 files changed, 261 insertions, 145 deletions
diff --git a/app/assets/javascripts/project_find_file.js b/app/assets/javascripts/project_find_file.js
index e73a828c0ae..c198c4eea4a 100644
--- a/app/assets/javascripts/project_find_file.js
+++ b/app/assets/javascripts/project_find_file.js
@@ -81,7 +81,7 @@ export default class ProjectFindFile {
// find file
}
- // files pathes load
+ // files paths load
load(url) {
axios
.get(url)
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index 43d0e51e4c9..b9cfcf6ce5c 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -171,7 +171,7 @@
position: absolute;
top: $gl-padding;
bottom: $gl-padding;
- left: map-get($spacers, 2) - 1px;
+ left: map-get($spacers, 2) - px-to-rem(1px);
}
&-row {
@@ -187,7 +187,7 @@
* 2px extra is to give a little more height than needed
* to hide timeline line before/after the element starts/ends
*/
- height: map-get($spacers, 4) + 2px;
+ height: map-get($spacers, 4) + px-to-rem(2px);
z-index: 1;
position: relative;
top: -3px;
diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb
index da8a371acaa..50399a8cfbb 100644
--- a/app/controllers/projects/artifacts_controller.rb
+++ b/app/controllers/projects/artifacts_controller.rb
@@ -8,10 +8,37 @@ class Projects::ArtifactsController < Projects::ApplicationController
layout 'project'
before_action :authorize_read_build!
before_action :authorize_update_build!, only: [:keep]
+ before_action :authorize_destroy_artifacts!, only: [:destroy]
before_action :extract_ref_name_and_path
- before_action :validate_artifacts!, except: [:download]
+ before_action :validate_artifacts!, except: [:index, :download, :destroy]
before_action :entry, only: [:file]
+ MAX_PER_PAGE = 20
+
+ def index
+ # Loading artifacts is very expensive in projects with a lot of artifacts.
+ # This feature flag prevents a DOS attack vector.
+ # It should be removed only after resolving the underlying performance
+ # issues: https://gitlab.com/gitlab-org/gitlab/issues/32281
+ return head :no_content unless Feature.enabled?(:artifacts_management_page, @project)
+
+ finder = ArtifactsFinder.new(@project, artifacts_params)
+ all_artifacts = finder.execute
+
+ @artifacts = all_artifacts.page(params[:page]).per(MAX_PER_PAGE)
+ @total_size = all_artifacts.total_size
+ end
+
+ def destroy
+ notice = if artifact.destroy
+ _('Artifact was successfully deleted.')
+ else
+ _('Artifact could not be deleted.')
+ end
+
+ redirect_to project_artifacts_path(@project), status: :see_other, notice: notice
+ end
+
def download
return render_404 unless artifacts_file
@@ -74,6 +101,10 @@ class Projects::ArtifactsController < Projects::ApplicationController
@ref_name, @path = extract_ref(params[:ref_name_and_path])
end
+ def artifacts_params
+ params.permit(:sort)
+ end
+
def validate_artifacts!
render_404 unless build&.artifacts?
end
@@ -85,6 +116,11 @@ class Projects::ArtifactsController < Projects::ApplicationController
end
end
+ def artifact
+ @artifact ||=
+ project.job_artifacts.find(params[:id])
+ end
+
def build_from_id
project.builds.find_by_id(params[:job_id]) if params[:job_id]
end
diff --git a/app/finders/artifacts_finder.rb b/app/finders/artifacts_finder.rb
new file mode 100644
index 00000000000..81c5168d782
--- /dev/null
+++ b/app/finders/artifacts_finder.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class ArtifactsFinder
+ def initialize(project, params = {})
+ @project = project
+ @params = params
+ end
+
+ def execute
+ artifacts = @project.job_artifacts
+
+ sort(artifacts)
+ end
+
+ private
+
+ def sort_key
+ @params[:sort] || 'created_desc'
+ end
+
+ def sort(artifacts)
+ artifacts.order_by(sort_key)
+ end
+end
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index d680e10525d..33f3bb0b749 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -28,7 +28,9 @@ module SortingHelper
sort_value_priority => sort_title_priority,
sort_value_upvotes => sort_title_upvotes,
sort_value_contacted_date => sort_title_contacted_date,
- sort_value_relative_position => sort_title_relative_position
+ sort_value_relative_position => sort_title_relative_position,
+ sort_value_size => sort_title_size,
+ sort_value_expire_date => sort_title_expire_date
}
end
@@ -406,6 +408,14 @@ module SortingHelper
s_('SortOptions|Manual')
end
+ def sort_title_size
+ s_('SortOptions|Size')
+ end
+
+ def sort_title_expire_date
+ s_('SortOptions|Expired date')
+ end
+
# Values.
def sort_value_access_level_asc
'access_level_asc'
@@ -558,4 +568,12 @@ module SortingHelper
def sort_value_relative_position
'relative_position'
end
+
+ def sort_value_size
+ 'size_desc'
+ end
+
+ def sort_value_expire_date
+ 'expired_asc'
+ end
end
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index da2758507ce..add9110ee5e 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -5,6 +5,7 @@ module Ci
include AfterCommitQueue
include ObjectStorage::BackgroundMove
include UpdateProjectStatistics
+ include Sortable
extend Gitlab::Ci::Model
NotSupportedAdapterError = Class.new(StandardError)
@@ -143,6 +144,10 @@ module Ci
self.update_column(:file_store, file.object_store)
end
+ def self.total_size
+ self.sum(:size)
+ end
+
def self.artifacts_size_for(project)
self.where(project: project).sum(:size)
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 7c065db9829..18afccf7ddc 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -273,6 +273,7 @@ class Project < ApplicationRecord
has_many :builds, class_name: 'Ci::Build', inverse_of: :project, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :build_trace_section_names, class_name: 'Ci::BuildTraceSectionName'
has_many :build_trace_chunks, class_name: 'Ci::BuildTraceChunk', through: :builds, source: :trace_chunks
+ has_many :job_artifacts, class_name: 'Ci::JobArtifact'
has_many :runner_projects, class_name: 'Ci::RunnerProject', inverse_of: :project
has_many :runners, through: :runner_projects, source: :runner, class_name: 'Ci::Runner'
has_many :variables, class_name: 'Ci::Variable'
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 1857a59e01c..8769d3eb916 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -40,11 +40,6 @@ class ProtectedBranch < ApplicationRecord
def self.protected_refs(project)
project.protected_branches.select(:name)
end
-
- def self.branch_requires_code_owner_approval?(project, branch_name)
- # NOOP
- #
- end
end
ProtectedBranch.prepend_if_ee('EE::ProtectedBranch')
diff --git a/app/models/release.rb b/app/models/release.rb
index cd63b4d5fef..9117a475ee9 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -22,7 +22,6 @@ class Release < ApplicationRecord
accepts_nested_attributes_for :links, allow_destroy: true
validates :description, :project, :tag, presence: true
- validates :name, presence: true, on: :create
validates_associated :milestone_releases, message: -> (_, obj) { obj[:value].map(&:errors).map(&:full_messages).join(",") }
scope :sorted, -> { order(released_at: :desc) }
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 4a2898915b1..5225cd5b054 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -37,6 +37,8 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
scope '-' do
get 'archive/*id', constraints: { format: Gitlab::PathRegex.archive_formats_regex, id: /.+?/ }, to: 'repositories#archive', as: 'archive'
+ resources :artifacts, only: [:index, :destroy]
+
resources :jobs, only: [:index, :show], constraints: { id: /\d+/ } do
collection do
resources :artifacts, only: [] do
diff --git a/db/post_migrate/20190827102026_migrate_code_owner_approval_status_to_protected_branches_in_batches.rb b/db/post_migrate/20190827102026_migrate_code_owner_approval_status_to_protected_branches_in_batches.rb
deleted file mode 100644
index b109f582909..00000000000
--- a/db/post_migrate/20190827102026_migrate_code_owner_approval_status_to_protected_branches_in_batches.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateCodeOwnerApprovalStatusToProtectedBranchesInBatches < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- DOWNTIME = false
- BATCH_SIZE = 200
-
- class Project < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'projects'
- self.inheritance_column = :_type_disabled
-
- has_many :protected_branches
- end
-
- class ProtectedBranch < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'protected_branches'
- self.inheritance_column = :_type_disabled
-
- belongs_to :project
- end
-
- def up
- add_concurrent_index :projects, :id, name: "temp_active_projects_with_prot_branches", where: 'archived = false and pending_delete = false and merge_requests_require_code_owner_approval = true'
-
- ProtectedBranch
- .joins(:project)
- .where(projects: { archived: false, pending_delete: false, merge_requests_require_code_owner_approval: true })
- .each_batch(of: BATCH_SIZE) do |batch|
- batch.update_all(code_owner_approval_required: true)
- end
-
- remove_concurrent_index_by_name(:projects, "temp_active_projects_with_prot_branches")
- end
-
- def down
- # noop
- #
- end
-end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 1acf483135f..b72a5f45658 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -1860,6 +1860,12 @@ msgstr ""
msgid "Artifact ID"
msgstr ""
+msgid "Artifact could not be deleted."
+msgstr ""
+
+msgid "Artifact was successfully deleted."
+msgstr ""
+
msgid "Artifacts"
msgstr ""
@@ -14483,6 +14489,9 @@ msgstr ""
msgid "SortOptions|Due soon"
msgstr ""
+msgid "SortOptions|Expired date"
+msgstr ""
+
msgid "SortOptions|Label priority"
msgstr ""
@@ -14573,6 +14582,9 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
+msgid "SortOptions|Size"
+msgstr ""
+
msgid "SortOptions|Sort direction"
msgstr ""
@@ -17962,7 +17974,7 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don’t have acces to Productivity Analaytics in this group"
+msgid "You don’t have access to Productivity Analytics in this group"
msgstr ""
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
diff --git a/package.json b/package.json
index c468f7875ae..8298e72e8aa 100644
--- a/package.json
+++ b/package.json
@@ -37,9 +37,9 @@
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-syntax-import-meta": "^7.2.0",
"@babel/preset-env": "^7.5.5",
- "@gitlab/svgs": "^1.73.0",
- "@gitlab/ui": "5.25.2",
- "@gitlab/visual-review-tools": "1.0.1",
+ "@gitlab/svgs": "^1.74.0",
+ "@gitlab/ui": "5.26.0",
+ "@gitlab/visual-review-tools": "1.0.2",
"apollo-cache-inmemory": "^1.5.1",
"apollo-client": "^2.5.1",
"apollo-link": "^1.2.11",
diff --git a/spec/controllers/projects/artifacts_controller_spec.rb b/spec/controllers/projects/artifacts_controller_spec.rb
index 6ea82785e98..c0b01e573b2 100644
--- a/spec/controllers/projects/artifacts_controller_spec.rb
+++ b/spec/controllers/projects/artifacts_controller_spec.rb
@@ -6,7 +6,7 @@ describe Projects::ArtifactsController do
let(:user) { project.owner }
set(:project) { create(:project, :repository, :public) }
- let(:pipeline) do
+ set(:pipeline) do
create(:ci_pipeline,
project: project,
sha: project.commit.sha,
@@ -14,12 +14,119 @@ describe Projects::ArtifactsController do
status: 'success')
end
- let(:job) { create(:ci_build, :success, :artifacts, pipeline: pipeline) }
+ let!(:job) { create(:ci_build, :success, :artifacts, pipeline: pipeline) }
before do
sign_in(user)
end
+ describe 'GET index' do
+ subject { get :index, params: { namespace_id: project.namespace, project_id: project } }
+
+ context 'when feature flag is on' do
+ before do
+ stub_feature_flags(artifacts_management_page: true)
+ end
+
+ it 'sets the artifacts variable' do
+ subject
+
+ expect(assigns(:artifacts)).to contain_exactly(*project.job_artifacts)
+ end
+
+ it 'sets the total size variable' do
+ subject
+
+ expect(assigns(:total_size)).to eq(project.job_artifacts.total_size)
+ end
+
+ describe 'pagination' do
+ before do
+ stub_const("#{described_class}::MAX_PER_PAGE", 1)
+ end
+
+ it 'paginates artifacts' do
+ subject
+
+ expect(assigns(:artifacts)).to contain_exactly(project.job_artifacts.last)
+ end
+ end
+ end
+
+ context 'when feature flag is off' do
+ before do
+ stub_feature_flags(artifacts_management_page: false)
+ end
+
+ it 'renders no content' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+
+ it 'does not set the artifacts variable' do
+ subject
+
+ expect(assigns(:artifacts)).to eq(nil)
+ end
+
+ it 'does not set the total size variable' do
+ subject
+
+ expect(assigns(:total_size)).to eq(nil)
+ end
+ end
+ end
+
+ describe 'DELETE destroy' do
+ let!(:artifact) { job.job_artifacts.erasable.first }
+
+ subject { delete :destroy, params: { namespace_id: project.namespace, project_id: project, id: artifact } }
+
+ it 'deletes the artifact' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(-1)
+ expect(artifact).not_to exist
+ end
+
+ it 'redirects to artifacts index page' do
+ subject
+
+ expect(response).to redirect_to(project_artifacts_path(project))
+ end
+
+ it 'sets the notice' do
+ subject
+
+ expect(flash[:notice]).to eq('Artifact was successfully deleted.')
+ end
+
+ context 'when artifact deletion fails' do
+ before do
+ allow_any_instance_of(Ci::JobArtifact).to receive(:destroy).and_return(false)
+ end
+
+ it 'redirects to artifacts index page' do
+ subject
+
+ expect(response).to redirect_to(project_artifacts_path(project))
+ end
+
+ it 'sets the notice' do
+ subject
+
+ expect(flash[:notice]).to eq('Artifact could not be deleted.')
+ end
+ end
+
+ context 'when user is not authorized' do
+ let(:user) { create(:user) }
+
+ it 'does not delete the artifact' do
+ expect { subject }.not_to change { Ci::JobArtifact.count }
+ end
+ end
+ end
+
describe 'GET download' do
def download_artifact(extra_params = {})
params = { namespace_id: project.namespace, project_id: project, job_id: job }.merge(extra_params)
diff --git a/spec/finders/artifacts_finder_spec.rb b/spec/finders/artifacts_finder_spec.rb
new file mode 100644
index 00000000000..b956e2c9515
--- /dev/null
+++ b/spec/finders/artifacts_finder_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ArtifactsFinder do
+ let(:project) { create(:project) }
+
+ describe '#execute' do
+ before do
+ create(:ci_build, :artifacts, project: project)
+ end
+
+ subject { described_class.new(project, params).execute }
+
+ context 'with empty params' do
+ let(:params) { {} }
+
+ it 'returns all artifacts belonging to the project' do
+ expect(subject).to contain_exactly(*project.job_artifacts)
+ end
+ end
+
+ context 'with sort param' do
+ let(:params) { { sort: 'size_desc' } }
+
+ it 'sorts the artifacts' do
+ expect(subject).to eq(project.job_artifacts.order_by('size_desc'))
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index d3be1e86539..3b43ff3a4e1 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -349,6 +349,7 @@ project:
- members_and_requesters
- build_trace_section_names
- build_trace_chunks
+- job_artifacts
- root_of_fork_network
- fork_network_member
- fork_network
diff --git a/spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb b/spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb
deleted file mode 100644
index 67ac40d4d39..00000000000
--- a/spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190827102026_migrate_code_owner_approval_status_to_protected_branches_in_batches.rb')
-
-describe MigrateCodeOwnerApprovalStatusToProtectedBranchesInBatches, :migration do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:protected_branches) { table(:protected_branches) }
-
- let(:namespace) do
- namespaces.create!(
- path: 'gitlab-instance-administrators',
- name: 'GitLab Instance Administrators'
- )
- end
-
- let(:project) do
- projects.create!(
- namespace_id: namespace.id,
- name: 'GitLab Instance Administration'
- )
- end
-
- let!(:protected_branch_1) do
- protected_branches.create!(
- name: "branch name",
- project_id: project.id
- )
- end
-
- describe '#up' do
- context "when there's no projects needing approval" do
- it "doesn't change any protected branch records" do
- expect { migrate! }
- .not_to change { ProtectedBranch.where(code_owner_approval_required: true).count }
- end
- end
-
- context "when there's a project needing approval" do
- let!(:project_needing_approval) do
- projects.create!(
- namespace_id: namespace.id,
- name: 'GitLab Instance Administration',
- merge_requests_require_code_owner_approval: true
- )
- end
-
- let!(:protected_branch_2) do
- protected_branches.create!(
- name: "branch name",
- project_id: project_needing_approval.id
- )
- end
-
- it "changes N protected branch records" do
- expect { migrate! }
- .to change { ProtectedBranch.where(code_owner_approval_required: true).count }
- .by(1)
- end
- end
- end
-end
diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb
index 8714c67f29d..e7a8d27a036 100644
--- a/spec/models/release_spec.rb
+++ b/spec/models/release_spec.rb
@@ -20,7 +20,6 @@ RSpec.describe Release do
describe 'validation' do
it { is_expected.to validate_presence_of(:project) }
it { is_expected.to validate_presence_of(:description) }
- it { is_expected.to validate_presence_of(:name) }
context 'when a release exists in the database without a name' do
it 'does not require name' do
diff --git a/yarn.lock b/yarn.lock
index 0186f8aad61..69e0644ac4a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -991,15 +991,15 @@
dependencies:
vue-eslint-parser "^6.0.4"
-"@gitlab/svgs@^1.73.0":
- version "1.73.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.73.0.tgz#e44b347e4be77b94474c80cf5c2ee26ca0325c2f"
- integrity sha512-4on+l5CS8Ae8OOcrnxwkO5s2zq1kHl/YjnOrHaX7megr6jsTYsVzKGaEMe0ViMSIPXA2+QnGD6vElKMkeD2+YQ==
+"@gitlab/svgs@^1.74.0":
+ version "1.74.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.74.0.tgz#2883c47c476a08e8c9c3621117a544204f4c13a3"
+ integrity sha512-L/Jga3EzGgOWF1rdQrH8wNm4dBFXcAVPZnFOEvBoe5OoWZgR3Ac/5Bgz4fYXYyPEKYUSorO7eyE6OVSvjKoM7g==
-"@gitlab/ui@5.25.2":
- version "5.25.2"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-5.25.2.tgz#599954fefcc228d31a398dbe3c1e2287a0fcdb3e"
- integrity sha512-mwwvEhVTomnZQjG0dADD+9Kg1UHZXAIb4s5QwQxwpgTkemILYIb1r96oKWfmPe8Pl/xrzAoMUtGEPT3XbxDqYQ==
+"@gitlab/ui@5.26.0":
+ version "5.26.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-5.26.0.tgz#303dcb339947b04bd04378828bd6b6ee1509ea9e"
+ integrity sha512-F8zjN6oiXUy787/4xD+vApuqRxiNe5ZhWg96gT23cUk5SL1Oj4NyMETpAh0v9R9J/i70ETmBYW011EGogjlAVA==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.2.1"
@@ -1013,10 +1013,10 @@
vue "^2.6.10"
vue-loader "^15.4.2"
-"@gitlab/visual-review-tools@1.0.1":
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.0.1.tgz#7e588328ed018d91560633d56865d65b72c3a11b"
- integrity sha512-vNqpui0khtPi3crrrFtfuT+nw0SdD/nMyb+aurbJzc3RXuVJGCdgYwosvTLPcJkdMOVfTijizV5+ys75s8INBw==
+"@gitlab/visual-review-tools@1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.0.2.tgz#d7b410d962cf32e6b6159207917134f7e6a90c68"
+ integrity sha512-U6cw/y/Hf9gYhpV9zBPv4SoIXf1hKye2Xrynj+1Yt2ZmJJG/+QnJfvS6MEuFcNcJRL42p1VDG98uzYMp3rJ7ww==
"@gitlab/vue-toasted@^1.2.1":
version "1.2.1"
@@ -11122,16 +11122,11 @@ sort-keys@^2.0.0:
dependencies:
is-plain-obj "^1.0.0"
-sortablejs@^1.10.0:
+sortablejs@^1.10.0, sortablejs@^1.9.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.10.0.tgz#0ebc054acff2486569194a2f975b2b145dd5e7d6"
integrity sha512-+e0YakK1BxgEZpf9l9UiFaiQ8ZOBn1p/4qkkXr8QDVmYyCrUDTyDRRGm0AgW4E4cD0wtgxJ6yzIRkSPUwqhuhg==
-sortablejs@^1.9.0:
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.9.0.tgz#2d1e74ae6bac2cb4ad0622908f340848969eb88d"
- integrity sha512-Ot6bYJ6PoqPmpsqQYXjn1+RKrY2NWQvQt/o4jfd/UYwVWndyO5EPO8YHbnm5HIykf8ENsm4JUrdAvolPT86yYA==
-
source-list-map@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085"