Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
c20b560205
commit
951d67d14f
|
|
@ -1 +1 @@
|
|||
80d41b90597e1ca027cc6f02a09a6d3607d75ba2
|
||||
6857897d8b352850ed2c3f5c9396c782a930d052
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<script>
|
||||
import { GlButton, GlModalDirective } from '@gitlab/ui';
|
||||
import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
|
||||
import { trackFileUploadEvent } from '../upload_file_experiment_tracking';
|
||||
|
||||
const UPLOAD_BLOB_MODAL_ID = 'details-modal-upload-blob';
|
||||
|
||||
|
|
@ -30,11 +29,6 @@ export default {
|
|||
default: '',
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
trackOpenModal() {
|
||||
trackFileUploadEvent('click_upload_modal_trigger');
|
||||
},
|
||||
},
|
||||
uploadBlobModalId: UPLOAD_BLOB_MODAL_ID,
|
||||
};
|
||||
</script>
|
||||
|
|
@ -44,7 +38,6 @@ export default {
|
|||
v-gl-modal="$options.uploadBlobModalId"
|
||||
icon="upload"
|
||||
data-testid="upload-file-button"
|
||||
@click="trackOpenModal"
|
||||
>{{ __('Upload File') }}</gl-button
|
||||
>
|
||||
<upload-blob-modal
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import createRouter from '~/repository/router';
|
|||
import UploadButton from './details/upload_button.vue';
|
||||
|
||||
export const initUploadFileTrigger = () => {
|
||||
const uploadFileTriggerEl = document.querySelector('.js-upload-file-experiment-trigger');
|
||||
const uploadFileTriggerEl = document.querySelector('.js-upload-file-trigger');
|
||||
|
||||
if (!uploadFileTriggerEl) return false;
|
||||
|
||||
|
|
@ -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);
|
||||
};
|
||||
|
|
@ -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 {
|
|||
<input type="hidden" name="_method" value="delete" />
|
||||
<input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
|
||||
<template v-if="emptyRepo">
|
||||
<!-- Once "empty_repo_upload_experiment" is made available, will need to add class 'js-branch-name'
|
||||
Follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/335721 -->
|
||||
<input type="hidden" name="branch_name" :value="originalBranch" />
|
||||
<input type="hidden" name="branch_name" :value="originalBranch" class="js-branch-name" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<input type="hidden" name="original_branch" :value="originalBranch" />
|
||||
|
|
|
|||
|
|
@ -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(() => {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import CiIcon from './ci_icon.vue';
|
|||
* - Job show view - header
|
||||
* - MR widget
|
||||
* - Terraform table
|
||||
* - On-demand scans list
|
||||
*/
|
||||
|
||||
export default {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1 @@
|
|||
38643fbd719e7d65e5e79eeb279a5732cee5c28774a300859a2bace13d882ee2
|
||||
|
|
@ -0,0 +1 @@
|
|||
8542de6f3bf260b4e7596ed497ff8ed4204c81519d8f19e64ac86cd5532e7a61
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ""
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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|
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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 = `<a class='js-upload-file-experiment-trigger'></a><div class='project-home-panel empty-project'></div>`;
|
||||
|
||||
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',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -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.',
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue