Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
65688a5092
commit
53af44b90f
|
@ -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() {
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
});
|
||||
}
|
|
@ -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 {
|
|||
<gl-button
|
||||
v-if="canDelete"
|
||||
v-gl-modal="'delete-modal'"
|
||||
class="js-delete-button"
|
||||
variant="danger"
|
||||
category="primary"
|
||||
data-qa-selector="delete_button"
|
||||
data-testid="delete-package"
|
||||
>
|
||||
{{ __('Delete') }}
|
||||
</gl-button>
|
||||
|
@ -303,7 +328,6 @@ export default {
|
|||
|
||||
<gl-modal
|
||||
ref="deleteModal"
|
||||
class="js-delete-modal"
|
||||
modal-id="delete-modal"
|
||||
:action-primary="$options.modal.packageDeletePrimaryAction"
|
||||
:action-cancel="$options.modal.cancelAction"
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
mutation destroyPackage($id: PackagesPackageID!) {
|
||||
destroyPackage(input: { id: $id }) {
|
||||
errors
|
||||
}
|
||||
}
|
|
@ -52,7 +52,7 @@ class GroupPolicy < BasePolicy
|
|||
|
||||
condition(:dependency_proxy_access_allowed) do
|
||||
if Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: true)
|
||||
access_level >= GroupMember::REPORTER || valid_dependency_proxy_deploy_token
|
||||
access_level >= GroupMember::GUEST || valid_dependency_proxy_deploy_token
|
||||
else
|
||||
can?(:read_group)
|
||||
end
|
||||
|
|
|
@ -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**.
|
||||
|
||||
|
|
|
@ -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).
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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)** | | | ✓ | ✓ | ✓ |
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ""
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -148,7 +148,7 @@ module QA
|
|||
|
||||
Capybara::Selenium::Driver.new(
|
||||
app,
|
||||
selenium_options
|
||||
**selenium_options
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue