Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-03-16 21:08:34 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-03-16 21:08:34 +0300
commitcc9ff71e31ecc954f819741ba1285b1b9adbf3b9 (patch)
tree5f1ff13cc95f2b1860419c45b8def31cde56d1f9 /app
parentf01d3c8c095e70981ffc1d20c050c153f3766421 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/deprecated_notes.js57
-rw-r--r--app/assets/javascripts/incidents/constants.js1
-rw-r--r--app/assets/javascripts/init_deprecated_notes.js4
-rw-r--r--app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue7
-rw-r--r--app/assets/javascripts/issues/list/components/issues_list_app.vue7
-rw-r--r--app/assets/javascripts/issues/list/constants.js1
-rw-r--r--app/assets/javascripts/issues/list/utils.js4
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/constants.js1
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/actions.js2
-rw-r--r--app/graphql/types/ci/job_type.rb18
-rw-r--r--app/graphql/types/ci/runner_machine_type.rb4
-rw-r--r--app/helpers/notes_helper.rb1
-rw-r--r--app/models/bulk_imports/batch_tracker.rb46
-rw-r--r--app/models/bulk_imports/export.rb1
-rw-r--r--app/models/bulk_imports/export_batch.rb33
-rw-r--r--app/models/bulk_imports/export_upload.rb1
-rw-r--r--app/models/bulk_imports/tracker.rb2
-rw-r--r--app/models/ci/runner_machine_build.rb8
-rw-r--r--app/models/integration.rb3
-rw-r--r--app/models/integrations/squash_tm.rb82
-rw-r--r--app/models/preloaders/runner_machine_policy_preloader.rb23
-rw-r--r--app/models/project.rb1
-rw-r--r--app/models/user.rb4
-rw-r--r--app/services/concerns/update_repository_storage_methods.rb9
-rw-r--r--app/services/packages/debian/generate_distribution_service.rb2
-rw-r--r--app/services/projects/update_repository_storage_service.rb13
-rw-r--r--app/services/users/validate_manual_otp_service.rb3
-rw-r--r--app/views/admin/background_migrations/index.html.haml2
-rw-r--r--app/views/dashboard/projects/_blank_state_admin_welcome.html.haml8
-rw-r--r--app/views/dashboard/projects/_blank_state_welcome.html.haml8
-rw-r--r--app/views/groups/_import_group_from_file_panel.html.haml2
-rw-r--r--app/views/groups/settings/_export.html.haml3
-rw-r--r--app/views/search/_results.html.haml2
-rw-r--r--app/views/search/_results_list.html.haml2
-rw-r--r--app/workers/packages/debian/generate_distribution_worker.rb2
35 files changed, 299 insertions, 68 deletions
diff --git a/app/assets/javascripts/deprecated_notes.js b/app/assets/javascripts/deprecated_notes.js
index 5b398623164..32a91506ab4 100644
--- a/app/assets/javascripts/deprecated_notes.js
+++ b/app/assets/javascripts/deprecated_notes.js
@@ -53,9 +53,9 @@ const MAX_VISIBLE_COMMIT_LIST_COUNT = 3;
const REGEX_QUICK_ACTIONS = /^\/\w+.*$/gm;
export default class Notes {
- static initialize(notes_url, note_ids, last_fetched_at, view, enableGFM) {
+ static initialize(notes_url, last_fetched_at, view, enableGFM) {
if (!this.instance) {
- this.instance = new Notes(notes_url, note_ids, last_fetched_at, view, enableGFM);
+ this.instance = new Notes(notes_url, last_fetched_at, view, enableGFM);
}
}
@@ -63,7 +63,7 @@ export default class Notes {
return this.instance;
}
- constructor(notes_url, note_ids, last_fetched_at, view, enableGFM = defaultAutocompleteConfig) {
+ constructor(notes_url, last_fetched_at, view, enableGFM = defaultAutocompleteConfig) {
this.updateTargetButtons = this.updateTargetButtons.bind(this);
this.updateComment = this.updateComment.bind(this);
this.visibilityChange = this.visibilityChange.bind(this);
@@ -85,9 +85,9 @@ export default class Notes {
this.postComment = this.postComment.bind(this);
this.clearAlertWrapper = this.clearAlert.bind(this);
this.onHashChange = this.onHashChange.bind(this);
+ this.note_ids = [];
this.notes_url = notes_url;
- this.note_ids = note_ids;
this.enableGFM = enableGFM;
// Used to keep track of updated notes while people are editing things
this.updatedNotesTrackingMap = {};
@@ -449,8 +449,6 @@ export default class Notes {
return;
}
- this.note_ids.push(noteEntity.id);
-
if ($notesList.length) {
$notesList.find('.system-note.being-posted').remove();
}
@@ -497,7 +495,6 @@ export default class Notes {
if (!Notes.isNewNote(noteEntity, this.note_ids)) {
return;
}
- this.note_ids.push(noteEntity.id);
const form =
$form || $(`.js-discussion-note-form[data-discussion-id="${noteEntity.discussion_id}"]`);
@@ -745,7 +742,7 @@ export default class Notes {
$noteAvatar.append($targetNoteBadge);
this.revertNoteEditForm($targetNote);
- renderGFM($noteEntityEl.get(0));
+ renderGFM(Notes.getNodeToRender($noteEntityEl));
// Find the note's `li` element by ID and replace it with the updated HTML
const $note_li = $(`.note-row-${noteEntity.id}`);
@@ -1396,8 +1393,28 @@ export default class Notes {
/**
* Check if note does not exist on page
*/
- static isNewNote(noteEntity, noteIds) {
- return $.inArray(noteEntity.id, noteIds) === -1;
+ static isNewNote(noteEntity, note_ids) {
+ if (note_ids.length === 0) {
+ Notes.loadNotesIds(note_ids);
+ }
+ const isNewEntry = $.inArray(noteEntity.id, note_ids) === -1;
+ if (isNewEntry) {
+ note_ids.push(noteEntity.id);
+ }
+ return isNewEntry;
+ }
+
+ /**
+ * Load notes ids
+ */
+ static loadNotesIds(note_ids) {
+ const $notesList = $('.main-notes-list').children();
+ for (const $noteItem of $notesList) {
+ if (Notes.isNodeTypeElement($noteItem)) {
+ const noteId = parseInt($noteItem.id.split('_')[1], 10);
+ note_ids.push(noteId);
+ }
+ }
}
/**
@@ -1422,7 +1439,7 @@ export default class Notes {
const $note = $(noteHtml);
$note.addClass('fade-in-full');
- renderGFM($note.get(0));
+ renderGFM(Notes.getNodeToRender($note));
$notesList.append($note);
return $note;
}
@@ -1431,11 +1448,20 @@ export default class Notes {
const $updatedNote = $(noteHtml);
$updatedNote.addClass('fade-in');
- renderGFM($updatedNote.get(0));
+ renderGFM(Notes.getNodeToRender($updatedNote));
$note.replaceWith($updatedNote);
return $updatedNote;
}
+ static getNodeToRender($note) {
+ for (const $item of $note) {
+ if (Notes.isNodeTypeElement($item)) {
+ return $item;
+ }
+ }
+ return '';
+ }
+
/**
* Get data from Form attributes to use for saving/submitting comment.
*/
@@ -1829,4 +1855,11 @@ export default class Notes {
return $closeBtn.text($closeBtn.data('originalText'));
}
+
+ /**
+ * Function to check if node is element to avoid comment and text
+ */
+ static isNodeTypeElement($node) {
+ return $node.nodeType === Node.ELEMENT_NODE;
+ }
}
diff --git a/app/assets/javascripts/incidents/constants.js b/app/assets/javascripts/incidents/constants.js
index ee3f30de880..dde40ec2983 100644
--- a/app/assets/javascripts/incidents/constants.js
+++ b/app/assets/javascripts/incidents/constants.js
@@ -44,7 +44,6 @@ export const ESCALATION_STATUSES = {
RESOLVED: s__('AlertManagement|Resolved'),
};
-export const DEFAULT_PAGE_SIZE = 20;
export const TH_CREATED_AT_TEST_ID = { 'data-testid': 'incident-management-created-at-sort' };
export const TH_SEVERITY_TEST_ID = { 'data-testid': 'incident-management-severity-sort' };
export const TH_ESCALATION_STATUS_TEST_ID = { 'data-testid': 'incident-management-status-sort' };
diff --git a/app/assets/javascripts/init_deprecated_notes.js b/app/assets/javascripts/init_deprecated_notes.js
index 5f918b0d2f5..8657a1dcb67 100644
--- a/app/assets/javascripts/init_deprecated_notes.js
+++ b/app/assets/javascripts/init_deprecated_notes.js
@@ -2,9 +2,9 @@ import Notes from './deprecated_notes';
export default () => {
const dataEl = document.querySelector('.js-notes-data');
- const { notesUrl, notesIds, now, diffView, enableGFM } = JSON.parse(dataEl.innerHTML);
+ const { notesUrl, now, diffView, enableGFM } = JSON.parse(dataEl.innerHTML);
// Create a singleton so that we don't need to assign
// into the window object, we can just access the current isntance with Notes.instance
- Notes.initialize(notesUrl, notesIds, now, diffView, enableGFM);
+ Notes.initialize(notesUrl, now, diffView, enableGFM);
};
diff --git a/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue b/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue
index 32aceb0040a..2546bface58 100644
--- a/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue
+++ b/app/assets/javascripts/issues/dashboard/components/issues_dashboard_app.vue
@@ -9,7 +9,6 @@ import {
CREATED_DESC,
defaultTypeTokenOptions,
i18n,
- PAGE_SIZE,
PARAM_STATE,
UPDATED_DESC,
urlSortParams,
@@ -49,7 +48,7 @@ import {
TOKEN_TYPE_TYPE,
} from '~/vue_shared/components/filtered_search_bar/constants';
import IssuableList from '~/vue_shared/issuable/list/components/issuable_list_root.vue';
-import { IssuableListTabs } from '~/vue_shared/issuable/list/constants';
+import { DEFAULT_PAGE_SIZE, IssuableListTabs } from '~/vue_shared/issuable/list/constants';
import getIssuesCountsQuery from '../queries/get_issues_counts.query.graphql';
import { AutocompleteCache } from '../utils';
@@ -386,14 +385,14 @@ export default {
handleNextPage() {
this.pageParams = {
afterCursor: this.pageInfo.endCursor,
- firstPageSize: PAGE_SIZE,
+ firstPageSize: DEFAULT_PAGE_SIZE,
};
scrollUp();
},
handlePreviousPage() {
this.pageParams = {
beforeCursor: this.pageInfo.startCursor,
- lastPageSize: PAGE_SIZE,
+ lastPageSize: DEFAULT_PAGE_SIZE,
};
scrollUp();
},
diff --git a/app/assets/javascripts/issues/list/components/issues_list_app.vue b/app/assets/javascripts/issues/list/components/issues_list_app.vue
index d8fc5ba8a48..5c4bf8f19e4 100644
--- a/app/assets/javascripts/issues/list/components/issues_list_app.vue
+++ b/app/assets/javascripts/issues/list/components/issues_list_app.vue
@@ -52,7 +52,7 @@ import {
TOKEN_TYPE_TYPE,
} from '~/vue_shared/components/filtered_search_bar/constants';
import IssuableList from '~/vue_shared/issuable/list/components/issuable_list_root.vue';
-import { IssuableListTabs } from '~/vue_shared/issuable/list/constants';
+import { DEFAULT_PAGE_SIZE, IssuableListTabs } from '~/vue_shared/issuable/list/constants';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import NewResourceDropdown from '~/vue_shared/components/new_resource_dropdown/new_resource_dropdown.vue';
import {
@@ -62,7 +62,6 @@ import {
i18n,
ISSUE_REFERENCE,
MAX_LIST_SIZE,
- PAGE_SIZE,
PARAM_FIRST_PAGE_SIZE,
PARAM_LAST_PAGE_SIZE,
PARAM_PAGE_AFTER,
@@ -184,7 +183,7 @@ export default {
showBulkEditSidebar: false,
sortKey: CREATED_DESC,
state: STATUS_OPEN,
- pageSize: PAGE_SIZE,
+ pageSize: DEFAULT_PAGE_SIZE,
};
},
apollo: {
@@ -453,7 +452,7 @@ export default {
return this.issues.length > 0 && (this.pageInfo.hasNextPage || this.pageInfo.hasPreviousPage);
},
showPageSizeControls() {
- return this.currentTabCount > PAGE_SIZE;
+ return this.currentTabCount > DEFAULT_PAGE_SIZE;
},
sortOptions() {
return getSortOptions({
diff --git a/app/assets/javascripts/issues/list/constants.js b/app/assets/javascripts/issues/list/constants.js
index 31a43c95f5e..99064a50e3f 100644
--- a/app/assets/javascripts/issues/list/constants.js
+++ b/app/assets/javascripts/issues/list/constants.js
@@ -33,7 +33,6 @@ import {
export const ISSUE_REFERENCE = /^#\d+$/;
export const MAX_LIST_SIZE = 10;
-export const PAGE_SIZE = 20;
export const PARAM_ASSIGNEE_ID = 'assignee_id';
export const PARAM_FIRST_PAGE_SIZE = 'first_page_size';
export const PARAM_LAST_PAGE_SIZE = 'last_page_size';
diff --git a/app/assets/javascripts/issues/list/utils.js b/app/assets/javascripts/issues/list/utils.js
index 281e48d9aa7..b086640cd12 100644
--- a/app/assets/javascripts/issues/list/utils.js
+++ b/app/assets/javascripts/issues/list/utils.js
@@ -16,6 +16,7 @@ import {
TOKEN_TYPE_HEALTH,
TOKEN_TYPE_LABEL,
} from '~/vue_shared/components/filtered_search_bar/constants';
+import { DEFAULT_PAGE_SIZE } from '~/vue_shared/issuable/list/constants';
import {
ALTERNATIVE_FILTER,
API_PARAM,
@@ -35,7 +36,6 @@ import {
MILESTONE_DUE_ASC,
MILESTONE_DUE_DESC,
NORMAL_FILTER,
- PAGE_SIZE,
PARAM_ASSIGNEE_ID,
POPULARITY_ASC,
POPULARITY_DESC,
@@ -56,7 +56,7 @@ import {
export const getInitialPageParams = (
pageSize,
- firstPageSize = pageSize ?? PAGE_SIZE,
+ firstPageSize = pageSize ?? DEFAULT_PAGE_SIZE,
lastPageSize,
afterCursor,
beforeCursor,
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/constants.js b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/constants.js
index 7af3fc1c2db..05673215a66 100644
--- a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/constants.js
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/constants.js
@@ -6,7 +6,6 @@ export const FETCH_PACKAGES_LIST_ERROR_MESSAGE = __(
export const DELETE_PACKAGE_SUCCESS_MESSAGE = __('Package deleted successfully');
export const DEFAULT_PAGE = 1;
-export const DEFAULT_PAGE_SIZE = 20;
export const GROUP_PAGE_TYPE = 'groups';
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/actions.js b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/actions.js
index ecd987e5cf7..122123f49cd 100644
--- a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/actions.js
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/actions.js
@@ -3,11 +3,11 @@ import { createAlert, VARIANT_SUCCESS } from '~/alert';
import axios from '~/lib/utils/axios_utils';
import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages_and_registries/shared/constants';
import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants';
+import { DEFAULT_PAGE_SIZE } from '~/vue_shared/issuable/list/constants';
import {
FETCH_PACKAGES_LIST_ERROR_MESSAGE,
DELETE_PACKAGE_SUCCESS_MESSAGE,
DEFAULT_PAGE,
- DEFAULT_PAGE_SIZE,
MISSING_DELETE_PATH_ERROR,
TERRAFORM_SEARCH_TYPE,
} from '../constants';
diff --git a/app/graphql/types/ci/job_type.rb b/app/graphql/types/ci/job_type.rb
index a97e9cee4b1..d0830aff5c4 100644
--- a/app/graphql/types/ci/job_type.rb
+++ b/app/graphql/types/ci/job_type.rb
@@ -25,6 +25,9 @@ module Types
description: 'References to builds that must complete before the jobs run.'
field :pipeline, Types::Ci::PipelineType, null: true,
description: 'Pipeline the job belongs to.'
+ field :runner_machine, ::Types::Ci::RunnerMachineType, null: true,
+ description: 'Runner machine assigned to the job.',
+ alpha: { milestone: '15.11' }
field :stage, Types::Ci::StageType, null: true,
description: 'Stage of the job.'
field :status,
@@ -157,6 +160,21 @@ module Types
::Gitlab::Graphql::Loaders::BatchModelLoader.new(::Ci::Stage, object.stage_id).find
end
+ def runner_machine
+ BatchLoader::GraphQL.for(object.id).batch(key: :runner_machines) do |build_ids, loader|
+ plucked_build_to_machine_ids = ::Ci::RunnerMachineBuild.for_build(build_ids).pluck_build_id_and_runner_machine_id
+ runner_machines = ::Ci::RunnerMachine.id_in(plucked_build_to_machine_ids.values.uniq)
+ Preloaders::RunnerMachinePolicyPreloader.new(runner_machines, current_user).execute
+ runner_machines_by_id = runner_machines.index_by(&:id)
+
+ build_ids.each do |build_id|
+ runner_machine_id = plucked_build_to_machine_ids[build_id]
+
+ loader.call(build_id, runner_machines_by_id[runner_machine_id])
+ end
+ end
+ end
+
# This class is a secret union!
# TODO: turn this into an actual union, so that fields can be referenced safely!
def id
diff --git a/app/graphql/types/ci/runner_machine_type.rb b/app/graphql/types/ci/runner_machine_type.rb
index db0ff722f4e..8e6656288d9 100644
--- a/app/graphql/types/ci/runner_machine_type.rb
+++ b/app/graphql/types/ci/runner_machine_type.rb
@@ -35,6 +35,10 @@ module Types
Types::Ci::RunnerStatusEnum,
null: false,
description: 'Status of the runner machine.'
+ field :system_id, GraphQL::Types::String,
+ null: false,
+ description: 'System ID associated with the runner machine.',
+ method: :system_xid
field :version, GraphQL::Types::String, null: true, description: 'Version of the runner.'
def executor_name
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index 3df9d68b03e..3e8872dc199 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -153,7 +153,6 @@ module NotesHelper
def initial_notes_data(autocomplete)
{
notesUrl: notes_url,
- notesIds: @noteable.notes.pluck(:id), # rubocop: disable CodeReuse/ActiveRecord
now: Time.now.to_i,
diffView: diff_view,
enableGFM: {
diff --git a/app/models/bulk_imports/batch_tracker.rb b/app/models/bulk_imports/batch_tracker.rb
new file mode 100644
index 00000000000..df1fab89ee6
--- /dev/null
+++ b/app/models/bulk_imports/batch_tracker.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module BulkImports
+ class BatchTracker < ApplicationRecord
+ self.table_name = 'bulk_import_batch_trackers'
+
+ belongs_to :tracker, class_name: 'BulkImports::Tracker'
+
+ validates :batch_number, presence: true, uniqueness: { scope: :tracker_id }
+
+ state_machine :status, initial: :created do
+ state :created, value: 0
+ state :started, value: 1
+ state :finished, value: 2
+ state :timeout, value: 3
+ state :failed, value: -1
+ state :skipped, value: -2
+
+ event :start do
+ transition created: :started
+ end
+
+ event :retry do
+ transition started: :created
+ end
+
+ event :finish do
+ transition started: :finished
+ transition failed: :failed
+ transition skipped: :skipped
+ end
+
+ event :skip do
+ transition any => :skipped
+ end
+
+ event :fail_op do
+ transition any => :failed
+ end
+
+ event :cleanup_stale do
+ transition [:created, :started] => :timeout
+ end
+ end
+ end
+end
diff --git a/app/models/bulk_imports/export.rb b/app/models/bulk_imports/export.rb
index 8d4d31ee92d..1ea317a100a 100644
--- a/app/models/bulk_imports/export.rb
+++ b/app/models/bulk_imports/export.rb
@@ -14,6 +14,7 @@ module BulkImports
belongs_to :group, optional: true
has_one :upload, class_name: 'BulkImports::ExportUpload'
+ has_many :batches, class_name: 'BulkImports::ExportBatch'
validates :project, presence: true, unless: :group
validates :group, presence: true, unless: :project
diff --git a/app/models/bulk_imports/export_batch.rb b/app/models/bulk_imports/export_batch.rb
new file mode 100644
index 00000000000..9d34dae12d0
--- /dev/null
+++ b/app/models/bulk_imports/export_batch.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module BulkImports
+ class ExportBatch < ApplicationRecord
+ self.table_name = 'bulk_import_export_batches'
+
+ BATCH_SIZE = 1000
+
+ belongs_to :export, class_name: 'BulkImports::Export'
+ has_one :upload, class_name: 'BulkImports::ExportUpload', foreign_key: :batch_id, inverse_of: :batch
+
+ validates :batch_number, presence: true, uniqueness: { scope: :export_id }
+
+ state_machine :status, initial: :started do
+ state :started, value: 0
+ state :finished, value: 1
+ state :failed, value: -1
+
+ event :start do
+ transition any => :started
+ end
+
+ event :finish do
+ transition started: :finished
+ transition failed: :failed
+ end
+
+ event :fail_op do
+ transition any => :failed
+ end
+ end
+ end
+end
diff --git a/app/models/bulk_imports/export_upload.rb b/app/models/bulk_imports/export_upload.rb
index 4304032b28c..00f8e8f1304 100644
--- a/app/models/bulk_imports/export_upload.rb
+++ b/app/models/bulk_imports/export_upload.rb
@@ -7,6 +7,7 @@ module BulkImports
self.table_name = 'bulk_import_export_uploads'
belongs_to :export, class_name: 'BulkImports::Export'
+ belongs_to :batch, class_name: 'BulkImports::ExportBatch', optional: true
mount_uploader :export_file, ExportUploader
diff --git a/app/models/bulk_imports/tracker.rb b/app/models/bulk_imports/tracker.rb
index 701f1a9e49e..55502721a76 100644
--- a/app/models/bulk_imports/tracker.rb
+++ b/app/models/bulk_imports/tracker.rb
@@ -11,6 +11,8 @@ class BulkImports::Tracker < ApplicationRecord
foreign_key: :bulk_import_entity_id,
optional: false
+ has_many :batches, class_name: 'BulkImports::BatchTracker', inverse_of: :tracker
+
validates :relation,
presence: true,
uniqueness: { scope: :bulk_import_entity_id }
diff --git a/app/models/ci/runner_machine_build.rb b/app/models/ci/runner_machine_build.rb
index 95418db3619..d4f2c403337 100644
--- a/app/models/ci/runner_machine_build.rb
+++ b/app/models/ci/runner_machine_build.rb
@@ -14,5 +14,13 @@ module Ci
validates :build, presence: true
validates :runner_machine, presence: true
+
+ scope :for_build, ->(build_id) { where(build_id: build_id) }
+
+ def self.pluck_build_id_and_runner_machine_id
+ select(:build_id, :runner_machine_id)
+ .pluck(:build_id, :runner_machine_id)
+ .to_h
+ end
end
end
diff --git a/app/models/integration.rb b/app/models/integration.rb
index 15fae97895e..860739fe5aa 100644
--- a/app/models/integration.rb
+++ b/app/models/integration.rb
@@ -21,7 +21,8 @@ class Integration < ApplicationRecord
asana assembla bamboo bugzilla buildkite campfire confluence custom_issue_tracker datadog discord
drone_ci emails_on_push ewm external_wiki hangouts_chat harbor irker jira
mattermost mattermost_slash_commands microsoft_teams packagist pipelines_email
- pivotaltracker prometheus pumble pushover redmine slack slack_slash_commands teamcity unify_circuit webex_teams youtrack zentao
+ pivotaltracker prometheus pumble pushover redmine slack slack_slash_commands squash_tm teamcity
+ unify_circuit webex_teams youtrack zentao
].freeze
# TODO Shimo is temporary disabled on group and instance-levels.
diff --git a/app/models/integrations/squash_tm.rb b/app/models/integrations/squash_tm.rb
new file mode 100644
index 00000000000..e0a63b5ae6a
--- /dev/null
+++ b/app/models/integrations/squash_tm.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+module Integrations
+ class SquashTm < Integration
+ include HasWebHook
+
+ field :url,
+ placeholder: 'https://your-instance.squashcloud.io/squash/plugin/xsquash4gitlab/webhook/issue',
+ title: -> { s_('SquashTmIntegration|Squash TM webhook URL') },
+ exposes_secrets: true,
+ required: true
+
+ field :token,
+ type: 'password',
+ title: -> { s_('SquashTmIntegration|Secret token (optional)') },
+ non_empty_password_title: -> { s_('ProjectService|Enter new token') },
+ non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current token.') },
+ required: false
+
+ with_options if: :activated? do
+ validates :url, presence: true, public_url: true
+ validates :token, length: { maximum: 255 }, allow_blank: true
+ end
+
+ def title
+ 'Squash TM'
+ end
+
+ def description
+ s_("SquashTmIntegration|Update Squash TM requirements when GitLab issues are modified.")
+ end
+
+ def help
+ docs_link = ActionController::Base.helpers.link_to(
+ _('Learn more.'),
+ Rails.application.routes.url_helpers.help_page_url('user/project/integrations/squash_tm'),
+ target: '_blank',
+ rel: 'noopener noreferrer'
+ )
+
+ Kernel.format(
+ s_('SquashTmIntegration|Update Squash TM requirements when GitLab issues are modified. %{docs_link}'),
+ { docs_link: docs_link.html_safe }
+ ).html_safe
+ end
+
+ def self.supported_events
+ %w[issue confidential_issue]
+ end
+
+ def self.to_param
+ 'squash_tm'
+ end
+
+ def self.default_test_event
+ 'issue'
+ end
+
+ def execute(data)
+ return unless supported_events.include?(data[:object_kind])
+
+ execute_web_hook!(data, "#{data[:object_kind]} Hook")
+ end
+
+ def test(data)
+ result = execute_web_hook!(data, "Test Configuration Hook")
+
+ { success: result.payload[:http_status] == 200, result: result.message }
+ rescue StandardError => error
+ { success: false, result: error.message }
+ end
+
+ override :hook_url
+ def hook_url
+ format("#{url}%s", ('?token={token}' unless token.blank?))
+ end
+
+ def url_variables
+ { 'token' => token }.compact
+ end
+ end
+end
diff --git a/app/models/preloaders/runner_machine_policy_preloader.rb b/app/models/preloaders/runner_machine_policy_preloader.rb
new file mode 100644
index 00000000000..52864eeba8d
--- /dev/null
+++ b/app/models/preloaders/runner_machine_policy_preloader.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Preloaders
+ class RunnerMachinePolicyPreloader
+ def initialize(runner_machines, current_user)
+ @runner_machines = runner_machines
+ @current_user = current_user
+ end
+
+ def execute
+ return if runner_machines.is_a?(ActiveRecord::NullRelation)
+
+ ActiveRecord::Associations::Preloader.new(
+ records: runner_machines,
+ associations: [:runner]
+ ).call
+ end
+
+ private
+
+ attr_reader :runner_machines, :current_user
+ end
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index 738484338dc..cb218c0a49f 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -214,6 +214,7 @@ class Project < ApplicationRecord
has_one :shimo_integration, class_name: 'Integrations::Shimo'
has_one :slack_integration, class_name: 'Integrations::Slack'
has_one :slack_slash_commands_integration, class_name: 'Integrations::SlackSlashCommands'
+ has_one :squash_tm_integration, class_name: 'Integrations::SquashTm'
has_one :teamcity_integration, class_name: 'Integrations::Teamcity'
has_one :unify_circuit_integration, class_name: 'Integrations::UnifyCircuit'
has_one :webex_teams_integration, class_name: 'Integrations::WebexTeams'
diff --git a/app/models/user.rb b/app/models/user.rb
index ed001dadcbb..3bd8a035357 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -28,6 +28,7 @@ class User < ApplicationRecord
include UpdateHighestRole
include HasUserType
include Gitlab::Auth::Otp::Fortinet
+ include Gitlab::Auth::Otp::DuoAuth
include RestrictedSignup
include StripAttribute
include EachBatch
@@ -1068,7 +1069,8 @@ class User < ApplicationRecord
def two_factor_otp_enabled?
otp_required_for_login? ||
forti_authenticator_enabled?(self) ||
- forti_token_cloud_enabled?(self)
+ forti_token_cloud_enabled?(self) ||
+ duo_auth_enabled?(self)
end
def two_factor_webauthn_enabled?
diff --git a/app/services/concerns/update_repository_storage_methods.rb b/app/services/concerns/update_repository_storage_methods.rb
index b21d05f4178..a0b4040cff7 100644
--- a/app/services/concerns/update_repository_storage_methods.rb
+++ b/app/services/concerns/update_repository_storage_methods.rb
@@ -28,10 +28,7 @@ module UpdateRepositoryStorageMethods
track_repository(destination_storage_name)
end
- unless same_filesystem?
- remove_old_paths
- enqueue_housekeeping
- end
+ remove_old_paths unless same_filesystem?
repository_storage_move.finish_cleanup!
@@ -95,10 +92,6 @@ module UpdateRepositoryStorageMethods
end
end
- def enqueue_housekeeping
- # no-op
- end
-
def wait_for_pushes(type)
reference_counter = container.reference_counter(type: type)
diff --git a/app/services/packages/debian/generate_distribution_service.rb b/app/services/packages/debian/generate_distribution_service.rb
index 2ced2e5f275..ee43fe208c9 100644
--- a/app/services/packages/debian/generate_distribution_service.rb
+++ b/app/services/packages/debian/generate_distribution_service.rb
@@ -269,7 +269,7 @@ module Packages
# used by ExclusiveLeaseGuard
def lease_key
- "packages:debian:generate_distribution_service:distribution:#{@distribution.id}"
+ "packages:debian:generate_distribution_service:#{@distribution.class.container_type}_distribution:#{@distribution.id}"
end
# used by ExclusiveLeaseGuard
diff --git a/app/services/projects/update_repository_storage_service.rb b/app/services/projects/update_repository_storage_service.rb
index 7c63216af5e..cadf3012131 100644
--- a/app/services/projects/update_repository_storage_service.rb
+++ b/app/services/projects/update_repository_storage_service.rb
@@ -25,19 +25,6 @@ module Projects
end
end
- # The underlying FetchInternalRemote call uses a `git fetch` to move data
- # to the new repository, which leaves it in a less-well-packed state,
- # lacking bitmaps and commit graphs. Housekeeping will boost performance
- # significantly.
- def enqueue_housekeeping
- return unless Gitlab::CurrentSettings.housekeeping_enabled?
- return unless Feature.enabled?(:repack_after_shard_migration, project)
-
- Repositories::HousekeepingService.new(project, :gc).execute
- rescue Repositories::HousekeepingService::LeaseTaken
- # No action required
- end
-
def remove_old_paths
super
diff --git a/app/services/users/validate_manual_otp_service.rb b/app/services/users/validate_manual_otp_service.rb
index 96a827db13c..8ba76f5f593 100644
--- a/app/services/users/validate_manual_otp_service.rb
+++ b/app/services/users/validate_manual_otp_service.rb
@@ -3,6 +3,7 @@
module Users
class ValidateManualOtpService < BaseService
include ::Gitlab::Auth::Otp::Fortinet
+ include ::Gitlab::Auth::Otp::DuoAuth
def initialize(current_user)
@current_user = current_user
@@ -10,6 +11,8 @@ module Users
::Gitlab::Auth::Otp::Strategies::FortiAuthenticator::ManualOtp.new(current_user)
elsif forti_token_cloud_enabled?(current_user)
::Gitlab::Auth::Otp::Strategies::FortiTokenCloud.new(current_user)
+ elsif duo_auth_enabled?(current_user)
+ ::Gitlab::Auth::Otp::Strategies::DuoAuth::ManualOtp.new(current_user)
else
::Gitlab::Auth::Otp::Strategies::Devise.new(current_user)
end
diff --git a/app/views/admin/background_migrations/index.html.haml b/app/views/admin/background_migrations/index.html.haml
index 0f76fdce416..00859bf6b66 100644
--- a/app/views/admin/background_migrations/index.html.haml
+++ b/app/views/admin/background_migrations/index.html.haml
@@ -5,7 +5,7 @@
.gl-flex-grow-1
%h3= s_('BackgroundMigrations|Background Migrations')
%p.light.gl-mb-0
- - learnmore_link = help_page_path('user/admin_area/monitoring/background_migrations')
+ - learnmore_link = help_page_path('update/background_migrations')
- learnmore_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: learnmore_link }
= html_escape(s_('BackgroundMigrations|Background migrations are used to perform data migrations whenever a migration exceeds the time limits in our guidelines. %{linkStart}Learn more%{linkEnd}')) % { linkStart: learnmore_link_start, linkEnd: '</a>'.html_safe }
diff --git a/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml b/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml
index eba5e7c6e9b..855177fd836 100644
--- a/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml
+++ b/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml
@@ -7,7 +7,7 @@
= link_to new_project_path, class: link_classes do
.blank-state-icon
= custom_icon("add_new_project", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Create a project')
%p
@@ -17,7 +17,7 @@
= link_to new_group_path, class: link_classes do
.blank-state-icon
= custom_icon("add_new_group", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Create a group')
%p
@@ -26,7 +26,7 @@
= link_to new_admin_user_path, class: link_classes do
.blank-state-icon
= custom_icon("add_new_user", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Add people')
%p
@@ -35,7 +35,7 @@
= link_to admin_root_path, class: link_classes do
.blank-state-icon
= custom_icon("configure_server", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Configure GitLab')
%p
diff --git a/app/views/dashboard/projects/_blank_state_welcome.html.haml b/app/views/dashboard/projects/_blank_state_welcome.html.haml
index a9a34af3f96..c5fdc31a775 100644
--- a/app/views/dashboard/projects/_blank_state_welcome.html.haml
+++ b/app/views/dashboard/projects/_blank_state_welcome.html.haml
@@ -5,7 +5,7 @@
= link_to new_project_path, class: link_classes do
.blank-state-icon
= custom_icon("add_new_project", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Create a project')
%p
@@ -19,7 +19,7 @@
= link_to new_group_path, class: link_classes do
.blank-state-icon
= custom_icon("add_new_group", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Create a group')
%p
@@ -28,7 +28,7 @@
= link_to trending_explore_projects_path, class: link_classes do
.blank-state-icon
= custom_icon("globe", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Explore public projects')
%p
@@ -37,7 +37,7 @@
= link_to Gitlab::Saas::doc_url, class: link_classes do
.blank-state-icon
= custom_icon("lightbulb", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Learn more about GitLab')
%p
diff --git a/app/views/groups/_import_group_from_file_panel.html.haml b/app/views/groups/_import_group_from_file_panel.html.haml
index 94ad9dc6da9..775b9c79817 100644
--- a/app/views/groups/_import_group_from_file_panel.html.haml
+++ b/app/views/groups/_import_group_from_file_panel.html.haml
@@ -17,7 +17,7 @@
.form-group
= f.label :file, s_('GroupsNew|Upload file')
.gl-font-weight-normal
- - import_export_link_start = '<a href="%{url}" target="_blank">'.html_safe % { url: help_page_path('user/group/settings/import_export') }
+ - import_export_link_start = '<a href="%{url}" target="_blank">'.html_safe % { url: help_page_path('user/group/import/index') }
= s_('GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here.').html_safe % { link_start: import_export_link_start, link_end: '</a>'.html_safe }
.gl-mt-3
= render 'shared/file_picker_button', f: f, field: :file, help_text: nil, classes: 'gl-button btn-confirm-secondary gl-mr-2'
diff --git a/app/views/groups/settings/_export.html.haml b/app/views/groups/settings/_export.html.haml
index b60eb134a9c..6b505755727 100644
--- a/app/views/groups/settings/_export.html.haml
+++ b/app/views/groups/settings/_export.html.haml
@@ -5,13 +5,12 @@
%p= _('Export this group with all related data.')
= render Pajamas::AlertComponent.new(variant: :warning, dismissible: false, alert_options: { class: 'gl-mb-4' }) do |c|
= c.body do
- - docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/group/import/index.md', anchor: 'migrate-groups-by-direct-transfer-recommended') }
+ - docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/group/import/index', anchor: 'migrate-groups-by-direct-transfer-recommended') }
- docs_link_end = '</a>'.html_safe
= s_('GroupsNew|This feature is deprecated and replaced by group migration by direct transfer. %{docs_link_start}Learn more%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: docs_link_end }
%p
- export_information = _('After the export is complete, download the data file from a notification email or from this page. You can then import the data file from the %{strong_text_start}Create new group%{strong_text_end} page of another GitLab instance.') % { strong_text_start: '<strong>'.html_safe, strong_text_end: '</strong>'.html_safe}
= export_information.html_safe
- = link_to _('Learn more.'), help_page_path('user/group/settings/import_export.md'), target: '_blank', rel: 'noopener noreferrer'
= render Pajamas::AlertComponent.new(dismissible: false, alert_options: { class: 'gl-mb-5' }) do |c|
= c.body do
%p.gl-mb-0
diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml
index fee943042f9..3280dcf2cd4 100644
--- a/app/views/search/_results.html.haml
+++ b/app/views/search/_results.html.haml
@@ -5,5 +5,5 @@
.results.gl-md-display-flex.gl-mt-0
#js-search-sidebar{ class: search_bar_classes, data: { navigation_json: search_navigation_json } }
.gl-w-full.gl-flex-grow-1.gl-overflow-x-hidden
- = render partial: 'search/results_status' unless @search_objects.to_a.empty?
+ = render partial: 'search/results_status' if @search_objects.present?
= render partial: 'search/results_list'
diff --git a/app/views/search/_results_list.html.haml b/app/views/search/_results_list.html.haml
index ce4dd02b41d..c36acaf9ea8 100644
--- a/app/views/search/_results_list.html.haml
+++ b/app/views/search/_results_list.html.haml
@@ -2,7 +2,7 @@
= render partial: "search/results/timeout"
- elsif @search_results.respond_to?(:failed?) && @search_results.failed?
= render partial: "search/results/error"
-- elsif @search_objects.to_a.empty?
+- elsif @search_objects.blank?
= render partial: "search/results/empty"
- else
.gl-md-pl-5
diff --git a/app/workers/packages/debian/generate_distribution_worker.rb b/app/workers/packages/debian/generate_distribution_worker.rb
index 1eff3ea02dd..f0c753c3a9b 100644
--- a/app/workers/packages/debian/generate_distribution_worker.rb
+++ b/app/workers/packages/debian/generate_distribution_worker.rb
@@ -20,7 +20,7 @@ module Packages
loggable_arguments 0
def perform(container_type, distribution_id)
- @container_type = container_type
+ @container_type = container_type.to_sym
@distribution_id = distribution_id
return unless distribution