Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
0d1ffbe0b6
commit
8280d80718
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
# Cop supports --autocorrect.
|
||||
GraphQL/FieldHashKey:
|
||||
Exclude:
|
||||
- 'app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb'
|
||||
|
|
@ -214,19 +214,6 @@ Layout/SpaceInLambdaLiteral:
|
|||
- 'lib/api/entities/ci/lint/result.rb'
|
||||
- 'lib/api/entities/ci/reset_token_result.rb'
|
||||
- 'lib/api/entities/ci/variable.rb'
|
||||
- 'lib/api/events.rb'
|
||||
- 'lib/api/feature_flags_user_lists.rb'
|
||||
- 'lib/api/files.rb'
|
||||
- 'lib/api/helm_packages.rb'
|
||||
- 'lib/api/helpers/caching.rb'
|
||||
- 'lib/api/merge_requests.rb'
|
||||
- 'lib/api/metadata.rb'
|
||||
- 'lib/api/metrics/dashboard/annotations.rb'
|
||||
- 'lib/api/releases.rb'
|
||||
- 'lib/api/settings.rb'
|
||||
- 'lib/api/tags.rb'
|
||||
- 'lib/api/unleash.rb'
|
||||
- 'lib/api/users.rb'
|
||||
- 'lib/atlassian/jira_connect/serializers/author_entity.rb'
|
||||
- 'lib/bulk_imports/groups/transformers/group_attributes_transformer.rb'
|
||||
- 'lib/container_registry/base_client.rb'
|
||||
|
|
|
|||
|
|
@ -19,20 +19,3 @@ Rails/NegateInclude:
|
|||
- 'ee/app/services/epic_issues/create_service.rb'
|
||||
- 'ee/app/services/security/ingestion/tasks/ingest_remediations.rb'
|
||||
- 'ee/app/services/security/security_orchestration_policies/validate_policy_service.rb'
|
||||
- 'lib/api/maven_packages.rb'
|
||||
- 'lib/gitlab/background_migration/legacy_upload_mover.rb'
|
||||
- 'lib/gitlab/ci/build/rules/rule/clause/exists.rb'
|
||||
- 'lib/gitlab/ci/parsers/coverage/sax_document.rb'
|
||||
- 'lib/gitlab/ci/queue/metrics.rb'
|
||||
- 'lib/gitlab/database/each_database.rb'
|
||||
- 'lib/gitlab/email/handler/create_issue_handler.rb'
|
||||
- 'lib/gitlab/email/handler/service_desk_handler.rb'
|
||||
- 'lib/gitlab/graphql/queries.rb'
|
||||
- 'lib/gitlab/import_export/attributes_permitter.rb'
|
||||
- 'lib/gitlab/task_helpers.rb'
|
||||
- 'qa/qa/tools/delete_test_users.rb'
|
||||
- 'spec/lib/container_registry/blob_spec.rb'
|
||||
- 'spec/lib/container_registry/client_spec.rb'
|
||||
- 'spec/lib/gitlab/metrics/subscribers/active_record_spec.rb'
|
||||
- 'spec/support/matchers/pushed_frontend_feature_flags_matcher.rb'
|
||||
- 'spec/uploaders/object_storage_spec.rb'
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
v17.0.0-rc4
|
||||
v17.0.0-rc42
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import { GlIcon } from '@gitlab/ui';
|
||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||
|
||||
export default {
|
||||
name: 'LogViewer',
|
||||
|
|
@ -20,25 +21,38 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
hiddenSections: new Set(), // Use Set instead of Array. has() is more performant than includes() and it's executed more frequently
|
||||
collapsedSections: new Set(), // Use Set instead of Array. has() is more performant than includes() and it's executed more frequently
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
log: {
|
||||
immediate: true,
|
||||
handler() {
|
||||
// Reset the currently collapsed sections when log is loaded
|
||||
const collapsed = this.log
|
||||
.filter(({ options }) => parseBoolean(options?.collapsed))
|
||||
.map(({ header }) => header);
|
||||
|
||||
this.collapsedSections = new Set(collapsed);
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
isLineHidden(sections = []) {
|
||||
for (const s of sections) {
|
||||
if (this.hiddenSections.has(s)) {
|
||||
if (this.collapsedSections.has(s)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
toggleSection(section) {
|
||||
if (this.hiddenSections.has(section)) {
|
||||
this.hiddenSections.delete(section);
|
||||
if (this.collapsedSections.has(section)) {
|
||||
this.collapsedSections.delete(section);
|
||||
} else {
|
||||
this.hiddenSections.add(section);
|
||||
this.collapsedSections.add(section);
|
||||
}
|
||||
this.hiddenSections = new Set(this.hiddenSections); // `Set` is not reactive in Vue 2, create new instance it to trigger reactivity
|
||||
this.collapsedSections = new Set(this.collapsedSections); // `Set` is not reactive in Vue 2, create new instance it to trigger reactivity
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -62,7 +76,7 @@ export default {
|
|||
<div>
|
||||
<gl-icon
|
||||
v-if="line.header"
|
||||
:name="hiddenSections.has(line.header) ? 'chevron-lg-right' : 'chevron-lg-down'"
|
||||
:name="collapsedSections.has(line.header) ? 'chevron-lg-right' : 'chevron-lg-down'"
|
||||
/><a :id="`L${index + 1}`" :href="`#L${index + 1}`" class="log-line-number" @click.stop>{{
|
||||
index + 1
|
||||
}}</a>
|
||||
|
|
|
|||
|
|
@ -33,6 +33,16 @@ const parseSection = (input, offset) => {
|
|||
return [null, to];
|
||||
};
|
||||
|
||||
const parseSectionOptions = (optionsStr = '') => {
|
||||
return optionsStr.split(',').reduce((acc, option) => {
|
||||
const [key, value] = option.split('=');
|
||||
return {
|
||||
...acc,
|
||||
[key]: value,
|
||||
};
|
||||
}, {});
|
||||
};
|
||||
|
||||
const parseAnsi = (input, offset) => {
|
||||
const from = offset;
|
||||
let to = offset;
|
||||
|
|
@ -111,6 +121,7 @@ export default class {
|
|||
// returns a header line, which can toggle other lines
|
||||
return {
|
||||
header: section.name,
|
||||
options: section.options,
|
||||
sections: this.sections.map(({ name }) => name).slice(0, -1),
|
||||
content,
|
||||
};
|
||||
|
|
@ -136,7 +147,17 @@ export default class {
|
|||
handleSection(type, time, name) {
|
||||
switch (type) {
|
||||
case SECTION_START: {
|
||||
this.sections.push({ name, time, start: true });
|
||||
const section = { name, time, start: true };
|
||||
|
||||
// Find options of a section with shape: section_name[key=value]
|
||||
const optsFrom = name.indexOf('[');
|
||||
const optsTo = name.lastIndexOf(']');
|
||||
if (optsFrom > 0 && optsTo > optsFrom) {
|
||||
section.name = name.substring(0, optsFrom);
|
||||
section.options = parseSectionOptions(name.substring(optsFrom + 1, optsTo));
|
||||
}
|
||||
|
||||
this.sections.push(section);
|
||||
break;
|
||||
}
|
||||
case SECTION_END: {
|
||||
|
|
|
|||
|
|
@ -4,11 +4,6 @@
|
|||
// https://gitlab.com/gitlab-org/gitlab/-/issues/420777
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/issues/421441
|
||||
|
||||
import { organizationProjects } from 'ee_else_ce/organizations/mock_projects';
|
||||
import { organizationGroups } from 'ee_else_ce/organizations/mock_groups';
|
||||
|
||||
export { organizationProjects, organizationGroups };
|
||||
|
||||
export const defaultOrganization = {
|
||||
id: 1,
|
||||
name: 'Default',
|
||||
|
|
|
|||
|
|
@ -1,212 +0,0 @@
|
|||
/* eslint-disable @gitlab/require-i18n-strings */
|
||||
|
||||
// This is temporary mock data that will be removed when completing the following:
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/issues/420777
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/issues/421441
|
||||
|
||||
export const organizationGroups = [
|
||||
{
|
||||
id: 'gid://gitlab/Group/29',
|
||||
fullPath: 'group/29',
|
||||
fullName: 'Commit451',
|
||||
parent: null,
|
||||
webUrl: 'http://127.0.0.1:3000/groups/Commit451',
|
||||
descriptionHtml:
|
||||
'<p data-sourcepos="1:1-1:52" dir="auto">Autem praesentium vel ut ratione itaque ullam culpa. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse libero sem, congue ut sem id, semper pharetra ante. Sed at dui ac nunc pellentesque congue. Phasellus posuere, nisl non pellentesque dignissim, lacus nisi molestie ex, vel placerat neque ligula non libero. Curabitur ipsum enim, pretium eu dignissim vitae, euismod nec nibh. Praesent eget ipsum eleifend, pellentesque tortor vel, consequat neque. Etiam suscipit dolor massa, sed consectetur nunc tincidunt ut. Suspendisse posuere malesuada finibus. Maecenas iaculis et diam eu iaculis. Proin at nulla sit amet erat sollicitudin suscipit sit amet a libero.</p>',
|
||||
avatarUrl: null,
|
||||
descendantGroupsCount: 0,
|
||||
projectsCount: 3,
|
||||
groupMembersCount: 2,
|
||||
visibility: 'public',
|
||||
userPermissions: {
|
||||
removeGroup: true,
|
||||
},
|
||||
maxAccessLevel: {
|
||||
integerValue: 30,
|
||||
},
|
||||
createdAt: '2023-09-19T14:42:38Z',
|
||||
updatedAt: '2024-04-24T03:47:38Z',
|
||||
__typename: 'Group',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/Group/33',
|
||||
fullPath: 'group/33',
|
||||
fullName: 'Flightjs',
|
||||
parent: null,
|
||||
webUrl: 'http://127.0.0.1:3000/groups/flightjs',
|
||||
descriptionHtml:
|
||||
'<p data-sourcepos="1:1-1:60" dir="auto">Ipsa reiciendis deleniti officiis illum nostrum quo aliquam.</p>',
|
||||
avatarUrl: null,
|
||||
descendantGroupsCount: 4,
|
||||
projectsCount: 3,
|
||||
groupMembersCount: 1,
|
||||
visibility: 'private',
|
||||
userPermissions: {
|
||||
removeGroup: true,
|
||||
},
|
||||
maxAccessLevel: {
|
||||
integerValue: 30,
|
||||
},
|
||||
createdAt: '2023-09-19T14:42:38Z',
|
||||
updatedAt: '2024-04-24T03:47:38Z',
|
||||
__typename: 'Group',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/Group/24',
|
||||
fullPath: 'group/24',
|
||||
fullName: 'Gitlab Org',
|
||||
parent: null,
|
||||
webUrl: 'http://127.0.0.1:3000/groups/gitlab-org',
|
||||
descriptionHtml:
|
||||
'<p data-sourcepos="1:1-1:64" dir="auto">Dolorem dolorem omnis impedit cupiditate pariatur officia velit.</p>',
|
||||
avatarUrl: null,
|
||||
descendantGroupsCount: 1,
|
||||
projectsCount: 1,
|
||||
groupMembersCount: 2,
|
||||
visibility: 'internal',
|
||||
userPermissions: {
|
||||
removeGroup: true,
|
||||
},
|
||||
maxAccessLevel: {
|
||||
integerValue: 30,
|
||||
},
|
||||
createdAt: '2023-09-19T14:42:38Z',
|
||||
updatedAt: '2024-04-24T03:47:38Z',
|
||||
__typename: 'Group',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/Group/27',
|
||||
fullPath: 'group/27',
|
||||
fullName: 'Gnuwget',
|
||||
parent: null,
|
||||
webUrl: 'http://127.0.0.1:3000/groups/gnuwgetf',
|
||||
descriptionHtml:
|
||||
'<p data-sourcepos="1:1-1:47" dir="auto">Culpa soluta aut eius dolores est vel sapiente.</p>',
|
||||
avatarUrl: null,
|
||||
descendantGroupsCount: 4,
|
||||
projectsCount: 2,
|
||||
groupMembersCount: 3,
|
||||
visibility: 'public',
|
||||
userPermissions: {
|
||||
removeGroup: true,
|
||||
},
|
||||
maxAccessLevel: {
|
||||
integerValue: 30,
|
||||
},
|
||||
createdAt: '2023-09-19T14:42:38Z',
|
||||
updatedAt: '2024-04-24T03:47:38Z',
|
||||
__typename: 'Group',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/Group/31',
|
||||
fullPath: 'group/31',
|
||||
fullName: 'Jashkenas',
|
||||
parent: null,
|
||||
webUrl: 'http://127.0.0.1:3000/groups/jashkenas',
|
||||
descriptionHtml: '<p data-sourcepos="1:1-1:25" dir="auto">Ut ut id aliquid nostrum.</p>',
|
||||
avatarUrl: null,
|
||||
descendantGroupsCount: 3,
|
||||
projectsCount: 3,
|
||||
groupMembersCount: 10,
|
||||
visibility: 'private',
|
||||
userPermissions: {
|
||||
removeGroup: true,
|
||||
},
|
||||
maxAccessLevel: {
|
||||
integerValue: 30,
|
||||
},
|
||||
createdAt: '2023-09-19T14:42:38Z',
|
||||
updatedAt: '2024-04-24T03:47:38Z',
|
||||
__typename: 'Group',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/Group/22',
|
||||
fullPath: 'group/22',
|
||||
fullName: 'Toolbox',
|
||||
parent: null,
|
||||
webUrl: 'http://127.0.0.1:3000/groups/toolbox',
|
||||
descriptionHtml:
|
||||
'<p data-sourcepos="1:1-1:46" dir="auto">Quo voluptatem magnam facere voluptates alias.</p>',
|
||||
avatarUrl: null,
|
||||
descendantGroupsCount: 2,
|
||||
projectsCount: 3,
|
||||
groupMembersCount: 40,
|
||||
visibility: 'internal',
|
||||
userPermissions: {
|
||||
removeGroup: true,
|
||||
},
|
||||
maxAccessLevel: {
|
||||
integerValue: 30,
|
||||
},
|
||||
createdAt: '2023-09-19T14:42:38Z',
|
||||
updatedAt: '2024-04-24T03:47:38Z',
|
||||
__typename: 'Group',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/Group/35',
|
||||
fullPath: 'group/35',
|
||||
fullName: 'Twitter',
|
||||
parent: null,
|
||||
webUrl: 'http://127.0.0.1:3000/groups/twitter',
|
||||
descriptionHtml:
|
||||
'<p data-sourcepos="1:1-1:40" dir="auto">Quae nulla consequatur assumenda id quo.</p>',
|
||||
avatarUrl: null,
|
||||
descendantGroupsCount: 20,
|
||||
projectsCount: 30,
|
||||
groupMembersCount: 100,
|
||||
visibility: 'public',
|
||||
userPermissions: {
|
||||
removeGroup: true,
|
||||
},
|
||||
maxAccessLevel: {
|
||||
integerValue: 30,
|
||||
},
|
||||
createdAt: '2023-09-19T14:42:38Z',
|
||||
updatedAt: '2024-04-24T03:47:38Z',
|
||||
__typename: 'Group',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/Group/73',
|
||||
fullPath: 'group/73',
|
||||
fullName: 'test',
|
||||
parent: null,
|
||||
webUrl: 'http://127.0.0.1:3000/groups/test',
|
||||
descriptionHtml: '',
|
||||
avatarUrl: null,
|
||||
descendantGroupsCount: 1,
|
||||
projectsCount: 1,
|
||||
groupMembersCount: 1,
|
||||
visibility: 'private',
|
||||
userPermissions: {
|
||||
removeGroup: true,
|
||||
},
|
||||
maxAccessLevel: {
|
||||
integerValue: 30,
|
||||
},
|
||||
createdAt: '2023-09-19T14:42:38Z',
|
||||
updatedAt: '2024-04-24T03:47:38Z',
|
||||
__typename: 'Group',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/Group/74',
|
||||
fullPath: 'group/74',
|
||||
fullName: 'Twitter / test subgroup',
|
||||
parent: null,
|
||||
webUrl: 'http://127.0.0.1:3000/groups/twitter/test-subgroup',
|
||||
descriptionHtml: '',
|
||||
avatarUrl: null,
|
||||
descendantGroupsCount: 4,
|
||||
projectsCount: 4,
|
||||
groupMembersCount: 4,
|
||||
visibility: 'internal',
|
||||
userPermissions: {
|
||||
removeGroup: false,
|
||||
},
|
||||
maxAccessLevel: {
|
||||
integerValue: 30,
|
||||
},
|
||||
createdAt: '2023-09-19T14:42:38Z',
|
||||
updatedAt: '2024-04-24T03:47:38Z',
|
||||
__typename: 'Group',
|
||||
},
|
||||
];
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
/* eslint-disable @gitlab/require-i18n-strings */
|
||||
|
||||
// This is temporary mock data that will be removed when completing the following:
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/issues/420777
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/issues/421441
|
||||
|
||||
export const organizationProjects = [
|
||||
{
|
||||
id: 'gid://gitlab/Project/8',
|
||||
fullPath: 'project/8',
|
||||
nameWithNamespace: 'Twitter / Typeahead.Js',
|
||||
organizationEditPath: '/-/organizations/default/projects/twitter/Typeahead.Js/edit',
|
||||
webUrl: 'http://127.0.0.1:3000/twitter/Typeahead.Js',
|
||||
topics: ['JavaScript', 'Vue.js', 'GraphQL', 'Jest', 'CSS', 'HTML'],
|
||||
forksCount: 4,
|
||||
avatarUrl: null,
|
||||
starCount: 0,
|
||||
visibility: 'public',
|
||||
openMergeRequestsCount: 5,
|
||||
openIssuesCount: 48,
|
||||
descriptionHtml:
|
||||
'<p data-sourcepos="1:1-1:59" dir="auto">Optio et reprehenderit enim doloremque deserunt et commodi. Sed sit amet iaculis neque. Morbi vel convallis elit. Aliquam vitae arcu orci. Aenean sem velit, dapibus eget enim id, tempor lobortis orci. Pellentesque dignissim nec velit eget sagittis. Maecenas lectus sapien, tincidunt ac cursus a, aliquam eu ipsum. Aliquam posuere maximus augue, ut vehicula elit vulputate condimentum. In libero leo, vehicula nec risus in, ullamcorper convallis risus. Phasellus sit amet lectus sit amet sem volutpat cursus. Nullam facilisis nulla nec lacus pretium, in pretium ex aliquam.</p>',
|
||||
archived: false,
|
||||
mergeRequestsAccessLevel: {
|
||||
stringValue: 'ENABLED',
|
||||
},
|
||||
issuesAccessLevel: {
|
||||
stringValue: 'ENABLED',
|
||||
},
|
||||
forkingAccessLevel: {
|
||||
stringValue: 'ENABLED',
|
||||
},
|
||||
userPermissions: {
|
||||
removeProject: true,
|
||||
viewEditPage: true,
|
||||
},
|
||||
maxAccessLevel: {
|
||||
integerValue: 30,
|
||||
},
|
||||
createdAt: '2023-09-19T14:42:38Z',
|
||||
updatedAt: '2024-04-24T03:47:38Z',
|
||||
__typename: 'Project',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/Project/7',
|
||||
fullPath: 'project/7',
|
||||
nameWithNamespace: 'Flightjs / Flight',
|
||||
organizationEditPath: '/-/organizations/default/projects/flightjs/Flight/edit',
|
||||
webUrl: 'http://127.0.0.1:3000/flightjs/Flight',
|
||||
topics: [],
|
||||
forksCount: 0,
|
||||
avatarUrl: null,
|
||||
starCount: 0,
|
||||
visibility: 'private',
|
||||
openMergeRequestsCount: 10,
|
||||
openIssuesCount: 37,
|
||||
descriptionHtml:
|
||||
'<p data-sourcepos="1:1-1:49" dir="auto">Dolor dicta rerum et ut eius voluptate earum qui.</p>',
|
||||
archived: false,
|
||||
mergeRequestsAccessLevel: {
|
||||
stringValue: 'ENABLED',
|
||||
},
|
||||
issuesAccessLevel: {
|
||||
stringValue: 'ENABLED',
|
||||
},
|
||||
forkingAccessLevel: {
|
||||
stringValue: 'ENABLED',
|
||||
},
|
||||
userPermissions: {
|
||||
removeProject: true,
|
||||
viewEditPage: true,
|
||||
},
|
||||
maxAccessLevel: {
|
||||
integerValue: 30,
|
||||
},
|
||||
createdAt: '2023-09-19T14:42:38Z',
|
||||
updatedAt: '2024-04-24T03:47:38Z',
|
||||
__typename: 'Project',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/Project/6',
|
||||
fullPath: 'project/6',
|
||||
nameWithNamespace: 'Jashkenas / Underscore',
|
||||
organizationEditPath: '/-/organizations/default/projects/jashkenas/Underscore/edit',
|
||||
webUrl: 'http://127.0.0.1:3000/jashkenas/Underscore',
|
||||
topics: [],
|
||||
forksCount: 0,
|
||||
avatarUrl: null,
|
||||
starCount: 0,
|
||||
visibility: 'private',
|
||||
openMergeRequestsCount: 0,
|
||||
openIssuesCount: 34,
|
||||
descriptionHtml:
|
||||
'<p data-sourcepos="1:1-1:52" dir="auto">Incidunt est aliquam autem nihil eveniet quis autem.</p>',
|
||||
archived: false,
|
||||
mergeRequestsAccessLevel: {
|
||||
stringValue: 'ENABLED',
|
||||
},
|
||||
issuesAccessLevel: {
|
||||
stringValue: 'ENABLED',
|
||||
},
|
||||
forkingAccessLevel: {
|
||||
stringValue: 'ENABLED',
|
||||
},
|
||||
userPermissions: {
|
||||
removeProject: true,
|
||||
viewEditPage: true,
|
||||
},
|
||||
maxAccessLevel: {
|
||||
integerValue: 30,
|
||||
},
|
||||
createdAt: '2023-09-19T14:42:38Z',
|
||||
updatedAt: '2024-04-24T03:47:38Z',
|
||||
__typename: 'Project',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/Project/5',
|
||||
fullPath: 'project/5',
|
||||
nameWithNamespace: 'Commit451 / Lab Coat',
|
||||
organizationEditPath: '/-/organizations/default/projects/Commit451/lab-coat/edit',
|
||||
webUrl: 'http://127.0.0.1:3000/Commit451/lab-coat',
|
||||
topics: [],
|
||||
forksCount: 0,
|
||||
avatarUrl: null,
|
||||
starCount: 0,
|
||||
visibility: 'internal',
|
||||
openMergeRequestsCount: 3,
|
||||
openIssuesCount: 49,
|
||||
descriptionHtml:
|
||||
'<p data-sourcepos="1:1-1:34" dir="auto">Sint eos dolorem impedit rerum et.</p>',
|
||||
archived: true,
|
||||
mergeRequestsAccessLevel: {
|
||||
stringValue: 'ENABLED',
|
||||
},
|
||||
issuesAccessLevel: {
|
||||
stringValue: 'ENABLED',
|
||||
},
|
||||
forkingAccessLevel: {
|
||||
stringValue: 'ENABLED',
|
||||
},
|
||||
userPermissions: {
|
||||
removeProject: true,
|
||||
viewEditPage: true,
|
||||
},
|
||||
maxAccessLevel: {
|
||||
integerValue: 30,
|
||||
},
|
||||
createdAt: '2023-09-19T14:42:38Z',
|
||||
updatedAt: '2024-04-24T03:47:38Z',
|
||||
__typename: 'Project',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/Project/1',
|
||||
fullPath: 'project/1',
|
||||
nameWithNamespace: 'Toolbox / Gitlab Smoke Tests',
|
||||
organizationEditPath: '/-/organizations/default/projects/toolbox/gitlab-smoke-tests/edit',
|
||||
webUrl: 'http://127.0.0.1:3000/toolbox/gitlab-smoke-tests',
|
||||
topics: [],
|
||||
forksCount: 0,
|
||||
avatarUrl: null,
|
||||
starCount: 0,
|
||||
visibility: 'internal',
|
||||
openMergeRequestsCount: 20,
|
||||
openIssuesCount: 34,
|
||||
descriptionHtml:
|
||||
'<p data-sourcepos="1:1-1:40" dir="auto">Veritatis error laboriosam libero autem.</p>',
|
||||
archived: false,
|
||||
mergeRequestsAccessLevel: {
|
||||
stringValue: 'ENABLED',
|
||||
},
|
||||
issuesAccessLevel: {
|
||||
stringValue: 'ENABLED',
|
||||
},
|
||||
forkingAccessLevel: {
|
||||
stringValue: 'ENABLED',
|
||||
},
|
||||
userPermissions: {
|
||||
removeProject: false,
|
||||
viewEditPage: true,
|
||||
},
|
||||
maxAccessLevel: {
|
||||
integerValue: 30,
|
||||
},
|
||||
createdAt: '2023-09-19T14:42:38Z',
|
||||
updatedAt: '2024-04-24T03:47:38Z',
|
||||
__typename: 'Project',
|
||||
},
|
||||
];
|
||||
|
|
@ -9,36 +9,20 @@ module Types
|
|||
|
||||
field :col, GraphQL::Types::String,
|
||||
null: true,
|
||||
description: 'Function in which the Sentry error occurred.'
|
||||
description: 'Function in which the Sentry error occurred.', hash_key: "colNo"
|
||||
field :file_name, GraphQL::Types::String,
|
||||
null: true,
|
||||
description: 'File in which the Sentry error occurred.'
|
||||
description: 'File in which the Sentry error occurred.', hash_key: "filename"
|
||||
field :function, GraphQL::Types::String,
|
||||
null: true,
|
||||
description: 'Function in which the Sentry error occurred.'
|
||||
description: 'Function in which the Sentry error occurred.', hash_key: "function"
|
||||
field :line, GraphQL::Types::String,
|
||||
null: true,
|
||||
description: 'Function in which the Sentry error occurred.'
|
||||
description: 'Function in which the Sentry error occurred.', hash_key: "lineNo"
|
||||
field :trace_context, [Types::ErrorTracking::SentryErrorStackTraceContextType],
|
||||
null: true,
|
||||
description: 'Context of the Sentry error.'
|
||||
|
||||
def function
|
||||
object['function']
|
||||
end
|
||||
|
||||
def col
|
||||
object['colNo']
|
||||
end
|
||||
|
||||
def line
|
||||
object['lineNo']
|
||||
end
|
||||
|
||||
def file_name
|
||||
object['filename']
|
||||
end
|
||||
|
||||
def trace_context
|
||||
object['context']
|
||||
end
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ The following steps enable a GitLab site to serve as the Geo **primary** site.
|
|||
### Step 1: Configure the **primary** frontend nodes
|
||||
|
||||
NOTE:
|
||||
Avoid using [`geo_primary_role`](https://docs.gitlab.com/omnibus/roles/#gitlab-geo-roles) because it is intended for a single-node site.
|
||||
Do not use [`geo_primary_role`](https://docs.gitlab.com/omnibus/roles/#gitlab-geo-roles) because it is intended for a single-node site.
|
||||
|
||||
1. Edit `/etc/gitlab/gitlab.rb` and add the following:
|
||||
|
||||
|
|
@ -194,7 +194,7 @@ After streaming replication is enabled in the secondary Geo site's read-replica
|
|||
### Step 4: Configure the frontend application nodes on the Geo **secondary** site
|
||||
|
||||
NOTE:
|
||||
Avoid using [`geo_secondary_role`](https://docs.gitlab.com/omnibus/roles/#gitlab-geo-roles) because it is intended for a single-node site.
|
||||
Do not use [`geo_secondary_role`](https://docs.gitlab.com/omnibus/roles/#gitlab-geo-roles) because it is intended for a single-node site.
|
||||
|
||||
In the minimal [architecture diagram](#architecture-overview) above, there are two
|
||||
machines running the GitLab application services. These services are enabled
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
status: proposed
|
||||
creation-date: "2023-10-10"
|
||||
authors: [ "@thomasrandolph", "@patrickbajao", "@igor.drozdov", "@jerasmus", "@iamphill", "@slashmanov", "@psjakubowska" ]
|
||||
authors: [ "@patrickbajao", "@igor.drozdov", "@jerasmus", "@iamphill", "@slashmanov", "@psjakubowska", "@thomasrandolph" ]
|
||||
coach: [ "@ntepluhina" ]
|
||||
approvers: [ ]
|
||||
owning-stage: "~devops::create"
|
||||
|
|
|
|||
|
|
@ -691,7 +691,8 @@ which variables take precedence.
|
|||
The order of precedence for variables is (from highest to lowest):
|
||||
|
||||
1. [Scan Execution Policies variables](../../user/application_security/policies/scan-execution-policies.md).
|
||||
1. These variables all have the same (highest) precedence:
|
||||
1. Pipeline variables. These variables all have the same precedence:
|
||||
- [Variables passed to downstream pipelines](../pipelines/downstream_pipelines.md#pass-cicd-variables-to-a-downstream-pipeline).
|
||||
- [Trigger variables](../triggers/index.md#pass-cicd-variables-in-the-api-call).
|
||||
- [Scheduled pipeline variables](../pipelines/schedules.md#add-a-pipeline-schedule).
|
||||
- [Manual pipeline run variables](../pipelines/index.md#run-a-pipeline-manually).
|
||||
|
|
|
|||
|
|
@ -5101,10 +5101,11 @@ trigger-multi-project-pipeline:
|
|||
for more details.
|
||||
- You cannot [manually specify CI/CD variables](../jobs/index.md#specifying-variables-when-running-manual-jobs)
|
||||
before running a manual trigger job.
|
||||
- [Manual pipeline variables](../variables/index.md#override-a-defined-cicd-variable)
|
||||
and [scheduled pipeline variables](../pipelines/schedules.md#add-a-pipeline-schedule)
|
||||
are not passed to downstream pipelines by default. Use [trigger:forward](#triggerforward)
|
||||
to forward these variables to downstream pipelines.
|
||||
- [CI/CD variables](#variables) defined in a top-level `variables` section (globally) or in the trigger job are forwarded
|
||||
to the downstream pipeline as [trigger variables](../pipelines/downstream_pipelines.md#pass-cicd-variables-to-a-downstream-pipeline).
|
||||
- [Pipeline variables](../variables/index.md#cicd-variable-precedence) are not passed
|
||||
to downstream pipelines by default. Use [trigger:forward](#triggerforward) to forward
|
||||
these variables to downstream pipelines.
|
||||
- [Job-level persisted variables](../variables/where_variables_can_be_used.md#persisted-variables)
|
||||
are not available in trigger jobs.
|
||||
- Environment variables [defined in the runner's `config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section) are not available to trigger jobs and are not passed to downstream pipelines.
|
||||
|
|
@ -5226,12 +5227,15 @@ Use `trigger:forward` to specify what to forward to the downstream pipeline. You
|
|||
what is forwarded to both [parent-child pipelines](../pipelines/downstream_pipelines.md#parent-child-pipelines)
|
||||
and [multi-project pipelines](../pipelines/downstream_pipelines.md#multi-project-pipelines).
|
||||
|
||||
Forwarded variables do not get forwarded again in nested downstream pipelines by default,
|
||||
unless the nested downstream trigger job also uses `trigger:forward`.
|
||||
|
||||
**Possible inputs**:
|
||||
|
||||
- `yaml_variables`: `true` (default), or `false`. When `true`, variables defined
|
||||
in the trigger job are passed to downstream pipelines.
|
||||
- `pipeline_variables`: `true` or `false` (default). When `true`, [manual pipeline variables](../variables/index.md#override-a-defined-cicd-variable) and [scheduled pipeline variables](../pipelines/schedules.md#add-a-pipeline-schedule)
|
||||
are passed to downstream pipelines.
|
||||
- `pipeline_variables`: `true` or `false` (default). When `true`, [pipeline variables](../variables/index.md#cicd-variable-precedence)
|
||||
are passed to the downstream pipeline.
|
||||
|
||||
**Example of `trigger:forward`**:
|
||||
|
||||
|
|
@ -5270,10 +5274,9 @@ child3:
|
|||
|
||||
**Additional details**:
|
||||
|
||||
- CI/CD variables forwarded to downstream pipelines with `trigger:forward` have the
|
||||
[highest precedence](../variables/index.md#cicd-variable-precedence). If a variable
|
||||
with the same name is defined in the downstream pipeline, that variable is overwritten
|
||||
by the forwarded variable.
|
||||
- CI/CD variables forwarded to downstream pipelines with `trigger:forward` are [pipeline variables](../variables/index.md#cicd-variable-precedence),
|
||||
which have high precedence. If a variable with the same name is defined in the downstream pipeline,
|
||||
that variable is usually overwritten by the forwarded variable.
|
||||
|
||||
### `variables`
|
||||
|
||||
|
|
|
|||
|
|
@ -262,6 +262,10 @@ you must take one of the following actions based on your configuration:
|
|||
in GitLab 16.7 and earlier have been implemented on all self-managed instances. Dependent changes can then be released
|
||||
in GitLab 16.8 and later. [Issue 429611](https://gitlab.com/gitlab-org/gitlab/-/issues/429611) provides more details.
|
||||
|
||||
- If you skip 16.6 in your upgrade path, you might experience performance issues after upgrading to 16.7
|
||||
when your instance processes a background database migration from the GitLab 16.6 release.
|
||||
Read more about the `ci_builds` migration in the [16.6.0 upgrade notes](#1660).
|
||||
|
||||
- Normally, backups in environments that have PgBouncer must [bypass PgBouncer by setting variables that are prefixed with `GITLAB_BACKUP_`](../../administration/backup_restore/backup_gitlab.md#bypassing-pgbouncer). However, due to an [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/422163), `gitlab-backup` uses the regular database connection through PgBouncer instead of the direct connection defined in the override, and the database backup fails. The workaround is to use `pg_dump` directly.
|
||||
|
||||
**Affected releases**:
|
||||
|
|
@ -329,6 +333,33 @@ take one of the following actions based on your configuration:
|
|||
|
||||
## 16.6.0
|
||||
|
||||
- GitLab 16.6 introduces a background migration that re-writes every row in the
|
||||
CI jobs table (`ci_builds`) as part of upgrading the primary key to 64 bits.
|
||||
`ci_builds` is one of the largest tables on most GitLab instances, so this
|
||||
migration runs more aggressively than usual to ensure it takes a reasonable amount of time.
|
||||
Background migrations usually pause between batches of rows, but this migration does not.
|
||||
|
||||
This might cause performance issues in self-managed environments:
|
||||
|
||||
- Disk I/O will be higher than usual. This will be a particular issue for instances
|
||||
hosted by cloud providers where disk I/O is restricted.
|
||||
- Autovacuum might run more frequently in the background to ensure the old
|
||||
rows (dead tuples) are removed, and to perform other related housekeeping.
|
||||
- Queries might run slowly, temporarily, because inefficient query plans get
|
||||
selected by PostgreSQL. This might be triggered by the volume of change on the table.
|
||||
|
||||
Workarounds:
|
||||
|
||||
- Pause the running migration in the [Admin Area](../background_migrations.md#from-the-gitlab-ui).
|
||||
- Recreate table statistics manually on the
|
||||
[database console](../../administration/troubleshooting/postgresql.md#start-a-database-console)
|
||||
to ensure the right query plan is selected:
|
||||
|
||||
```sql
|
||||
SET statement_timeout = 0;
|
||||
VACUUM FREEZE VERBOSE ANALYZE public.ci_builds;
|
||||
```
|
||||
|
||||
- Old [CI Environment destroy jobs may be spawned](https://gitlab.com/gitlab-org/gitlab/-/issues/433264#) after upgrading to GitLab 16.6.
|
||||
- Normally, backups in environments that have PgBouncer must [bypass PgBouncer by setting variables that are prefixed with `GITLAB_BACKUP_`](../../administration/backup_restore/backup_gitlab.md#bypassing-pgbouncer). However, due to an [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/422163), `gitlab-backup` uses the regular database connection through PgBouncer instead of the direct connection defined in the override, and the database backup fails. The workaround is to use `pg_dump` directly.
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,16 @@ DETAILS:
|
|||
- LLM: Vertex AI Codey [`text-bison`](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/text)
|
||||
- [View documentation](project/merge_requests/ai_in_merge_requests.md#summarize-merge-request-changes).
|
||||
|
||||
### Merge request template population
|
||||
|
||||
DETAILS:
|
||||
**Tier:** Freely available for Ultimate for a limited time. In the future, will require Ultimate with [GitLab Duo Enterprise](../subscriptions/subscription-add-ons.md).
|
||||
**Offering:** GitLab.com
|
||||
|
||||
- Generates a description for the merge request based on the contents of the template.
|
||||
- LLM: Vertex AI Codey [`text-bison`](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/text)
|
||||
- [View documentation](project/merge_requests/ai_in_merge_requests.md#fill-in-merge-request-templates).
|
||||
|
||||
### Vulnerability explanation
|
||||
|
||||
DETAILS:
|
||||
|
|
@ -124,16 +134,6 @@ DETAILS:
|
|||
- LLM: Anthropic [`Claude-2.1`](https://docs.anthropic.com/claude/docs/models-overview#model-comparison)
|
||||
- [View documentation](ai_experiments.md#summarize-an-issue-with-issue-description-generation).
|
||||
|
||||
### Merge request template population
|
||||
|
||||
DETAILS:
|
||||
**Tier:** Freely available for Ultimate for a limited time. In the future, will require Ultimate with [GitLab Duo Enterprise](../subscriptions/subscription-add-ons.md).
|
||||
**Offering:** GitLab.com
|
||||
|
||||
- Generates a description for the merge request based on the contents of the template.
|
||||
- LLM: Vertex AI Codey [`text-bison`](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/text)
|
||||
- [View documentation](project/merge_requests/ai_in_merge_requests.md#fill-in-merge-request-templates).
|
||||
|
||||
### Code review summary
|
||||
|
||||
DETAILS:
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ module API
|
|||
include APIGuard
|
||||
helpers ::API::Helpers::EventsHelpers
|
||||
|
||||
allow_access_with_scope :read_user, if: -> (request) { request.get? || request.head? }
|
||||
allow_access_with_scope :read_user, if: ->(request) { request.get? || request.head? }
|
||||
|
||||
feature_category :user_profile
|
||||
urgency :low
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ module API
|
|||
|
||||
feature_flags_user_lists_tags = %w[feature_flags_user_lists]
|
||||
|
||||
error_formatter :json, -> (message, _backtrace, _options, _env, _original_exception) {
|
||||
error_formatter :json, ->(message, _backtrace, _options, _env, _original_exception) {
|
||||
message.is_a?(String) ? { message: message }.to_json : message.to_json
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ module API
|
|||
requires :id, type: String, desc: 'The project ID', documentation: { example: 'gitlab-org/gitlab' }
|
||||
end
|
||||
resource :projects, requirements: FILE_ENDPOINT_REQUIREMENTS do
|
||||
allow_access_with_scope :read_repository, if: -> (request) { request.get? || request.head? }
|
||||
allow_access_with_scope :read_repository, if: ->(request) { request.get? || request.head? }
|
||||
|
||||
desc 'Get blame file metadata from repository'
|
||||
params do
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ module API
|
|||
content_type :binary, 'application/octet-stream'
|
||||
content_type :yaml, 'text/yaml'
|
||||
|
||||
formatter :yaml, -> (object, _) { object.serializable_hash.stringify_keys.to_yaml }
|
||||
formatter :yaml, ->(object, _) { object.serializable_hash.stringify_keys.to_yaml }
|
||||
|
||||
authenticate_with do |accept|
|
||||
accept.token_types(:personal_access_token, :deploy_token, :job_token)
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ module API
|
|||
# @param expires_in [ActiveSupport::Duration, Integer] an expiry time for the cache entry
|
||||
# @param presenter_args [Hash] keyword arguments to be passed to the entity
|
||||
# @return [Gitlab::Json::PrecompiledJson]
|
||||
def present_cached(obj_or_collection, with:, cache_context: -> (_) { current_user&.cache_key }, expires_in: Gitlab::Cache::Helpers::DEFAULT_EXPIRY, **presenter_args)
|
||||
def present_cached(obj_or_collection, with:, cache_context: ->(_) { current_user&.cache_key }, expires_in: Gitlab::Cache::Helpers::DEFAULT_EXPIRY, **presenter_args)
|
||||
json =
|
||||
if obj_or_collection.is_a?(Enumerable)
|
||||
cached_collection(
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ module API
|
|||
|
||||
present_cached merge_requests,
|
||||
expires_in: 8.hours,
|
||||
cache_context: -> (mr) do
|
||||
cache_context: ->(mr) do
|
||||
[
|
||||
current_user&.cache_key,
|
||||
mr.merge_status,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ module API
|
|||
helpers ::API::Helpers::GraphqlHelpers
|
||||
include APIGuard
|
||||
|
||||
allow_access_with_scope [:read_user, :ai_features], if: -> (request) { request.get? || request.head? }
|
||||
allow_access_with_scope [:read_user, :ai_features], if: ->(request) { request.get? || request.head? }
|
||||
|
||||
before { authenticate! }
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ module API
|
|||
desc: 'Date time string, ISO 8601 formatted, such as 2016-03-11T03:45:40Z.'\
|
||||
'Timestamp marking end point of annotation.'\
|
||||
'When not supplied, an annotation displays as a single event at the start point.'
|
||||
requires :dashboard_path, type: String, coerce_with: -> (val) { CGI.unescape(val) },
|
||||
requires :dashboard_path, type: String, coerce_with: ->(val) { CGI.unescape(val) },
|
||||
desc: 'ID of the dashboard which needs to be annotated.'\
|
||||
'Treated as a CGI-escaped path, and automatically un-escaped.'
|
||||
requires :description, type: String, desc: 'Description of the annotation.'
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ module API
|
|||
# `current_user` could be absent if the releases are publicly accesible.
|
||||
# We should not use `cache_key` for the user because the version/updated_at
|
||||
# context is unnecessary here.
|
||||
cache_context: -> (_) { "user:{#{current_user&.id}}" },
|
||||
cache_context: ->(_) { "user:{#{current_user&.id}}" },
|
||||
expires_in: 5.minutes,
|
||||
current_user: current_user,
|
||||
include_html_description: declared_params[:include_html_description]
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ module API
|
|||
optional :domain_denylist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Enter multiple entries on separate lines. Ex: domain.com, *.domain.com'
|
||||
optional :domain_allowlist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'ONLY users with e-mail addresses that match these domain(s) will be able to sign-up. Wildcards allowed. Enter multiple entries on separate lines. Ex: domain.com, *.domain.com'
|
||||
optional :eks_integration_enabled, type: Boolean, desc: 'Enable integration with Amazon EKS'
|
||||
given eks_integration_enabled: -> (val) { val } do
|
||||
given eks_integration_enabled: ->(val) { val } do
|
||||
requires :eks_account_id, type: String, desc: 'Amazon account ID for EKS integration'
|
||||
requires :eks_access_key_id, type: String, desc: 'Access key ID for the EKS integration IAM user'
|
||||
requires :eks_secret_access_key, type: String, desc: 'Secret access key for the EKS integration IAM user'
|
||||
|
|
@ -223,7 +223,7 @@ module API
|
|||
optional :ci_max_includes, type: Integer, desc: 'Maximum number of includes per pipeline'
|
||||
optional :security_policy_global_group_approvers_enabled, type: Boolean, desc: 'Query scan result policy approval groups globally'
|
||||
optional :slack_app_enabled, type: Grape::API::Boolean, desc: 'Enable the GitLab for Slack app'
|
||||
given slack_app_enabled: -> (val) { val } do
|
||||
given slack_app_enabled: ->(val) { val } do
|
||||
requires :slack_app_id, type: String, desc: 'The client ID of the GitLab for Slack app'
|
||||
requires :slack_app_secret, type: String, desc: 'The client secret of the GitLab for Slack app. Used for authenticating OAuth requests from the app'
|
||||
requires :slack_app_signing_secret, type: String, desc: 'The signing secret of the GitLab for Slack app. Used for authenticating API requests from the app'
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ module API
|
|||
project: user_project,
|
||||
releases: find_releases(paginated_tags),
|
||||
current_user: current_user,
|
||||
cache_context: -> (_tag) do
|
||||
cache_context: ->(_tag) do
|
||||
[user_project.cache_key, can?(current_user, :read_release, user_project)].join(':')
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ module API
|
|||
def present_feature_flags
|
||||
present_cached feature_flags_client,
|
||||
with: ::API::Entities::Unleash::ClientFeatureFlags,
|
||||
cache_context: -> (client) { client.unleash_api_cache_key }
|
||||
cache_context: ->(client) { client.unleash_api_cache_key }
|
||||
end
|
||||
|
||||
def feature_flags_client
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ module Gitlab
|
|||
old_path = upload.absolute_path
|
||||
old_path_sub = '-/system/note/attachment'
|
||||
|
||||
if !File.exist?(old_path) || !old_path.include?(old_path_sub)
|
||||
if !File.exist?(old_path) || old_path.exclude?(old_path_sub)
|
||||
log_legacy_diff_note_problem(old_path)
|
||||
return false
|
||||
end
|
||||
|
|
|
|||
|
|
@ -119,19 +119,19 @@ module Gitlab
|
|||
|
||||
# matches glob patterns that only match files in the top level directory
|
||||
def top_level_glob?(glob)
|
||||
!glob.include?('/') && !glob.include?('**')
|
||||
glob.exclude?('/') && glob.exclude?('**')
|
||||
end
|
||||
|
||||
# matches glob patterns that have no metacharacters for File#fnmatch?
|
||||
def exact_glob?(glob)
|
||||
!glob.include?('*') && !glob.include?('?') && !glob.include?('[') && !glob.include?('{')
|
||||
glob.exclude?('*') && glob.exclude?('?') && glob.exclude?('[') && glob.exclude?('{')
|
||||
end
|
||||
|
||||
# matches glob patterns like **/*.js or **/*.so.1 to optimize with path.end_with?('.js')
|
||||
def extension_glob?(glob)
|
||||
without_nested = without_wildcard_nested_pattern(glob)
|
||||
|
||||
without_nested.start_with?('.') && !without_nested.include?('/') && exact_glob?(without_nested)
|
||||
without_nested.start_with?('.') && without_nested.exclude?('/') && exact_glob?(without_nested)
|
||||
end
|
||||
|
||||
def without_wildcard_nested_pattern(glob)
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def parse_source(node)
|
||||
return unless project_path && paths && !node.include?(GO_SOURCE_PATTERN)
|
||||
return unless project_path && paths && node.exclude?(GO_SOURCE_PATTERN)
|
||||
|
||||
source = build_source_path(node)
|
||||
self.sources << source if source.present?
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ module Gitlab
|
|||
def observe_queue_depth(queue, size)
|
||||
return unless Feature.enabled?(:gitlab_ci_builds_queuing_metrics, type: :ops)
|
||||
|
||||
if !Rails.env.production? && !QUEUE_DEPTH_HISTOGRAMS.include?(queue)
|
||||
if !Rails.env.production? && QUEUE_DEPTH_HISTOGRAMS.exclude?(queue)
|
||||
raise ArgumentError, "unknown queue depth label: #{queue}"
|
||||
end
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def self.increment_queue_operation(operation)
|
||||
if !Rails.env.production? && !OPERATION_COUNTERS.include?(operation)
|
||||
if !Rails.env.production? && OPERATION_COUNTERS.exclude?(operation)
|
||||
raise ArgumentError, "unknown queue operation: #{operation}"
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ module Gitlab
|
|||
next unless shared_model.limit_connection_names.include?(connection_name.to_sym)
|
||||
end
|
||||
|
||||
next if selected_databases.present? && !selected_databases.include?(connection_name.to_sym)
|
||||
next if selected_databases.present? && selected_databases.exclude?(connection_name.to_sym)
|
||||
|
||||
with_shared_connection(connection_model.connection, connection_name) do
|
||||
yield shared_model, connection_name
|
||||
|
|
@ -63,7 +63,7 @@ module Gitlab
|
|||
def with_model_connection(model, selected_databases, &blk)
|
||||
connection_name = model.connection_db_config.name
|
||||
|
||||
return if selected_databases.present? && !selected_databases.include?(connection_name.to_sym)
|
||||
return if selected_databases.present? && selected_databases.exclude?(connection_name.to_sym)
|
||||
|
||||
with_shared_connection(model.connection, connection_name) do
|
||||
yield model, connection_name
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def can_handle_legacy_format?
|
||||
project_path && !incoming_email_token.include?('+') && !mail_key.include?(Gitlab::Email::Common::UNSUBSCRIBE_SUFFIX_LEGACY)
|
||||
project_path && incoming_email_token.exclude?('+') && mail_key.exclude?(Gitlab::Email::Common::UNSUBSCRIBE_SUFFIX_LEGACY)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def can_handle_legacy_format?
|
||||
project_path && project_path.include?('/') && !mail_key.include?('+')
|
||||
project_path && project_path.include?('/') && mail_key.exclude?('+')
|
||||
end
|
||||
|
||||
def author
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ module Gitlab
|
|||
|
||||
# remove variable definitions only used in skipped (client) fields
|
||||
vars = op.variables.reject do |v|
|
||||
@skipped_arguments.include?(v.name) && !@printed_arguments.include?(v.name)
|
||||
@skipped_arguments.include?(v.name) && @printed_arguments.exclude?(v.name)
|
||||
end
|
||||
|
||||
if vars.any?
|
||||
|
|
@ -117,7 +117,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def print_fragment_definition(fragment_def, indent: "")
|
||||
if skips? && @skipped_fragments.include?(fragment_def.name) && !@used_fragments.include?(fragment_def.name)
|
||||
if skips? && @skipped_fragments.include?(fragment_def.name) && @used_fragments.exclude?(fragment_def.name)
|
||||
return
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def permitted_attributes_defined?(relation_sym)
|
||||
!DISABLED_RELATION_NAMES.include?(relation_sym) && @attributes_finder.included_attributes.key?(relation_sym)
|
||||
DISABLED_RELATION_NAMES.exclude?(relation_sym) && @attributes_finder.included_attributes.key?(relation_sym)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ module Gitlab
|
|||
begin
|
||||
print(message)
|
||||
answer = $stdin.gets.chomp
|
||||
end while choices.present? && !choices.include?(answer)
|
||||
end while choices.present? && choices.exclude?(answer)
|
||||
answer
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ module QA
|
|||
raise ArgumentError, "Please provide GITLAB_QA_ADMIN_ACCESS_TOKEN" unless ENV['GITLAB_QA_ADMIN_ACCESS_TOKEN']
|
||||
|
||||
@api_client = Runtime::API::Client.new(ENV['GITLAB_ADDRESS'], personal_access_token: ENV['GITLAB_QA_ADMIN_ACCESS_TOKEN'])
|
||||
@dry_run = !FALSY_VALUES.include?(dry_run.to_s.downcase)
|
||||
@dry_run = FALSY_VALUES.exclude?(dry_run.to_s.downcase)
|
||||
@delete_before = Date.parse(delete_before)
|
||||
@page_no = '1'
|
||||
@exclude_users = Array(exclude_users.to_s.split(',')) + EXCLUDE_USERS
|
||||
|
|
@ -61,7 +61,7 @@ module QA
|
|||
JSON.parse(response.body).select do |user|
|
||||
user['username'].start_with?('qa-user-', 'test-user-') \
|
||||
&& (user['name'] == 'QA Tests' || user['name'].start_with?('QA User')) \
|
||||
&& !@exclude_users.include?(user['username']) \
|
||||
&& @exclude_users.exclude?(user['username']) \
|
||||
&& Date.parse(user.fetch('created_at', Date.today.to_s)) < @delete_before
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -75,55 +75,80 @@ describe('LogViewer', () => {
|
|||
});
|
||||
|
||||
describe('when displaying a section', () => {
|
||||
let log;
|
||||
|
||||
beforeEach(() => {
|
||||
createWrapper({
|
||||
props: {
|
||||
log: [
|
||||
{
|
||||
sections: [],
|
||||
content: [{ text: 'log:' }],
|
||||
},
|
||||
{
|
||||
sections: [],
|
||||
header: 'section_1',
|
||||
content: [{ text: 'header' }],
|
||||
},
|
||||
{
|
||||
sections: ['section_1'],
|
||||
header: 'section_1_1',
|
||||
content: [{ text: 'line 1' }],
|
||||
},
|
||||
{
|
||||
sections: ['section_1', 'section_1_1'],
|
||||
content: [{ text: 'line 1.1' }],
|
||||
},
|
||||
{
|
||||
sections: [],
|
||||
content: [{ text: 'done!' }],
|
||||
},
|
||||
],
|
||||
log = [
|
||||
{
|
||||
sections: [],
|
||||
header: 'section_1',
|
||||
content: [{ text: 'level 0' }],
|
||||
},
|
||||
});
|
||||
{
|
||||
sections: ['section_1'],
|
||||
header: 'section_1_1',
|
||||
content: [{ text: 'level 1' }],
|
||||
},
|
||||
{
|
||||
sections: ['section_1', 'section_1_1'],
|
||||
content: [{ text: 'level 2' }],
|
||||
},
|
||||
];
|
||||
|
||||
createWrapper({ props: { log } });
|
||||
});
|
||||
|
||||
it('shows an open section', () => {
|
||||
it('shows a section', () => {
|
||||
expect(findLogLineAt(0).findComponent(GlIcon).props('name')).toBe('chevron-lg-down');
|
||||
expect(findLogLineAt(1).findComponent(GlIcon).props('name')).toBe('chevron-lg-down');
|
||||
|
||||
expect(getShownLines()).toEqual(['1 log:', '2 header', '3 line 1', '4 line 1.1', '5 done!']);
|
||||
expect(getShownLines()).toEqual(['1 level 0', '2 level 1', '3 level 2']);
|
||||
});
|
||||
|
||||
it('collapses a section', async () => {
|
||||
await findLogLineAt(1).trigger('click');
|
||||
await findLogLineAt(0).trigger('click');
|
||||
|
||||
expect(findLogLineAt(1).findComponent(GlIcon).props('name')).toBe('chevron-lg-right');
|
||||
expect(getShownLines()).toEqual(['1 log:', '2 header', '5 done!']);
|
||||
expect(findLogLineAt(0).findComponent(GlIcon).props('name')).toBe('chevron-lg-right');
|
||||
expect(getShownLines()).toEqual(['1 level 0']);
|
||||
});
|
||||
|
||||
it('collapses a subsection', async () => {
|
||||
await findLogLineAt(2).trigger('click');
|
||||
await findLogLineAt(1).trigger('click');
|
||||
|
||||
expect(findLogLineAt(2).findComponent(GlIcon).props('name')).toBe('chevron-lg-right');
|
||||
expect(getShownLines()).toEqual(['1 log:', '2 header', '3 line 1', '5 done!']);
|
||||
expect(findLogLineAt(1).findComponent(GlIcon).props('name')).toBe('chevron-lg-right');
|
||||
expect(getShownLines()).toEqual(['1 level 0', '2 level 1']);
|
||||
});
|
||||
|
||||
describe('when displaying a pre-collapsed section', () => {
|
||||
beforeEach(() => {
|
||||
log[1].options = { collapsed: 'true' };
|
||||
|
||||
createWrapper({
|
||||
props: { log },
|
||||
});
|
||||
});
|
||||
|
||||
it('shows a collapsed section', () => {
|
||||
expect(findLogLineAt(1).findComponent(GlIcon).props('name')).toBe('chevron-lg-right');
|
||||
|
||||
expect(getShownLines()).toEqual(['1 level 0', '2 level 1']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when displaying a collapsed section', () => {
|
||||
beforeEach(() => {
|
||||
log[1].options = { collapsed: 'false' };
|
||||
|
||||
createWrapper({
|
||||
props: { log },
|
||||
});
|
||||
});
|
||||
|
||||
it('shows a collapsed section', () => {
|
||||
expect(findLogLineAt(1).findComponent(GlIcon).props('name')).toBe('chevron-lg-down');
|
||||
|
||||
expect(getShownLines()).toEqual(['1 level 0', '2 level 1', '3 level 2']);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -65,6 +65,25 @@ describe('Log scanner', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it('scans a section with options', () => {
|
||||
const lines = [
|
||||
'section_start:1000:my_section[key1=value1,key2=value2]\rheader 1',
|
||||
'line 1',
|
||||
'section_end:1010:my_section',
|
||||
];
|
||||
|
||||
expect(lines.map((l) => scanner.scan(l))).toEqual([
|
||||
{
|
||||
content: [{ style: [], text: 'header 1' }],
|
||||
header: 'my_section',
|
||||
options: { key1: 'value1', key2: 'value2' },
|
||||
sections: [],
|
||||
},
|
||||
{ content: [{ style: [], text: 'line 1' }], sections: ['my_section'] },
|
||||
{ content: [{ duration: 10, section: 'my_section' }], sections: [] },
|
||||
]);
|
||||
});
|
||||
|
||||
it('scans a sub section with their durations', () => {
|
||||
const lines = [
|
||||
'section_start:1010:my_section\rheader 1',
|
||||
|
|
|
|||
|
|
@ -34,6 +34,15 @@ RSpec.describe 'Organizations (GraphQL fixtures)', feature_category: :cell do
|
|||
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
let_it_be(:organizations) { create_list(:organization, 3) }
|
||||
let_it_be(:organization) { organizations.first }
|
||||
let_it_be(:groups) { create_list(:group, 3, organization: organization) }
|
||||
let_it_be(:group) { groups.first }
|
||||
let_it_be(:projects) do
|
||||
groups.map do |group|
|
||||
create(:project, :public, namespace: group, organization: organization)
|
||||
end
|
||||
end
|
||||
|
||||
let_it_be(:organization_users) do
|
||||
organizations.map do |organization|
|
||||
create(:organization_user, organization: organization, user: current_user)
|
||||
|
|
@ -46,6 +55,10 @@ RSpec.describe 'Organizations (GraphQL fixtures)', feature_category: :cell do
|
|||
end
|
||||
end
|
||||
|
||||
before_all do
|
||||
group.add_owner(current_user)
|
||||
end
|
||||
|
||||
before do
|
||||
sign_in(current_user)
|
||||
end
|
||||
|
|
@ -63,5 +76,41 @@ RSpec.describe 'Organizations (GraphQL fixtures)', feature_category: :cell do
|
|||
expect_graphql_errors_to_be_empty
|
||||
end
|
||||
end
|
||||
|
||||
describe 'organization groups' do
|
||||
base_input_path = 'organizations/shared/graphql/queries/'
|
||||
base_output_path = 'graphql/organizations/'
|
||||
query_name = 'groups.query.graphql'
|
||||
|
||||
it "#{base_output_path}#{query_name}.json" do
|
||||
query = get_graphql_query_as_string("#{base_input_path}#{query_name}")
|
||||
|
||||
post_graphql(
|
||||
query,
|
||||
current_user: current_user,
|
||||
variables: { id: organization.to_global_id, search: '', first: 3, sort: 'created_at_asc' }
|
||||
)
|
||||
|
||||
expect_graphql_errors_to_be_empty
|
||||
end
|
||||
end
|
||||
|
||||
describe 'organization projects' do
|
||||
base_input_path = 'organizations/shared/graphql/queries/'
|
||||
base_output_path = 'graphql/organizations/'
|
||||
query_name = 'projects.query.graphql'
|
||||
|
||||
it "#{base_output_path}#{query_name}.json" do
|
||||
query = get_graphql_query_as_string("#{base_input_path}#{query_name}")
|
||||
|
||||
post_graphql(
|
||||
query,
|
||||
current_user: current_user,
|
||||
variables: { id: organization.to_global_id, search: '', first: 3, sort: 'created_at_asc' }
|
||||
)
|
||||
|
||||
expect_graphql_errors_to_be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import VueApollo from 'vue-apollo';
|
||||
import Vue from 'vue';
|
||||
import { GlEmptyState, GlLoadingIcon, GlKeysetPagination } from '@gitlab/ui';
|
||||
import organizationGroupsGraphQlResponse from 'test_fixtures/graphql/organizations/groups.query.graphql.json';
|
||||
import GroupsView from '~/organizations/shared/components/groups_view.vue';
|
||||
import { SORT_DIRECTION_ASC, SORT_ITEM_NAME } from '~/organizations/shared/constants';
|
||||
import NewGroupButton from '~/organizations/shared/components/new_group_button.vue';
|
||||
|
|
@ -19,13 +20,20 @@ import { DEFAULT_PER_PAGE } from '~/api';
|
|||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { organizationGroups as nodes } from '~/organizations/mock_data';
|
||||
import {
|
||||
pageInfoMultiplePages,
|
||||
pageInfoEmpty,
|
||||
pageInfoOnePage,
|
||||
} from 'jest/organizations/mock_data';
|
||||
|
||||
const {
|
||||
data: {
|
||||
organization: {
|
||||
groups: { nodes },
|
||||
},
|
||||
},
|
||||
} = organizationGroupsGraphQlResponse;
|
||||
|
||||
const MOCK_DELETE_PARAMS = {
|
||||
testParam: true,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import VueApollo from 'vue-apollo';
|
||||
import Vue from 'vue';
|
||||
import { GlLoadingIcon, GlEmptyState, GlKeysetPagination } from '@gitlab/ui';
|
||||
import organizationProjectsGraphQlResponse from 'test_fixtures/graphql/organizations/projects.query.graphql.json';
|
||||
import ProjectsView from '~/organizations/shared/components/projects_view.vue';
|
||||
import { SORT_DIRECTION_ASC, SORT_ITEM_NAME } from '~/organizations/shared/constants';
|
||||
import NewProjectButton from '~/organizations/shared/components/new_project_button.vue';
|
||||
|
|
@ -19,7 +20,6 @@ import { DEFAULT_PER_PAGE } from '~/api';
|
|||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { organizationProjects as nodes } from '~/organizations/mock_data';
|
||||
import {
|
||||
pageInfoMultiplePages,
|
||||
pageInfoEmpty,
|
||||
|
|
@ -41,6 +41,14 @@ jest.mock('ee_else_ce/organizations/shared/utils', () => ({
|
|||
|
||||
Vue.use(VueApollo);
|
||||
|
||||
const {
|
||||
data: {
|
||||
organization: {
|
||||
projects: { nodes },
|
||||
},
|
||||
},
|
||||
} = organizationProjectsGraphQlResponse;
|
||||
|
||||
describe('ProjectsView', () => {
|
||||
let wrapper;
|
||||
let mockApollo;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import organizationGroupsGraphQlResponse from 'test_fixtures/graphql/organizations/groups.query.graphql.json';
|
||||
import organizationProjectsGraphQlResponse from 'test_fixtures/graphql/organizations/projects.query.graphql.json';
|
||||
import {
|
||||
formatProjects,
|
||||
formatGroups,
|
||||
|
|
@ -10,7 +12,6 @@ import { SORT_CREATED_AT, SORT_UPDATED_AT, SORT_NAME } from '~/organizations/sha
|
|||
import { ACTION_EDIT, ACTION_DELETE } from '~/vue_shared/components/list_actions/constants';
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import toast from '~/vue_shared/plugins/global_toast';
|
||||
import { organizationProjects, organizationGroups } from '~/organizations/mock_data';
|
||||
import {
|
||||
TIMESTAMP_TYPE_CREATED_AT,
|
||||
TIMESTAMP_TYPE_UPDATED_AT,
|
||||
|
|
@ -18,6 +19,22 @@ import {
|
|||
|
||||
jest.mock('~/vue_shared/plugins/global_toast');
|
||||
|
||||
const {
|
||||
data: {
|
||||
organization: {
|
||||
groups: { nodes: organizationGroups },
|
||||
},
|
||||
},
|
||||
} = organizationGroupsGraphQlResponse;
|
||||
|
||||
const {
|
||||
data: {
|
||||
organization: {
|
||||
projects: { nodes: organizationProjects },
|
||||
},
|
||||
},
|
||||
} = organizationProjectsGraphQlResponse;
|
||||
|
||||
describe('formatProjects', () => {
|
||||
it('correctly formats the projects', () => {
|
||||
const [firstMockProject] = organizationProjects;
|
||||
|
|
@ -31,7 +48,7 @@ describe('formatProjects', () => {
|
|||
issuesAccessLevel: firstMockProject.issuesAccessLevel.stringValue,
|
||||
forkingAccessLevel: firstMockProject.forkingAccessLevel.stringValue,
|
||||
accessLevel: {
|
||||
integerValue: 30,
|
||||
integerValue: 50,
|
||||
},
|
||||
availableActions: [ACTION_EDIT, ACTION_DELETE],
|
||||
actionLoadingStates: {
|
||||
|
|
@ -43,28 +60,18 @@ describe('formatProjects', () => {
|
|||
});
|
||||
|
||||
describe('when project does not have delete permissions', () => {
|
||||
const [firstProject] = organizationProjects;
|
||||
const nonDeletableProject = {
|
||||
...firstProject,
|
||||
userPermissions: { ...firstProject.userPermissions, removeProject: false },
|
||||
};
|
||||
const [nonDeletableFormattedProject] = formatProjects([nonDeletableProject]);
|
||||
const nonDeletableFormattedProject = formatProjects(organizationProjects)[1];
|
||||
|
||||
it('does not include delete action in `availableActions`', () => {
|
||||
expect(nonDeletableFormattedProject.availableActions).toEqual([ACTION_EDIT]);
|
||||
expect(nonDeletableFormattedProject.availableActions).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when project does not have edit permissions', () => {
|
||||
const [firstProject] = organizationProjects;
|
||||
const nonEditableProject = {
|
||||
...firstProject,
|
||||
userPermissions: { ...firstProject.userPermissions, viewEditPage: false },
|
||||
};
|
||||
const [nonEditableFormattedProject] = formatProjects([nonEditableProject]);
|
||||
const nonEditableFormattedProject = formatProjects(organizationProjects)[1];
|
||||
|
||||
it('does not include edit action in `availableActions`', () => {
|
||||
expect(nonEditableFormattedProject.availableActions).toEqual([ACTION_DELETE]);
|
||||
expect(nonEditableFormattedProject.availableActions).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -82,7 +89,7 @@ describe('formatGroups', () => {
|
|||
parent: null,
|
||||
editPath: `${firstFormattedGroup.webUrl}/-/edit`,
|
||||
accessLevel: {
|
||||
integerValue: 30,
|
||||
integerValue: 50,
|
||||
},
|
||||
availableActions: [ACTION_EDIT, ACTION_DELETE],
|
||||
actionLoadingStates: {
|
||||
|
|
@ -93,9 +100,9 @@ describe('formatGroups', () => {
|
|||
});
|
||||
|
||||
it('correctly formats the groups without delete permissions', () => {
|
||||
const nonDeletableGroup = organizationGroups[organizationGroups.length - 1];
|
||||
const nonDeletableGroup = organizationGroups[1];
|
||||
const formattedGroups = formatGroups(organizationGroups);
|
||||
const nonDeletableFormattedGroup = formattedGroups[formattedGroups.length - 1];
|
||||
const nonDeletableFormattedGroup = formattedGroups[1];
|
||||
|
||||
expect(nonDeletableFormattedGroup).toMatchObject({
|
||||
id: getIdFromGraphQLId(nonDeletableGroup.id),
|
||||
|
|
@ -104,7 +111,7 @@ describe('formatGroups', () => {
|
|||
parent: null,
|
||||
editPath: `${nonDeletableFormattedGroup.webUrl}/-/edit`,
|
||||
accessLevel: {
|
||||
integerValue: 30,
|
||||
integerValue: 0,
|
||||
},
|
||||
availableActions: [ACTION_EDIT],
|
||||
actionLoadingStates: {
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ RSpec.describe ContainerRegistry::Blob do
|
|||
context 'for a valid address' do
|
||||
before do
|
||||
stub_request(:get, location)
|
||||
.with { |request| !request.headers.include?('Authorization') }
|
||||
.with { |request| request.headers.exclude?('Authorization') }
|
||||
.to_return(
|
||||
status: 200,
|
||||
headers: { 'Content-Type' => 'application/json' },
|
||||
|
|
@ -115,7 +115,7 @@ RSpec.describe ContainerRegistry::Blob do
|
|||
context 'for a relative address' do
|
||||
before do
|
||||
stub_request(:get, 'http://registry.gitlab/relative')
|
||||
.with { |request| !request.headers.include?('Authorization') }
|
||||
.with { |request| request.headers.exclude?('Authorization') }
|
||||
.to_return(
|
||||
status: 200,
|
||||
headers: { 'Content-Type' => 'application/json' },
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ RSpec.describe ContainerRegistry::Client, feature_category: :container_registry
|
|||
# https://github.com/bblimke/webmock/blob/master/lib/webmock/matchers/hash_excluding_matcher.rb
|
||||
stub_request(:get, redirect_location)
|
||||
.with(headers: redirect_header) do |request|
|
||||
!request.headers.include?('Authorization')
|
||||
request.headers.exclude?('Authorization')
|
||||
end
|
||||
.to_return(status: 200, body: "Successfully redirected")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ RSpec::Matchers.define :have_pushed_frontend_feature_flags do |expected|
|
|||
|
||||
failure_message do |actual|
|
||||
missing = expected.select do |feature_flag_name, enabled|
|
||||
!html(actual).include?(to_js(feature_flag_name, enabled))
|
||||
html(actual).exclude?(to_js(feature_flag_name, enabled))
|
||||
end
|
||||
|
||||
formatted_missing_flags = missing.map { |feature_flag_name, enabled| to_js(feature_flag_name, enabled) }.join("\n")
|
||||
|
|
|
|||
|
|
@ -313,7 +313,7 @@ RSpec.describe ObjectStorage, :clean_gitlab_redis_shared_state, feature_category
|
|||
|
||||
# We need to check the Host header not including the port because AWS does not accept
|
||||
stub_request(:get, %r{s3.amazonaws.com/#{uploader.path}})
|
||||
.with { |request| !request.headers['Host'].to_s.include?(':443') }
|
||||
.with { |request| request.headers['Host'].to_s.exclude?(':443') }
|
||||
.to_return(status: 200, body: '')
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue