Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
3563f19374
commit
c1436508fa
|
@ -2558,7 +2558,6 @@ Style/OpenStructUse:
|
|||
- 'ee/spec/graphql/ee/resolvers/board_lists_resolver_spec.rb'
|
||||
- 'ee/spec/graphql/mutations/merge_requests/accept_spec.rb'
|
||||
- 'ee/spec/graphql/resolvers/board_groupings/epics_resolvers_spec.rb'
|
||||
- 'ee/spec/helpers/billing_plans_helper_spec.rb'
|
||||
- 'ee/spec/helpers/ee/blob_helper_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/auth/group_saml/failure_handler_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb'
|
||||
|
|
|
@ -17,4 +17,7 @@ export default CodeBlockHighlight.extend({
|
|||
addNodeView() {
|
||||
return new VueNodeViewRenderer(FrontmatterWrapper);
|
||||
},
|
||||
addInputRules() {
|
||||
return [];
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
<script>
|
||||
import { mapState, mapActions } from 'vuex';
|
||||
import { s__ } from '~/locale';
|
||||
import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
|
||||
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
|
||||
import UrlSync from '~/vue_shared/components/url_sync.vue';
|
||||
import { sortableFields } from '../utils';
|
||||
import PackageTypeToken from './tokens/package_type_token.vue';
|
||||
|
||||
export default {
|
||||
tokens: [
|
||||
{
|
||||
type: 'type',
|
||||
icon: 'package',
|
||||
title: s__('PackageRegistry|Type'),
|
||||
unique: true,
|
||||
token: PackageTypeToken,
|
||||
operators: OPERATOR_IS_ONLY,
|
||||
},
|
||||
],
|
||||
components: { RegistrySearch, UrlSync },
|
||||
computed: {
|
||||
...mapState({
|
||||
isGroupPage: (state) => state.config.isGroupPage,
|
||||
sorting: (state) => state.sorting,
|
||||
filter: (state) => state.filter,
|
||||
}),
|
||||
sortableFields() {
|
||||
return sortableFields(this.isGroupPage);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['setSorting', 'setFilter']),
|
||||
updateSorting(newValue) {
|
||||
this.setSorting(newValue);
|
||||
this.$emit('update');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<url-sync>
|
||||
<template #default="{ updateQuery }">
|
||||
<registry-search
|
||||
:filter="filter"
|
||||
:sorting="sorting"
|
||||
:tokens="$options.tokens"
|
||||
:sortable-fields="sortableFields"
|
||||
@sorting:changed="updateSorting"
|
||||
@filter:changed="setFilter"
|
||||
@filter:submit="$emit('update')"
|
||||
@query:changed="updateQuery"
|
||||
/>
|
||||
</template>
|
||||
</url-sync>
|
||||
</template>
|
|
@ -1,47 +0,0 @@
|
|||
<script>
|
||||
import { n__ } from '~/locale';
|
||||
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
|
||||
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
|
||||
import { LIST_INTRO_TEXT, LIST_TITLE_TEXT } from '../constants';
|
||||
|
||||
export default {
|
||||
name: 'PackageTitle',
|
||||
components: {
|
||||
TitleArea,
|
||||
MetadataItem,
|
||||
},
|
||||
props: {
|
||||
count: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
helpUrl: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
showPackageCount() {
|
||||
return Number.isInteger(this.count);
|
||||
},
|
||||
packageAmountText() {
|
||||
return n__(`%d Package`, `%d Packages`, this.count);
|
||||
},
|
||||
infoMessages() {
|
||||
return [{ text: LIST_INTRO_TEXT, link: this.helpUrl }];
|
||||
},
|
||||
},
|
||||
i18n: {
|
||||
LIST_TITLE_TEXT,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<title-area :title="$options.i18n.LIST_TITLE_TEXT" :info-messages="infoMessages">
|
||||
<template #metadata-amount>
|
||||
<metadata-item v-if="showPackageCount" icon="package" :text="packageAmountText" />
|
||||
</template>
|
||||
</title-area>
|
||||
</template>
|
|
@ -7,6 +7,8 @@ import { s__ } from '~/locale';
|
|||
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
|
||||
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
|
||||
import { getQueryParams, extractFilterAndSorting } from '~/packages_and_registries/shared/utils';
|
||||
import InfrastructureTitle from '~/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue';
|
||||
import InfrastructureSearch from '~/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue';
|
||||
import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '../constants';
|
||||
import PackageList from './packages_list.vue';
|
||||
|
||||
|
@ -16,28 +18,10 @@ export default {
|
|||
GlLink,
|
||||
GlSprintf,
|
||||
PackageList,
|
||||
PackageTitle: () =>
|
||||
import(/* webpackChunkName: 'package_registry_components' */ './package_title.vue'),
|
||||
PackageSearch: () =>
|
||||
import(/* webpackChunkName: 'package_registry_components' */ './package_search.vue'),
|
||||
InfrastructureTitle: () =>
|
||||
import(
|
||||
/* webpackChunkName: 'infrastructure_registry_components' */ '~/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue'
|
||||
),
|
||||
InfrastructureSearch: () =>
|
||||
import(
|
||||
/* webpackChunkName: 'infrastructure_registry_components' */ '~/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue'
|
||||
),
|
||||
InfrastructureTitle,
|
||||
InfrastructureSearch,
|
||||
},
|
||||
inject: {
|
||||
titleComponent: {
|
||||
from: 'titleComponent',
|
||||
default: 'PackageTitle',
|
||||
},
|
||||
searchComponent: {
|
||||
from: 'searchComponent',
|
||||
default: 'PackageSearch',
|
||||
},
|
||||
emptyPageTitle: {
|
||||
from: 'emptyPageTitle',
|
||||
default: s__('PackageRegistry|There are no packages yet'),
|
||||
|
@ -111,8 +95,8 @@ export default {
|
|||
|
||||
<template>
|
||||
<div>
|
||||
<component :is="titleComponent" :help-url="packageHelpUrl" :count="packagesCount" />
|
||||
<component :is="searchComponent" @update="requestPackagesList" />
|
||||
<infrastructure-title :help-url="packageHelpUrl" :count="packagesCount" />
|
||||
<infrastructure-search @update="requestPackagesList" />
|
||||
|
||||
<package-list @page:changed="onPageChanged" @package:delete="onPackageDeleteRequest">
|
||||
<template #empty-state>
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
<script>
|
||||
import { GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitlab/ui';
|
||||
import { PACKAGE_TYPES } from '../../constants';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlFilteredSearchToken,
|
||||
GlFilteredSearchSuggestion,
|
||||
},
|
||||
PACKAGE_TYPES,
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<gl-filtered-search-token v-bind="{ ...$attrs }" v-on="$listeners">
|
||||
<template #suggestions>
|
||||
<gl-filtered-search-suggestion
|
||||
v-for="(type, index) in $options.PACKAGE_TYPES"
|
||||
:key="index"
|
||||
:value="type.type"
|
||||
>
|
||||
{{ type.title }}
|
||||
</gl-filtered-search-suggestion>
|
||||
</template>
|
||||
</gl-filtered-search-token>
|
||||
</template>
|
|
@ -96,10 +96,4 @@ export const PACKAGE_TYPES = [
|
|||
},
|
||||
];
|
||||
|
||||
export const LIST_TITLE_TEXT = s__('PackageRegistry|Package Registry');
|
||||
|
||||
export const LIST_INTRO_TEXT = s__(
|
||||
'PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}',
|
||||
);
|
||||
|
||||
export const TERRAFORM_SEARCH_TYPE = Object.freeze({ value: { data: 'terraform_module' } });
|
||||
|
|
|
@ -3,6 +3,8 @@ import destroyPackageMutation from '~/packages_and_registries/package_registry/g
|
|||
import createFlash from '~/flash';
|
||||
import { s__ } from '~/locale';
|
||||
|
||||
import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages_and_registries/package_registry/constants';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
refetchQueries: {
|
||||
|
@ -18,7 +20,7 @@ export default {
|
|||
},
|
||||
i18n: {
|
||||
errorMessage: s__('PackageRegistry|Something went wrong while deleting the package.'),
|
||||
successMessage: s__('PackageRegistry|Package deleted successfully'),
|
||||
successMessage: DELETE_PACKAGE_SUCCESS_MESSAGE,
|
||||
},
|
||||
methods: {
|
||||
async deletePackage(packageEntity) {
|
||||
|
|
|
@ -3,12 +3,12 @@ import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
|
|||
import createFlash from '~/flash';
|
||||
import { historyReplaceState } from '~/lib/utils/common_utils';
|
||||
import { s__ } from '~/locale';
|
||||
import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages/list/constants';
|
||||
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
|
||||
import {
|
||||
PROJECT_RESOURCE_TYPE,
|
||||
GROUP_RESOURCE_TYPE,
|
||||
GRAPHQL_PAGE_SIZE,
|
||||
DELETE_PACKAGE_SUCCESS_MESSAGE,
|
||||
} from '~/packages_and_registries/package_registry/constants';
|
||||
import getPackagesQuery from '~/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql';
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { s__ } from '~/locale';
|
||||
import { sortableFields } from '~/packages/list/utils';
|
||||
import { sortableFields } from '~/packages_and_registries/package_registry/utils';
|
||||
import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
|
||||
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
|
||||
import UrlSync from '~/vue_shared/components/url_sync.vue';
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<script>
|
||||
import { n__ } from '~/locale';
|
||||
import { LIST_INTRO_TEXT, LIST_TITLE_TEXT } from '~/packages/list/constants';
|
||||
import { n__, s__ } from '~/locale';
|
||||
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
|
||||
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
|
||||
|
||||
|
@ -29,11 +28,14 @@ export default {
|
|||
return n__(`%d Package`, `%d Packages`, this.count);
|
||||
},
|
||||
infoMessages() {
|
||||
return [{ text: LIST_INTRO_TEXT, link: this.helpUrl }];
|
||||
return [{ text: this.$options.i18n.LIST_INTRO_TEXT, link: this.helpUrl }];
|
||||
},
|
||||
},
|
||||
i18n: {
|
||||
LIST_TITLE_TEXT,
|
||||
LIST_TITLE_TEXT: s__('PackageRegistry|Package Registry'),
|
||||
LIST_INTRO_TEXT: s__(
|
||||
'PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}',
|
||||
),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitlab/ui';
|
||||
import { PACKAGE_TYPES } from '~/packages/list/constants';
|
||||
import { PACKAGE_TYPES } from '~/packages_and_registries/package_registry/constants';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -17,9 +17,9 @@ export default {
|
|||
<gl-filtered-search-suggestion
|
||||
v-for="(type, index) in $options.PACKAGE_TYPES"
|
||||
:key="index"
|
||||
:value="type.type"
|
||||
:value="type"
|
||||
>
|
||||
{{ type.title }}
|
||||
{{ type }}
|
||||
</gl-filtered-search-suggestion>
|
||||
</template>
|
||||
</gl-filtered-search-token>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { s__ } from '~/locale';
|
||||
import { s__, __ } from '~/locale';
|
||||
|
||||
export const PACKAGE_TYPE_CONAN = 'CONAN';
|
||||
export const PACKAGE_TYPE_MAVEN = 'MAVEN';
|
||||
|
@ -70,6 +70,8 @@ export const FETCH_PACKAGE_DETAILS_ERROR_MESSAGE = s__(
|
|||
'PackageRegistry|Failed to load the package data',
|
||||
);
|
||||
|
||||
export const DELETE_PACKAGE_SUCCESS_MESSAGE = s__('PackageRegistry|Package deleted successfully');
|
||||
|
||||
export const PACKAGE_ERROR_STATUS = 'ERROR';
|
||||
export const PACKAGE_DEFAULT_STATUS = 'DEFAULT';
|
||||
export const PACKAGE_HIDDEN_STATUS = 'HIDDEN';
|
||||
|
@ -84,3 +86,51 @@ export const INSTANCE_PACKAGE_ENDPOINT_TYPE = 'instance';
|
|||
export const PROJECT_RESOURCE_TYPE = 'project';
|
||||
export const GROUP_RESOURCE_TYPE = 'group';
|
||||
export const GRAPHQL_PAGE_SIZE = 20;
|
||||
|
||||
export const LIST_KEY_NAME = 'name';
|
||||
export const LIST_KEY_PROJECT = 'project_path';
|
||||
export const LIST_KEY_VERSION = 'version';
|
||||
export const LIST_KEY_PACKAGE_TYPE = 'type';
|
||||
export const LIST_KEY_CREATED_AT = 'created_at';
|
||||
|
||||
export const LIST_LABEL_NAME = __('Name');
|
||||
export const LIST_LABEL_PROJECT = __('Project');
|
||||
export const LIST_LABEL_VERSION = __('Version');
|
||||
export const LIST_LABEL_PACKAGE_TYPE = __('Type');
|
||||
export const LIST_LABEL_CREATED_AT = __('Published');
|
||||
|
||||
export const SORT_FIELDS = [
|
||||
{
|
||||
orderBy: LIST_KEY_NAME,
|
||||
label: LIST_LABEL_NAME,
|
||||
},
|
||||
{
|
||||
orderBy: LIST_KEY_PROJECT,
|
||||
label: LIST_LABEL_PROJECT,
|
||||
},
|
||||
{
|
||||
orderBy: LIST_KEY_VERSION,
|
||||
label: LIST_LABEL_VERSION,
|
||||
},
|
||||
{
|
||||
orderBy: LIST_KEY_PACKAGE_TYPE,
|
||||
label: LIST_LABEL_PACKAGE_TYPE,
|
||||
},
|
||||
{
|
||||
orderBy: LIST_KEY_CREATED_AT,
|
||||
label: LIST_LABEL_CREATED_AT,
|
||||
},
|
||||
];
|
||||
|
||||
export const PACKAGE_TYPES = [
|
||||
s__('PackageRegistry|Composer'),
|
||||
s__('PackageRegistry|Conan'),
|
||||
s__('PackageRegistry|Generic'),
|
||||
s__('PackageRegistry|Maven'),
|
||||
s__('PackageRegistry|npm'),
|
||||
s__('PackageRegistry|NuGet'),
|
||||
s__('PackageRegistry|PyPI'),
|
||||
s__('PackageRegistry|RubyGems'),
|
||||
s__('PackageRegistry|Debian'),
|
||||
s__('PackageRegistry|Helm'),
|
||||
];
|
||||
|
|
|
@ -11,6 +11,8 @@ import {
|
|||
PACKAGE_TYPE_GENERIC,
|
||||
PACKAGE_TYPE_DEBIAN,
|
||||
PACKAGE_TYPE_HELM,
|
||||
LIST_KEY_PROJECT,
|
||||
SORT_FIELDS,
|
||||
} from './constants';
|
||||
|
||||
export const getPackageTypeLabel = (packageType) => {
|
||||
|
@ -41,3 +43,6 @@ export const getPackageTypeLabel = (packageType) => {
|
|||
};
|
||||
|
||||
export const packageTypeToTrackCategory = (type) => `UI::${capitalize(type)}Packages`;
|
||||
|
||||
export const sortableFields = (isGroupPage) =>
|
||||
SORT_FIELDS.filter((f) => f.orderBy !== LIST_KEY_PROJECT || isGroupPage);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import registryExplorer from '~/registry/explorer/index';
|
||||
import registryExplorer from '~/packages_and_registries/container_registry/explorer/index';
|
||||
|
||||
const explorer = registryExplorer();
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import registryExplorer from '~/registry/explorer/index';
|
||||
import registryExplorer from '~/packages_and_registries/container_registry/explorer/index';
|
||||
|
||||
const explorer = registryExplorer();
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@ import { OBSTACLE_TYPES } from './constants';
|
|||
|
||||
const OBSTACLE_TEXT = {
|
||||
[OBSTACLE_TYPES.oncallSchedules]: s__(
|
||||
'OnCallSchedules|On-call schedule %{obstacle} in Project %{project}',
|
||||
'OnCallSchedules|On-call schedule %{obstacle} in project %{project}',
|
||||
),
|
||||
[OBSTACLE_TYPES.escalationPolicies]: s__(
|
||||
'EscalationPolicies|Escalation policy %{obstacle} in Project %{project}',
|
||||
'EscalationPolicies|Escalation policy %{obstacle} in project %{project}',
|
||||
),
|
||||
};
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@ class EventsFinder
|
|||
events = by_created_at_after(events)
|
||||
events = sort(events)
|
||||
|
||||
events = events.with_associations if params[:with_associations]
|
||||
paginated_filtered_by_user_visibility(events)
|
||||
end
|
||||
|
||||
|
@ -113,10 +112,12 @@ class EventsFinder
|
|||
end
|
||||
|
||||
def paginated_filtered_by_user_visibility(events)
|
||||
events_count = events.count
|
||||
events = events.with_associations if params[:with_associations]
|
||||
limited_events = events.page(page).per(per_page)
|
||||
visible_events = limited_events.select { |event| event.visible_to_user?(current_user) }
|
||||
|
||||
Kaminari.paginate_array(visible_events, total_count: events.count)
|
||||
Kaminari.paginate_array(visible_events, total_count: events_count)
|
||||
end
|
||||
|
||||
def per_page
|
||||
|
|
|
@ -15,7 +15,13 @@ module MergeRequests
|
|||
|
||||
def execute
|
||||
end_position = position.line_range["end"]
|
||||
diff_line_index = diff_lines.find_index { |l| l.new_line == end_position["new_line"] || l.old_line == end_position["old_line"] }
|
||||
diff_line_index = diff_lines.find_index do |l|
|
||||
if end_position["new_line"]
|
||||
l.new_line == end_position["new_line"]
|
||||
elsif end_position["old_line"]
|
||||
l.old_line == end_position["old_line"]
|
||||
end
|
||||
end
|
||||
initial_line_index = [diff_line_index - OVERFLOW_LINES_COUNT, 0].max
|
||||
last_line_index = [diff_line_index + OVERFLOW_LINES_COUNT, diff_lines.length].min
|
||||
|
||||
|
|
|
@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344617
|
|||
milestone: '14.5'
|
||||
type: development
|
||||
group: group::integrations
|
||||
default_enabled: false
|
||||
default_enabled: true
|
||||
|
|
|
@ -41,9 +41,15 @@ swap:
|
|||
developer access: the Developer role
|
||||
developer permission: the Developer role
|
||||
developer permissions: the Developer role
|
||||
guest access: the Guest role
|
||||
guest permission: the Guest role
|
||||
guest permissions: the Guest role
|
||||
maintainer access: the Maintainer role
|
||||
maintainer permission: the Maintainer role
|
||||
maintainer permissions: the Maintainer role
|
||||
owner access: the Owner role
|
||||
owner permission: the Owner role
|
||||
owner permissions: the Owner role
|
||||
reporter access: the Reporter role
|
||||
reporter permission: the Reporter role
|
||||
reporter permissions: the Reporter role
|
||||
|
|
|
@ -10,7 +10,7 @@ type: reference, api
|
|||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in GitLab 13.10.
|
||||
> - The legacy key/value pair `{ "<date>" => "<value>" }` was removed from the payload in GitLab 14.0.
|
||||
|
||||
All methods require [reporter permissions and above](../../user/permissions.md).
|
||||
All methods require at least the Reporter [role](../../user/permissions.md).
|
||||
|
||||
## Get project-level DORA metrics
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ You can even access a [web terminal](#web-terminals-deprecated) for your environ
|
|||
|
||||
Prerequisites:
|
||||
|
||||
- You must have a minimum of [Reporter permission](../../user/permissions.md#project-members-permissions).
|
||||
- You must have at least the Reporter [role](../../user/permissions.md#project-members-permissions).
|
||||
|
||||
To view a list of environments and deployments:
|
||||
|
||||
|
|
|
@ -102,10 +102,9 @@ The group now has access and can be seen in the UI.
|
|||
|
||||
## Environment access by group membership
|
||||
|
||||
A user may be granted access to protected environments as part of
|
||||
[group membership](../../user/group/index.md). Users with
|
||||
[Reporter permissions](../../user/permissions.md), can only be granted access to
|
||||
protected environments with this method.
|
||||
A user may be granted access to protected environments as part of [group membership](../../user/group/index.md). Users
|
||||
with the Reporter [role](../../user/permissions.md) can only be granted access to protected environments with this
|
||||
method.
|
||||
|
||||
## Deployment branch access
|
||||
|
||||
|
@ -126,8 +125,8 @@ they have the following privileges:
|
|||
|
||||
Users granted access to a protected environment, but not push or merge access
|
||||
to the branch deployed to it, are only granted access to deploy the environment. An individual in a
|
||||
group with the Reporter permission, or in groups added to the project with Reporter permissions,
|
||||
appears in the dropdown menu for deployment-only access.
|
||||
group with the Reporter [role](../../user/permissions.md), or in groups added to the project with the Reporter
|
||||
role, appears in the dropdown menu for deployment-only access.
|
||||
|
||||
To add deployment-only access:
|
||||
|
||||
|
@ -136,7 +135,8 @@ To add deployment-only access:
|
|||
1. Invite the group to be a project member.
|
||||
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).
|
||||
Note that deployment-only access is the only possible access level for groups with the Reporter
|
||||
[role](../../user/permissions.md).
|
||||
|
||||
## Modifying and unprotecting environments
|
||||
|
||||
|
|
|
@ -156,7 +156,7 @@ the GitLab instance. To determine this:
|
|||
1. On the left sidebar, select **Overview > Runners**.
|
||||
1. Find the runner in the table and view the **IP Address** column.
|
||||
|
||||
![shared runner IP address](img/shared_runner_ip_address_14_1.png)
|
||||
![shared runner IP address](img/shared_runner_ip_address_14_5.png)
|
||||
|
||||
### Determine the IP address of a specific runner
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 8.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
|
@ -111,7 +111,7 @@ Each line represents a rule that was evaluated. There are a few things to note:
|
|||
|
||||
Here you can see that the first four rules were evaluated `false` for
|
||||
which user and subject. For example, you can see in the last line that
|
||||
the rule was activated because the user `john` had Reporter access to
|
||||
the rule was activated because the user `john` had the Reporter [role](../user/permissions.md) on
|
||||
`Project/4`.
|
||||
|
||||
When a policy is asked whether a particular ability is allowed
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 13 KiB |
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
|
@ -315,11 +315,11 @@ To search runners' descriptions:
|
|||
|
||||
You can also filter runners by status, type, and tag. To filter:
|
||||
|
||||
1. Click in the **Search or filter results...** field.
|
||||
1. Select **Status**, **Type**, or **Tags**.
|
||||
1. Select a tab or the **Search or filter results...** field.
|
||||
1. Select any **Type**, or filter by **Status** or **Tags**.
|
||||
1. Select or enter your search criteria.
|
||||
|
||||
![Attributes of a runner, with the **Search or filter results...** field active](img/index_runners_search_or_filter_v14_1.png)
|
||||
![Attributes of a runner, with the **Search or filter results...** field active](img/index_runners_search_or_filter_v14_5.png)
|
||||
|
||||
For each runner, the following attributes are listed:
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ Initially, no data appears. Data is populated as users comment on open merge req
|
|||
|
||||
## Overview
|
||||
|
||||
Code Review Analytics is available to users with Reporter access and above, and displays a table of open merge requests that have at least one non-author comment. The review time is measured from the time the first non-author comment was submitted.
|
||||
Code Review Analytics is available to users with at least the Reporter [role](../permissions.md), and displays a table of open merge requests that have at least one non-author comment. The review time is measured from the time the first non-author comment was submitted.
|
||||
|
||||
To access Code Review Analytics, from your project's menu, go to **Analytics > Code Review**.
|
||||
|
||||
|
|
|
@ -116,4 +116,4 @@ bookmark for those preferred settings in your browser.
|
|||
The **Merge Request Analytics** feature can be accessed only:
|
||||
|
||||
- On [GitLab Premium](https://about.gitlab.com/pricing/) and above.
|
||||
- By users with [Reporter access](../permissions.md) and above.
|
||||
- By users with at least the Reporter [role](../permissions.md).
|
||||
|
|
|
@ -103,4 +103,4 @@ You can filter analytics based on a date range. To filter results:
|
|||
The **Productivity Analytics** dashboard can be accessed only:
|
||||
|
||||
- On [GitLab Premium](https://about.gitlab.com/pricing/) and above.
|
||||
- By users with [Reporter access](../permissions.md) and above.
|
||||
- By users with at least the Reporter [role](../permissions.md).
|
||||
|
|
|
@ -16,7 +16,7 @@ enabling you to see statistics about the resources that Terraform creates,
|
|||
modifies, or destroys.
|
||||
|
||||
WARNING:
|
||||
Like any other job artifact, Terraform Plan data is [viewable by anyone with Guest access](../../permissions.md) to the repository.
|
||||
Like any other job artifact, Terraform Plan data is viewable by anyone with the Guest [role](../../permissions.md) on the repository.
|
||||
Neither Terraform nor GitLab encrypts the plan file by default. If your Terraform Plan
|
||||
includes sensitive data such as passwords, access tokens, or certificates, we strongly
|
||||
recommend encrypting plan output or modifying the project visibility settings.
|
||||
|
|
|
@ -205,7 +205,7 @@ and the CI YAML file:
|
|||
The output from the above `terraform` commands should be viewable in the job logs.
|
||||
|
||||
WARNING:
|
||||
Like any other job artifact, Terraform plan data is [viewable by anyone with Guest access](../../permissions.md) to the repository.
|
||||
Like any other job artifact, Terraform plan data is viewable by anyone with the Guest [role](../../permissions.md) on the repository.
|
||||
Neither Terraform nor GitLab encrypts the plan file by default. If your Terraform plan
|
||||
includes sensitive data such as passwords, access tokens, or certificates, GitLab strongly
|
||||
recommends encrypting plan output or modifying the project visibility settings.
|
||||
|
|
|
@ -434,7 +434,7 @@ Be aware that this regex could lead to a
|
|||
|
||||
## Free Guest users **(ULTIMATE)**
|
||||
|
||||
When a user is given Guest permissions on a project, group, or both, and holds no
|
||||
When a user is given the Guest role on a project, group, or both, and holds no
|
||||
higher permission level on any other project or group on the GitLab instance,
|
||||
the user is considered a guest user by GitLab and does not consume a license seat.
|
||||
There is no other specific "guest" designation for newly created users.
|
||||
|
|
|
@ -594,7 +594,7 @@ You can move issues and lists by dragging them.
|
|||
|
||||
Prerequisites:
|
||||
|
||||
- A minimum of [Reporter](../permissions.md#project-members-permissions) access to a project in GitLab.
|
||||
- You must have at least the Reporter [role](../permissions.md#project-members-permissions) for a project in GitLab.
|
||||
|
||||
To move an issue, select the issue card and drag it to another position in its current list or
|
||||
into a different list. Learn about possible effects in [Dragging issues between lists](#dragging-issues-between-lists).
|
||||
|
|
|
@ -25,7 +25,7 @@ In an issue, leave a comment using the `/zoom` quick action followed by a valid
|
|||
/zoom https://zoom.us/j/123456789
|
||||
```
|
||||
|
||||
If the Zoom meeting URL is valid and you have at least [Reporter permissions](../../permissions.md),
|
||||
If the Zoom meeting URL is valid and you have at least the Reporter [role](../../permissions.md),
|
||||
a system alert notifies you of its successful addition.
|
||||
The issue's description is automatically edited to include the Zoom link, and a button
|
||||
appears right under the issue's title.
|
||||
|
@ -44,5 +44,5 @@ Similarly to adding a Zoom meeting, you can remove it with a quick action:
|
|||
/remove_zoom
|
||||
```
|
||||
|
||||
If you have at least [Reporter permissions](../../permissions.md),
|
||||
If you have at least the Reporter [role](../../permissions.md),
|
||||
a system alert notifies you that the meeting URL was successfully removed.
|
||||
|
|
|
@ -77,14 +77,14 @@ that prevent leaks of private data.
|
|||
|
||||
There are two kinds of level access for confidential issues. The general rule
|
||||
is that confidential issues are visible only to members of a project with at
|
||||
least [Reporter access](../../permissions.md#project-members-permissions). However, a guest user can also create
|
||||
least the Reporter [role](../../permissions.md#project-members-permissions). However, a guest user can also create
|
||||
confidential issues, but can only view the ones that they created themselves.
|
||||
|
||||
Confidential issues are also hidden in search results for unprivileged users.
|
||||
For example, here's what a user with the [Maintainer role](../../permissions.md) and Guest access
|
||||
For example, here's what a user with the [Maintainer role](../../permissions.md) and the Guest role
|
||||
sees in the project's search results respectively.
|
||||
|
||||
| Maintainer role | Guest access |
|
||||
| Maintainer role | Guest role |
|
||||
|:---------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------|
|
||||
| ![Confidential issues search by maintainer](img/confidential_issues_search_master.png) | ![Confidential issues search by guest](img/confidential_issues_search_guest.png) |
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
# Due dates **(FREE)**
|
||||
|
||||
Due dates can be used in [issues](index.md) to keep track of deadlines and make sure features are
|
||||
shipped on time. Users need at least [Reporter permissions](../../permissions.md)
|
||||
shipped on time. Users need at least the Reporter [role](../../permissions.md)
|
||||
to be able to edit the due date. All users with permission to view
|
||||
the issue can view the due date.
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ for protected branches. **(PREMIUM)**
|
|||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40491) in GitLab 13.4.
|
||||
> - Moved to GitLab Premium in 13.9.
|
||||
|
||||
You may need to grant users with [Reporter permissions](../../../permissions.md#project-members-permissions),
|
||||
You may have to grant users with the Reporter [role](../../../permissions.md#project-members-permissions)
|
||||
permission to approve merge requests before they can merge to a protected branch.
|
||||
Some users (like managers) may not need permission to push or merge code, but still need
|
||||
oversight on proposed work. To enable approval permissions for these users without
|
||||
|
|
|
@ -40,7 +40,7 @@ protected branch.
|
|||
## Forking workflow
|
||||
|
||||
With the forking workflow, maintainers get the [Maintainer role](../../permissions.md) and regular
|
||||
developers get Reporter access to the authoritative repository, which prohibits
|
||||
developers get the Reporter role on the authoritative repository, which prohibits
|
||||
them from pushing any changes to it.
|
||||
|
||||
Developers create forks of the authoritative project and push their feature
|
||||
|
|
|
@ -716,11 +716,11 @@ In the API:
|
|||
|
||||
### View a release and download assets
|
||||
|
||||
> [The Guest permission for read action was adjusted](https://gitlab.com/gitlab-org/gitlab/-/issues/335209) in GitLab 14.5.
|
||||
> [Changes were made to the Guest role access](https://gitlab.com/gitlab-org/gitlab/-/issues/335209) in GitLab 14.5.
|
||||
|
||||
- Users with [Reporter role or above](../../../user/permissions.md#project-members-permissions)
|
||||
- Users with the [Reporter role or above](../../../user/permissions.md#project-members-permissions)
|
||||
have read and download access to the project releases.
|
||||
- Users with [Guest role](../../../user/permissions.md#project-members-permissions)
|
||||
- Users with the [Guest role](../../../user/permissions.md#project-members-permissions)
|
||||
have read and download access to the project releases.
|
||||
This includes associated Git-tag-names, release description, author information of the releases.
|
||||
However, other repository-related information, such as [source code](#source-code), [release evidence](#release-evidence) are redacted.
|
||||
|
|
|
@ -101,7 +101,7 @@ module API
|
|||
# of time after a Gitaly timeout, to mitigate frequent Gitaly timeouts
|
||||
# for some Commit diffs.
|
||||
def diff_files(commit)
|
||||
return commit.diffs.diff_files unless Feature.enabled?(:api_v3_commits_skip_diff_files, commit.project)
|
||||
return commit.diffs.diff_files unless Feature.enabled?(:api_v3_commits_skip_diff_files, commit.project, default_enabled: :yaml)
|
||||
|
||||
cache_key = [
|
||||
GITALY_TIMEOUT_CACHE_KEY,
|
||||
|
|
|
@ -13811,7 +13811,7 @@ msgstr ""
|
|||
msgid "EscalationPolicies|Escalation policies"
|
||||
msgstr ""
|
||||
|
||||
msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
|
||||
msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
|
||||
msgstr ""
|
||||
|
||||
msgid "EscalationPolicies|Escalation rules"
|
||||
|
@ -23996,7 +23996,7 @@ msgstr ""
|
|||
msgid "OnCallSchedules|For this rotation, on-call will be:"
|
||||
msgstr ""
|
||||
|
||||
msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
|
||||
msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
|
||||
msgstr ""
|
||||
|
||||
msgid "OnCallSchedules|On-call schedules"
|
||||
|
|
|
@ -44,6 +44,7 @@ User-Agent: *
|
|||
Disallow: /groups/*/analytics
|
||||
Disallow: /groups/*/contribution_analytics
|
||||
Disallow: /groups/*/group_members
|
||||
Disallow: /groups/*/-/saml/sso
|
||||
|
||||
# Project details
|
||||
User-Agent: *
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = 'mygem'
|
||||
s.authors = ['Tanuki Steve', 'Hal 9000']
|
||||
s.author = 'Tanuki Steve'
|
||||
s.version = '0.0.1'
|
||||
s.date = '2011-09-29'
|
||||
s.summary = 'package is the best'
|
||||
s.files = ['lib/hello_gem.rb']
|
||||
s.require_paths = ['lib']
|
||||
|
||||
s.description = 'A test package for GitLab.'
|
||||
s.email = 'tanuki@not_real.com'
|
||||
s.homepage = 'https://gitlab.com/ruby-co/my-package'
|
||||
s.license = 'MIT'
|
||||
|
||||
s.metadata = {
|
||||
'bug_tracker_uri' => 'https://gitlab.com/ruby-co/my-package/issues',
|
||||
'changelog_uri' => 'https://gitlab.com/ruby-co/my-package/CHANGELOG.md',
|
||||
'documentation_uri' => 'https://gitlab.com/ruby-co/my-package/docs',
|
||||
'mailing_list_uri' => 'https://gitlab.com/ruby-co/my-package/mailme',
|
||||
'source_code_uri' => 'https://gitlab.com/ruby-co/my-package'
|
||||
}
|
||||
|
||||
s.bindir = 'bin'
|
||||
s.platform = Gem::Platform::RUBY
|
||||
s.post_install_message = 'Installed, thank you!'
|
||||
s.rdoc_options = ['--main']
|
||||
s.required_ruby_version = '>= 2.7.0'
|
||||
s.required_rubygems_version = '>= 1.8.11'
|
||||
s.requirements = 'A high powered server or calculator'
|
||||
s.rubygems_version = '1.8.09'
|
||||
|
||||
s.add_dependency 'dependency_1', '~> 1.2.3'
|
||||
s.add_dependency 'dependency_2', '3.0.0'
|
||||
s.add_dependency 'dependency_3', '>= 1.0.0'
|
||||
s.add_dependency 'dependency_4'
|
||||
end
|
|
@ -5,15 +5,15 @@ module QA
|
|||
module Project
|
||||
module Registry
|
||||
class Show < QA::Page::Base
|
||||
view 'app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue' do
|
||||
view 'app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue' do
|
||||
element :registry_image_content
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue' do
|
||||
view 'app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue' do
|
||||
element :more_actions_menu
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue' do
|
||||
view 'app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue' do
|
||||
element :tag_delete_button
|
||||
end
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ module QA
|
|||
|
||||
let(:package) do
|
||||
Resource::Package.init do |package|
|
||||
package.name = 'conantest'
|
||||
package.name = "conantest-#{SecureRandom.hex(8)}"
|
||||
package.project = project
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,7 +11,7 @@ module QA
|
|||
|
||||
let(:package) do
|
||||
Resource::Package.init do |package|
|
||||
package.name = "my_package"
|
||||
package.name = "my_package-#{SecureRandom.hex(8)}"
|
||||
package.project = project
|
||||
end
|
||||
end
|
||||
|
@ -36,13 +36,13 @@ module QA
|
|||
upload:
|
||||
stage: upload
|
||||
script:
|
||||
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file file.txt ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/my_package/0.0.1/file.txt'
|
||||
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file file.txt ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/#{package.name}/0.0.1/file.txt'
|
||||
tags:
|
||||
- "runner-for-#{project.name}"
|
||||
download:
|
||||
stage: download
|
||||
script:
|
||||
- 'wget --header="JOB-TOKEN: $CI_JOB_TOKEN" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/my_package/0.0.1/file.txt -O file_downloaded.txt'
|
||||
- 'wget --header="JOB-TOKEN: $CI_JOB_TOKEN" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/#{package.name}/0.0.1/file.txt -O file_downloaded.txt'
|
||||
tags:
|
||||
- "runner-for-#{project.name}"
|
||||
YAML
|
||||
|
|
|
@ -6,7 +6,7 @@ module QA
|
|||
include Runtime::Fixtures
|
||||
include_context 'packages registry qa scenario'
|
||||
|
||||
let(:package_name) { 'gitlab_qa_helm' }
|
||||
let(:package_name) { "gitlab_qa_helm-#{SecureRandom.hex(8)}" }
|
||||
let(:package_version) { '1.3.7' }
|
||||
let(:package_type) { 'helm' }
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ module QA
|
|||
include_context 'packages registry qa scenario'
|
||||
|
||||
let(:group_id) { 'com.gitlab.qa' }
|
||||
let(:artifact_id) { 'maven_gradle' }
|
||||
let(:artifact_id) { "maven_gradle-#{SecureRandom.hex(8)}" }
|
||||
let(:package_name) { "#{group_id}/#{artifact_id}".tr('.', '/') }
|
||||
let(:package_version) { '1.3.7' }
|
||||
let(:package_type) { 'maven_gradle' }
|
||||
|
|
|
@ -125,7 +125,7 @@ module QA
|
|||
|
||||
let(:package) do
|
||||
Resource::Package.init do |package|
|
||||
package.name = "@#{registry_scope}/#{project.name}"
|
||||
package.name = "@#{registry_scope}/#{project.name}-#{SecureRandom.hex(8)}"
|
||||
package.project = project
|
||||
end
|
||||
end
|
||||
|
|
|
@ -104,7 +104,7 @@ module QA
|
|||
|
||||
let(:package) do
|
||||
Resource::Package.init do |package|
|
||||
package.name = "@#{registry_scope}/mypackage"
|
||||
package.name = "@#{registry_scope}/mypackage-#{SecureRandom.hex(8)}"
|
||||
package.project = project
|
||||
end
|
||||
end
|
||||
|
@ -133,7 +133,7 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
it "push and pull a npm package via CI using a #{params[:token_name]}", quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/344537', type: :investigating } do
|
||||
it "push and pull a npm package via CI using a #{params[:token_name]}" do
|
||||
Resource::Repository::Commit.fabricate_via_api! do |commit|
|
||||
commit.project = project
|
||||
commit.commit_message = 'Add .gitlab-ci.yml'
|
||||
|
|
|
@ -12,7 +12,7 @@ module QA
|
|||
|
||||
let(:package) do
|
||||
Resource::Package.init do |package|
|
||||
package.name = 'mypypipackage'
|
||||
package.name = "mypypipackage-#{SecureRandom.hex(8)}"
|
||||
package.project = project
|
||||
end
|
||||
end
|
||||
|
@ -57,7 +57,7 @@ module QA
|
|||
install:
|
||||
stage: install
|
||||
script:
|
||||
- "pip install mypypipackage --no-deps --index-url #{uri.scheme}://#{personal_access_token}:#{personal_access_token}@#{gitlab_host_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host #{gitlab_host_with_port}"
|
||||
- "pip install #{package.name} --no-deps --index-url #{uri.scheme}://#{personal_access_token}:#{personal_access_token}@#{gitlab_host_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host #{gitlab_host_with_port}"
|
||||
tags:
|
||||
- "runner-for-#{project.name}"
|
||||
|
||||
|
@ -70,7 +70,7 @@ module QA
|
|||
import setuptools
|
||||
|
||||
setuptools.setup(
|
||||
name="mypypipackage",
|
||||
name="#{package.name}",
|
||||
version="0.0.1",
|
||||
author="Example Author",
|
||||
author_email="author@example.com",
|
||||
|
|
|
@ -13,7 +13,7 @@ module QA
|
|||
|
||||
let(:package) do
|
||||
Resource::Package.init do |package|
|
||||
package.name = 'mygem'
|
||||
package.name = "mygem-#{SecureRandom.hex(8)}"
|
||||
package.project = project
|
||||
end
|
||||
end
|
||||
|
@ -46,17 +46,9 @@ module QA
|
|||
it 'publishes and deletes a Ruby gem', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1906' do
|
||||
Flow::Login.sign_in
|
||||
|
||||
Resource::Repository::ProjectPush.fabricate! do |push|
|
||||
push.project = project
|
||||
push.directory = Pathname
|
||||
.new(__dir__)
|
||||
.join('../../../../../fixtures/rubygems_package')
|
||||
push.commit_message = 'RubyGems package'
|
||||
end
|
||||
|
||||
Resource::Repository::Commit.fabricate_via_api! do |commit|
|
||||
commit.project = project
|
||||
commit.commit_message = 'Add mygem.gemspec'
|
||||
commit.commit_message = 'Add package files'
|
||||
commit.add_files(
|
||||
[
|
||||
{
|
||||
|
@ -74,8 +66,8 @@ module QA
|
|||
echo "#{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems: '${CI_JOB_TOKEN}'" >> ~/.gem/credentials
|
||||
- chmod 0600 ~/.gem/credentials
|
||||
script:
|
||||
- gem build mygem
|
||||
- gem push mygem-0.0.1.gem --host #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems
|
||||
- gem build #{package.name}
|
||||
- gem push #{package.name}-0.0.1.gem --host #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems
|
||||
tags:
|
||||
- "runner-for-#{project.name}"
|
||||
YAML
|
||||
|
@ -90,6 +82,52 @@ module QA
|
|||
end
|
||||
end
|
||||
RUBY
|
||||
},
|
||||
{
|
||||
file_path: "#{package.name}.gemspec",
|
||||
content:
|
||||
<<~RUBY
|
||||
# frozen_string_literal: true
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = '#{package.name}'
|
||||
s.authors = ['Tanuki Steve', 'Hal 9000']
|
||||
s.author = 'Tanuki Steve'
|
||||
s.version = '0.0.1'
|
||||
s.date = '2011-09-29'
|
||||
s.summary = 'this is a test package'
|
||||
s.files = ['lib/hello_gem.rb']
|
||||
s.require_paths = ['lib']
|
||||
|
||||
s.description = 'A test package for GitLab.'
|
||||
s.email = 'tanuki@not_real.com'
|
||||
s.homepage = 'https://gitlab.com/ruby-co/my-package'
|
||||
s.license = 'MIT'
|
||||
|
||||
s.metadata = {
|
||||
'bug_tracker_uri' => 'https://gitlab.com/ruby-co/my-package/issues',
|
||||
'changelog_uri' => 'https://gitlab.com/ruby-co/my-package/CHANGELOG.md',
|
||||
'documentation_uri' => 'https://gitlab.com/ruby-co/my-package/docs',
|
||||
'mailing_list_uri' => 'https://gitlab.com/ruby-co/my-package/mailme',
|
||||
'source_code_uri' => 'https://gitlab.com/ruby-co/my-package'
|
||||
}
|
||||
|
||||
s.bindir = 'bin'
|
||||
s.platform = Gem::Platform::RUBY
|
||||
s.post_install_message = 'Installed, thank you!'
|
||||
s.rdoc_options = ['--main']
|
||||
s.required_ruby_version = '>= 2.7.0'
|
||||
s.required_rubygems_version = '>= 1.8.11'
|
||||
s.requirements = 'A high powered server or calculator'
|
||||
s.rubygems_version = '1.8.09'
|
||||
|
||||
s.add_dependency 'dependency_1', '~> 1.2.3'
|
||||
s.add_dependency 'dependency_2', '3.0.0'
|
||||
s.add_dependency 'dependency_3', '>= 1.0.0'
|
||||
s.add_dependency 'dependency_4'
|
||||
end
|
||||
|
||||
RUBY
|
||||
}
|
||||
]
|
||||
)
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
import Frontmatter from '~/content_editor/extensions/frontmatter';
|
||||
import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/frontmatter', () => {
|
||||
let tiptapEditor;
|
||||
let doc;
|
||||
let p;
|
||||
|
||||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [Frontmatter] });
|
||||
|
||||
({
|
||||
builders: { doc, p },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
frontmatter: { nodeType: Frontmatter.name },
|
||||
},
|
||||
}));
|
||||
});
|
||||
|
||||
it('does not insert a frontmatter block when executing code block input rule', () => {
|
||||
const expectedDoc = doc(p(''));
|
||||
const inputRuleText = '``` ';
|
||||
|
||||
triggerNodeInputRule({ tiptapEditor, inputRuleText });
|
||||
|
||||
expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
|
||||
});
|
||||
});
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
exports[`packages_list_app renders 1`] = `
|
||||
<div>
|
||||
<div
|
||||
help-url="foo"
|
||||
<infrastructure-title-stub
|
||||
helpurl="foo"
|
||||
/>
|
||||
|
||||
<div />
|
||||
<infrastructure-search-stub />
|
||||
|
||||
<div>
|
||||
<section
|
||||
|
|
|
@ -9,6 +9,7 @@ import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages/list/constants';
|
|||
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
|
||||
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
|
||||
import * as packageUtils from '~/packages_and_registries/shared/utils';
|
||||
import InfrastructureSearch from '~/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue';
|
||||
|
||||
jest.mock('~/lib/utils/common_utils');
|
||||
jest.mock('~/flash');
|
||||
|
@ -26,18 +27,9 @@ describe('packages_list_app', () => {
|
|||
};
|
||||
const GlLoadingIcon = { name: 'gl-loading-icon', template: '<div>loading</div>' };
|
||||
|
||||
// we need to manually stub dynamic imported components because shallowMount is not able to stub them automatically. See: https://github.com/vuejs/vue-test-utils/issues/1279
|
||||
const PackageSearch = { name: 'PackageSearch', template: '<div></div>' };
|
||||
const PackageTitle = { name: 'PackageTitle', template: '<div></div>' };
|
||||
const InfrastructureTitle = { name: 'InfrastructureTitle', template: '<div></div>' };
|
||||
const InfrastructureSearch = { name: 'InfrastructureSearch', template: '<div></div>' };
|
||||
|
||||
const emptyListHelpUrl = 'helpUrl';
|
||||
const findEmptyState = () => wrapper.find(GlEmptyState);
|
||||
const findListComponent = () => wrapper.find(PackageList);
|
||||
const findPackageSearch = () => wrapper.find(PackageSearch);
|
||||
const findPackageTitle = () => wrapper.find(PackageTitle);
|
||||
const findInfrastructureTitle = () => wrapper.find(InfrastructureTitle);
|
||||
const findInfrastructureSearch = () => wrapper.find(InfrastructureSearch);
|
||||
|
||||
const createStore = (filter = []) => {
|
||||
|
@ -66,10 +58,6 @@ describe('packages_list_app', () => {
|
|||
PackageList,
|
||||
GlSprintf,
|
||||
GlLink,
|
||||
PackageSearch,
|
||||
PackageTitle,
|
||||
InfrastructureTitle,
|
||||
InfrastructureSearch,
|
||||
},
|
||||
provide,
|
||||
});
|
||||
|
@ -191,48 +179,23 @@ describe('packages_list_app', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Package Search', () => {
|
||||
describe('Search', () => {
|
||||
it('exists', () => {
|
||||
mountComponent();
|
||||
|
||||
expect(findPackageSearch().exists()).toBe(true);
|
||||
expect(findInfrastructureSearch().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('on update fetches data from the store', () => {
|
||||
mountComponent();
|
||||
store.dispatch.mockClear();
|
||||
|
||||
findPackageSearch().vm.$emit('update');
|
||||
findInfrastructureSearch().vm.$emit('update');
|
||||
|
||||
expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Infrastructure config', () => {
|
||||
it('defaults to package registry components', () => {
|
||||
mountComponent();
|
||||
|
||||
expect(findPackageSearch().exists()).toBe(true);
|
||||
expect(findPackageTitle().exists()).toBe(true);
|
||||
|
||||
expect(findInfrastructureTitle().exists()).toBe(false);
|
||||
expect(findInfrastructureSearch().exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('mount different component based on the provided values', () => {
|
||||
mountComponent({
|
||||
titleComponent: 'InfrastructureTitle',
|
||||
searchComponent: 'InfrastructureSearch',
|
||||
});
|
||||
|
||||
expect(findPackageSearch().exists()).toBe(false);
|
||||
expect(findPackageTitle().exists()).toBe(false);
|
||||
|
||||
expect(findInfrastructureTitle().exists()).toBe(true);
|
||||
expect(findInfrastructureSearch().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete alert handling', () => {
|
||||
const originalLocation = window.location.href;
|
||||
const search = `?${SHOW_DELETE_SUCCESS_ALERT}=true`;
|
||||
|
|
|
@ -1,128 +0,0 @@
|
|||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
import Vuex from 'vuex';
|
||||
import component from '~/packages/list/components/package_search.vue';
|
||||
import PackageTypeToken from '~/packages/list/components/tokens/package_type_token.vue';
|
||||
import { sortableFields } from '~/packages/list/utils';
|
||||
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
|
||||
import UrlSync from '~/vue_shared/components/url_sync.vue';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
describe('Package Search', () => {
|
||||
let wrapper;
|
||||
let store;
|
||||
|
||||
const findRegistrySearch = () => wrapper.findComponent(RegistrySearch);
|
||||
const findUrlSync = () => wrapper.findComponent(UrlSync);
|
||||
|
||||
const createStore = (isGroupPage) => {
|
||||
const state = {
|
||||
config: {
|
||||
isGroupPage,
|
||||
},
|
||||
sorting: {
|
||||
orderBy: 'version',
|
||||
sort: 'desc',
|
||||
},
|
||||
filter: [],
|
||||
};
|
||||
store = new Vuex.Store({
|
||||
state,
|
||||
});
|
||||
store.dispatch = jest.fn();
|
||||
};
|
||||
|
||||
const mountComponent = (isGroupPage = false) => {
|
||||
createStore(isGroupPage);
|
||||
|
||||
wrapper = shallowMount(component, {
|
||||
localVue,
|
||||
store,
|
||||
stubs: {
|
||||
UrlSync,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
});
|
||||
|
||||
it('has a registry search component', () => {
|
||||
mountComponent();
|
||||
|
||||
expect(findRegistrySearch().exists()).toBe(true);
|
||||
expect(findRegistrySearch().props()).toMatchObject({
|
||||
filter: store.state.filter,
|
||||
sorting: store.state.sorting,
|
||||
tokens: expect.arrayContaining([
|
||||
expect.objectContaining({ token: PackageTypeToken, type: 'type', icon: 'package' }),
|
||||
]),
|
||||
sortableFields: sortableFields(),
|
||||
});
|
||||
});
|
||||
|
||||
it.each`
|
||||
isGroupPage | page
|
||||
${false} | ${'project'}
|
||||
${true} | ${'group'}
|
||||
`('in a $page page binds the right props', ({ isGroupPage }) => {
|
||||
mountComponent(isGroupPage);
|
||||
|
||||
expect(findRegistrySearch().props()).toMatchObject({
|
||||
filter: store.state.filter,
|
||||
sorting: store.state.sorting,
|
||||
tokens: expect.arrayContaining([
|
||||
expect.objectContaining({ token: PackageTypeToken, type: 'type', icon: 'package' }),
|
||||
]),
|
||||
sortableFields: sortableFields(isGroupPage),
|
||||
});
|
||||
});
|
||||
|
||||
it('on sorting:changed emits update event and calls vuex setSorting', () => {
|
||||
const payload = { sort: 'foo' };
|
||||
|
||||
mountComponent();
|
||||
|
||||
findRegistrySearch().vm.$emit('sorting:changed', payload);
|
||||
|
||||
expect(store.dispatch).toHaveBeenCalledWith('setSorting', payload);
|
||||
expect(wrapper.emitted('update')).toEqual([[]]);
|
||||
});
|
||||
|
||||
it('on filter:changed calls vuex setFilter', () => {
|
||||
const payload = ['foo'];
|
||||
|
||||
mountComponent();
|
||||
|
||||
findRegistrySearch().vm.$emit('filter:changed', payload);
|
||||
|
||||
expect(store.dispatch).toHaveBeenCalledWith('setFilter', payload);
|
||||
});
|
||||
|
||||
it('on filter:submit emits update event', () => {
|
||||
mountComponent();
|
||||
|
||||
findRegistrySearch().vm.$emit('filter:submit');
|
||||
|
||||
expect(wrapper.emitted('update')).toEqual([[]]);
|
||||
});
|
||||
|
||||
it('has a UrlSync component', () => {
|
||||
mountComponent();
|
||||
|
||||
expect(findUrlSync().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('on query:changed calls updateQuery from UrlSync', () => {
|
||||
jest.spyOn(UrlSync.methods, 'updateQuery').mockImplementation(() => {});
|
||||
|
||||
mountComponent();
|
||||
|
||||
findRegistrySearch().vm.$emit('query:changed');
|
||||
|
||||
expect(UrlSync.methods.updateQuery).toHaveBeenCalled();
|
||||
});
|
||||
});
|
|
@ -1,71 +0,0 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { LIST_INTRO_TEXT, LIST_TITLE_TEXT } from '~/packages/list//constants';
|
||||
import PackageTitle from '~/packages/list/components/package_title.vue';
|
||||
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
|
||||
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
|
||||
|
||||
describe('PackageTitle', () => {
|
||||
let wrapper;
|
||||
let store;
|
||||
|
||||
const findTitleArea = () => wrapper.find(TitleArea);
|
||||
const findMetadataItem = () => wrapper.find(MetadataItem);
|
||||
|
||||
const mountComponent = (propsData = { helpUrl: 'foo' }) => {
|
||||
wrapper = shallowMount(PackageTitle, {
|
||||
store,
|
||||
propsData,
|
||||
stubs: {
|
||||
TitleArea,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
});
|
||||
|
||||
describe('title area', () => {
|
||||
it('exists', () => {
|
||||
mountComponent();
|
||||
|
||||
expect(findTitleArea().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('has the correct props', () => {
|
||||
mountComponent();
|
||||
|
||||
expect(findTitleArea().props()).toMatchObject({
|
||||
title: LIST_TITLE_TEXT,
|
||||
infoMessages: [{ text: LIST_INTRO_TEXT, link: 'foo' }],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe.each`
|
||||
count | exist | text
|
||||
${null} | ${false} | ${''}
|
||||
${undefined} | ${false} | ${''}
|
||||
${0} | ${true} | ${'0 Packages'}
|
||||
${1} | ${true} | ${'1 Package'}
|
||||
${2} | ${true} | ${'2 Packages'}
|
||||
`('when count is $count metadata item', ({ count, exist, text }) => {
|
||||
beforeEach(() => {
|
||||
mountComponent({ count, helpUrl: 'foo' });
|
||||
});
|
||||
|
||||
it(`is ${exist} that it exists`, () => {
|
||||
expect(findMetadataItem().exists()).toBe(exist);
|
||||
});
|
||||
|
||||
if (exist) {
|
||||
it('has the correct props', () => {
|
||||
expect(findMetadataItem().props()).toMatchObject({
|
||||
icon: 'package',
|
||||
text,
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,48 +0,0 @@
|
|||
import { GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import component from '~/packages/list/components/tokens/package_type_token.vue';
|
||||
import { PACKAGE_TYPES } from '~/packages/list/constants';
|
||||
|
||||
describe('packages_filter', () => {
|
||||
let wrapper;
|
||||
|
||||
const findFilteredSearchToken = () => wrapper.find(GlFilteredSearchToken);
|
||||
const findFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion);
|
||||
|
||||
const mountComponent = ({ attrs, listeners } = {}) => {
|
||||
wrapper = shallowMount(component, {
|
||||
attrs,
|
||||
listeners,
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
});
|
||||
|
||||
it('it binds all of his attrs to filtered search token', () => {
|
||||
mountComponent({ attrs: { foo: 'bar' } });
|
||||
|
||||
expect(findFilteredSearchToken().attributes('foo')).toBe('bar');
|
||||
});
|
||||
|
||||
it('it binds all of his events to filtered search token', () => {
|
||||
const clickListener = jest.fn();
|
||||
mountComponent({ listeners: { click: clickListener } });
|
||||
|
||||
findFilteredSearchToken().vm.$emit('click');
|
||||
|
||||
expect(clickListener).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it.each(PACKAGE_TYPES.map((p, index) => [p, index]))(
|
||||
'displays a suggestion for %p',
|
||||
(packageType, index) => {
|
||||
mountComponent();
|
||||
const item = findFilteredSearchSuggestions().at(index);
|
||||
expect(item.text()).toBe(packageType.title);
|
||||
expect(item.props('value')).toBe(packageType.type);
|
||||
},
|
||||
);
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue