diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 070f920c0f6..21d8b6bc278 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-80d41b90597e1ca027cc6f02a09a6d3607d75ba2
+6857897d8b352850ed2c3f5c9396c782a930d052
diff --git a/app/assets/javascripts/pages/projects/show/index.js b/app/assets/javascripts/pages/projects/show/index.js
index 78b3f2f1b30..31d69a731fe 100644
--- a/app/assets/javascripts/pages/projects/show/index.js
+++ b/app/assets/javascripts/pages/projects/show/index.js
@@ -7,7 +7,7 @@ import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import leaveByUrl from '~/namespaces/leave_by_url';
import initVueNotificationsDropdown from '~/notifications';
-import { initUploadFileTrigger } from '~/projects/upload_file_experiment';
+import { initUploadFileTrigger } from '~/projects/upload_file';
import initReadMore from '~/read_more';
import UserCallout from '~/user_callout';
import Star from '../../../star';
diff --git a/app/assets/javascripts/projects/details/upload_button.vue b/app/assets/javascripts/projects/details/upload_button.vue
index 5b19f15c233..e1c8c66a214 100644
--- a/app/assets/javascripts/projects/details/upload_button.vue
+++ b/app/assets/javascripts/projects/details/upload_button.vue
@@ -1,7 +1,6 @@
@@ -44,7 +38,6 @@ export default {
v-gl-modal="$options.uploadBlobModalId"
icon="upload"
data-testid="upload-file-button"
- @click="trackOpenModal"
>{{ __('Upload File') }}
{
- const uploadFileTriggerEl = document.querySelector('.js-upload-file-experiment-trigger');
+ const uploadFileTriggerEl = document.querySelector('.js-upload-file-trigger');
if (!uploadFileTriggerEl) return false;
diff --git a/app/assets/javascripts/projects/upload_file_experiment_tracking.js b/app/assets/javascripts/projects/upload_file_experiment_tracking.js
deleted file mode 100644
index c5e93f19b32..00000000000
--- a/app/assets/javascripts/projects/upload_file_experiment_tracking.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import ExperimentTracking from '~/experimentation/experiment_tracking';
-
-export const trackFileUploadEvent = (eventName) => {
- const isEmpty = Boolean(document.querySelector('.project-home-panel.empty-project'));
- const property = isEmpty ? 'empty' : 'nonempty';
- const label = 'blob-upload-modal';
- const FileUploadTracking = new ExperimentTracking('empty_repo_upload', { label, property });
- FileUploadTracking.event(eventName);
-};
diff --git a/app/assets/javascripts/repository/components/delete_blob_modal.vue b/app/assets/javascripts/repository/components/delete_blob_modal.vue
index a307b7c0b8a..4a8cedb60b4 100644
--- a/app/assets/javascripts/repository/components/delete_blob_modal.vue
+++ b/app/assets/javascripts/repository/components/delete_blob_modal.vue
@@ -116,15 +116,14 @@ export default {
],
};
},
- /* eslint-disable dot-notation */
showCreateNewMrToggle() {
- return this.canPushCode && this.form.fields['branch_name'].value !== this.originalBranch;
+ return this.canPushCode && this.form.fields.branch_name.value !== this.originalBranch;
},
formCompleted() {
- return this.form.fields['commit_message'].value && this.form.fields['branch_name'].value;
+ return this.form.fields.commit_message.value && this.form.fields.branch_name.value;
},
showHint() {
- const splitCommitMessageByLineBreak = this.form.fields['commit_message'].value
+ const splitCommitMessageByLineBreak = this.form.fields.commit_message.value
.trim()
.split('\n');
const [firstLine, ...otherLines] = splitCommitMessageByLineBreak;
@@ -136,7 +135,7 @@ export default {
otherLines.some((text) => text.length > COMMIT_MESSAGE_BODY_MAX_LENGTH);
return (
- !this.form.fields['commit_message'].feedback &&
+ !this.form.fields.commit_message.feedback &&
(hasFirstLineExceedMaxLength || hasOtherLineExceedMaxLength)
);
},
@@ -173,9 +172,7 @@ export default {
-
-
+
diff --git a/app/assets/javascripts/repository/components/upload_blob_modal.vue b/app/assets/javascripts/repository/components/upload_blob_modal.vue
index 0199b893453..11e5b5608cb 100644
--- a/app/assets/javascripts/repository/components/upload_blob_modal.vue
+++ b/app/assets/javascripts/repository/components/upload_blob_modal.vue
@@ -15,7 +15,6 @@ import { ContentTypeMultipartFormData } from '~/lib/utils/headers';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { visitUrl, joinPaths } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
-import { trackFileUploadEvent } from '~/projects/upload_file_experiment_tracking';
import UploadDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
import {
SECONDARY_OPTIONS_TEXT,
@@ -165,9 +164,6 @@ export default {
},
})
.then((response) => {
- if (!this.replacePath) {
- trackFileUploadEvent('click_upload_modal_form_submit');
- }
visitUrl(response.data.filePath);
})
.catch(() => {
diff --git a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
index f388a468fd2..5de71c35be9 100644
--- a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
@@ -21,6 +21,7 @@ import CiIcon from './ci_icon.vue';
* - Job show view - header
* - MR widget
* - Terraform table
+ * - On-demand scans list
*/
export default {
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 4888f40febc..bda52cd94e4 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -336,11 +336,6 @@ class ProjectsController < Projects::ApplicationController
if can?(current_user, :download_code, @project)
return render 'projects/no_repo' unless @project.repository_exists?
- if @project.can_current_user_push_to_default_branch?
- property = @project.empty_repo? ? 'empty' : 'nonempty'
- experiment(:empty_repo_upload, project: @project).track(:view_project_show, property: property)
- end
-
render 'projects/empty' if @project.empty_repo?
else
if can?(current_user, :read_wiki, @project)
diff --git a/app/models/concerns/has_user_type.rb b/app/models/concerns/has_user_type.rb
index 4b4f9c0df84..28ee54afaa9 100644
--- a/app/models/concerns/has_user_type.rb
+++ b/app/models/concerns/has_user_type.rb
@@ -28,6 +28,7 @@ module HasUserType
scope :non_internal, -> { humans.or(where(user_type: NON_INTERNAL_USER_TYPES)) }
scope :without_ghosts, -> { humans.or(where.not(user_type: :ghost)) }
scope :without_project_bot, -> { humans.or(where.not(user_type: :project_bot)) }
+ scope :human_or_service_user, -> { humans.or(where(user_type: :service_user)) }
enum user_type: USER_TYPES
diff --git a/app/models/user.rb b/app/models/user.rb
index 83558044c21..54e25a0d70d 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -454,8 +454,8 @@ class User < ApplicationRecord
scope :order_recent_last_activity, -> { reorder(Gitlab::Database.nulls_last_order('last_activity_on', 'DESC')) }
scope :order_oldest_last_activity, -> { reorder(Gitlab::Database.nulls_first_order('last_activity_on', 'ASC')) }
scope :by_id_and_login, ->(id, login) { where(id: id).where('username = LOWER(:login) OR email = LOWER(:login)', login: login) }
- scope :dormant, -> { active.where('last_activity_on <= ?', MINIMUM_INACTIVE_DAYS.day.ago.to_date) }
- scope :with_no_activity, -> { active.where(last_activity_on: nil) }
+ scope :dormant, -> { with_state(:active).human_or_service_user.where('last_activity_on <= ?', MINIMUM_INACTIVE_DAYS.day.ago.to_date) }
+ scope :with_no_activity, -> { with_state(:active).human_or_service_user.where(last_activity_on: nil) }
scope :by_provider_and_extern_uid, ->(provider, extern_uid) { joins(:identities).merge(Identity.with_extern_uid(provider, extern_uid)) }
scope :get_ids_by_username, -> (username) { where(username: username).pluck(:id) }
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index bbd8c715f5c..ec66f9bdd4f 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -249,33 +249,23 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
strong_memoize(:upload_anchor_data) do
next unless can_current_user_push_to_default_branch?
- experiment(:empty_repo_upload, project: project) do |e|
- e.use {}
- e.try do
- AnchorData.new(false,
- statistic_icon('upload') + _('Upload file'),
- '#modal-upload-blob',
- 'js-upload-file-experiment-trigger',
- nil,
- nil,
- {
- 'target_branch' => default_branch_or_main,
- 'original_branch' => default_branch_or_main,
- 'can_push_code' => 'true',
- 'path' => project_create_blob_path(project, default_branch_or_main),
- 'project_path' => project.full_path
- }
- )
- end
- e.run
- end
+ AnchorData.new(false,
+ statistic_icon('upload') + _('Upload file'),
+ '#modal-upload-blob',
+ 'js-upload-file-trigger',
+ nil,
+ nil,
+ {
+ 'target_branch' => default_branch_or_main,
+ 'original_branch' => default_branch_or_main,
+ 'can_push_code' => 'true',
+ 'path' => project_create_blob_path(project, default_branch_or_main),
+ 'project_path' => project.full_path
+ }
+ )
end
end
- def empty_repo_upload_experiment?
- upload_anchor_data.present?
- end
-
def new_file_anchor_data
if can_current_user_push_to_default_branch?
new_file_path = empty_repo? ? ide_edit_path(project, default_branch_or_main) : project_new_blob_path(project, default_branch_or_main)
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 905794c0730..c3fbf774faa 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -77,5 +77,5 @@
git push -u origin --all
git push -u origin --tags
-- if @project.empty_repo_upload_experiment?
+- if @project.upload_anchor_data.present?
= render 'projects/blob/upload', title: _('Upload New File'), placeholder: _('Upload New File'), button_title: _('Upload file'), form_path: project_create_blob_path(@project, default_branch_name), ref: default_branch_name, method: :post
diff --git a/app/views/shared/_new_commit_form.html.haml b/app/views/shared/_new_commit_form.html.haml
index 5641c67e462..14ea96f9669 100644
--- a/app/views/shared/_new_commit_form.html.haml
+++ b/app/views/shared/_new_commit_form.html.haml
@@ -5,9 +5,7 @@
- if project.empty_repo?
- ref = local_assigns[:ref] || @ref
- - branch_name_class = project.empty_repo_upload_experiment? ? 'js-branch-name' : nil
-
- = hidden_field_tag 'branch_name', ref, class: branch_name_class
+ = hidden_field_tag 'branch_name', ref, class: 'js-branch-name'
- else
- if can?(current_user, :push_code, @project)
.form-group.row.branch
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 7d0322361b8..45af15216fc 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -128,7 +128,6 @@ class PostReceive
end
def after_project_changes_hooks(project, user, refs, changes)
- experiment(:empty_repo_upload, project: project).track_initial_write
repository_update_hook_data = Gitlab::DataBuilder::Repository.update(project, user, changes, refs)
SystemHooksService.new.execute_hooks(repository_update_hook_data, :repository_update_hooks)
Gitlab::UsageDataCounters::SourceCodeCounter.count(:pushes)
diff --git a/config/feature_flags/experiment/empty_repo_upload.yml b/config/feature_flags/experiment/empty_repo_upload.yml
deleted file mode 100644
index 9655a4d3cb4..00000000000
--- a/config/feature_flags/experiment/empty_repo_upload.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: empty_repo_upload
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52755
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285296
-milestone: '13.9'
-type: experiment
-group: group::adoption
-default_enabled: false
diff --git a/db/migrate/20211027203950_add_updated_index_for_dormant_users.rb b/db/migrate/20211027203950_add_updated_index_for_dormant_users.rb
new file mode 100644
index 00000000000..8b004af06c0
--- /dev/null
+++ b/db/migrate/20211027203950_add_updated_index_for_dormant_users.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddUpdatedIndexForDormantUsers < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_users_on_id_and_last_activity_on_for_active_human_service'
+
+ disable_ddl_transaction!
+
+ def up
+ index_condition = "state = 'active' AND (users.user_type IS NULL OR users.user_type = 4)"
+
+ add_concurrent_index :users, [:id, :last_activity_on], where: index_condition, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :users, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211027204011_remove_index_for_dormant_users.rb b/db/post_migrate/20211027204011_remove_index_for_dormant_users.rb
new file mode 100644
index 00000000000..5e556fe1f32
--- /dev/null
+++ b/db/post_migrate/20211027204011_remove_index_for_dormant_users.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveIndexForDormantUsers < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_users_on_id_and_last_activity_on_for_non_internal_active'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :users, INDEX_NAME
+ end
+
+ def down
+ index_condition = "state = 'active' AND (users.user_type IS NULL OR users.user_type IN (NULL, 6, 4))"
+
+ add_concurrent_index :users, [:id, :last_activity_on], where: index_condition, name: INDEX_NAME
+ end
+end
diff --git a/db/schema_migrations/20211027203950 b/db/schema_migrations/20211027203950
new file mode 100644
index 00000000000..4e4265a34c9
--- /dev/null
+++ b/db/schema_migrations/20211027203950
@@ -0,0 +1 @@
+38643fbd719e7d65e5e79eeb279a5732cee5c28774a300859a2bace13d882ee2
\ No newline at end of file
diff --git a/db/schema_migrations/20211027204011 b/db/schema_migrations/20211027204011
new file mode 100644
index 00000000000..7c1e07a87c0
--- /dev/null
+++ b/db/schema_migrations/20211027204011
@@ -0,0 +1 @@
+8542de6f3bf260b4e7596ed497ff8ed4204c81519d8f19e64ac86cd5532e7a61
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index eb7536199a3..6beaf177af8 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -26938,7 +26938,7 @@ CREATE INDEX index_users_on_feed_token ON users USING btree (feed_token);
CREATE INDEX index_users_on_group_view ON users USING btree (group_view);
-CREATE INDEX index_users_on_id_and_last_activity_on_for_non_internal_active ON users USING btree (id, last_activity_on) WHERE (((state)::text = 'active'::text) AND ((user_type IS NULL) OR (user_type = ANY (ARRAY[NULL::integer, 6, 4]))));
+CREATE INDEX index_users_on_id_and_last_activity_on_for_active_human_service ON users USING btree (id, last_activity_on) WHERE (((state)::text = 'active'::text) AND ((user_type IS NULL) OR (user_type = 4)));
CREATE INDEX index_users_on_incoming_email_token ON users USING btree (incoming_email_token);
diff --git a/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
index 47cb043f2ba..a0ec07e61e1 100644
--- a/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
@@ -53,10 +53,9 @@ cache:
- cd ${TF_ROOT}
- gitlab-terraform apply
resource_group: ${TF_STATE_NAME}
- when: manual
- only:
- variables:
- - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ when: manual
.terraform:destroy: &terraform_destroy
stage: cleanup
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 01e5000db10..9b1fe63518a 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -23916,6 +23916,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23931,6 +23934,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry_omnibus_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb
similarity index 100%
rename from qa/qa/specs/features/browser_ui/5_package/container_registry_omnibus_spec.rb
rename to qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb
diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb
similarity index 100%
rename from qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb
rename to qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb
diff --git a/qa/qa/specs/features/browser_ui/5_package/online_garbage_collection_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb
similarity index 100%
rename from qa/qa/specs/features/browser_ui/5_package/online_garbage_collection_spec.rb
rename to qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb
diff --git a/qa/qa/specs/features/browser_ui/5_package/dependency_proxy_spec.rb b/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb
similarity index 100%
rename from qa/qa/specs/features/browser_ui/5_package/dependency_proxy_spec.rb
rename to qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb
diff --git a/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb
similarity index 100%
rename from qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb
rename to qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb
diff --git a/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb
similarity index 100%
rename from qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb
rename to qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb
diff --git a/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb
similarity index 100%
rename from qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb
rename to qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb
diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb
similarity index 100%
rename from qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb
rename to qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb
diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb
similarity index 100%
rename from qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb
rename to qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb
diff --git a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
similarity index 90%
rename from qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb
rename to qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
index f87b324fe81..e603eb1c2a3 100644
--- a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Package', :orchestrated, :packages, :reliable, :object_storage do
- describe 'npm registry' do
+ RSpec.describe 'Package Registry', :orchestrated, :packages, :reliable, :object_storage do
+ describe 'npm instance level endpoint' do
using RSpec::Parameterized::TableSyntax
include Runtime::Fixtures
@@ -28,13 +28,13 @@ module QA
let!(:project) do
Resource::Project.fabricate_via_api! do |project|
- project.name = 'npm-project'
+ project.name = 'npm-instace-level-publish'
end
end
let!(:another_project) do
Resource::Project.fabricate_via_api! do |another_project|
- another_project.name = 'npm-another-project'
+ another_project.name = 'npm-instance-level-install'
another_project.template_name = 'express'
another_project.group = project.group
end
@@ -54,7 +54,7 @@ module QA
file_path: '.gitlab-ci.yml',
content:
<<~YAML
- image: node:14-buster
+ image: node:latest
stages:
- deploy
@@ -62,6 +62,7 @@ module QA
deploy:
stage: deploy
script:
+ - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=#{auth_token}">.npmrc
- npm publish
only:
- "#{project.default_branch}"
@@ -149,23 +150,12 @@ module QA
end
end
- let(:npmrc) do
- {
- file_path: '.npmrc',
- content: <<~NPMRC
- //#{gitlab_host_with_port}/api/v4/projects/#{project.id}/packages/npm/:_authToken=#{auth_token}
- @#{registry_scope}:registry=#{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/npm/
- NPMRC
- }
- end
-
it "push and pull a npm package via CI using a #{params[:token_name]}" do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
commit.add_files([
gitlab_ci_deploy_yaml,
- npmrc,
package_json
])
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
new file mode 100644
index 00000000000..f4b306d6830
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
@@ -0,0 +1,192 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package Registry', :orchestrated, :packages, :reliable, :object_storage do
+ describe 'npm project level endpoint' do
+ using RSpec::Parameterized::TableSyntax
+ include Runtime::Fixtures
+
+ let!(:registry_scope) { Runtime::Namespace.sandbox_name }
+ let!(:personal_access_token) do
+ unless Page::Main::Menu.perform(&:signed_in?)
+ Flow::Login.sign_in
+ end
+
+ Resource::PersonalAccessToken.fabricate!.token
+ end
+
+ let(:project_deploy_token) do
+ Resource::DeployToken.fabricate_via_browser_ui! do |deploy_token|
+ deploy_token.name = 'npm-deploy-token'
+ deploy_token.project = project
+ end
+ end
+
+ let(:uri) { URI.parse(Runtime::Scenario.gitlab_address) }
+ let(:gitlab_address_with_port) { "#{uri.scheme}://#{uri.host}:#{uri.port}" }
+ let(:gitlab_host_with_port) { "#{uri.host}:#{uri.port}" }
+
+ let!(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'npm-project-level'
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.name}"]
+ runner.executor = :docker
+ runner.project = project
+ end
+ end
+
+ let(:gitlab_ci_yaml) do
+ {
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ image: node:latest
+
+ stages:
+ - deploy
+ - install
+
+ deploy:
+ stage: deploy
+ script:
+ - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=#{auth_token}">.npmrc
+ - npm publish
+ only:
+ - "#{project.default_branch}"
+ tags:
+ - "runner-for-#{project.name}"
+ install:
+ stage: install
+ script:
+ - "npm config set @#{registry_scope}:registry #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/"
+ - "npm install #{package.name}"
+ cache:
+ key: ${CI_BUILD_REF_NAME}
+ paths:
+ - node_modules/
+ artifacts:
+ paths:
+ - node_modules/
+ only:
+ - "#{project.default_branch}"
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ }
+ end
+
+ let(:package_json) do
+ {
+ file_path: 'package.json',
+ content: <<~JSON
+ {
+ "name": "@#{registry_scope}/mypackage",
+ "version": "1.0.0",
+ "description": "Example package for GitLab npm registry",
+ "publishConfig": {
+ "@#{registry_scope}:registry": "#{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/npm/"
+ }
+ }
+ JSON
+ }
+ end
+
+ let(:package) do
+ Resource::Package.init do |package|
+ package.name = "@#{registry_scope}/mypackage"
+ package.project = project
+ end
+ end
+
+ after do
+ package.remove_via_api!
+ runner.remove_via_api!
+ project.remove_via_api!
+ end
+
+ where(:authentication_token_type, :token_name) do
+ :personal_access_token | 'Personal Access Token'
+ :ci_job_token | 'CI Job Token'
+ :project_deploy_token | 'Deploy Token'
+ end
+
+ with_them do
+ let(:auth_token) do
+ case authentication_token_type
+ when :personal_access_token
+ "\"#{personal_access_token}\""
+ when :ci_job_token
+ '${CI_JOB_TOKEN}'
+ when :project_deploy_token
+ "\"#{project_deploy_token.password}\""
+ end
+ end
+
+ it "push and pull a npm package via CI using a #{params[:token_name]}" do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([
+ gitlab_ci_yaml,
+ package_json
+ ])
+ end
+
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('deploy')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('install')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ job.click_browse_button
+ end
+
+ Page::Project::Artifact::Show.perform do |artifacts|
+ artifacts.go_to_directory('node_modules')
+ artifacts.go_to_directory("@#{registry_scope}")
+ expect(artifacts).to have_content("mypackage")
+ end
+
+ project.visit!
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package.name)
+
+ index.click_package(package.name)
+ end
+
+ Page::Project::Packages::Show.perform do |show|
+ expect(show).to have_package_info(package.name, "1.0.0")
+
+ show.click_delete
+ end
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_content("Package deleted successfully")
+ expect(index).not_to have_package(package.name)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb
similarity index 100%
rename from qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
rename to qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb
diff --git a/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb
similarity index 100%
rename from qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb
rename to qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb
diff --git a/qa/qa/specs/features/browser_ui/5_package/rubygems_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb
similarity index 98%
rename from qa/qa/specs/features/browser_ui/5_package/rubygems_registry_spec.rb
rename to qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb
index 9a45b072eed..45e44a2d9e0 100644
--- a/qa/qa/specs/features/browser_ui/5_package/rubygems_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb
@@ -50,7 +50,7 @@ module QA
push.project = project
push.directory = Pathname
.new(__dir__)
- .join('../../../../fixtures/rubygems_package')
+ .join('../../../../../fixtures/rubygems_package')
push.commit_message = 'RubyGems package'
end
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index b34cfedb767..91ed46a8bb5 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -213,21 +213,6 @@ RSpec.describe ProjectsController do
before do
sign_in(user)
-
- allow(controller).to receive(:record_experiment_user)
- end
-
- context 'when user can push to default branch', :experiment do
- let(:user) { empty_project.owner }
-
- it 'creates an "view_project_show" experiment tracking event' do
- expect(experiment(:empty_repo_upload)).to track(
- :view_project_show,
- property: 'empty'
- ).on_next_instance
-
- get :show, params: { namespace_id: empty_project.namespace, id: empty_project }
- end
end
User.project_views.keys.each do |project_view|
diff --git a/spec/experiments/empty_repo_upload_experiment_spec.rb b/spec/experiments/empty_repo_upload_experiment_spec.rb
deleted file mode 100644
index 10cbedbe8ba..00000000000
--- a/spec/experiments/empty_repo_upload_experiment_spec.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe EmptyRepoUploadExperiment, :experiment do
- subject { described_class.new(project: project) }
-
- let(:project) { create(:project, :repository) }
-
- describe '#track_initial_write' do
- context 'when experiment is turned on' do
- before do
- stub_experiments(empty_repo_upload: :control)
- end
-
- it "tracks an event for the first commit on a project" do
- expect(subject).to receive(:commit_count_for).with(project, max_count: described_class::INITIAL_COMMIT_COUNT, experiment: 'empty_repo_upload').and_return(1)
-
- expect(subject).to receive(:track).with(:initial_write, project: project).and_call_original
-
- subject.track_initial_write
- end
-
- it "doesn't track an event for projects with a commit count more than 1" do
- expect(subject).to receive(:commit_count_for).and_return(2)
-
- expect(subject).not_to receive(:track)
-
- subject.track_initial_write
- end
-
- it "doesn't track if the project is older" do
- expect(project).to receive(:created_at).and_return(described_class::TRACKING_START_DATE - 1.minute)
-
- expect(subject).not_to receive(:track)
-
- subject.track_initial_write
- end
- end
-
- context 'when experiment is turned off' do
- it "doesn't track when we generally shouldn't" do
- expect(subject).not_to receive(:track)
-
- subject.track_initial_write
- end
- end
- end
-end
diff --git a/spec/features/projects/show/user_uploads_files_spec.rb b/spec/features/projects/show/user_uploads_files_spec.rb
index 51e41397439..92b54d83ef3 100644
--- a/spec/features/projects/show/user_uploads_files_spec.rb
+++ b/spec/features/projects/show/user_uploads_files_spec.rb
@@ -44,27 +44,27 @@ RSpec.describe 'Projects > Show > User uploads files' do
end
end
- context 'when in the empty_repo_upload experiment' do
- before do
- stub_experiments(empty_repo_upload: :candidate)
+ context 'with an empty repo' do
+ let(:project) { create(:project, :empty_repo, creator: user) }
+ before do
visit(project_path(project))
end
- context 'with an empty repo' do
- let(:project) { create(:project, :empty_repo, creator: user) }
+ [true, false].each do |value|
+ include_examples 'uploads and commits a new text file via "upload file" button', drop: value
+ end
+ end
- [true, false].each do |value|
- include_examples 'uploads and commits a new text file via "upload file" button', drop: value
- end
+ context 'with a nonempty repo' do
+ let(:project) { create(:project, :repository, creator: user) }
+
+ before do
+ visit(project_path(project))
end
- context 'with a nonempty repo' do
- let(:project) { create(:project, :repository, creator: user) }
-
- [true, false].each do |value|
- include_examples 'uploads and commits a new text file via "upload file" button', drop: value
- end
+ [true, false].each do |value|
+ include_examples 'uploads and commits a new text file via "upload file" button', drop: value
end
end
end
diff --git a/spec/frontend/projects/details/upload_button_spec.js b/spec/frontend/projects/details/upload_button_spec.js
index ebb2b499ead..d7308963088 100644
--- a/spec/frontend/projects/details/upload_button_spec.js
+++ b/spec/frontend/projects/details/upload_button_spec.js
@@ -1,11 +1,8 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import UploadButton from '~/projects/details/upload_button.vue';
-import { trackFileUploadEvent } from '~/projects/upload_file_experiment_tracking';
import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
-jest.mock('~/projects/upload_file_experiment_tracking');
-
const MODAL_ID = 'details-modal-upload-blob';
describe('UploadButton', () => {
@@ -50,10 +47,6 @@ describe('UploadButton', () => {
wrapper.find(GlButton).vm.$emit('click');
});
- it('tracks the click_upload_modal_trigger event', () => {
- expect(trackFileUploadEvent).toHaveBeenCalledWith('click_upload_modal_trigger');
- });
-
it('opens the modal', () => {
expect(glModalDirective).toHaveBeenCalledWith(MODAL_ID);
});
diff --git a/spec/frontend/projects/upload_file_experiment_tracking_spec.js b/spec/frontend/projects/upload_file_experiment_tracking_spec.js
deleted file mode 100644
index 6817529e07e..00000000000
--- a/spec/frontend/projects/upload_file_experiment_tracking_spec.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import ExperimentTracking from '~/experimentation/experiment_tracking';
-import { trackFileUploadEvent } from '~/projects/upload_file_experiment_tracking';
-
-jest.mock('~/experimentation/experiment_tracking');
-
-const eventName = 'click_upload_modal_form_submit';
-const fixture = ``;
-
-beforeEach(() => {
- document.body.innerHTML = fixture;
-});
-
-afterEach(() => {
- document.body.innerHTML = '';
-});
-
-describe('trackFileUploadEvent', () => {
- it('initializes ExperimentTracking with the correct tracking event', () => {
- trackFileUploadEvent(eventName);
-
- expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(eventName);
- });
-
- it('calls ExperimentTracking with the correct arguments', () => {
- trackFileUploadEvent(eventName);
-
- expect(ExperimentTracking).toHaveBeenCalledWith('empty_repo_upload', {
- label: 'blob-upload-modal',
- property: 'empty',
- });
- });
-
- it('calls ExperimentTracking with the correct arguments when the project is not empty', () => {
- document.querySelector('.empty-project').remove();
-
- trackFileUploadEvent(eventName);
-
- expect(ExperimentTracking).toHaveBeenCalledWith('empty_repo_upload', {
- label: 'blob-upload-modal',
- property: 'nonempty',
- });
- });
-});
diff --git a/spec/frontend/repository/components/upload_blob_modal_spec.js b/spec/frontend/repository/components/upload_blob_modal_spec.js
index 08a6583b60c..36847107558 100644
--- a/spec/frontend/repository/components/upload_blob_modal_spec.js
+++ b/spec/frontend/repository/components/upload_blob_modal_spec.js
@@ -6,11 +6,9 @@ import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status';
import { visitUrl } from '~/lib/utils/url_utility';
-import { trackFileUploadEvent } from '~/projects/upload_file_experiment_tracking';
import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
import UploadDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
-jest.mock('~/projects/upload_file_experiment_tracking');
jest.mock('~/flash');
jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn(),
@@ -162,10 +160,6 @@ describe('UploadBlobModal', () => {
await waitForPromises();
});
- it('tracks the click_upload_modal_trigger event when opening the modal', () => {
- expect(trackFileUploadEvent).toHaveBeenCalledWith('click_upload_modal_form_submit');
- });
-
it('redirects to the uploaded file', () => {
expect(visitUrl).toHaveBeenCalled();
});
@@ -185,10 +179,6 @@ describe('UploadBlobModal', () => {
await waitForPromises();
});
- it('does not track an event', () => {
- expect(trackFileUploadEvent).not.toHaveBeenCalled();
- });
-
it('creates a flash error', () => {
expect(createFlash).toHaveBeenCalledWith({
message: 'Error uploading file. Please try again.',
diff --git a/spec/presenters/project_presenter_spec.rb b/spec/presenters/project_presenter_spec.rb
index 5f789f59908..27b777dec5f 100644
--- a/spec/presenters/project_presenter_spec.rb
+++ b/spec/presenters/project_presenter_spec.rb
@@ -567,44 +567,27 @@ RSpec.describe ProjectPresenter do
end
describe '#upload_anchor_data' do
- context 'with empty_repo_upload enabled' do
+ context 'when a user can push to the default branch' do
before do
- stub_experiments(empty_repo_upload: :candidate)
- end
-
- context 'user can push to branch' do
- before do
- project.add_developer(user)
- end
-
- it 'returns upload_anchor_data' do
- expect(presenter.upload_anchor_data).to have_attributes(
- is_link: false,
- label: a_string_including('Upload file'),
- data: {
- "can_push_code" => "true",
- "original_branch" => "master",
- "path" => "/#{project.full_path}/-/create/master",
- "project_path" => project.full_path,
- "target_branch" => "master"
- }
- )
- end
- end
-
- context 'user cannot push to branch' do
- it 'returns nil' do
- expect(presenter.upload_anchor_data).to be_nil
- end
- end
- end
-
- context 'with empty_repo_upload disabled' do
- before do
- stub_experiments(empty_repo_upload: :control)
project.add_developer(user)
end
+ it 'returns upload_anchor_data' do
+ expect(presenter.upload_anchor_data).to have_attributes(
+ is_link: false,
+ label: a_string_including('Upload file'),
+ data: {
+ "can_push_code" => "true",
+ "original_branch" => "master",
+ "path" => "/#{project.full_path}/-/create/master",
+ "project_path" => project.full_path,
+ "target_branch" => "master"
+ }
+ )
+ end
+ end
+
+ context 'when the user cannot push to default branch' do
it 'returns nil' do
expect(presenter.upload_anchor_data).to be_nil
end
@@ -666,7 +649,6 @@ RSpec.describe ProjectPresenter do
context 'for a developer' do
before do
project.add_developer(user)
- stub_experiments(empty_repo_upload: :candidate)
end
it 'orders the items correctly' do
@@ -680,16 +662,6 @@ RSpec.describe ProjectPresenter do
a_string_including('CI/CD')
)
end
-
- context 'when not in the upload experiment' do
- before do
- stub_experiments(empty_repo_upload: :control)
- end
-
- it 'does not include upload button' do
- expect(empty_repo_statistics_buttons.map(&:label)).not_to start_with(a_string_including('Upload'))
- end
- end
end
end
@@ -781,20 +753,4 @@ RSpec.describe ProjectPresenter do
it { is_expected.to match(/code_quality_walkthrough=true.*template=Code-Quality/) }
end
-
- describe 'empty_repo_upload_experiment?' do
- subject { presenter.empty_repo_upload_experiment? }
-
- it 'returns false when upload_anchor_data is nil' do
- allow(presenter).to receive(:upload_anchor_data).and_return(nil)
-
- expect(subject).to be false
- end
-
- it 'returns true when upload_anchor_data exists' do
- allow(presenter).to receive(:upload_anchor_data).and_return(true)
-
- expect(subject).to be true
- end
- end
end
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index 039f86f1911..42e39c51a88 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -91,14 +91,6 @@ RSpec.describe PostReceive do
perform
end
-
- it 'tracks an event for the empty_repo_upload experiment', :experiment do
- expect_next_instance_of(EmptyRepoUploadExperiment) do |e|
- expect(e).to receive(:track_initial_write)
- end
-
- perform
- end
end
shared_examples 'not updating remote mirrors' do
diff --git a/spec/workers/users/deactivate_dormant_users_worker_spec.rb b/spec/workers/users/deactivate_dormant_users_worker_spec.rb
index 934c497c79a..20cd55e19eb 100644
--- a/spec/workers/users/deactivate_dormant_users_worker_spec.rb
+++ b/spec/workers/users/deactivate_dormant_users_worker_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Users::DeactivateDormantUsersWorker do
+ using RSpec::Parameterized::TableSyntax
+
describe '#perform' do
let_it_be(:dormant) { create(:user, last_activity_on: User::MINIMUM_INACTIVE_DAYS.days.ago.to_date) }
let_it_be(:inactive) { create(:user, last_activity_on: nil) }
@@ -22,12 +24,12 @@ RSpec.describe Users::DeactivateDormantUsersWorker do
context 'when automatic deactivation of dormant users is enabled' do
before do
stub_application_setting(deactivate_dormant_users: true)
+ stub_const("#{described_class.name}::PAUSE_SECONDS", 0)
end
it 'deactivates dormant users' do
freeze_time do
stub_const("#{described_class.name}::BATCH_SIZE", 1)
- stub_const("#{described_class.name}::PAUSE_SECONDS", 0)
expect(worker).to receive(:sleep).twice
@@ -37,6 +39,38 @@ RSpec.describe Users::DeactivateDormantUsersWorker do
expect(User.with_no_activity.count).to eq(0)
end
end
+
+ where(:user_type, :expected_state) do
+ :human | 'deactivated'
+ :support_bot | 'active'
+ :alert_bot | 'active'
+ :visual_review_bot | 'active'
+ :service_user | 'deactivated'
+ :ghost | 'active'
+ :project_bot | 'active'
+ :migration_bot | 'active'
+ :security_bot | 'active'
+ :automation_bot | 'active'
+ end
+ with_them do
+ it 'deactivates certain user types' do
+ user = create(:user, user_type: user_type, state: :active, last_activity_on: User::MINIMUM_INACTIVE_DAYS.days.ago.to_date)
+
+ worker.perform
+
+ expect(user.reload.state).to eq(expected_state)
+ end
+ end
+
+ it 'does not deactivate non-active users' do
+ human_user = create(:user, user_type: :human, state: :blocked, last_activity_on: User::MINIMUM_INACTIVE_DAYS.days.ago.to_date)
+ service_user = create(:user, user_type: :service_user, state: :blocked, last_activity_on: User::MINIMUM_INACTIVE_DAYS.days.ago.to_date)
+
+ worker.perform
+
+ expect(human_user.reload.state).to eq('blocked')
+ expect(service_user.reload.state).to eq('blocked')
+ end
end
context 'when automatic deactivation of dormant users is disabled' do