Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-10-29 03:12:09 +00:00
parent c20b560205
commit 951d67d14f
46 changed files with 339 additions and 305 deletions

View File

@ -1 +1 @@
80d41b90597e1ca027cc6f02a09a6d3607d75ba2
6857897d8b352850ed2c3f5c9396c782a930d052

View File

@ -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';

View File

@ -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

View File

@ -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;

View File

@ -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);
};

View File

@ -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" />

View File

@ -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(() => {

View File

@ -21,6 +21,7 @@ import CiIcon from './ci_icon.vue';
* - Job show view - header
* - MR widget
* - Terraform table
* - On-demand scans list
*/
export default {

View File

@ -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)

View File

@ -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

View File

@ -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) }

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
38643fbd719e7d65e5e79eeb279a5732cee5c28774a300859a2bace13d882ee2

View File

@ -0,0 +1 @@
8542de6f3bf260b4e7596ed497ff8ed4204c81519d8f19e64ac86cd5532e7a61

View File

@ -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);

View File

@ -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

View File

@ -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 ""

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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|

View File

@ -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

View File

@ -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

View File

@ -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);
});

View File

@ -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',
});
});
});

View File

@ -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.',

View File

@ -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

View File

@ -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

View File

@ -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