diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-13 15:10:20 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-13 15:10:20 +0000 |
commit | e958867b2e341329243be8db0c262233ae1238c0 (patch) | |
tree | c5d57d56735b4cf750f14a49ca576920b0458a85 | |
parent | 3748ae5cbbefd3de0111951e71e74b676c276d61 (diff) | |
download | gitlab-ce-e958867b2e341329243be8db0c262233ae1238c0.tar.gz |
Add latest changes from gitlab-org/gitlab@master
68 files changed, 1237 insertions, 1010 deletions
diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js index 3a2f2078e44..43f44370af8 100644 --- a/app/assets/javascripts/awards_handler.js +++ b/app/assets/javascripts/awards_handler.js @@ -12,7 +12,6 @@ import axios from './lib/utils/axios_utils'; import { isInVueNoteablePage } from './lib/utils/dom_utils'; import { __ } from './locale'; -window.axios = axios; const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd'; const transitionEndEventString = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'; diff --git a/app/assets/javascripts/behaviors/date_picker.js b/app/assets/javascripts/behaviors/date_picker.js new file mode 100644 index 00000000000..efd89ec4330 --- /dev/null +++ b/app/assets/javascripts/behaviors/date_picker.js @@ -0,0 +1,33 @@ +import $ from 'jquery'; +import Pikaday from 'pikaday'; +import { parsePikadayDate, pikadayToString } from '~/lib/utils/datetime_utility'; + +export default function initDatePickers() { + $('.datepicker').each(function initPikaday() { + const $datePicker = $(this); + const datePickerVal = $datePicker.val(); + + const calendar = new Pikaday({ + field: $datePicker.get(0), + theme: 'gitlab-theme animate-picker', + format: 'yyyy-mm-dd', + container: $datePicker.parent().get(0), + parse: (dateString) => parsePikadayDate(dateString), + toString: (date) => pikadayToString(date), + onSelect(dateText) { + $datePicker.val(calendar.toString(dateText)); + }, + firstDay: gon.first_day_of_week, + }); + + calendar.setDate(parsePikadayDate(datePickerVal)); + + $datePicker.data('pikaday', calendar); + }); + + $('.js-clear-due-date,.js-clear-start-date').on('click', (e) => { + e.preventDefault(); + const calendar = $(e.target).siblings('.datepicker').data('pikaday'); + calendar.setDate(null); + }); +} diff --git a/app/assets/javascripts/due_date_select.js b/app/assets/javascripts/due_date_select.js index 1f57d73d3d3..aa223270f2c 100644 --- a/app/assets/javascripts/due_date_select.js +++ b/app/assets/javascripts/due_date_select.js @@ -2,6 +2,7 @@ import dateFormat from 'dateformat'; import $ from 'jquery'; import Pikaday from 'pikaday'; +import initDatePicker from '~/behaviors/date_picker'; import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; import { __ } from '~/locale'; import boardsStore from './boards/stores/boards_store'; @@ -168,40 +169,10 @@ class DueDateSelect { export default class DueDateSelectors { constructor() { - this.initMilestoneDatePicker(); + initDatePicker(); this.initIssuableSelect(); } // eslint-disable-next-line class-methods-use-this - initMilestoneDatePicker() { - $('.datepicker').each(function initPikadayMilestone() { - const $datePicker = $(this); - const datePickerVal = $datePicker.val(); - - const calendar = new Pikaday({ - field: $datePicker.get(0), - theme: 'gitlab-theme animate-picker', - format: 'yyyy-mm-dd', - container: $datePicker.parent().get(0), - parse: (dateString) => parsePikadayDate(dateString), - toString: (date) => pikadayToString(date), - onSelect(dateText) { - $datePicker.val(calendar.toString(dateText)); - }, - firstDay: gon.first_day_of_week, - }); - - calendar.setDate(parsePikadayDate(datePickerVal)); - - $datePicker.data('pikaday', calendar); - }); - - $('.js-clear-due-date,.js-clear-start-date').on('click', (e) => { - e.preventDefault(); - const calendar = $(e.target).siblings('.datepicker').data('pikaday'); - calendar.setDate(null); - }); - } - // eslint-disable-next-line class-methods-use-this initIssuableSelect() { const $loading = $('.js-issuable-update .due_date') .find('.block-loading') diff --git a/app/assets/javascripts/init_issuable_sidebar.js b/app/assets/javascripts/init_issuable_sidebar.js index 59038b3d9fb..17c73fdf1c3 100644 --- a/app/assets/javascripts/init_issuable_sidebar.js +++ b/app/assets/javascripts/init_issuable_sidebar.js @@ -1,7 +1,6 @@ /* eslint-disable no-new */ import { mountSidebarLabels, getSidebarOptions } from '~/sidebar/mount_sidebar'; -import DueDateSelectors from './due_date_select'; import IssuableContext from './issuable_context'; import LabelsSelect from './labels_select'; import MilestoneSelect from './milestone_select'; @@ -19,7 +18,6 @@ export default () => { }); new LabelsSelect(); new IssuableContext(sidebarOptions.currentUser); - new DueDateSelectors(); Sidebar.initialize(); mountSidebarLabels(); diff --git a/app/assets/javascripts/logs/stores/actions.js b/app/assets/javascripts/logs/stores/actions.js index e813f91d2fa..c3dc9f4bc12 100644 --- a/app/assets/javascripts/logs/stores/actions.js +++ b/app/assets/javascripts/logs/stores/actions.js @@ -127,7 +127,7 @@ export const fetchEnvironments = ({ commit, dispatch }, environmentsPath) => { return axios .get(environmentsPath) .then(({ data }) => { - commit(types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS, data.environments); + commit(types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS, data); dispatch('fetchLogs', tracking.ENVIRONMENT_SELECTED); }) .catch(() => { diff --git a/app/assets/javascripts/pages/groups/milestones/edit/index.js b/app/assets/javascripts/pages/groups/milestones/edit/index.js index 364b0d95d9c..4f8514a9a1d 100644 --- a/app/assets/javascripts/pages/groups/milestones/edit/index.js +++ b/app/assets/javascripts/pages/groups/milestones/edit/index.js @@ -1,3 +1,3 @@ -import initForm from '../../../../shared/milestones/form'; +import initForm from '~/shared/milestones/form'; initForm(); diff --git a/app/assets/javascripts/pages/groups/milestones/new/index.js b/app/assets/javascripts/pages/groups/milestones/new/index.js index 364b0d95d9c..4f8514a9a1d 100644 --- a/app/assets/javascripts/pages/groups/milestones/new/index.js +++ b/app/assets/javascripts/pages/groups/milestones/new/index.js @@ -1,3 +1,3 @@ -import initForm from '../../../../shared/milestones/form'; +import initForm from '~/shared/milestones/form'; initForm(); diff --git a/app/assets/javascripts/pages/groups/settings/repository/show/index.js b/app/assets/javascripts/pages/groups/settings/repository/show/index.js index 92405f205cb..f048955dadf 100644 --- a/app/assets/javascripts/pages/groups/settings/repository/show/index.js +++ b/app/assets/javascripts/pages/groups/settings/repository/show/index.js @@ -1,7 +1,8 @@ -import DueDateSelectors from '~/due_date_select'; +import initDatePicker from '~/behaviors/date_picker'; import initSettingsPanels from '~/settings_panels'; // Initialize expandable settings panels initSettingsPanels(); -new DueDateSelectors(); // eslint-disable-line no-new +// Used for deploy tokens "expires at" field +initDatePicker(); diff --git a/app/assets/javascripts/pages/projects/milestones/new/index.js b/app/assets/javascripts/pages/projects/milestones/new/index.js index 364b0d95d9c..4f8514a9a1d 100644 --- a/app/assets/javascripts/pages/projects/milestones/new/index.js +++ b/app/assets/javascripts/pages/projects/milestones/new/index.js @@ -1,3 +1,3 @@ -import initForm from '../../../../shared/milestones/form'; +import initForm from '~/shared/milestones/form'; initForm(); diff --git a/app/assets/javascripts/pages/projects/settings/repository/form.js b/app/assets/javascripts/pages/projects/settings/repository/form.js index 8d390c8586b..380091a3501 100644 --- a/app/assets/javascripts/pages/projects/settings/repository/form.js +++ b/app/assets/javascripts/pages/projects/settings/repository/form.js @@ -1,7 +1,7 @@ /* eslint-disable no-new */ +import initDatePicker from '~/behaviors/date_picker'; import initDeployKeys from '~/deploy_keys'; -import DueDateSelectors from '~/due_date_select'; import fileUpload from '~/lib/utils/file_upload'; import ProtectedBranchCreate from '~/protected_branches/protected_branch_create'; import ProtectedBranchEditList from '~/protected_branches/protected_branch_edit_list'; @@ -16,6 +16,6 @@ export default () => { initSettingsPanels(); new ProtectedBranchCreate({ hasLicense: false }); new ProtectedBranchEditList(); - new DueDateSelectors(); + initDatePicker(); // Used for deploy token "expires at" field fileUpload('.js-choose-file', '.js-object-map-input'); }; diff --git a/app/assets/javascripts/shared/milestones/form.js b/app/assets/javascripts/shared/milestones/form.js index 467cd321fb8..3ca9288b156 100644 --- a/app/assets/javascripts/shared/milestones/form.js +++ b/app/assets/javascripts/shared/milestones/form.js @@ -1,11 +1,12 @@ import $ from 'jquery'; -import DueDateSelectors from '../../due_date_select'; +import initDatePicker from '~/behaviors/date_picker'; import GLForm from '../../gl_form'; import ZenMode from '../../zen_mode'; export default (initGFM = true) => { new ZenMode(); // eslint-disable-line no-new - new DueDateSelectors(); // eslint-disable-line no-new + initDatePicker(); + // eslint-disable-next-line no-new new GLForm($('.milestone-form'), { emojis: true, diff --git a/app/graphql/resolvers/group_packages_resolver.rb b/app/graphql/resolvers/group_packages_resolver.rb index 3849b870b40..d91fe84317d 100644 --- a/app/graphql/resolvers/group_packages_resolver.rb +++ b/app/graphql/resolvers/group_packages_resolver.rb @@ -1,26 +1,19 @@ # frozen_string_literal: true +# rubocop: disable Graphql/ResolverType module Resolvers - class GroupPackagesResolver < BaseResolver - type Types::Packages::PackageType.connection_type, null: true + class GroupPackagesResolver < PackagesBaseResolver + # The GraphQL type is defined in the extended class argument :sort, Types::Packages::PackageGroupSortEnum, description: 'Sort packages by this criteria.', required: false, default_value: :created_desc - SORT_TO_PARAMS_MAP = { - created_desc: { order_by: 'created', sort: 'desc' }, - created_asc: { order_by: 'created', sort: 'asc' }, - name_desc: { order_by: 'name', sort: 'desc' }, - name_asc: { order_by: 'name', sort: 'asc' }, - version_desc: { order_by: 'version', sort: 'desc' }, - version_asc: { order_by: 'version', sort: 'asc' }, - type_desc: { order_by: 'type', sort: 'desc' }, - type_asc: { order_by: 'type', sort: 'asc' }, + GROUP_SORT_TO_PARAMS_MAP = SORT_TO_PARAMS_MAP.merge({ project_path_desc: { order_by: 'project_path', sort: 'desc' }, project_path_asc: { order_by: 'project_path', sort: 'asc' } - }.freeze + }).freeze def ready?(**args) context[self.class] ||= { executions: 0 } @@ -30,16 +23,11 @@ module Resolvers super end - def resolve(sort:) + def resolve(sort:, **filters) return unless packages_available? - ::Packages::GroupPackagesFinder.new(current_user, object, SORT_TO_PARAMS_MAP[sort]).execute - end - - private - - def packages_available? - ::Gitlab.config.packages.enabled + ::Packages::GroupPackagesFinder.new(current_user, object, filters.merge(GROUP_SORT_TO_PARAMS_MAP.fetch(sort))).execute end end end +# rubocop: enable Graphql/ResolverType diff --git a/app/graphql/resolvers/packages_base_resolver.rb b/app/graphql/resolvers/packages_base_resolver.rb new file mode 100644 index 00000000000..3378cc32c9f --- /dev/null +++ b/app/graphql/resolvers/packages_base_resolver.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +module Resolvers + class PackagesBaseResolver < BaseResolver + type Types::Packages::PackageType.connection_type, null: true + + argument :sort, Types::Packages::PackageSortEnum, + description: 'Sort packages by this criteria.', + required: false, + default_value: :created_desc + + argument :package_name, GraphQL::STRING_TYPE, + description: 'Search a package by name.', + required: false, + default_value: nil + + argument :package_type, Types::Packages::PackageTypeEnum, + description: 'Filter a package by type.', + required: false, + default_value: nil + + argument :status, Types::Packages::PackageStatusEnum, + description: 'Filter a package by status.', + required: false, + default_value: nil + + argument :include_versionless, GraphQL::BOOLEAN_TYPE, + description: 'Include versionless packages.', + required: false, + default_value: false + + SORT_TO_PARAMS_MAP = { + created_desc: { order_by: 'created', sort: 'desc' }, + created_asc: { order_by: 'created', sort: 'asc' }, + name_desc: { order_by: 'name', sort: 'desc' }, + name_asc: { order_by: 'name', sort: 'asc' }, + version_desc: { order_by: 'version', sort: 'desc' }, + version_asc: { order_by: 'version', sort: 'asc' }, + type_desc: { order_by: 'type', sort: 'desc' }, + type_asc: { order_by: 'type', sort: 'asc' } + }.freeze + + def resolve + raise NotImplementedError + end + + private + + def packages_available? + ::Gitlab.config.packages.enabled + end + end +end diff --git a/app/graphql/resolvers/project_packages_resolver.rb b/app/graphql/resolvers/project_packages_resolver.rb index 2f90a2fda1f..6d66c2fe460 100644 --- a/app/graphql/resolvers/project_packages_resolver.rb +++ b/app/graphql/resolvers/project_packages_resolver.rb @@ -1,35 +1,15 @@ # frozen_string_literal: true +# rubocop: disable Graphql/ResolverType module Resolvers - class ProjectPackagesResolver < BaseResolver - type Types::Packages::PackageType.connection_type, null: true + class ProjectPackagesResolver < PackagesBaseResolver + # The GraphQL type is defined in the extended class - argument :sort, Types::Packages::PackageSortEnum, - description: 'Sort packages by this criteria.', - required: false, - default_value: :created_desc - - SORT_TO_PARAMS_MAP = { - created_desc: { order_by: 'created', sort: 'desc' }, - created_asc: { order_by: 'created', sort: 'asc' }, - name_desc: { order_by: 'name', sort: 'desc' }, - name_asc: { order_by: 'name', sort: 'asc' }, - version_desc: { order_by: 'version', sort: 'desc' }, - version_asc: { order_by: 'version', sort: 'asc' }, - type_desc: { order_by: 'type', sort: 'desc' }, - type_asc: { order_by: 'type', sort: 'asc' } - }.freeze - - def resolve(sort:) + def resolve(sort:, **filters) return unless packages_available? - ::Packages::PackagesFinder.new(object, SORT_TO_PARAMS_MAP.fetch(sort)).execute - end - - private - - def packages_available? - ::Gitlab.config.packages.enabled + ::Packages::PackagesFinder.new(object, filters.merge(SORT_TO_PARAMS_MAP.fetch(sort))).execute end end end +# rubocop: enable Graphql/ResolverType diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb index 5add24500e2..594c6fedef1 100644 --- a/app/helpers/environments_helper.rb +++ b/app/helpers/environments_helper.rb @@ -34,7 +34,7 @@ module EnvironmentsHelper def environment_logs_data(project, environment) { "environment_name": environment.name, - "environments_path": project_environments_path(project, format: :json), + "environments_path": api_v4_projects_environments_path(id: project.id), "environment_id": environment.id, "cluster_applications_documentation_path" => help_page_path('user/clusters/applications.md', anchor: 'elastic-stack'), "clusters_path": project_clusters_path(project, format: :json) diff --git a/app/models/ci/pipeline_schedule.rb b/app/models/ci/pipeline_schedule.rb index b76f1d48631..9e5d517c1fe 100644 --- a/app/models/ci/pipeline_schedule.rb +++ b/app/models/ci/pipeline_schedule.rb @@ -5,7 +5,7 @@ module Ci extend Gitlab::Ci::Model include Importable include StripAttribute - include Schedulable + include CronSchedulable include Limitable include EachBatch @@ -51,36 +51,14 @@ module Ci update_attribute(:active, false) end - ## - # The `next_run_at` column is set to the actual execution date of `PipelineScheduleWorker`. - # This way, a schedule like `*/1 * * * *` won't be triggered in a short interval - # when PipelineScheduleWorker runs irregularly by Sidekiq Memory Killer. - def set_next_run_at - now = Time.zone.now - ideal_next_run = ideal_next_run_from(now) - - self.next_run_at = if ideal_next_run == cron_worker_next_run_from(now) - ideal_next_run - else - cron_worker_next_run_from(ideal_next_run) - end - end - def job_variables variables&.map(&:to_runner_variable) || [] end private - def ideal_next_run_from(start_time) - Gitlab::Ci::CronParser.new(cron, cron_timezone) - .next_time_from(start_time) - end - - def cron_worker_next_run_from(start_time) - Gitlab::Ci::CronParser.new(Settings.cron_jobs['pipeline_schedule_worker']['cron'], - Time.zone.name) - .next_time_from(start_time) + def worker_cron_expression + Settings.cron_jobs['pipeline_schedule_worker']['cron'] end end end diff --git a/app/models/concerns/cron_schedulable.rb b/app/models/concerns/cron_schedulable.rb new file mode 100644 index 00000000000..beb3a09c119 --- /dev/null +++ b/app/models/concerns/cron_schedulable.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module CronSchedulable + extend ActiveSupport::Concern + include Schedulable + + ## + # The `next_run_at` column is set to the actual execution date of worker that + # triggers the schedule. This way, a schedule like `*/1 * * * *` won't be triggered + # in a short interval when the worker runs irregularly by Sidekiq Memory Killer. + def set_next_run_at + now = Time.zone.now + ideal_next_run = ideal_next_run_from(now) + + self.next_run_at = if ideal_next_run == cron_worker_next_run_from(now) + ideal_next_run + else + cron_worker_next_run_from(ideal_next_run) + end + end + + private + + def ideal_next_run_from(start_time) + next_time_from(start_time, cron, cron_timezone) + end + + def cron_worker_next_run_from(start_time) + next_time_from(start_time, worker_cron_expression, Time.zone.name) + end + + def next_time_from(start_time, cron, cron_timezone) + Gitlab::Ci::CronParser + .new(cron, cron_timezone) + .next_time_from(start_time) + end + + def worker_cron_expression + raise NotImplementedError + end +end diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb index 0535bc625ac..a3de5021076 100644 --- a/app/services/web_hook_service.rb +++ b/app/services/web_hook_service.rb @@ -27,6 +27,7 @@ class WebHookService REQUEST_BODY_SIZE_LIMIT = 25.megabytes GITLAB_EVENT_HEADER = 'X-Gitlab-Event' + MAX_FAILURES = 100 attr_accessor :hook, :data, :hook_name, :request_options @@ -141,7 +142,7 @@ class WebHookService next_backoff = hook.next_backoff hook.update!(disabled_until: next_backoff.from_now, backoff_count: hook.backoff_count + 1) else - hook.update!(recent_failures: hook.recent_failures + 1) + hook.update!(recent_failures: hook.recent_failures + 1) if hook.recent_failures < MAX_FAILURES end end diff --git a/changelogs/unreleased/285467-package-registry-graphql-api-3.yml b/changelogs/unreleased/285467-package-registry-graphql-api-3.yml new file mode 100644 index 00000000000..6307cbc75af --- /dev/null +++ b/changelogs/unreleased/285467-package-registry-graphql-api-3.yml @@ -0,0 +1,5 @@ +--- +title: 'Package: group and project graphql types - add search' +merge_request: 61001 +author: +type: added diff --git a/changelogs/unreleased/ph-enableImprovedEmojiPicker.yml b/changelogs/unreleased/ph-enableImprovedEmojiPicker.yml new file mode 100644 index 00000000000..24d71a00040 --- /dev/null +++ b/changelogs/unreleased/ph-enableImprovedEmojiPicker.yml @@ -0,0 +1,5 @@ +--- +title: Improve UX of the award emoji picker +merge_request: 61384 +author: +type: added diff --git a/config/feature_flags/development/improved_emoji_picker.yml b/config/feature_flags/development/improved_emoji_picker.yml index 2d72c38630a..211f0264446 100644 --- a/config/feature_flags/development/improved_emoji_picker.yml +++ b/config/feature_flags/development/improved_emoji_picker.yml @@ -5,4 +5,4 @@ rollout_issue_url: milestone: '13.9' type: development group: group::code review -default_enabled: false +default_enabled: true diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 64ae868735a..65d6299bb89 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -691,6 +691,12 @@ Gitlab.ee do Settings.cron_jobs['vulnerability_historical_statistics_deletion_worker'] ||= Settingslogic.new({}) Settings.cron_jobs['vulnerability_historical_statistics_deletion_worker']['cron'] ||= '15 3 * * *' Settings.cron_jobs['vulnerability_historical_statistics_deletion_worker']['job_class'] = 'Vulnerabilities::HistoricalStatistics::DeletionWorker' + Settings.cron_jobs['security_create_orchestration_policy_worker'] ||= Settingslogic.new({}) + Settings.cron_jobs['security_create_orchestration_policy_worker']['cron'] ||= '*/10 * * * *' + Settings.cron_jobs['security_create_orchestration_policy_worker']['job_class'] = 'Security::CreateOrchestrationPolicyWorker' + Settings.cron_jobs['security_orchestration_policy_rule_schedule_worker'] ||= Settingslogic.new({}) + Settings.cron_jobs['security_orchestration_policy_rule_schedule_worker']['cron'] ||= '*/15 * * * *' + Settings.cron_jobs['security_orchestration_policy_rule_schedule_worker']['job_class'] = 'Security::OrchestrationPolicyRuleScheduleWorker' end # diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index f0189971b56..3cff4218a32 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -9107,7 +9107,11 @@ four standard [pagination arguments](#connection-pagination-arguments): | Name | Type | Description | | ---- | ---- | ----------- | +| <a id="grouppackagesincludeversionless"></a>`includeVersionless` | [`Boolean`](#boolean) | Include versionless packages. | +| <a id="grouppackagespackagename"></a>`packageName` | [`String`](#string) | Search a package by name. | +| <a id="grouppackagespackagetype"></a>`packageType` | [`PackageTypeEnum`](#packagetypeenum) | Filter a package by type. | | <a id="grouppackagessort"></a>`sort` | [`PackageGroupSort`](#packagegroupsort) | Sort packages by this criteria. | +| <a id="grouppackagesstatus"></a>`status` | [`PackageStatus`](#packagestatus) | Filter a package by status. | ##### `Group.projects` @@ -11362,7 +11366,11 @@ four standard [pagination arguments](#connection-pagination-arguments): | Name | Type | Description | | ---- | ---- | ----------- | +| <a id="projectpackagesincludeversionless"></a>`includeVersionless` | [`Boolean`](#boolean) | Include versionless packages. | +| <a id="projectpackagespackagename"></a>`packageName` | [`String`](#string) | Search a package by name. | +| <a id="projectpackagespackagetype"></a>`packageType` | [`PackageTypeEnum`](#packagetypeenum) | Filter a package by type. | | <a id="projectpackagessort"></a>`sort` | [`PackageSort`](#packagesort) | Sort packages by this criteria. | +| <a id="projectpackagesstatus"></a>`status` | [`PackageStatus`](#packagestatus) | Filter a package by status. | ##### `Project.pipeline` diff --git a/doc/api/notes.md b/doc/api/notes.md index edc479601bf..0fb13e56f78 100644 --- a/doc/api/notes.md +++ b/doc/api/notes.md @@ -4,7 +4,7 @@ group: Project Management info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- -# Notes API +# Notes API **(FREE)** Notes are comments on: @@ -19,15 +19,15 @@ assignee changes, GitLab posts a system note). ## Resource events > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/38096) in GitLab 13.3 for state, milestone, and weight events. -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40850) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.4 for iteration events. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40850) in GitLab 13.4 for iteration events. Some system notes are not part of this API, but are recorded as separate events: - [Resource label events](resource_label_events.md) - [Resource state events](resource_state_events.md) - [Resource milestone events](resource_milestone_events.md) -- [Resource weight events](resource_weight_events.md) **(STARTER)** -- [Resource iteration events](resource_iteration_events.md) **(STARTER)** +- [Resource weight events](resource_weight_events.md) +- [Resource iteration events](resource_iteration_events.md) ## Notes pagination diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md index f2a33e821b8..f35f146f8b9 100644 --- a/doc/subscriptions/gitlab_com/index.md +++ b/doc/subscriptions/gitlab_com/index.md @@ -265,6 +265,11 @@ To remove a billable user: 1. In the row for the user you want to remove, on the right side, select the ellipsis and **Remove user**. 1. Re-type the username and select **Remove user**. +If you add a member to a group by using the [share a group with another group](../../user/group/index.md#share-a-group-with-another-group) feature, you can't remove the member by using this method. Instead, you can either: + +- Remove the member from the shared group. You must be a group owner to do this. +- From the group's membership page, remove access from the entire shared group. + ## CI pipeline minutes CI pipeline minutes are the execution time for your diff --git a/doc/topics/git/bisect.md b/doc/topics/git/bisect.md new file mode 100644 index 00000000000..8af77031c93 --- /dev/null +++ b/doc/topics/git/bisect.md @@ -0,0 +1,76 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +comments: false +--- + +# Bisect + +- Find a commit that introduced a bug +- Works through a process of elimination +- Specify a known good and bad revision to begin + +## Bisect sample workflow + +1. Start the bisect process +1. Enter the bad revision (usually latest commit) +1. Enter a known good revision (commit/branch) +1. Run code to see if bug still exists +1. Tell bisect the result +1. Repeat the previous 2 items until you find the offending commit + +## Setup + +```shell + mkdir bisect-ex + cd bisect-ex + touch index.html + git add -A + git commit -m "starting out" + vi index.html + # Add all good + git add -A + git commit -m "second commit" + vi index.html + # Add all good 2 + git add -A + git commit -m "third commit" + vi index.html +``` + +```shell + # Add all good 3 + git add -A + git commit -m "fourth commit" + vi index.html + # This looks bad + git add -A + git commit -m "fifth commit" + vi index.html + # Really bad + git add -A + git commit -m "sixth commit" + vi index.html + # again just bad + git add -A + git commit -m "seventh commit" +``` + +## Commands + +```shell + git bisect start + # Test your code + git bisect bad + git bisect next + # Say yes to the warning + # Test + git bisect good + # Test + git bisect bad + # Test + git bisect good + # done + git bisect reset +``` diff --git a/doc/topics/git/feature_branching.md b/doc/topics/git/feature_branching.md new file mode 100644 index 00000000000..f6233bddb18 --- /dev/null +++ b/doc/topics/git/feature_branching.md @@ -0,0 +1,31 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +comments: false +--- + +# Feature branching + +- Efficient parallel workflow for teams +- Develop each feature in a branch +- Keeps changes isolated +- Consider a 1-to-1 link to issues +- Push branches to the server frequently + - Hint: This is a cheap backup for your work-in-progress code + +## Feature branching sample workflow + +1. Create a new feature branch called 'squash_some_bugs' +1. Edit '`bugs.rb`' and remove all the bugs. +1. Commit +1. Push + +```shell +git checkout -b squash_some_bugs +# Edit `bugs.rb` +git status +git add bugs.rb +git commit -m 'Fix some buggy code' +git push origin squash_some_bugs +``` diff --git a/doc/topics/git/getting_started.md b/doc/topics/git/getting_started.md new file mode 100644 index 00000000000..2c3d5fe15de --- /dev/null +++ b/doc/topics/git/getting_started.md @@ -0,0 +1,86 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +comments: false +--- + +# Getting Started + +## Instantiating Repositories + +- Create a new repository by instantiating it through: + + ```shell + git init + ``` + +- Copy an existing project by cloning the repository through: + + ```shell + git clone <url> + ``` + +## Central Repositories + +- To instantiate a central repository a `--bare` flag is required. +- Bare repositories don't allow file editing or committing changes. +- Create a bare repository with: + + ```shell + git init --bare project-name.git + ``` + +## Instantiate workflow with clone + +1. Create a project in your user namespace. + - Choose to import from **Any Repository by URL** and use <https://gitlab.com/gitlab-org/training-examples.git>. +1. Create a '`Workspace`' directory in your home directory. +1. Clone the '`training-examples`' project. + +```shell +mkdir ~/workspace +cd ~/workspace + +git clone git@gitlab.example.com:<username>/training-examples.git +cd training-examples +``` + +## Git concepts + +**Untracked files** + +New files that Git has not been told to track previously. + +**Working area** + +Files that have been modified but are not committed. + +**Staging area** + +Modified files that have been marked to go in the next commit. + +## Committing Workflow + +1. Edit '`edit_this_file.rb`' in '`training-examples`' +1. See it listed as a changed file (working area) +1. View the differences +1. Stage the file +1. Commit +1. Push the commit to the remote +1. View the Git log + +```shell +# Edit `edit_this_file.rb` +git status +git diff +git add <file> +git commit -m 'My change' +git push origin master +git log +``` + +## Note + +- `git fetch` vs `git pull` +- Pull is `git fetch` + `git merge` diff --git a/doc/topics/git/git_add.md b/doc/topics/git/git_add.md new file mode 100644 index 00000000000..d136b9151bc --- /dev/null +++ b/doc/topics/git/git_add.md @@ -0,0 +1,40 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +comments: false +--- + +# Git Add + +Adds content to the index or staging area. + +- Adds a list of file: + + ```shell + git add <files> + ``` + +- Adds all files including deleted ones: + + ```shell + git add -A + ``` + +- Add all text files in current dir: + + ```shell + git add *.txt + ``` + +- Add all text file in the project: + + ```shell + git add "*.txt*" + ``` + +- Adds all files in directory: + + ```shell + git add views/layouts/ + ``` diff --git a/doc/topics/git/git_log.md b/doc/topics/git/git_log.md new file mode 100644 index 00000000000..ae4ae69ce76 --- /dev/null +++ b/doc/topics/git/git_log.md @@ -0,0 +1,60 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +comments: false +--- + +# Git Log + +Git log lists commit history. It allows searching and filtering. + +- Initiate log: + + ```shell + git log + ``` + +- Retrieve set number of records: + + ```shell + git log -n 2 + ``` + +- Search commits by author. Allows user name or a regular expression. + + ```shell + git log --author="user_name" + ``` + +- Search by comment message: + + ```shell + git log --grep="<pattern>" + ``` + +- Search by date: + + ```shell + git log --since=1.month.ago --until=3.weeks.ago + ``` + +## Git Log Workflow + +1. Change to workspace directory +1. Clone the multi runner projects +1. Change to project dir +1. Search by author +1. Search by date +1. Combine + +## Commands + +```shell +cd ~/workspace +git clone git@gitlab.com:gitlab-org/gitlab-runner.git +cd gitlab-runner +git log --author="Travis" +git log --since=1.month.ago --until=3.weeks.ago +git log --since=1.month.ago --until=1.day.ago --author="Travis" +``` diff --git a/doc/topics/git/index.md b/doc/topics/git/index.md index a4fc5f6fbf1..f676329e41b 100644 --- a/doc/topics/git/index.md +++ b/doc/topics/git/index.md @@ -39,7 +39,7 @@ The following resources can help you get started with Git: - [Squashing commits](../gitlab_flow.md#squashing-commits-with-rebase) - [Squash-and-merge](../../user/project/merge_requests/squash_and_merge.md) - [Signing commits](../../user/project/repository/gpg_signed_commits/index.md) -- [Git stash](../../university/training/topics/stash.md) +- [Git stash](stash.md) - [Git file blame](../../user/project/repository/git_blame.md) - [Git file history](../../user/project/repository/git_history.md) - [Git tags](tags.md) diff --git a/doc/topics/git/merge_conflicts.md b/doc/topics/git/merge_conflicts.md new file mode 100644 index 00000000000..66771559298 --- /dev/null +++ b/doc/topics/git/merge_conflicts.md @@ -0,0 +1,69 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +comments: false +--- + +# Merge conflicts + +- Happen often +- Learning to fix conflicts is hard +- Practice makes perfect +- Force push after fixing conflicts. Be careful! + +## Merge conflicts sample workflow + +1. Checkout a new branch and edit `conflicts.rb`. Add 'Line4' and 'Line5'. +1. Commit and push. +1. Checkout master and edit `conflicts.rb`. Add 'Line6' and 'Line7' below 'Line3'. +1. Commit and push to master. +1. Create a merge request and watch it fail. +1. Rebase our new branch with master. +1. Fix conflicts on the `conflicts.rb` file. +1. Stage the file and continue rebasing. +1. Force push the changes. +1. Finally continue with the Merge Request. + +```shell +git checkout -b conflicts_branch + +# vi conflicts.rb +# Add 'Line4' and 'Line5' + +git commit -am "add line4 and line5" +git push origin conflicts_branch + +git checkout master + +# vi conflicts.rb +# Add 'Line6' and 'Line7' +git commit -am "add line6 and line7" +git push origin master +``` + +Create a merge request on the GitLab web UI, and a conflict warning displays. + +```shell +git checkout conflicts_branch +git fetch +git rebase master + +# Fix conflicts by editing the files. + +git add conflicts.rb +# No need to commit this file + +git rebase --continue + +# Remember that we have rewritten our commit history so we +# need to force push so that our remote branch is restructured +git push origin conflicts_branch -f +``` + +## Note + +- When to use `git merge` and when to use `git rebase` +- Rebase when updating your branch with master +- Merge when bringing changes from feature to master +- Reference: <https://www.atlassian.com/git/tutorials/merging-vs-rebasing> diff --git a/doc/topics/git/merge_requests.md b/doc/topics/git/merge_requests.md new file mode 100644 index 00000000000..a4a3108ebd1 --- /dev/null +++ b/doc/topics/git/merge_requests.md @@ -0,0 +1,40 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +comments: false +--- + +# Code review and collaboration with Merge Requests + +- When you want feedback create a merge request +- Target is the default branch (usually master) +- Assign or mention the person you would like to review +- Add `[Draft]` to the title if it's a work in progress +- When accepting, always delete the branch +- Anyone can comment, not just the assignee +- Push corrections to the same branch + +## Merge requests + +**Create your first merge request** + +1. Use the blue button in the activity feed +1. View the diff (changes) and leave a comment +1. Push a new commit to the same branch +1. Review the changes again and notice the update + +## Feedback and Collaboration + +- Merge requests are a time for feedback and collaboration +- Giving feedback is hard +- Be as kind as possible +- Receiving feedback is hard +- Be as receptive as possible +- Feedback is about the best code, not the person. You are not your code + +Review the Thoughtbot code-review guide for suggestions to follow when reviewing merge requests: +[https://github.com/thoughtbot/guides/tree/master/code-review](https://github.com/thoughtbot/guides/tree/master/code-review) + +See GitLab merge requests for examples: +[https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests) diff --git a/doc/topics/git/rollback_commits.md b/doc/topics/git/rollback_commits.md new file mode 100644 index 00000000000..34c2d9687bb --- /dev/null +++ b/doc/topics/git/rollback_commits.md @@ -0,0 +1,81 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +comments: false +--- + +# Rollback Commits + +## Undo Commits + +- Undo last commit putting everything back into the staging area: + + ```shell + git reset --soft HEAD^ + ``` + +- Add files and change message with: + + ```shell + git commit --amend -m "New Message" + ``` + +- Undo last and remove changes: + + ```shell + git reset --hard HEAD^ + ``` + +- Same as last one but for two commits back: + + ```shell + git reset --hard HEAD^^ + ``` + +**Don't reset after pushing** + +## Reset Workflow + +1. Edit file again 'edit_this_file.rb' +1. Check status +1. Add and commit with wrong message +1. Check log +1. Amend commit +1. Check log +1. Soft reset +1. Check log +1. Pull for updates +1. Push changes + +## Commands + +```shell +# Change file edit_this_file.rb +git status +git commit -am "kjkfjkg" +git log +git commit --amend -m "New comment added" +git log +git reset --soft HEAD^ +git log +git pull origin master +git push origin master +``` + +## Note + +- `git revert` vs `git reset` +- Reset removes the commit while revert removes the changes but leaves the commit +- Revert is safer considering we can revert a revert + +```shell +# Changed file +git commit -am "bug introduced" +git revert HEAD +# New commit created reverting changes +# Now we want to re apply the reverted commit +git log # take hash from the revert commit +git revert <rev commit hash> +# reverted commit is back (new commit created again) +``` diff --git a/doc/topics/git/stash.md b/doc/topics/git/stash.md new file mode 100644 index 00000000000..051103e5f4b --- /dev/null +++ b/doc/topics/git/stash.md @@ -0,0 +1,82 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +comments: false +--- + +# Git Stash + +We use `git stash` to store our changes when they are not ready to be committed +and we need to change to a different branch. + +- Stash: + + ```shell + git stash save + # or + git stash + # or with a message + git stash save "this is a message to display on the list" + ``` + +- Apply stash to keep working on it: + + ```shell + git stash apply + # or apply a specific one from out stack + git stash apply stash@{3} + ``` + +- Every time we save a stash it gets stacked so by using `list` we can see all our + stashes. + + ```shell + git stash list + # or for more information (log methods) + git stash list --stat + ``` + +- To clean our stack we need to manually remove them: + + ```shell + # drop top stash + git stash drop + # or + git stash drop <name> + # to clear all history we can use + git stash clear + ``` + +- Apply and drop on one command: + + ```shell + git stash pop + ``` + +- If we meet conflicts we need to either reset or commit our changes. +- Conflicts through `pop` doesn't drop a stash afterwards. + +## Git Stash sample workflow + +1. Modify a file +1. Stage file +1. Stash it +1. View our stash list +1. Confirm no pending changes through status +1. Apply with pop +1. View list to confirm changes + +```shell +# Modify edit_this_file.rb file +git add . + +git stash save "Saving changes from edit this file" + +git stash list +git status + +git stash pop +git stash list +git status +``` diff --git a/doc/topics/git/subtree.md b/doc/topics/git/subtree.md new file mode 100644 index 00000000000..54461915a05 --- /dev/null +++ b/doc/topics/git/subtree.md @@ -0,0 +1,52 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +comments: false +--- + +# Subtree + +- Used when there are nested repositories. +- Not recommended when the amount of dependencies is too large. +- For these cases we need a dependency control system. +- Command are painfully long so aliases are necessary. + +## Subtree Aliases + +- Add: `git subtree add --prefix <target-folder> <url> <branch> --squash` +- Pull: `git subtree pull --prefix <target-folder> <url> <branch> --squash` +- Push: `git subtree add --prefix <target-folder> <url> <branch>` +- Ex: `git config alias.sbp 'subtree pull --prefix st / + git@gitlab.com:balameb/subtree-nested-example.git master --squash'` + +```shell + # Add an alias + # Add + git config alias.sba 'subtree add --prefix st / + git@gitlab.com:balameb/subtree-nested-example.git master --squash' + # Pull + git config alias.sbpl 'subtree pull --prefix st / + git@gitlab.com:balameb/subtree-nested-example.git master --squash' + # Push + git config alias.sbph 'subtree push --prefix st / + git@gitlab.com:balameb/subtree-nested-example.git master' + + # Adding this subtree adds a st dir with a readme + git sba + vi st/README.md + # Edit file + git status shows differences + +``` + +```shell + # Adding, or committing won't change the sub repo at remote + # even if we push + git add -A + git commit -m "Adding to subtree readme" + + # Push to subtree repo + git sbph + # now we can check our remote sub repo +``` diff --git a/doc/topics/git/unstage.md b/doc/topics/git/unstage.md new file mode 100644 index 00000000000..30d26854135 --- /dev/null +++ b/doc/topics/git/unstage.md @@ -0,0 +1,33 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +comments: false +--- + +# Unstage + +- To remove files from stage use reset HEAD where HEAD is the last commit of the current branch. This unstages the file but maintain the modifications. + + ```shell + git reset HEAD <file> + ``` + +- To revert the file back to the state it was in before the changes we can use: + + ```shell + git checkout -- <file> + ``` + +- To remove a file from disk and repository, use `git rm`. To remove a directory, use the `-r` flag: + + ```shell + git rm '*.txt' + git rm -r <dirname> + ``` + +- If we want to remove a file from the repository but keep it on disk, say we forgot to add it to our `.gitignore` file then use `--cache`: + + ```shell + git rm <filename> --cache + ``` diff --git a/doc/university/training/topics/bisect.md b/doc/university/training/topics/bisect.md index 8af77031c93..9c06f0b407d 100644 --- a/doc/university/training/topics/bisect.md +++ b/doc/university/training/topics/bisect.md @@ -1,76 +1,8 @@ --- -stage: none -group: unassigned -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -comments: false +redirect_to: '../../../topics/git/bisect.md' --- -# Bisect +This document was moved to [another location](../../../topics/git/bisect.md). -- Find a commit that introduced a bug -- Works through a process of elimination -- Specify a known good and bad revision to begin - -## Bisect sample workflow - -1. Start the bisect process -1. Enter the bad revision (usually latest commit) -1. Enter a known good revision (commit/branch) -1. Run code to see if bug still exists -1. Tell bisect the result -1. Repeat the previous 2 items until you find the offending commit - -## Setup - -```shell - mkdir bisect-ex - cd bisect-ex - touch index.html - git add -A - git commit -m "starting out" - vi index.html - # Add all good - git add -A - git commit -m "second commit" - vi index.html - # Add all good 2 - git add -A - git commit -m "third commit" - vi index.html -``` - -```shell - # Add all good 3 - git add -A - git commit -m "fourth commit" - vi index.html - # This looks bad - git add -A - git commit -m "fifth commit" - vi index.html - # Really bad - git add -A - git commit -m "sixth commit" - vi index.html - # again just bad - git add -A - git commit -m "seventh commit" -``` - -## Commands - -```shell - git bisect start - # Test your code - git bisect bad - git bisect next - # Say yes to the warning - # Test - git bisect good - # Test - git bisect bad - # Test - git bisect good - # done - git bisect reset -``` +<!-- This redirect file can be deleted after <2021-08-13>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/university/training/topics/feature_branching.md b/doc/university/training/topics/feature_branching.md index f6233bddb18..495462cdd00 100644 --- a/doc/university/training/topics/feature_branching.md +++ b/doc/university/training/topics/feature_branching.md @@ -1,31 +1,8 @@ --- -stage: none -group: unassigned -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -comments: false +redirect_to: '../../../topics/git/feature_branching.md' --- -# Feature branching +This document was moved to [another location](../../../topics/git/feature_branching.md). -- Efficient parallel workflow for teams -- Develop each feature in a branch -- Keeps changes isolated -- Consider a 1-to-1 link to issues -- Push branches to the server frequently - - Hint: This is a cheap backup for your work-in-progress code - -## Feature branching sample workflow - -1. Create a new feature branch called 'squash_some_bugs' -1. Edit '`bugs.rb`' and remove all the bugs. -1. Commit -1. Push - -```shell -git checkout -b squash_some_bugs -# Edit `bugs.rb` -git status -git add bugs.rb -git commit -m 'Fix some buggy code' -git push origin squash_some_bugs -``` +<!-- This redirect file can be deleted after <2021-08-13>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/university/training/topics/getting_started.md b/doc/university/training/topics/getting_started.md index 2c3d5fe15de..3dc3902c2e3 100644 --- a/doc/university/training/topics/getting_started.md +++ b/doc/university/training/topics/getting_started.md @@ -1,86 +1,8 @@ --- -stage: none -group: unassigned -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -comments: false +redirect_to: '../../../topics/git/getting_started.md' --- -# Getting Started +This document was moved to [another location](../../../topics/git/getting_started.md). -## Instantiating Repositories - -- Create a new repository by instantiating it through: - - ```shell - git init - ``` - -- Copy an existing project by cloning the repository through: - - ```shell - git clone <url> - ``` - -## Central Repositories - -- To instantiate a central repository a `--bare` flag is required. -- Bare repositories don't allow file editing or committing changes. -- Create a bare repository with: - - ```shell - git init --bare project-name.git - ``` - -## Instantiate workflow with clone - -1. Create a project in your user namespace. - - Choose to import from **Any Repository by URL** and use <https://gitlab.com/gitlab-org/training-examples.git>. -1. Create a '`Workspace`' directory in your home directory. -1. Clone the '`training-examples`' project. - -```shell -mkdir ~/workspace -cd ~/workspace - -git clone git@gitlab.example.com:<username>/training-examples.git -cd training-examples -``` - -## Git concepts - -**Untracked files** - -New files that Git has not been told to track previously. - -**Working area** - -Files that have been modified but are not committed. - -**Staging area** - -Modified files that have been marked to go in the next commit. - -## Committing Workflow - -1. Edit '`edit_this_file.rb`' in '`training-examples`' -1. See it listed as a changed file (working area) -1. View the differences -1. Stage the file -1. Commit -1. Push the commit to the remote -1. View the Git log - -```shell -# Edit `edit_this_file.rb` -git status -git diff -git add <file> -git commit -m 'My change' -git push origin master -git log -``` - -## Note - -- `git fetch` vs `git pull` -- Pull is `git fetch` + `git merge` +<!-- This redirect file can be deleted after <2021-08-13>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/university/training/topics/git_add.md b/doc/university/training/topics/git_add.md index d136b9151bc..aa5e756995f 100644 --- a/doc/university/training/topics/git_add.md +++ b/doc/university/training/topics/git_add.md @@ -1,40 +1,8 @@ --- -stage: none -group: unassigned -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -comments: false +redirect_to: '../../../topics/git/git_add.md' --- -# Git Add +This document was moved to [another location](../../../topics/git/git_add.md). -Adds content to the index or staging area. - -- Adds a list of file: - - ```shell - git add <files> - ``` - -- Adds all files including deleted ones: - - ```shell - git add -A - ``` - -- Add all text files in current dir: - - ```shell - git add *.txt - ``` - -- Add all text file in the project: - - ```shell - git add "*.txt*" - ``` - -- Adds all files in directory: - - ```shell - git add views/layouts/ - ``` +<!-- This redirect file can be deleted after <2021-08-13>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/university/training/topics/git_log.md b/doc/university/training/topics/git_log.md index ae4ae69ce76..1af8abb0782 100644 --- a/doc/university/training/topics/git_log.md +++ b/doc/university/training/topics/git_log.md @@ -1,60 +1,8 @@ --- -stage: none -group: unassigned -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -comments: false +redirect_to: '../../../topics/git/git_log.md' --- -# Git Log +This document was moved to [another location](../../../topics/git/git_log.md). -Git log lists commit history. It allows searching and filtering. - -- Initiate log: - - ```shell - git log - ``` - -- Retrieve set number of records: - - ```shell - git log -n 2 - ``` - -- Search commits by author. Allows user name or a regular expression. - - ```shell - git log --author="user_name" - ``` - -- Search by comment message: - - ```shell - git log --grep="<pattern>" - ``` - -- Search by date: - - ```shell - git log --since=1.month.ago --until=3.weeks.ago - ``` - -## Git Log Workflow - -1. Change to workspace directory -1. Clone the multi runner projects -1. Change to project dir -1. Search by author -1. Search by date -1. Combine - -## Commands - -```shell -cd ~/workspace -git clone git@gitlab.com:gitlab-org/gitlab-runner.git -cd gitlab-runner -git log --author="Travis" -git log --since=1.month.ago --until=3.weeks.ago -git log --since=1.month.ago --until=1.day.ago --author="Travis" -``` +<!-- This redirect file can be deleted after <2021-08-13>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/university/training/topics/merge_conflicts.md b/doc/university/training/topics/merge_conflicts.md index 66771559298..d76d297803f 100644 --- a/doc/university/training/topics/merge_conflicts.md +++ b/doc/university/training/topics/merge_conflicts.md @@ -1,69 +1,8 @@ --- -stage: none -group: unassigned -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -comments: false +redirect_to: '../../../topics/git/merge_conflicts.md' --- -# Merge conflicts +This document was moved to [another location](../../../topics/git/merge_conflicts.md). -- Happen often -- Learning to fix conflicts is hard -- Practice makes perfect -- Force push after fixing conflicts. Be careful! - -## Merge conflicts sample workflow - -1. Checkout a new branch and edit `conflicts.rb`. Add 'Line4' and 'Line5'. -1. Commit and push. -1. Checkout master and edit `conflicts.rb`. Add 'Line6' and 'Line7' below 'Line3'. -1. Commit and push to master. -1. Create a merge request and watch it fail. -1. Rebase our new branch with master. -1. Fix conflicts on the `conflicts.rb` file. -1. Stage the file and continue rebasing. -1. Force push the changes. -1. Finally continue with the Merge Request. - -```shell -git checkout -b conflicts_branch - -# vi conflicts.rb -# Add 'Line4' and 'Line5' - -git commit -am "add line4 and line5" -git push origin conflicts_branch - -git checkout master - -# vi conflicts.rb -# Add 'Line6' and 'Line7' -git commit -am "add line6 and line7" -git push origin master -``` - -Create a merge request on the GitLab web UI, and a conflict warning displays. - -```shell -git checkout conflicts_branch -git fetch -git rebase master - -# Fix conflicts by editing the files. - -git add conflicts.rb -# No need to commit this file - -git rebase --continue - -# Remember that we have rewritten our commit history so we -# need to force push so that our remote branch is restructured -git push origin conflicts_branch -f -``` - -## Note - -- When to use `git merge` and when to use `git rebase` -- Rebase when updating your branch with master -- Merge when bringing changes from feature to master -- Reference: <https://www.atlassian.com/git/tutorials/merging-vs-rebasing> +<!-- This redirect file can be deleted after <2021-08-13>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/university/training/topics/merge_requests.md b/doc/university/training/topics/merge_requests.md index a4a3108ebd1..c064bd78036 100644 --- a/doc/university/training/topics/merge_requests.md +++ b/doc/university/training/topics/merge_requests.md @@ -1,40 +1,8 @@ --- -stage: none -group: unassigned -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -comments: false +redirect_to: '../../../topics/git/merge_requests.md' --- -# Code review and collaboration with Merge Requests +This document was moved to [another location](../../../topics/git/merge_requests.md). -- When you want feedback create a merge request -- Target is the default branch (usually master) -- Assign or mention the person you would like to review -- Add `[Draft]` to the title if it's a work in progress -- When accepting, always delete the branch -- Anyone can comment, not just the assignee -- Push corrections to the same branch - -## Merge requests - -**Create your first merge request** - -1. Use the blue button in the activity feed -1. View the diff (changes) and leave a comment -1. Push a new commit to the same branch -1. Review the changes again and notice the update - -## Feedback and Collaboration - -- Merge requests are a time for feedback and collaboration -- Giving feedback is hard -- Be as kind as possible -- Receiving feedback is hard -- Be as receptive as possible -- Feedback is about the best code, not the person. You are not your code - -Review the Thoughtbot code-review guide for suggestions to follow when reviewing merge requests: -[https://github.com/thoughtbot/guides/tree/master/code-review](https://github.com/thoughtbot/guides/tree/master/code-review) - -See GitLab merge requests for examples: -[https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests) +<!-- This redirect file can be deleted after <2021-08-13>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/university/training/topics/rollback_commits.md b/doc/university/training/topics/rollback_commits.md index 34c2d9687bb..b87aa12b834 100644 --- a/doc/university/training/topics/rollback_commits.md +++ b/doc/university/training/topics/rollback_commits.md @@ -1,81 +1,8 @@ --- -stage: none -group: unassigned -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -comments: false +redirect_to: '../../../topics/git/rollback_commits.md' --- -# Rollback Commits +This document was moved to [another location](../../../topics/git/rollback_commits.md). -## Undo Commits - -- Undo last commit putting everything back into the staging area: - - ```shell - git reset --soft HEAD^ - ``` - -- Add files and change message with: - - ```shell - git commit --amend -m "New Message" - ``` - -- Undo last and remove changes: - - ```shell - git reset --hard HEAD^ - ``` - -- Same as last one but for two commits back: - - ```shell - git reset --hard HEAD^^ - ``` - -**Don't reset after pushing** - -## Reset Workflow - -1. Edit file again 'edit_this_file.rb' -1. Check status -1. Add and commit with wrong message -1. Check log -1. Amend commit -1. Check log -1. Soft reset -1. Check log -1. Pull for updates -1. Push changes - -## Commands - -```shell -# Change file edit_this_file.rb -git status -git commit -am "kjkfjkg" -git log -git commit --amend -m "New comment added" -git log -git reset --soft HEAD^ -git log -git pull origin master -git push origin master -``` - -## Note - -- `git revert` vs `git reset` -- Reset removes the commit while revert removes the changes but leaves the commit -- Revert is safer considering we can revert a revert - -```shell -# Changed file -git commit -am "bug introduced" -git revert HEAD -# New commit created reverting changes -# Now we want to re apply the reverted commit -git log # take hash from the revert commit -git revert <rev commit hash> -# reverted commit is back (new commit created again) -``` +<!-- This redirect file can be deleted after <2021-08-13>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/university/training/topics/stash.md b/doc/university/training/topics/stash.md index 051103e5f4b..ea9ba6a7bcc 100644 --- a/doc/university/training/topics/stash.md +++ b/doc/university/training/topics/stash.md @@ -1,82 +1,8 @@ --- -stage: none -group: unassigned -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -comments: false +redirect_to: '../../../topics/git/stash.md' --- -# Git Stash +This document was moved to [another location](../../../topics/git/stash.md). -We use `git stash` to store our changes when they are not ready to be committed -and we need to change to a different branch. - -- Stash: - - ```shell - git stash save - # or - git stash - # or with a message - git stash save "this is a message to display on the list" - ``` - -- Apply stash to keep working on it: - - ```shell - git stash apply - # or apply a specific one from out stack - git stash apply stash@{3} - ``` - -- Every time we save a stash it gets stacked so by using `list` we can see all our - stashes. - - ```shell - git stash list - # or for more information (log methods) - git stash list --stat - ``` - -- To clean our stack we need to manually remove them: - - ```shell - # drop top stash - git stash drop - # or - git stash drop <name> - # to clear all history we can use - git stash clear - ``` - -- Apply and drop on one command: - - ```shell - git stash pop - ``` - -- If we meet conflicts we need to either reset or commit our changes. -- Conflicts through `pop` doesn't drop a stash afterwards. - -## Git Stash sample workflow - -1. Modify a file -1. Stage file -1. Stash it -1. View our stash list -1. Confirm no pending changes through status -1. Apply with pop -1. View list to confirm changes - -```shell -# Modify edit_this_file.rb file -git add . - -git stash save "Saving changes from edit this file" - -git stash list -git status - -git stash pop -git stash list -git status -``` +<!-- This redirect file can be deleted after <2021-08-13>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/university/training/topics/subtree.md b/doc/university/training/topics/subtree.md index 54461915a05..5090ff8ca36 100644 --- a/doc/university/training/topics/subtree.md +++ b/doc/university/training/topics/subtree.md @@ -1,52 +1,8 @@ --- -stage: none -group: unassigned -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -comments: false +redirect_to: '../../../topics/git/subtree.md' --- -# Subtree +This document was moved to [another location](../../../topics/git/subtree.md). -- Used when there are nested repositories. -- Not recommended when the amount of dependencies is too large. -- For these cases we need a dependency control system. -- Command are painfully long so aliases are necessary. - -## Subtree Aliases - -- Add: `git subtree add --prefix <target-folder> <url> <branch> --squash` -- Pull: `git subtree pull --prefix <target-folder> <url> <branch> --squash` -- Push: `git subtree add --prefix <target-folder> <url> <branch>` -- Ex: `git config alias.sbp 'subtree pull --prefix st / - git@gitlab.com:balameb/subtree-nested-example.git master --squash'` - -```shell - # Add an alias - # Add - git config alias.sba 'subtree add --prefix st / - git@gitlab.com:balameb/subtree-nested-example.git master --squash' - # Pull - git config alias.sbpl 'subtree pull --prefix st / - git@gitlab.com:balameb/subtree-nested-example.git master --squash' - # Push - git config alias.sbph 'subtree push --prefix st / - git@gitlab.com:balameb/subtree-nested-example.git master' - - # Adding this subtree adds a st dir with a readme - git sba - vi st/README.md - # Edit file - git status shows differences - -``` - -```shell - # Adding, or committing won't change the sub repo at remote - # even if we push - git add -A - git commit -m "Adding to subtree readme" - - # Push to subtree repo - git sbph - # now we can check our remote sub repo -``` +<!-- This redirect file can be deleted after <2021-08-13>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/university/training/topics/unstage.md b/doc/university/training/topics/unstage.md index 30d26854135..13c21f5cbb2 100644 --- a/doc/university/training/topics/unstage.md +++ b/doc/university/training/topics/unstage.md @@ -1,33 +1,8 @@ --- -stage: none -group: unassigned -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -comments: false +redirect_to: '../../../topics/git/unstage.md' --- -# Unstage +This document was moved to [another location](../../../topics/git/unstage.md). -- To remove files from stage use reset HEAD where HEAD is the last commit of the current branch. This unstages the file but maintain the modifications. - - ```shell - git reset HEAD <file> - ``` - -- To revert the file back to the state it was in before the changes we can use: - - ```shell - git checkout -- <file> - ``` - -- To remove a file from disk and repository, use `git rm`. To remove a directory, use the `-r` flag: - - ```shell - git rm '*.txt' - git rm -r <dirname> - ``` - -- If we want to remove a file from the repository but keep it on disk, say we forgot to add it to our `.gitignore` file then use `--cache`: - - ```shell - git rm <filename> --cache - ``` +<!-- This redirect file can be deleted after <2021-08-13>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/user/group/value_stream_analytics/img/vsa_stage_table_v13_12.png b/doc/user/group/value_stream_analytics/img/vsa_stage_table_v13_12.png Binary files differindex 4ad7d2e353e..24d485306be 100644 --- a/doc/user/group/value_stream_analytics/img/vsa_stage_table_v13_12.png +++ b/doc/user/group/value_stream_analytics/img/vsa_stage_table_v13_12.png diff --git a/doc/user/group/value_stream_analytics/index.md b/doc/user/group/value_stream_analytics/index.md index 023eddfddd5..a0ddbf22d2a 100644 --- a/doc/user/group/value_stream_analytics/index.md +++ b/doc/user/group/value_stream_analytics/index.md @@ -226,6 +226,8 @@ Hovering over a stage item displays a popover with the following information: - Start event description for the given stage - End event description +- Median time items took to complete the stage +- Number of items that completed the stage ### Stream overview @@ -256,6 +258,9 @@ The stage table shows a list of related workflow items for the selected stage. T - Merge requests - Pipelines +A little badge next to the workflow items table header shows the number of workflow items that +completed the selected stage. + The stage table also includes the **Time** column, which shows how long it takes each item to pass through the selected value stream stage. diff --git a/doc/user/project/repository/branches/index.md b/doc/user/project/repository/branches/index.md index 5239f2bbf32..1a21616e3a5 100644 --- a/doc/user/project/repository/branches/index.md +++ b/doc/user/project/repository/branches/index.md @@ -40,7 +40,7 @@ You can also manage branches using the See also: - [Branches API](../../../../api/branches.md), for information on operating on repository branches using the GitLab API. -- [GitLab Flow](../../../../university/training/gitlab_flow.md) documentation. +- [GitLab Flow](../../../../topics/gitlab_flow.md) documentation. - [Getting started with Git](../../../../topics/git/index.md) and GitLab. ## Compare diff --git a/package.json b/package.json index b80d4013268..57d229cd8e9 100644 --- a/package.json +++ b/package.json @@ -51,9 +51,9 @@ "@babel/preset-env": "^7.10.1", "@gitlab/at.js": "1.5.7", "@gitlab/favicon-overlay": "2.0.0", - "@gitlab/svgs": "1.195.0", + "@gitlab/svgs": "1.196.0", "@gitlab/tributejs": "1.0.0", - "@gitlab/ui": "29.23.0", + "@gitlab/ui": "29.25.0", "@gitlab/visual-review-tools": "1.6.1", "@rails/actioncable": "^6.0.3-4", "@rails/ujs": "^6.0.3-4", diff --git a/spec/features/issues/user_interacts_with_awards_spec.rb b/spec/features/issues/user_interacts_with_awards_spec.rb index e862f7030c0..bbb7e8a028d 100644 --- a/spec/features/issues/user_interacts_with_awards_spec.rb +++ b/spec/features/issues/user_interacts_with_awards_spec.rb @@ -5,10 +5,6 @@ require 'spec_helper' RSpec.describe 'User interacts with awards' do let(:user) { create(:user) } - before do - stub_feature_flags(improved_emoji_picker: false) - end - describe 'User interacts with awards in an issue', :js do let(:issue) { create(:issue, project: project)} let(:project) { create(:project) } @@ -55,29 +51,24 @@ RSpec.describe 'User interacts with awards' do it 'toggles a custom award emoji' do page.within('.awards') do - page.find('.js-add-award').click + page.find('.add-reaction-button').click end - page.find('.emoji-menu.is-visible') - - expect(page).to have_selector('.js-emoji-menu-search') - expect(page.evaluate_script("document.activeElement.classList.contains('js-emoji-menu-search')")).to eq(true) - - page.within('.emoji-menu-content') do - emoji_button = page.first('.js-emoji-btn') + page.within('.emoji-picker') do + emoji_button = page.first('gl-emoji[data-name="8ball"]') emoji_button.hover emoji_button.click end page.within('.awards') do - expect(page).to have_selector('.js-emoji-btn') - expect(page.find('.js-emoji-btn.active .js-counter')).to have_content('1') - expect(page).to have_css(".js-emoji-btn.active[title='You']") + expect(page).to have_selector('[data-testid="award-button"]') + expect(page.find('[data-testid="award-button"].is-active .js-counter')).to have_content('1') + expect(page).to have_css('[data-testid="award-button"].is-active[title="You"]') expect do - page.find('.js-emoji-btn.active').click + page.find('[data-testid="award-button"].is-active').click wait_for_requests - end.to change { page.all('.award-control.js-emoji-btn').size }.from(3).to(2) + end.to change { page.all('[data-testid="award-button"]').size }.from(3).to(2) end end @@ -212,31 +203,25 @@ RSpec.describe 'User interacts with awards' do end it 'adds award to issue' do - first('.js-emoji-btn').click + first('[data-testid="award-button"]').click - expect(page).to have_selector('.js-emoji-btn.active') - expect(first('.js-emoji-btn')).to have_content '1' + expect(page).to have_selector('[data-testid="award-button"].is-active') + expect(first('[data-testid="award-button"]')).to have_content '1' visit project_issue_path(project, issue) - expect(first('.js-emoji-btn')).to have_content '1' + expect(first('[data-testid="award-button"]')).to have_content '1' end it 'removes award from issue' do - first('.js-emoji-btn').click - find('.js-emoji-btn.active').click + first('[data-testid="award-button"]').click + find('[data-testid="award-button"].is-active').click - expect(first('.js-emoji-btn')).to have_content '0' + expect(first('[data-testid="award-button"]')).to have_content '0' visit project_issue_path(project, issue) - expect(first('.js-emoji-btn')).to have_content '0' - end - - it 'only has one menu on the page' do - first('.js-add-award').click - - expect(page).to have_selector('.emoji-menu', count: 1) + expect(first('[data-testid="award-button"]')).to have_content '0' end end @@ -311,7 +296,7 @@ RSpec.describe 'User interacts with awards' do end context 'execute /award quick action' do - it 'toggles the emoji award on noteable', :js do + xit 'toggles the emoji award on noteable', :js do execute_quick_action('/award :100:') expect(find(noteable_award_counter)).to have_text("1") @@ -330,7 +315,7 @@ RSpec.describe 'User interacts with awards' do end it 'has disabled emoji button' do - expect(first('.award-control')[:class]).to have_text('disabled') + expect(first('[data-testid="award-button"]')[:class]).to have_text('disabled') end end @@ -356,7 +341,7 @@ RSpec.describe 'User interacts with awards' do end def noteable_award_counter - ".awards .active" + ".awards .is-active" end def toggle_smiley_emoji(status) diff --git a/spec/frontend/behaviors/date_picker_spec.js b/spec/frontend/behaviors/date_picker_spec.js new file mode 100644 index 00000000000..9f7701a0366 --- /dev/null +++ b/spec/frontend/behaviors/date_picker_spec.js @@ -0,0 +1,30 @@ +import * as Pikaday from 'pikaday'; +import initDatePickers from '~/behaviors/date_picker'; +import * as utils from '~/lib/utils/datetime_utility'; + +jest.mock('pikaday'); +jest.mock('~/lib/utils/datetime_utility'); + +describe('date_picker behavior', () => { + let pikadayMock; + let parseMock; + + beforeEach(() => { + pikadayMock = jest.spyOn(Pikaday, 'default'); + parseMock = jest.spyOn(utils, 'parsePikadayDate'); + setFixtures(` + <div> + <input class="datepicker" value="2020-10-01" /> + </div> + <div> + <input class="datepicker" value="" /> + </div>`); + }); + + it('Instantiates Pickaday for every instance of a .datepicker class', () => { + initDatePickers(); + + expect(pikadayMock.mock.calls.length).toEqual(2); + expect(parseMock.mock.calls).toEqual([['2020-10-01'], ['']]); + }); +}); diff --git a/spec/frontend/logs/stores/actions_spec.js b/spec/frontend/logs/stores/actions_spec.js index 92c2f82af27..d5118bbde8c 100644 --- a/spec/frontend/logs/stores/actions_spec.js +++ b/spec/frontend/logs/stores/actions_spec.js @@ -191,7 +191,7 @@ describe('Logs Store actions', () => { }); it('should commit RECEIVE_ENVIRONMENTS_DATA_SUCCESS mutation on correct data', () => { - mock.onGet(mockEnvironmentsEndpoint).replyOnce(200, { environments: mockEnvironments }); + mock.onGet(mockEnvironmentsEndpoint).replyOnce(200, mockEnvironments); return testAction( fetchEnvironments, mockEnvironmentsEndpoint, diff --git a/spec/graphql/resolvers/group_packages_resolver_spec.rb b/spec/graphql/resolvers/group_packages_resolver_spec.rb index d2695a3c43a..48f4c8ec4ca 100644 --- a/spec/graphql/resolvers/group_packages_resolver_spec.rb +++ b/spec/graphql/resolvers/group_packages_resolver_spec.rb @@ -16,38 +16,6 @@ RSpec.describe Resolvers::GroupPackagesResolver do describe '#resolve' do subject { resolve(described_class, ctx: { current_user: user }, obj: group, args: args).to_a } - context 'without sort' do - let_it_be(:package) { create(:package, project: project) } - - it { is_expected.to contain_exactly(package) } - end - - context 'with a sort argument' do - let_it_be(:project2) { create(:project, :public, group: group) } - - let_it_be(:sort_repository) do - create(:conan_package, name: 'bar', project: project, created_at: 1.day.ago, version: "1.0.0") - end - - let_it_be(:sort_repository2) do - create(:maven_package, name: 'foo', project: project2, created_at: 1.hour.ago, version: "2.0.0") - end - - [:created_desc, :name_desc, :version_desc, :type_asc, :project_path_desc].each do |order| - context "#{order}" do - let(:args) { { sort: order } } - - it { is_expected.to eq([sort_repository2, sort_repository]) } - end - end - - [:created_asc, :name_asc, :version_asc, :type_desc, :project_path_asc].each do |order| - context "#{order}" do - let(:args) { { sort: order } } - - it { is_expected.to eq([sort_repository, sort_repository2]) } - end - end - end + it_behaves_like 'group and projects packages resolver' end end diff --git a/spec/graphql/resolvers/packages_base_resolver_spec.rb b/spec/graphql/resolvers/packages_base_resolver_spec.rb new file mode 100644 index 00000000000..8f9865c3785 --- /dev/null +++ b/spec/graphql/resolvers/packages_base_resolver_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::PackagesBaseResolver do + include GraphqlHelpers + + describe '#resolve' do + subject { resolve(described_class) } + + it 'throws an error' do + expect { subject }.to raise_error(NotImplementedError) + end + end +end diff --git a/spec/graphql/resolvers/project_packages_resolver_spec.rb b/spec/graphql/resolvers/project_packages_resolver_spec.rb index 695db64743d..66a94bd42dd 100644 --- a/spec/graphql/resolvers/project_packages_resolver_spec.rb +++ b/spec/graphql/resolvers/project_packages_resolver_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Resolvers::ProjectPackagesResolver do include GraphqlHelpers let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, :public) } + let_it_be_with_reload(:project) { create(:project, :public) } let(:args) do { sort: :created_desc } @@ -15,36 +15,6 @@ RSpec.describe Resolvers::ProjectPackagesResolver do describe '#resolve' do subject { resolve(described_class, ctx: { current_user: user }, obj: project, args: args).to_a } - context 'without sort' do - let_it_be(:package) { create(:package, project: project) } - - it { is_expected.to contain_exactly(package) } - end - - context 'with a sort argument' do - let_it_be(:sort_repository) do - create(:conan_package, name: 'bar', project: project, created_at: 1.day.ago, version: "1.0.0") - end - - let_it_be(:sort_repository2) do - create(:maven_package, name: 'foo', project: project, created_at: 1.hour.ago, version: "2.0.0") - end - - [:created_desc, :name_desc, :version_desc, :type_asc].each do |order| - context "#{order}" do - let(:args) { { sort: order } } - - it { is_expected.to eq([sort_repository2, sort_repository]) } - end - end - - [:created_asc, :name_asc, :version_asc, :type_desc].each do |order| - context "#{order}" do - let(:args) { { sort: order } } - - it { is_expected.to eq([sort_repository, sort_repository2]) } - end - end - end + it_behaves_like 'group and projects packages resolver' end end diff --git a/spec/helpers/environments_helper_spec.rb b/spec/helpers/environments_helper_spec.rb index 8adb329e730..89cb0f72277 100644 --- a/spec/helpers/environments_helper_spec.rb +++ b/spec/helpers/environments_helper_spec.rb @@ -191,7 +191,7 @@ RSpec.describe EnvironmentsHelper do it 'returns logs data' do expected_data = { "environment_name": environment.name, - "environments_path": project_environments_path(project, format: :json), + "environments_path": api_v4_projects_environments_path(id: project.id), "environment_id": environment.id, "cluster_applications_documentation_path" => help_page_path('user/clusters/applications.md', anchor: 'elastic-stack'), "clusters_path": project_clusters_path(project, format: :json) diff --git a/spec/models/ci/pipeline_schedule_spec.rb b/spec/models/ci/pipeline_schedule_spec.rb index 028208a56f1..d5560edbbfd 100644 --- a/spec/models/ci/pipeline_schedule_spec.rb +++ b/spec/models/ci/pipeline_schedule_spec.rb @@ -126,16 +126,6 @@ RSpec.describe Ci::PipelineSchedule do end end - context 'when pipeline schedule runs every minute' do - let(:pipeline_schedule) { create(:ci_pipeline_schedule, :every_minute) } - - it "updates next_run_at to the sidekiq worker's execution time" do - travel_to(Time.zone.parse("2019-06-01 12:18:00+0000")) do - expect(pipeline_schedule.next_run_at).to eq(cron_worker_next_run_at) - end - end - end - context 'when there are two different pipeline schedules in different time zones' do let(:pipeline_schedule_1) { create(:ci_pipeline_schedule, :weekly, cron_timezone: 'Eastern Time (US & Canada)') } let(:pipeline_schedule_2) { create(:ci_pipeline_schedule, :weekly, cron_timezone: 'UTC') } @@ -144,24 +134,6 @@ RSpec.describe Ci::PipelineSchedule do expect(pipeline_schedule_1.next_run_at).not_to eq(pipeline_schedule_2.next_run_at) end end - - context 'when there are two different pipeline schedules in the same time zones' do - let(:pipeline_schedule_1) { create(:ci_pipeline_schedule, :weekly, cron_timezone: 'UTC') } - let(:pipeline_schedule_2) { create(:ci_pipeline_schedule, :weekly, cron_timezone: 'UTC') } - - it 'sets the sames next_run_at' do - expect(pipeline_schedule_1.next_run_at).to eq(pipeline_schedule_2.next_run_at) - end - end - - context 'when updates cron of exsisted pipeline schedule' do - let(:new_cron) { '0 0 1 1 *' } - - it 'updates next_run_at automatically' do - expect { pipeline_schedule.update!(cron: new_cron) } - .to change { pipeline_schedule.next_run_at } - end - end end describe '#schedule_next_run!' do diff --git a/spec/models/concerns/cron_schedulable_spec.rb b/spec/models/concerns/cron_schedulable_spec.rb new file mode 100644 index 00000000000..39c3d5e55d3 --- /dev/null +++ b/spec/models/concerns/cron_schedulable_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe CronSchedulable do + let(:ideal_next_run_at) { schedule.send(:ideal_next_run_from, Time.zone.now) } + let(:cron_worker_next_run_at) { schedule.send(:cron_worker_next_run_from, Time.zone.now) } + + context 'for ci_pipeline_schedule' do + let(:schedule) { create(:ci_pipeline_schedule, :every_minute) } + let(:schedule_1) { create(:ci_pipeline_schedule, :weekly, cron_timezone: 'UTC') } + let(:schedule_2) { create(:ci_pipeline_schedule, :weekly, cron_timezone: 'UTC') } + let(:new_cron) { '0 0 1 1 *' } + + it_behaves_like 'handles set_next_run_at' + end +end diff --git a/spec/requests/api/graphql/group/packages_spec.rb b/spec/requests/api/graphql/group/packages_spec.rb index 409771b13ac..adee556db3a 100644 --- a/spec/requests/api/graphql/group/packages_spec.rb +++ b/spec/requests/api/graphql/group/packages_spec.rb @@ -7,82 +7,19 @@ RSpec.describe 'getting a package list for a group' do let_it_be(:resource) { create(:group, :private) } let_it_be(:group_two) { create(:group, :private) } - let_it_be(:project) { create(:project, :repository, group: resource) } - let_it_be(:another_project) { create(:project, :repository, group: resource) } - let_it_be(:group_two_project) { create(:project, :repository, group: group_two) } + let_it_be(:project1) { create(:project, :repository, group: resource) } + let_it_be(:project2) { create(:project, :repository, group: resource) } let_it_be(:current_user) { create(:user) } - let_it_be(:npm_package) { create(:npm_package, project: group_two_project) } - let_it_be(:maven_package) { create(:maven_package, project: project, name: 'tab', version: '4.0.0', created_at: 5.days.ago) } - let_it_be(:package) { create(:npm_package, project: project, name: 'uab', version: '5.0.0', created_at: 4.days.ago) } - let_it_be(:composer_package) { create(:composer_package, project: another_project, name: 'vab', version: '6.0.0', created_at: 3.days.ago) } - let_it_be(:debian_package) { create(:debian_package, project: another_project, name: 'zab', version: '7.0.0', created_at: 2.days.ago) } - let_it_be(:composer_metadatum) do - create(:composer_metadatum, package: composer_package, - target_sha: 'afdeh', - composer_json: { name: 'x', type: 'y', license: 'z', version: 1 }) - end - - let(:package_names) { graphql_data_at(:group, :packages, :nodes, :name) } - let(:target_shas) { graphql_data_at(:group, :packages, :nodes, :metadata, :target_sha) } - let(:packages) { graphql_data_at(:group, :packages, :nodes) } - - let(:fields) do - <<~QUERY - nodes { - #{all_graphql_fields_for('packages'.classify, excluded: ['project'])} - metadata { #{query_graphql_fragment('ComposerMetadata')} } - } - QUERY - end - - let(:query) do - graphql_query_for( - 'group', - { 'fullPath' => resource.full_path }, - query_graphql_field('packages', {}, fields) - ) - end + let(:resource_type) { :group } it_behaves_like 'group and project packages query' - describe 'sorting and pagination' do - let_it_be(:ascending_packages) { [maven_package, package, composer_package, debian_package].map { |package| global_id_of(package)} } - - let(:data_path) { [:group, :packages] } - - before do - resource.add_reporter(current_user) - end - - [:CREATED_ASC, :NAME_ASC, :VERSION_ASC, :TYPE_ASC].each do |order| - context "#{order}" do - it_behaves_like 'sorted paginated query' do - let(:sort_param) { order } - let(:first_param) { 4 } - let(:expected_results) { ascending_packages } - end - end - end - - [:CREATED_DESC, :NAME_DESC, :VERSION_DESC, :TYPE_DESC].each do |order| - context "#{order}" do - it_behaves_like 'sorted paginated query' do - let(:sort_param) { order } - let(:first_param) { 4 } - let(:expected_results) { ascending_packages.reverse } - end - end - end - - def pagination_query(params) - graphql_query_for(:group, { 'fullPath' => resource.full_path }, - query_nodes(:packages, :id, include_pagination_info: true, args: params) - ) - end - end - context 'with a batched query' do + let_it_be(:group_two_project) { create(:project, :repository, group: group_two) } + let_it_be(:group_one_package) { create(:npm_package, project: project1) } + let_it_be(:group_two_package) { create(:npm_package, project: group_two_project) } + let(:batch_query) do <<~QUERY { @@ -101,12 +38,7 @@ RSpec.describe 'getting a package list for a group' do end it 'returns an error for the second group and data for the first' do - expect(a_packages_names).to contain_exactly( - package.name, - maven_package.name, - debian_package.name, - composer_package.name - ) + expect(a_packages_names).to contain_exactly(group_one_package.name) expect_graphql_errors_to_include [/Packages can be requested only for one group at a time/] expect(graphql_data_at(:b, :packages)).to be(nil) end diff --git a/spec/requests/api/graphql/project/packages_spec.rb b/spec/requests/api/graphql/project/packages_spec.rb index e7c6a4c0018..d9ee997eb02 100644 --- a/spec/requests/api/graphql/project/packages_spec.rb +++ b/spec/requests/api/graphql/project/packages_spec.rb @@ -7,72 +7,10 @@ RSpec.describe 'getting a package list for a project' do let_it_be(:resource) { create(:project, :repository) } let_it_be(:current_user) { create(:user) } - let_it_be(:maven_package) { create(:maven_package, project: resource, name: 'tab', version: '4.0.0', created_at: 5.days.ago) } - let_it_be(:package) { create(:npm_package, project: resource, name: 'uab', version: '5.0.0', created_at: 4.days.ago) } - let_it_be(:composer_package) { create(:composer_package, project: resource, name: 'vab', version: '6.0.0', created_at: 3.days.ago) } - let_it_be(:debian_package) { create(:debian_package, project: resource, name: 'zab', version: '7.0.0', created_at: 2.days.ago) } - let_it_be(:composer_metadatum) do - create(:composer_metadatum, package: composer_package, - target_sha: 'afdeh', - composer_json: { name: 'x', type: 'y', license: 'z', version: 1 }) - end + let_it_be(:project1) { resource } + let_it_be(:project2) { resource } - let(:package_names) { graphql_data_at(:project, :packages, :nodes, :name) } - let(:target_shas) { graphql_data_at(:project, :packages, :nodes, :metadata, :target_sha) } - let(:packages) { graphql_data_at(:project, :packages, :nodes) } - - let(:fields) do - <<~QUERY - nodes { - #{all_graphql_fields_for('packages'.classify, excluded: ['project'])} - metadata { #{query_graphql_fragment('ComposerMetadata')} } - } - QUERY - end - - let(:query) do - graphql_query_for( - 'project', - { 'fullPath' => resource.full_path }, - query_graphql_field('packages', {}, fields) - ) - end + let(:resource_type) { :project } it_behaves_like 'group and project packages query' - - describe 'sorting and pagination' do - let_it_be(:ascending_packages) { [maven_package, package, composer_package, debian_package].map { |package| global_id_of(package)} } - - let(:data_path) { [:project, :packages] } - - before do - resource.add_reporter(current_user) - end - - [:CREATED_ASC, :NAME_ASC, :VERSION_ASC, :TYPE_ASC].each do |order| - context "#{order}" do - it_behaves_like 'sorted paginated query' do - let(:sort_param) { order } - let(:first_param) { 4 } - let(:expected_results) { ascending_packages } - end - end - end - - [:CREATED_DESC, :NAME_DESC, :VERSION_DESC, :TYPE_DESC].each do |order| - context "#{order}" do - it_behaves_like 'sorted paginated query' do - let(:sort_param) { order } - let(:first_param) { 4 } - let(:expected_results) { ascending_packages.reverse } - end - end - end - - def pagination_query(params) - graphql_query_for(:project, { 'fullPath' => resource.full_path }, - query_nodes(:packages, :id, include_pagination_info: true, args: params) - ) - end - end end diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb index 46dab4fa171..696b0bcaaf2 100644 --- a/spec/services/web_hook_service_spec.rb +++ b/spec/services/web_hook_service_spec.rb @@ -240,6 +240,25 @@ RSpec.describe WebHookService do it 'does not change the disabled_until attribute' do expect { service_instance.execute }.not_to change(project_hook, :disabled_until) end + + it 'does not allow the failure count to overflow' do + project_hook.update!(recent_failures: 32767) + + expect { service_instance.execute }.not_to change(project_hook, :recent_failures) + end + + context 'when the web_hooks_disable_failed FF is disabled' do + before do + # Hook will only be executed if the flag is disabled. + stub_feature_flags(web_hooks_disable_failed: false) + end + + it 'does not allow the failure count to overflow' do + project_hook.update!(recent_failures: 32767) + + expect { service_instance.execute }.not_to change(project_hook, :recent_failures) + end + end end context 'with exception' do diff --git a/spec/support/shared_examples/graphql/resolvers/packages_resolvers_shared_examples.rb b/spec/support/shared_examples/graphql/resolvers/packages_resolvers_shared_examples.rb new file mode 100644 index 00000000000..3d6fec85490 --- /dev/null +++ b/spec/support/shared_examples/graphql/resolvers/packages_resolvers_shared_examples.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'group and projects packages resolver' do + context 'without sort' do + let_it_be(:npm_package) { create(:package, project: project) } + + it { is_expected.to contain_exactly(npm_package) } + end + + context 'with sorting and filtering' do + let_it_be(:conan_package) do + create(:conan_package, name: 'bar', project: project, created_at: 1.day.ago, version: "1.0.0", status: 'default') + end + + let_it_be(:maven_package) do + create(:maven_package, name: 'foo', project: project, created_at: 1.hour.ago, version: "2.0.0", status: 'error') + end + + let_it_be(:repository3) do + create(:maven_package, name: 'baz', project: project, created_at: 1.minute.ago, version: nil) + end + + [:created_desc, :name_desc, :version_desc, :type_asc].each do |order| + context "#{order}" do + let(:args) { { sort: order } } + + it { is_expected.to eq([maven_package, conan_package]) } + end + end + + [:created_asc, :name_asc, :version_asc, :type_desc].each do |order| + context "#{order}" do + let(:args) { { sort: order } } + + it { is_expected.to eq([conan_package, maven_package]) } + end + end + + context 'filter by package_name' do + let(:args) { { package_name: 'bar', sort: :created_desc } } + + it { is_expected.to eq([conan_package]) } + end + + context 'filter by package_type' do + let(:args) { { package_type: 'conan', sort: :created_desc } } + + it { is_expected.to eq([conan_package]) } + end + + context 'filter by status' do + let(:args) { { status: 'error', sort: :created_desc } } + + it { is_expected.to eq([maven_package]) } + end + + context 'include_versionless' do + let(:args) { { include_versionless: true, sort: :created_desc } } + + it { is_expected.to include(repository3) } + end + end +end diff --git a/spec/support/shared_examples/models/concerns/cron_schedulable_shared_examples.rb b/spec/support/shared_examples/models/concerns/cron_schedulable_shared_examples.rb new file mode 100644 index 00000000000..47a02a8fa49 --- /dev/null +++ b/spec/support/shared_examples/models/concerns/cron_schedulable_shared_examples.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'handles set_next_run_at' do + context 'when schedule runs every minute' do + it "updates next_run_at to the worker's execution time" do + travel_to(1.day.ago) do + expect(schedule.next_run_at).to eq(cron_worker_next_run_at) + end + end + end + + context 'when there are two different schedules in the same time zones' do + it 'sets the sames next_run_at' do + expect(schedule_1.next_run_at).to eq(schedule_2.next_run_at) + end + end + + context 'when cron is updated for existing schedules' do + it 'updates next_run_at automatically' do + expect { schedule.update!(cron: new_cron) }.to change { schedule.next_run_at } + end + end +end diff --git a/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb index 66fbfa798b0..af4c9286e7c 100644 --- a/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb @@ -3,6 +3,38 @@ RSpec.shared_examples 'group and project packages query' do include GraphqlHelpers + let_it_be(:versionaless_package) { create(:maven_package, project: project1, version: nil) } + let_it_be(:maven_package) { create(:maven_package, project: project1, name: 'tab', version: '4.0.0', created_at: 5.days.ago) } + let_it_be(:package) { create(:npm_package, project: project1, name: 'uab', version: '5.0.0', created_at: 4.days.ago) } + let_it_be(:composer_package) { create(:composer_package, project: project2, name: 'vab', version: '6.0.0', created_at: 3.days.ago) } + let_it_be(:debian_package) { create(:debian_package, project: project2, name: 'zab', version: '7.0.0', created_at: 2.days.ago) } + let_it_be(:composer_metadatum) do + create(:composer_metadatum, package: composer_package, + target_sha: 'afdeh', + composer_json: { name: 'x', type: 'y', license: 'z', version: 1 }) + end + + let(:package_names) { graphql_data_at(resource_type, :packages, :nodes, :name) } + let(:target_shas) { graphql_data_at(resource_type, :packages, :nodes, :metadata, :target_sha) } + let(:packages) { graphql_data_at(resource_type, :packages, :nodes) } + + let(:fields) do + <<~QUERY + nodes { + #{all_graphql_fields_for('packages'.classify, excluded: ['project'])} + metadata { #{query_graphql_fragment('ComposerMetadata')} } + } + QUERY + end + + let(:query) do + graphql_query_for( + resource_type, + { 'fullPath' => resource.full_path }, + query_graphql_field('packages', {}, fields) + ) + end + context 'when user has access to the resource' do before do resource.add_reporter(current_user) @@ -48,4 +80,101 @@ RSpec.shared_examples 'group and project packages query' do expect(packages).to be_nil end end + + describe 'sorting and pagination' do + let_it_be(:ascending_packages) { [maven_package, package, composer_package, debian_package].map { |package| global_id_of(package)} } + + let(:data_path) { [resource_type, :packages] } + + before do + resource.add_reporter(current_user) + end + + [:CREATED_ASC, :NAME_ASC, :VERSION_ASC, :TYPE_ASC].each do |order| + context "#{order}" do + it_behaves_like 'sorted paginated query' do + let(:sort_param) { order } + let(:first_param) { 4 } + let(:expected_results) { ascending_packages } + end + end + end + + [:CREATED_DESC, :NAME_DESC, :VERSION_DESC, :TYPE_DESC].each do |order| + context "#{order}" do + it_behaves_like 'sorted paginated query' do + let(:sort_param) { order } + let(:first_param) { 4 } + let(:expected_results) { ascending_packages.reverse } + end + end + end + + context 'with an invalid sort' do + let(:query) do + graphql_query_for( + resource_type, + { 'fullPath' => resource.full_path }, + query_nodes(:packages, :name, args: { sort: :WRONG_ORDER }) + ) + end + + before do + post_graphql(query, current_user: current_user) + end + + it 'throws an error' do + expect_graphql_errors_to_include(/Argument \'sort\' on Field \'packages\' has an invalid value/) + end + end + + def pagination_query(params) + graphql_query_for(resource_type, { 'fullPath' => resource.full_path }, + query_nodes(:packages, :id, include_pagination_info: true, args: params) + ) + end + end + + describe 'filtering' do + subject { packages } + + let(:query) do + graphql_query_for( + resource_type, + { 'fullPath' => resource.full_path }, + query_nodes(:packages, :name, args: params) + ) + end + + before do + resource.add_reporter(current_user) + post_graphql(query, current_user: current_user) + end + + context 'package_name' do + let(:params) { { package_name: maven_package.name } } + + it { is_expected.to contain_exactly({ "name" => maven_package.name }) } + end + + context 'package_type' do + let(:params) { { package_type: :COMPOSER } } + + it { is_expected.to contain_exactly({ "name" => composer_package.name }) } + end + + context 'status' do + let_it_be(:errored_package) { create(:maven_package, project: project1, status: 'error') } + + let(:params) { { status: :ERROR } } + + it { is_expected.to contain_exactly({ "name" => errored_package.name }) } + end + + context 'include_versionless' do + let(:params) { { include_versionless: true } } + + it { is_expected.to include({ "name" => versionaless_package.name }) } + end + end end diff --git a/yarn.lock b/yarn.lock index 99ab9c7780f..2353ff71ad5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -897,20 +897,20 @@ stylelint-declaration-strict-value "1.7.7" stylelint-scss "3.18.0" -"@gitlab/svgs@1.195.0": - version "1.195.0" - resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.195.0.tgz#addf7a31fe8b49a9b91af7373877ec46e56603b1" - integrity sha512-ZEVfFEONZSUf0SmUY1+BDCQPTXBKPamHp/qfTVPXvuXxkihsSBRGwqdu57fNQq/0/Jk95IY2uxm+I9fzb4uQUQ== +"@gitlab/svgs@1.196.0": + version "1.196.0" + resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.196.0.tgz#7905bc66ef9c69ba7b5225326c0eaf4e55d11386" + integrity sha512-X/UGCBXIZXBcPqfRy8qaxQG/SYyrZajAazORZjmnVF+cyM9lQTuCiZFi7dHtMQ1XLew+m1NREVngCmBLuuK98g== "@gitlab/tributejs@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8" integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw== -"@gitlab/ui@29.23.0": - version "29.23.0" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-29.23.0.tgz#cf0bf2ed85c679a618f0f78d7f5d4e4346663b55" - integrity sha512-ELMHentJ9v5WXlAAuSr5s5kYu8KW710N4qCnzdt09g+McSsvXUhOx2ltM0d4rZe+TZwgwAUndwCUDP+dHqDtrA== +"@gitlab/ui@29.25.0": + version "29.25.0" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-29.25.0.tgz#535f1e358176fb73d0e7df0315a8f50f7c8fc20b" + integrity sha512-Bt9wBj954Ev6UGbAJ0+ViT7ggOBXocyxru8NPDq060G7OAchtm6IQK0bwa4DugF5LxiP9IWXy34Oz55zjymwqw== dependencies: "@babel/standalone" "^7.0.0" "@gitlab/vue-toasted" "^1.3.0" |