From 53af44b90f87cdd8d7126d64669848b0e2be5960 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Mon, 9 Aug 2021 12:10:09 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .../javascripts/diffs/components/app.vue | 21 +-- app/assets/javascripts/diffs/constants.js | 2 + app/assets/javascripts/diffs/store/actions.js | 32 +++-- .../javascripts/diffs/utils/queue_events.js | 13 ++ .../components/details/app.vue | 42 ++++-- .../destroy_package.mutation.graphql | 5 + app/policies/group_policy.rb | 2 +- doc/ci/environments/index.md | 22 ++- doc/ci/environments/protected_environments.md | 27 ++-- doc/raketasks/backup_restore.md | 120 ++++++++-------- doc/update/index.md | 22 +-- doc/user/permissions.md | 2 +- lib/gitlab/setup_helper.rb | 2 +- locale/gitlab.pot | 3 + package.json | 2 +- qa/Gemfile | 4 +- qa/Gemfile.lock | 27 ++-- qa/qa/page/base.rb | 2 +- qa/qa/runtime/application_settings.rb | 2 +- qa/qa/runtime/browser.rb | 2 +- qa/qa/runtime/feature.rb | 10 +- qa/spec/qa_deprecation_toolkit_env.rb | 22 +++ qa/spec/runtime/api/request_spec.rb | 2 +- qa/spec/spec_helper.rb | 3 + ...cy_proxy_for_containers_controller_spec.rb | 10 +- .../frontend/diffs/utils/queue_events_spec.js | 36 +++++ .../components/details/app_spec.js | 133 +++++++++++++++++- .../package_registry/mock_data.js | 26 ++++ spec/support/helpers/test_env.rb | 2 +- yarn.lock | 8 +- 30 files changed, 441 insertions(+), 165 deletions(-) create mode 100644 app/assets/javascripts/diffs/utils/queue_events.js create mode 100644 app/assets/javascripts/packages_and_registries/package_registry/graphql/mutations/destroy_package.mutation.graphql create mode 100644 qa/spec/qa_deprecation_toolkit_env.rb create mode 100644 spec/frontend/diffs/utils/queue_events_spec.js diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue index 1860a45207f..4057e281a48 100644 --- a/app/assets/javascripts/diffs/components/app.vue +++ b/app/assets/javascripts/diffs/components/app.vue @@ -46,6 +46,7 @@ import diffsEventHub from '../event_hub'; import { reviewStatuses } from '../utils/file_reviews'; import { diffsApp } from '../utils/performance'; import { fileByFile } from '../utils/preferences'; +import { queueRedisHllEvents } from '../utils/queue_events'; import CollapsedFilesWarning from './collapsed_files_warning.vue'; import CommitWidget from './commit_widget.vue'; import CompareVersions from './compare_versions.vue'; @@ -336,29 +337,33 @@ export default { } if (window.gon?.features?.diffSettingsUsageData) { + const events = []; + if (this.renderTreeList) { - api.trackRedisHllUserEvent(TRACKING_FILE_BROWSER_TREE); + events.push(TRACKING_FILE_BROWSER_TREE); } else { - api.trackRedisHllUserEvent(TRACKING_FILE_BROWSER_LIST); + events.push(TRACKING_FILE_BROWSER_LIST); } if (this.diffViewType === INLINE_DIFF_VIEW_TYPE) { - api.trackRedisHllUserEvent(TRACKING_DIFF_VIEW_INLINE); + events.push(TRACKING_DIFF_VIEW_INLINE); } else { - api.trackRedisHllUserEvent(TRACKING_DIFF_VIEW_PARALLEL); + events.push(TRACKING_DIFF_VIEW_PARALLEL); } if (this.showWhitespace) { - api.trackRedisHllUserEvent(TRACKING_WHITESPACE_SHOW); + events.push(TRACKING_WHITESPACE_SHOW); } else { - api.trackRedisHllUserEvent(TRACKING_WHITESPACE_HIDE); + events.push(TRACKING_WHITESPACE_HIDE); } if (this.viewDiffsFileByFile) { - api.trackRedisHllUserEvent(TRACKING_SINGLE_FILE_MODE); + events.push(TRACKING_SINGLE_FILE_MODE); } else { - api.trackRedisHllUserEvent(TRACKING_MULTIPLE_FILES_MODE); + events.push(TRACKING_MULTIPLE_FILES_MODE); } + + queueRedisHllEvents(events); } }, beforeCreate() { diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js index f1cf556fde0..8dda5eadb16 100644 --- a/app/assets/javascripts/diffs/constants.js +++ b/app/assets/javascripts/diffs/constants.js @@ -111,6 +111,8 @@ export const CONFLICT_MARKER_OUR = 'conflict_marker_our'; export const CONFLICT_MARKER_THEIR = 'conflict_marker_their'; // Tracking events +export const DEFER_DURATION = 750; + export const TRACKING_CLICK_DIFF_VIEW_SETTING = 'i_code_review_click_diff_view_setting'; export const TRACKING_DIFF_VIEW_INLINE = 'i_code_review_diff_view_inline'; export const TRACKING_DIFF_VIEW_PARALLEL = 'i_code_review_diff_view_parallel'; diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js index d11e7dc838f..f7bdbe94bac 100644 --- a/app/assets/javascripts/diffs/store/actions.js +++ b/app/assets/javascripts/diffs/store/actions.js @@ -1,6 +1,5 @@ import Cookies from 'js-cookie'; import Vue from 'vue'; -import api from '~/api'; import createFlash from '~/flash'; import { diffViewerModes } from '~/ide/constants'; import axios from '~/lib/utils/axios_utils'; @@ -50,6 +49,7 @@ import eventHub from '../event_hub'; import { isCollapsed } from '../utils/diff_file'; import { markFileReview, setReviewsForMergeRequest } from '../utils/file_reviews'; import { getDerivedMergeRequestInformation } from '../utils/merge_request'; +import { queueRedisHllEvents } from '../utils/queue_events'; import TreeWorker from '../workers/tree_worker'; import * as types from './mutation_types'; import { @@ -368,8 +368,7 @@ export const setInlineDiffViewType = ({ commit }) => { historyPushState(url); if (window.gon?.features?.diffSettingsUsageData) { - api.trackRedisHllUserEvent(TRACKING_CLICK_DIFF_VIEW_SETTING); - api.trackRedisHllUserEvent(TRACKING_DIFF_VIEW_INLINE); + queueRedisHllEvents([TRACKING_CLICK_DIFF_VIEW_SETTING, TRACKING_DIFF_VIEW_INLINE]); } }; @@ -381,8 +380,7 @@ export const setParallelDiffViewType = ({ commit }) => { historyPushState(url); if (window.gon?.features?.diffSettingsUsageData) { - api.trackRedisHllUserEvent(TRACKING_CLICK_DIFF_VIEW_SETTING); - api.trackRedisHllUserEvent(TRACKING_DIFF_VIEW_PARALLEL); + queueRedisHllEvents([TRACKING_CLICK_DIFF_VIEW_SETTING, TRACKING_DIFF_VIEW_PARALLEL]); } }; @@ -570,13 +568,15 @@ export const setRenderTreeList = ({ commit }, { renderTreeList, trackClick = tru localStorage.setItem(TREE_LIST_STORAGE_KEY, renderTreeList); if (window.gon?.features?.diffSettingsUsageData && trackClick) { - api.trackRedisHllUserEvent(TRACKING_CLICK_FILE_BROWSER_SETTING); + const events = [TRACKING_CLICK_FILE_BROWSER_SETTING]; if (renderTreeList) { - api.trackRedisHllUserEvent(TRACKING_FILE_BROWSER_TREE); + events.push(TRACKING_FILE_BROWSER_TREE); } else { - api.trackRedisHllUserEvent(TRACKING_FILE_BROWSER_LIST); + events.push(TRACKING_FILE_BROWSER_LIST); } + + queueRedisHllEvents(events); } }; @@ -592,13 +592,15 @@ export const setShowWhitespace = async ( notesEventHub.$emit('refetchDiffData'); if (window.gon?.features?.diffSettingsUsageData && trackClick) { - api.trackRedisHllUserEvent(TRACKING_CLICK_WHITESPACE_SETTING); + const events = [TRACKING_CLICK_WHITESPACE_SETTING]; if (showWhitespace) { - api.trackRedisHllUserEvent(TRACKING_WHITESPACE_SHOW); + events.push(TRACKING_WHITESPACE_SHOW); } else { - api.trackRedisHllUserEvent(TRACKING_WHITESPACE_HIDE); + events.push(TRACKING_WHITESPACE_HIDE); } + + queueRedisHllEvents(events); } }; @@ -819,13 +821,15 @@ export const setFileByFile = ({ state, commit }, { fileByFile }) => { Cookies.set(DIFF_FILE_BY_FILE_COOKIE_NAME, fileViewMode); if (window.gon?.features?.diffSettingsUsageData) { - api.trackRedisHllUserEvent(TRACKING_CLICK_SINGLE_FILE_SETTING); + const events = [TRACKING_CLICK_SINGLE_FILE_SETTING]; if (fileByFile) { - api.trackRedisHllUserEvent(TRACKING_SINGLE_FILE_MODE); + events.push(TRACKING_SINGLE_FILE_MODE); } else { - api.trackRedisHllUserEvent(TRACKING_MULTIPLE_FILES_MODE); + events.push(TRACKING_MULTIPLE_FILES_MODE); } + + queueRedisHllEvents(events); } return axios diff --git a/app/assets/javascripts/diffs/utils/queue_events.js b/app/assets/javascripts/diffs/utils/queue_events.js new file mode 100644 index 00000000000..08fcc98d45f --- /dev/null +++ b/app/assets/javascripts/diffs/utils/queue_events.js @@ -0,0 +1,13 @@ +import { delay } from 'lodash'; +import api from '~/api'; +import { DEFER_DURATION } from '../constants'; + +function trackRedisHllUserEvent(event, deferDuration = 0) { + delay(() => api.trackRedisHllUserEvent(event), deferDuration); +} + +export function queueRedisHllEvents(events) { + events.forEach((event, index) => { + trackRedisHllUserEvent(event, DEFER_DURATION * (index + 1)); + }); +} diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue index 707f186d4da..65e396b34e9 100644 --- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue +++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue @@ -39,7 +39,9 @@ import { CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION, SHOW_DELETE_SUCCESS_ALERT, FETCH_PACKAGE_DETAILS_ERROR_MESSAGE, + DELETE_PACKAGE_ERROR_MESSAGE, } from '~/packages_and_registries/package_registry/constants'; +import destroyPackageMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package.mutation.graphql'; import getPackageDetails from '~/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql'; import Tracking from '~/tracking'; @@ -156,19 +158,42 @@ export default { // this.fetchPackageVersions(); } }, + deletePackage() { + return this.$apollo + .mutate({ + mutation: destroyPackageMutation, + variables: { + id: this.packageEntity.id, + }, + }) + .then(({ data }) => { + if (data?.destroyPackage?.errors[0]) { + throw data.destroyPackage.errors[0]; + } + }); + }, async confirmPackageDeletion() { this.track(DELETE_PACKAGE_TRACKING_ACTION); - await this.deletePackage(); + try { + await this.deletePackage(); - const returnTo = - !this.groupListUrl || document.referrer.includes(this.projectName) - ? this.projectListUrl - : this.groupListUrl; // to avoid security issue url are supplied from backend + const returnTo = + !this.groupListUrl || document.referrer.includes(this.projectName) + ? this.projectListUrl + : this.groupListUrl; // to avoid security issue url are supplied from backend - const modalQuery = objectToQuery({ [SHOW_DELETE_SUCCESS_ALERT]: true }); + const modalQuery = objectToQuery({ [SHOW_DELETE_SUCCESS_ALERT]: true }); - window.location.replace(`${returnTo}?${modalQuery}`); + window.location.replace(`${returnTo}?${modalQuery}`); + } catch (error) { + createFlash({ + message: DELETE_PACKAGE_ERROR_MESSAGE, + type: 'warning', + captureError: true, + error, + }); + } }, handleFileDelete(file) { this.track(REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION); @@ -225,10 +250,10 @@ export default { {{ __('Delete') }} @@ -303,7 +328,6 @@ export default { = GroupMember::REPORTER || valid_dependency_proxy_deploy_token + access_level >= GroupMember::GUEST || valid_dependency_proxy_deploy_token else can?(:read_group) end diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md index e647a704a87..9e7855ef826 100644 --- a/doc/ci/environments/index.md +++ b/doc/ci/environments/index.md @@ -31,7 +31,8 @@ Prerequisites: To view a list of environments and deployments: -1. Go to the project's **Deployments > Environments** page. +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Deployments > Environments**. The environments are displayed. ![Environments list](img/environments_list.png) @@ -57,7 +58,8 @@ You can create an environment and deployment in the UI or in your `.gitlab-ci.ym In the UI: -1. Go to the project's **Deployments > Environments** page. +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Deployments > Environments**. 1. Select **New environment**. 1. Enter a name and external URL. 1. Select **Save**. @@ -326,7 +328,8 @@ If there is a problem with a deployment, you can retry it or roll it back. To retry or rollback a deployment: -1. Go to the project's **Deployments > Environments**. +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Deployments > Environments**. 1. Select the environment. 1. To the right of the deployment name: - To retry a deployment, select **Re-deploy to environment**. @@ -465,7 +468,8 @@ GitLab automatically triggers the `stop_review_app` job to stop the environment. You can view a deployment's expiration date in the GitLab UI. -1. Go to the project's **Deployments > Environments** page. +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Deployments > Environments**. 1. Select the name of the deployment. In the top left, next to the environment name, the expiration date is displayed. @@ -474,7 +478,8 @@ In the top left, next to the environment name, the expiration date is displayed. You can manually override a deployment's expiration date. -1. Go to the project's **Deployments > Environments** page. +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Deployments > Environments**. 1. Select the deployment name. 1. On the top right, select the thumbtack (**{thumbtack}**). @@ -491,7 +496,8 @@ You can delete [stopped environments](#stopping-an-environment) in the GitLab UI To delete a stopped environment in the GitLab UI: -1. Go to the project's **Deployments > Environments** page. +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Deployments > Environments**. 1. Select the **Stopped** tab. 1. Next to the environment you want to delete, select **Delete environment**. 1. On the confirmation dialog box, select **Delete environment**. @@ -596,7 +602,9 @@ Limitations of GitLab Auto Rollback: GitLab Auto Rollback is turned off by default. To turn it on: -1. Go to **Project > Settings > CI/CD > Automatic deployment rollbacks**. +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Settings > CI/CD**. +1. Expand **Automatic deployment rollbacks**. 1. Select the checkbox for **Enable automatic rollbacks**. 1. Select **Save changes**. diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md index 0c29f0aa7a7..4d89bba9ec1 100644 --- a/doc/ci/environments/protected_environments.md +++ b/doc/ci/environments/protected_environments.md @@ -30,18 +30,19 @@ To protect, update, or unprotect an environment, you need to have at least the To protect an environment: -1. Navigate to your project's **Settings > CI/CD**. -1. Expand the **Protected environments** section. -1. From the **Environment** dropdown menu, select the environment you want to protect. -1. In the **Allowed to Deploy** dropdown menu, select the role, users, or groups you +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Settings > CI/CD**. +1. Expand **Protected environments**. +1. From the **Environment** list, select the environment you want to protect. +1. In the **Allowed to deploy** list, select the role, users, or groups you want to give deploy access to. Keep in mind that: - There are two roles to choose from: - - **Maintainers**: Allows access to all maintainers in the project. - - **Developers**: Allows access to all maintainers and all developers in the project. - - You can only select groups that are already associated with the project. - - Only users that have at least the Developer role appear in - the **Allowed to Deploy** dropdown menu. -1. Click the **Protect** button. + - **Maintainers**: Allows access to all of the project's users with the Maintainer role. + - **Developers**: Allows access to all of the project's users with the Maintainer and Developer role. + - You can select groups that are already associated with the project only. + - Users must have at least the Developer role to appear in + the **Allowed to deploy** list. +1. Select **Protect**. The protected environment now appears in the list of protected environments. @@ -134,10 +135,10 @@ appears in the dropdown menu for deployment-only access. To add deployment-only access: -1. Add a group with Reporter permissions. -1. Add user(s) to the group. +1. Add a group with the Reporter role. +1. Add users to the group. 1. Invite the group to be a project member. -1. Follow the steps outlined in [Protecting Environments](#protecting-environments). +1. Follow the steps in [Protecting Environments](#protecting-environments). Note that deployment-only access is the only possible access level for groups with [Reporter permissions](../../user/permissions.md). diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index 250abf2fa60..e9c9659d4f5 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -850,66 +850,6 @@ restoring the new data, which causes an error. Read more about [configuring NFS mounts](../administration/nfs.md) -### Restore for installation from source - -First, ensure your backup tar file is in the backup directory described in the -`gitlab.yml` configuration: - -```yaml -## Backup settings -backup: - path: "tmp/backups" # Relative paths are relative to Rails.root (default: tmp/backups/) -``` - -The default is `/home/git/gitlab/tmp/backups`, and it needs to be owned by the `git` user. Now, you can begin the backup procedure: - -```shell -# Stop processes that are connected to the database -sudo service gitlab stop - -sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production -``` - -Example output: - -```plaintext -Unpacking backup... [DONE] -Restoring database tables: --- create_table("events", {:force=>true}) - -> 0.2231s -[...] -- Loading fixture events...[DONE] -- Loading fixture issues...[DONE] -- Loading fixture keys...[SKIPPING] -- Loading fixture merge_requests...[DONE] -- Loading fixture milestones...[DONE] -- Loading fixture namespaces...[DONE] -- Loading fixture notes...[DONE] -- Loading fixture projects...[DONE] -- Loading fixture protected_branches...[SKIPPING] -- Loading fixture schema_migrations...[DONE] -- Loading fixture services...[SKIPPING] -- Loading fixture snippets...[SKIPPING] -- Loading fixture taggings...[SKIPPING] -- Loading fixture tags...[SKIPPING] -- Loading fixture users...[DONE] -- Loading fixture users_projects...[DONE] -- Loading fixture web_hooks...[SKIPPING] -- Loading fixture wikis...[SKIPPING] -Restoring repositories: -- Restoring repository abcd... [DONE] -- Object pool 1 ... -Deleting tmp directories...[DONE] -``` - -Next, restore `/home/git/gitlab/.secret` if necessary, [as previously mentioned](#restore-prerequisites). - -Restart GitLab: - -```shell -sudo service gitlab restart -``` - ### Restore for Omnibus GitLab installations This procedure assumes that: @@ -1027,6 +967,66 @@ issue. The GitLab Helm chart uses a different process, documented in [restoring a GitLab Helm chart installation](https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/backup-restore/restore.md). +### Restore for installation from source + +First, ensure your backup tar file is in the backup directory described in the +`gitlab.yml` configuration: + +```yaml +## Backup settings +backup: + path: "tmp/backups" # Relative paths are relative to Rails.root (default: tmp/backups/) +``` + +The default is `/home/git/gitlab/tmp/backups`, and it needs to be owned by the `git` user. Now, you can begin the backup procedure: + +```shell +# Stop processes that are connected to the database +sudo service gitlab stop + +sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production +``` + +Example output: + +```plaintext +Unpacking backup... [DONE] +Restoring database tables: +-- create_table("events", {:force=>true}) + -> 0.2231s +[...] +- Loading fixture events...[DONE] +- Loading fixture issues...[DONE] +- Loading fixture keys...[SKIPPING] +- Loading fixture merge_requests...[DONE] +- Loading fixture milestones...[DONE] +- Loading fixture namespaces...[DONE] +- Loading fixture notes...[DONE] +- Loading fixture projects...[DONE] +- Loading fixture protected_branches...[SKIPPING] +- Loading fixture schema_migrations...[DONE] +- Loading fixture services...[SKIPPING] +- Loading fixture snippets...[SKIPPING] +- Loading fixture taggings...[SKIPPING] +- Loading fixture tags...[SKIPPING] +- Loading fixture users...[DONE] +- Loading fixture users_projects...[DONE] +- Loading fixture web_hooks...[SKIPPING] +- Loading fixture wikis...[SKIPPING] +Restoring repositories: +- Restoring repository abcd... [DONE] +- Object pool 1 ... +Deleting tmp directories...[DONE] +``` + +Next, restore `/home/git/gitlab/.secret` if necessary, [as previously mentioned](#restore-prerequisites). + +Restart GitLab: + +```shell +sudo service gitlab restart +``` + ### Restoring only one or a few projects or groups from a backup Although the Rake task used to restore a GitLab instance doesn't support diff --git a/doc/update/index.md b/doc/update/index.md index 61419e563cc..ed057782bf9 100644 --- a/doc/update/index.md +++ b/doc/update/index.md @@ -203,15 +203,15 @@ accordingly, while also consulting the The following table, while not exhaustive, shows some examples of the supported upgrade paths. -| Target version | Your version | Supported upgrade path | Note | -| --------------------- | ------------ | ------------------------ | ---- | -| `14.1.0` | `13.9.2` | `13.9.2` -> `13.12.6` -> `14.0.5` -> `14.1.0` | Two intermediate versions are required: `13.12` and `14.0`, then `14.1`. | -| `13.5.4` | `12.9.2` | `12.9.2` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> `13.5.4` | Three intermediate versions are required: `12.10`, `13.0` and `13.1`, then `13.5.4`. | -| `13.2.10` | `11.5.0` | `11.5.0` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> `13.2.10` | Six intermediate versions are required: `11.11`, `12.0`, `12.1`, `12.10`, `13.0` and `13.1`, then `13.2.10`. | -| `12.10.14` | `11.3.4` | `11.3.4` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` | Three intermediate versions are required: `11.11`, `12.0` and `12.1`, then `12.10.14`. | -| `12.9.5` | `10.4.5` | `10.4.5` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.9.5` | Four intermediate versions are required: `10.8`, `11.11`, `12.0` and `12.1`, then `12.9.5`. | -| `12.2.5` | `9.2.6` | `9.2.6` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.2.5` | Five intermediate versions are required: `9.5`, `10.8`, `11.11`, `12.0`, `12.1`, then `12.2.5`. | -| `11.3.4` | `8.13.4` | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version 8, `9.5.10` is the last version in version 9, `10.8.7` is the last version in version 10. | +| Target version | Your version | Supported upgrade path | Note | +| -------------- | ------------ | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| `14.1.2` | `13.9.2` | `13.9.2` -> `13.12.9` -> `14.0.7` -> `14.1.2` | Two intermediate versions are required: `13.12` and `14.0`, then `14.1`. | +| `13.5.4` | `12.9.2` | `12.9.2` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> `13.5.4` | Three intermediate versions are required: `12.10`, `13.0` and `13.1`, then `13.5.4`. | +| `13.2.10` | `11.5.0` | `11.5.0` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> `13.2.10` | Six intermediate versions are required: `11.11`, `12.0`, `12.1`, `12.10`, `13.0` and `13.1`, then `13.2.10`. | +| `12.10.14` | `11.3.4` | `11.3.4` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` | Three intermediate versions are required: `11.11`, `12.0` and `12.1`, then `12.10.14`. | +| `12.9.5` | `10.4.5` | `10.4.5` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.9.5` | Four intermediate versions are required: `10.8`, `11.11`, `12.0` and `12.1`, then `12.9.5`. | +| `12.2.5` | `9.2.6` | `9.2.6` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.2.5` | Five intermediate versions are required: `9.5`, `10.8`, `11.11`, `12.0`, `12.1`, then `12.2.5`. | +| `11.3.4` | `8.13.4` | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version 8, `9.5.10` is the last version in version 9, `10.8.7` is the last version in version 10. | ## Upgrading to a new major version @@ -222,7 +222,7 @@ cannot guarantee that upgrading between major versions will be seamless. It is required to follow the following upgrade steps to ensure a successful *major* version upgrade: -1. Upgrade to the latest minor version of the preceeding major version. +1. Upgrade to the latest minor version of the preceding major version. 1. Upgrade to the first minor version (`X.0.Z`) of the target major version. 1. Proceed with upgrading to a newer release. @@ -379,7 +379,7 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap - Due to an issue where `BatchedBackgroundMigrationWorkers` were [not working](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/2785#note_614738345) for self-managed instances, a [fix was created](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65106) - and a [14.0.Z](#1400) version was released. If you haven't udpated to 14.0.Z, you need + and a [14.0.Z](#1400) version was released. If you haven't updated to 14.0.Z, you need to update to at least 14.1.0 that contains the same fix before you update to a later version. diff --git a/doc/user/permissions.md b/doc/user/permissions.md index ca4bb58fd05..f61131a15d4 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -301,7 +301,7 @@ The following table lists group permissions available for each role: | Create/edit/delete iterations | | | ✓ | ✓ | ✓ | | Create/edit/delete metrics dashboard annotations | | | ✓ | ✓ | ✓ | | Enable/disable a dependency proxy | | | ✓ | ✓ | ✓ | -| Pull a container image using the dependency proxy | | ✓ | ✓ | ✓ | ✓ | +| Pull a container image using the dependency proxy | ✓ | ✓ | ✓ | ✓ | ✓ | | Purge the dependency proxy for a group | | | | | ✓ | | Publish [packages](packages/index.md) | | | ✓ | ✓ | ✓ | | Use security dashboard **(ULTIMATE)** | | | ✓ | ✓ | ✓ | diff --git a/lib/gitlab/setup_helper.rb b/lib/gitlab/setup_helper.rb index c4b5ca58ff0..751405f1045 100644 --- a/lib/gitlab/setup_helper.rb +++ b/lib/gitlab/setup_helper.rb @@ -21,7 +21,7 @@ module Gitlab end rescue Errno::EEXIST puts 'Skipping config.toml generation:' - puts 'A configuration file already exists.' + puts "A configuration file for #{config_path} already exists." rescue ArgumentError => e puts 'Skipping config.toml generation:' puts e.message diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 17fe81abd71..c7cea4daae8 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -6497,6 +6497,9 @@ msgstr "" msgid "Checkout|%{totalCiMinutes} CI minutes" msgstr "" +msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})" +msgstr "" + msgid "Checkout|(x%{numberOfUsers})" msgstr "" diff --git a/package.json b/package.json index dca2e2add59..55e55088bfa 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "@gitlab/favicon-overlay": "2.0.0", "@gitlab/svgs": "1.209.0", "@gitlab/tributejs": "1.0.0", - "@gitlab/ui": "32.0.0", + "@gitlab/ui": "32.1.0", "@gitlab/visual-review-tools": "1.6.1", "@rails/actioncable": "6.1.3-2", "@rails/ujs": "6.1.3-2", diff --git a/qa/Gemfile b/qa/Gemfile index aef75b16089..f025e66fbe3 100644 --- a/qa/Gemfile +++ b/qa/Gemfile @@ -8,7 +8,7 @@ gem 'allure-rspec', '~> 2.14.1' gem 'capybara', '~> 3.35.0' gem 'capybara-screenshot', '~> 1.0.23' gem 'rake', '~> 12.3.3' -gem 'rspec', '~> 3.7' +gem 'rspec', '~> 3.10' gem 'selenium-webdriver', '~> 4.0.0.beta4' gem 'airborne', '~> 0.3.4' gem 'rest-client', '~> 2.1.0' @@ -28,6 +28,8 @@ gem 'webdrivers', '~> 4.6' gem 'chemlab', '~> 0.7' gem 'chemlab-library-www-gitlab-com', '~> 0.1' +gem 'deprecation_toolkit', '~> 1.5.1', require: false + group :development do gem 'pry-byebug', '~> 3.5.1', platform: :mri gem "ruby-debug-ide", "~> 0.7.0" diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock index ca6f7da1cc1..dfa7a49f2ef 100644 --- a/qa/Gemfile.lock +++ b/qa/Gemfile.lock @@ -56,6 +56,8 @@ GEM adamantium (~> 0.2.0) equalizer (~> 0.0.9) concurrent-ruby (1.1.9) + deprecation_toolkit (1.5.1) + activesupport (>= 4.2) diff-lcs (1.3) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) @@ -141,18 +143,18 @@ GEM netrc (~> 0.8) rexml (3.2.5) rotp (3.1.0) - rspec (3.9.0) - rspec-core (~> 3.9.0) - rspec-expectations (~> 3.9.0) - rspec-mocks (~> 3.9.0) - rspec-core (3.9.3) - rspec-support (~> 3.9.3) - rspec-expectations (3.9.1) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-mocks (3.9.1) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) + rspec-support (~> 3.10.0) rspec-parameterized (0.4.2) binding_ninja (>= 0.2.3) parser @@ -161,7 +163,7 @@ GEM unparser rspec-retry (0.6.1) rspec-core (> 3.3) - rspec-support (3.9.4) + rspec-support (3.10.2) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) ruby-debug-ide (0.7.2) @@ -215,6 +217,7 @@ DEPENDENCIES capybara-screenshot (~> 1.0.23) chemlab (~> 0.7) chemlab-library-www-gitlab-com (~> 0.1) + deprecation_toolkit (~> 1.5.1) faker (~> 1.6, >= 1.6.6) gitlab-qa knapsack (~> 1.17) @@ -226,7 +229,7 @@ DEPENDENCIES rake (~> 12.3.3) rest-client (~> 2.1.0) rotp (~> 3.1.0) - rspec (~> 3.7) + rspec (~> 3.10) rspec-parameterized (~> 0.4.2) rspec-retry (~> 0.6.1) rspec_junit_formatter (~> 0.4.1) diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb index 9ed9cb1634d..8aba1356fd0 100644 --- a/qa/qa/page/base.rb +++ b/qa/qa/page/base.rb @@ -108,7 +108,7 @@ module QA wait_for_requests(skip_finished_loading_check: skip_finished_loading_check) element_selector = element_selector_css(name, reject_capybara_query_keywords(kwargs)) - find(element_selector, only_capybara_query_keywords(kwargs)) + find(element_selector, **only_capybara_query_keywords(kwargs)) end def only_capybara_query_keywords(kwargs) diff --git a/qa/qa/runtime/application_settings.rb b/qa/qa/runtime/application_settings.rb index 428ed20c83f..0b2aef47576 100644 --- a/qa/qa/runtime/application_settings.rb +++ b/qa/qa/runtime/application_settings.rb @@ -26,7 +26,7 @@ module QA end def restore_application_settings(*application_settings_keys) - set_application_settings(@original_application_settings.slice(*application_settings_keys)) + set_application_settings(**@original_application_settings.slice(*application_settings_keys)) end private diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb index 3844c54f4db..9097690de57 100644 --- a/qa/qa/runtime/browser.rb +++ b/qa/qa/runtime/browser.rb @@ -148,7 +148,7 @@ module QA Capybara::Selenium::Driver.new( app, - selenium_options + **selenium_options ) end diff --git a/qa/qa/runtime/feature.rb b/qa/qa/runtime/feature.rb index dd7f9cf898c..7011f46542b 100644 --- a/qa/qa/runtime/feature.rb +++ b/qa/qa/runtime/feature.rb @@ -32,7 +32,7 @@ module QA def enabled?(key, **scopes) feature = JSON.parse(get_features).find { |flag| flag['name'] == key.to_s } - feature && (feature['state'] == 'on' || feature['state'] == 'conditional' && scopes.present? && enabled_scope?(feature['gates'], scopes)) + feature && (feature['state'] == 'on' || feature['state'] == 'conditional' && scopes.present? && enabled_scope?(feature['gates'], **scopes)) end private @@ -43,7 +43,7 @@ module QA raise AuthorizationError, "Administrator access is required to enable/disable feature flags. #{e.message}" end - def enabled_scope?(gates, scopes) + def enabled_scope?(gates, **scopes) scopes.each do |key, value| case key when :project, :group, :user @@ -71,16 +71,16 @@ module QA # scopes: Any scope (user, project, group) to restrict the change to def set_and_verify(key, enable:, **scopes) msg = "#{enable ? 'En' : 'Dis'}abling feature: #{key}" - msg += " for scope \"#{scopes_to_s(scopes)}\"" if scopes.present? + msg += " for scope \"#{scopes_to_s(**scopes)}\"" if scopes.present? QA::Runtime::Logger.info(msg) Support::Retrier.retry_on_exception(sleep_interval: 2) do - set_feature(key, enable, scopes) + set_feature(key, enable, **scopes) is_enabled = nil QA::Support::Waiter.wait_until(sleep_interval: 1) do - is_enabled = enabled?(key, scopes) + is_enabled = enabled?(key, **scopes) is_enabled == enable || !enable && scopes.present? end diff --git a/qa/spec/qa_deprecation_toolkit_env.rb b/qa/spec/qa_deprecation_toolkit_env.rb new file mode 100644 index 00000000000..cdd5d954b20 --- /dev/null +++ b/qa/spec/qa_deprecation_toolkit_env.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'deprecation_toolkit' +require 'deprecation_toolkit/rspec' +require 'concurrent/utility/monotonic_time' +require 'active_support/gem_version' + +module QaDeprecationToolkitEnv + # Taken from https://github.com/jeremyevans/ruby-warning/blob/1.1.0/lib/warning.rb#L18 + def self.kwargs_warning + %r{warning: (?:Using the last argument (?:for `.+' )?as keyword parameters is deprecated; maybe \*\* should be added to the call|Passing the keyword argument (?:for `.+' )?as the last hash parameter is deprecated|Splitting the last argument (?:for `.+' )?into positional and keyword parameters is deprecated|The called method (?:`.+' )?is defined here)\n\z} + end + + def self.configure! + # Enable ruby deprecations for keywords, it's suppressed by default in Ruby 2.7.2 + Warning[:deprecated] = true + + DeprecationToolkit::Configuration.test_runner = :rspec + DeprecationToolkit::Configuration.deprecation_path = 'deprecations' + DeprecationToolkit::Configuration.warnings_treated_as_deprecation = [kwargs_warning] + end +end diff --git a/qa/spec/runtime/api/request_spec.rb b/qa/spec/runtime/api/request_spec.rb index 93de2f4a87e..a1de71d31f0 100644 --- a/qa/spec/runtime/api/request_spec.rb +++ b/qa/spec/runtime/api/request_spec.rb @@ -14,7 +14,7 @@ RSpec.describe QA::Runtime::API::Request do end context 'when oauth_access_token is passed in the query string' do - let(:request) { described_class.new(client, '/users', { oauth_access_token: 'foo' }) } + let(:request) { described_class.new(client, '/users', oauth_access_token: 'foo') } it 'does not adds a private_token query string' do expect(request.url).to eq 'http://example.com/api/v4/users?oauth_access_token=foo' diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb index f4bfd57504e..c4da85d75b0 100644 --- a/qa/spec/spec_helper.rb +++ b/qa/spec/spec_helper.rb @@ -6,6 +6,9 @@ require 'rspec-parameterized' require 'active_support/core_ext/hash' require 'active_support/core_ext/object/blank' +require_relative 'qa_deprecation_toolkit_env' +QaDeprecationToolkitEnv.configure! + if ENV['CI'] && QA::Runtime::Env.knapsack? && !ENV['NO_KNAPSACK'] require 'knapsack' Knapsack::Adapters::RSpecAdapter.bind diff --git a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb index 00c3472bf55..dc25d75ee54 100644 --- a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb +++ b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb @@ -185,7 +185,7 @@ RSpec.describe Groups::DependencyProxyForContainersController do end before do - group.add_reporter(user) + group.add_guest(user) end it 'proxies status from the remote token request', :aggregate_failures do @@ -206,7 +206,7 @@ RSpec.describe Groups::DependencyProxyForContainersController do end before do - group.add_reporter(user) + group.add_guest(user) end it 'proxies status from the remote manifest request', :aggregate_failures do @@ -219,7 +219,7 @@ RSpec.describe Groups::DependencyProxyForContainersController do context 'a valid user' do before do - group.add_reporter(user) + group.add_guest(user) end it_behaves_like 'a successful manifest pull' @@ -308,7 +308,7 @@ RSpec.describe Groups::DependencyProxyForContainersController do end before do - group.add_reporter(user) + group.add_guest(user) end it 'proxies status from the remote blob request', :aggregate_failures do @@ -321,7 +321,7 @@ RSpec.describe Groups::DependencyProxyForContainersController do context 'a valid user' do before do - group.add_reporter(user) + group.add_guest(user) end it_behaves_like 'a successful blob pull' diff --git a/spec/frontend/diffs/utils/queue_events_spec.js b/spec/frontend/diffs/utils/queue_events_spec.js new file mode 100644 index 00000000000..007748d8b2c --- /dev/null +++ b/spec/frontend/diffs/utils/queue_events_spec.js @@ -0,0 +1,36 @@ +import api from '~/api'; +import { DEFER_DURATION } from '~/diffs/constants'; +import { queueRedisHllEvents } from '~/diffs/utils/queue_events'; + +jest.mock('~/api', () => ({ + trackRedisHllUserEvent: jest.fn(), +})); + +describe('diffs events queue', () => { + describe('queueRedisHllEvents', () => { + it('does not dispatch the event immediately', () => { + queueRedisHllEvents(['know_event']); + expect(api.trackRedisHllUserEvent).not.toHaveBeenCalled(); + }); + + it('does dispatch the event after the defer duration', () => { + queueRedisHllEvents(['know_event']); + jest.advanceTimersByTime(DEFER_DURATION + 1); + expect(api.trackRedisHllUserEvent).toHaveBeenCalled(); + }); + + it('increase defer duration based on the provided events count', () => { + let deferDuration = DEFER_DURATION + 1; + const events = ['know_event_a', 'know_event_b', 'know_event_c']; + queueRedisHllEvents(events); + + expect(api.trackRedisHllUserEvent).not.toHaveBeenCalled(); + + events.forEach((event, index) => { + jest.advanceTimersByTime(deferDuration); + expect(api.trackRedisHllUserEvent).toHaveBeenLastCalledWith(event); + deferDuration *= index + 1; + }); + }); + }); +}); diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/app_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/app_spec.js index d6214402fcc..f147bd67e39 100644 --- a/spec/frontend/packages_and_registries/package_registry/components/details/app_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/components/details/app_spec.js @@ -1,7 +1,9 @@ -import { GlEmptyState } from '@gitlab/ui'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { GlEmptyState, GlModal } from '@gitlab/ui'; +import { createLocalVue } from '@vue/test-utils'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; +import { useMockLocationHelper } from 'helpers/mock_window_location_helper'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import createFlash from '~/flash'; @@ -10,11 +12,22 @@ import PackagesApp from '~/packages_and_registries/package_registry/components/d import InstallationCommands from '~/packages_and_registries/package_registry/components/details/installation_commands.vue'; import PackageHistory from '~/packages_and_registries/package_registry/components/details/package_history.vue'; import PackageTitle from '~/packages_and_registries/package_registry/components/details/package_title.vue'; -import { FETCH_PACKAGE_DETAILS_ERROR_MESSAGE } from '~/packages_and_registries/package_registry/constants'; +import { + FETCH_PACKAGE_DETAILS_ERROR_MESSAGE, + DELETE_PACKAGE_ERROR_MESSAGE, +} from '~/packages_and_registries/package_registry/constants'; +import destroyPackageMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package.mutation.graphql'; import getPackageDetails from '~/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql'; -import { packageDetailsQuery, packageData, emptyPackageDetailsQuery } from '../../mock_data'; +import { + packageDetailsQuery, + packageData, + emptyPackageDetailsQuery, + packageDestroyMutation, + packageDestroyMutationError, +} from '../../mock_data'; jest.mock('~/flash'); +useMockLocationHelper(); const localVue = createLocalVue(); @@ -34,16 +47,23 @@ describe('PackagesApp', () => { groupListUrl: 'groupListUrl', }; - function createComponent({ resolver = jest.fn().mockResolvedValue(packageDetailsQuery()) } = {}) { + function createComponent({ + resolver = jest.fn().mockResolvedValue(packageDetailsQuery()), + mutationResolver = jest.fn().mockResolvedValue(packageDestroyMutation()), + } = {}) { localVue.use(VueApollo); - const requestHandlers = [[getPackageDetails, resolver]]; + const requestHandlers = [ + [getPackageDetails, resolver], + [destroyPackageMutation, mutationResolver], + ]; apolloProvider = createMockApollo(requestHandlers); - wrapper = shallowMount(PackagesApp, { + wrapper = shallowMountExtended(PackagesApp, { localVue, apolloProvider, provide, + stubs: { PackageTitle }, }); } @@ -52,6 +72,8 @@ describe('PackagesApp', () => { const findPackageHistory = () => wrapper.findComponent(PackageHistory); const findAdditionalMetadata = () => wrapper.findComponent(AdditionalMetadata); const findInstallationCommands = () => wrapper.findComponent(InstallationCommands); + const findDeleteModal = () => wrapper.findComponent(GlModal); + const findDeleteButton = () => wrapper.findByTestId('delete-package'); afterEach(() => { wrapper.destroy(); @@ -121,4 +143,101 @@ describe('PackagesApp', () => { packageEntity: expect.objectContaining(packageData()), }); }); + + describe('delete package', () => { + const originalReferrer = document.referrer; + const setReferrer = (value = provide.projectName) => { + Object.defineProperty(document, 'referrer', { + value, + configurable: true, + }); + }; + + const performDeletePackage = async () => { + await findDeleteButton().trigger('click'); + + findDeleteModal().vm.$emit('primary'); + + await waitForPromises(); + }; + + afterEach(() => { + Object.defineProperty(document, 'referrer', { + value: originalReferrer, + configurable: true, + }); + }); + + it('shows the delete confirmation modal when delete is clicked', async () => { + createComponent(); + + await waitForPromises(); + + await findDeleteButton().trigger('click'); + + expect(findDeleteModal().exists()).toBe(true); + }); + + describe('successful request', () => { + it('when referrer contains project name calls window.replace with project url', async () => { + setReferrer(); + + createComponent(); + + await waitForPromises(); + + await performDeletePackage(); + + expect(window.location.replace).toHaveBeenCalledWith( + 'projectListUrl?showSuccessDeleteAlert=true', + ); + }); + + it('when referrer does not contain project name calls window.replace with group url', async () => { + setReferrer('baz'); + + createComponent(); + + await waitForPromises(); + + await performDeletePackage(); + + expect(window.location.replace).toHaveBeenCalledWith( + 'groupListUrl?showSuccessDeleteAlert=true', + ); + }); + }); + + describe('request failure', () => { + it('on global failure it displays an alert', async () => { + createComponent({ mutationResolver: jest.fn().mockRejectedValue() }); + + await waitForPromises(); + + await performDeletePackage(); + + expect(createFlash).toHaveBeenCalledWith( + expect.objectContaining({ + message: DELETE_PACKAGE_ERROR_MESSAGE, + }), + ); + }); + + it('on payload with error it displays an alert', async () => { + createComponent({ + mutationResolver: jest.fn().mockResolvedValue(packageDestroyMutationError()), + }); + + await waitForPromises(); + + await performDeletePackage(); + + expect(createFlash).toHaveBeenCalledWith( + expect.objectContaining({ + message: DELETE_PACKAGE_ERROR_MESSAGE, + }), + ); + }); + }); + }); }); diff --git a/spec/frontend/packages_and_registries/package_registry/mock_data.js b/spec/frontend/packages_and_registries/package_registry/mock_data.js index d1b81aa8b5f..110cb5a3798 100644 --- a/spec/frontend/packages_and_registries/package_registry/mock_data.js +++ b/spec/frontend/packages_and_registries/package_registry/mock_data.js @@ -125,3 +125,29 @@ export const emptyPackageDetailsQuery = () => ({ }, }, }); + +export const packageDestroyMutation = () => ({ + data: { + destroyPackage: { + errors: [], + }, + }, +}); +export const packageDestroyMutationError = () => ({ + data: { + destroyPackage: null, + }, + errors: [ + { + message: + "The resource that you are attempting to access does not exist or you don't have permission to perform this action", + locations: [ + { + line: 2, + column: 3, + }, + ], + path: ['destroyPackage'], + }, + ], +}); diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb index eca0716f484..aa5fcf222f2 100644 --- a/spec/support/helpers/test_env.rb +++ b/spec/support/helpers/test_env.rb @@ -265,7 +265,7 @@ module TestEnv def setup_workhorse # Always rebuild the config file if skip_compile_workhorse? - Gitlab::SetupHelper::Workhorse.create_configuration(workhorse_dir, nil) + Gitlab::SetupHelper::Workhorse.create_configuration(workhorse_dir, nil, force: true) return end diff --git a/yarn.lock b/yarn.lock index 158d46b1679..92fdeeb3767 100644 --- a/yarn.lock +++ b/yarn.lock @@ -908,10 +908,10 @@ resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8" integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw== -"@gitlab/ui@32.0.0": - version "32.0.0" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.0.0.tgz#2bf8995e405f35c5fa9dcc2ad0de24d79dc9c006" - integrity sha512-GVQVx8Db9fb/BfYf7Vzdf6MxqLsF5RZta0VanwTm/asGdQxWG7I9fJIPUHqhCK3S9efZ83zXfZBF0M3uHuxveg== +"@gitlab/ui@32.1.0": + version "32.1.0" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.1.0.tgz#3b7a4b4d68a726f2e6a2d87db03cb604e4841398" + integrity sha512-FtNWIOE00lCLXAPrRpFTOoFDD6mvDiCB8qr03NQsvFSbEuwfkvxhElaKNeKy+w0HeM8S8Tt2JqSyz9UjprgFUQ== dependencies: "@babel/standalone" "^7.0.0" bootstrap-vue "2.18.1"