Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-05-25 15:08:05 +00:00
parent ba9892d3c1
commit 4dc41ac252
85 changed files with 666 additions and 328 deletions

View File

@ -30,9 +30,11 @@ import {
TOKEN_TITLE_ASSIGNEE,
TOKEN_TITLE_AUTHOR,
TOKEN_TITLE_CONFIDENTIAL,
TOKEN_TITLE_CONTACT,
TOKEN_TITLE_LABEL,
TOKEN_TITLE_MILESTONE,
TOKEN_TITLE_MY_REACTION,
TOKEN_TITLE_ORGANIZATION,
TOKEN_TITLE_RELEASE,
TOKEN_TITLE_TYPE,
} from '~/vue_shared/components/filtered_search_bar/constants';
@ -54,9 +56,11 @@ import {
TOKEN_TYPE_ASSIGNEE,
TOKEN_TYPE_AUTHOR,
TOKEN_TYPE_CONFIDENTIAL,
TOKEN_TYPE_CONTACT,
TOKEN_TYPE_LABEL,
TOKEN_TYPE_MILESTONE,
TOKEN_TYPE_MY_REACTION,
TOKEN_TYPE_ORGANIZATION,
TOKEN_TYPE_RELEASE,
TOKEN_TYPE_TYPE,
UPDATED_DESC,
@ -113,6 +117,8 @@ export default {
'autocompleteAwardEmojisPath',
'calendarPath',
'canBulkUpdate',
'canReadCrmContact',
'canReadCrmOrganization',
'emptyStateSvgPath',
'exportCsvPath',
'fullPath',
@ -360,6 +366,28 @@ export default {
});
}
if (this.canReadCrmContact) {
tokens.push({
type: TOKEN_TYPE_CONTACT,
title: TOKEN_TITLE_CONTACT,
icon: 'user',
token: GlFilteredSearchToken,
operators: OPERATOR_IS_ONLY,
unique: true,
});
}
if (this.canReadCrmOrganization) {
tokens.push({
type: TOKEN_TYPE_ORGANIZATION,
title: TOKEN_TITLE_ORGANIZATION,
icon: 'users',
token: GlFilteredSearchToken,
operators: OPERATOR_IS_ONLY,
unique: true,
});
}
if (this.eeSearchTokens.length) {
tokens.push(...this.eeSearchTokens);
}

View File

@ -82,6 +82,8 @@ export function mountIssuesListApp() {
canBulkUpdate,
canEdit,
canImportIssues,
canReadCrmContact,
canReadCrmOrganization,
email,
emailsHelpPagePath,
emptyStateSvgPath,
@ -131,6 +133,8 @@ export function mountIssuesListApp() {
autocompleteAwardEmojisPath,
calendarPath,
canBulkUpdate: parseBoolean(canBulkUpdate),
canReadCrmContact: parseBoolean(canReadCrmContact),
canReadCrmOrganization: parseBoolean(canReadCrmOrganization),
emptyStateSvgPath,
fullPath,
groupPath,

View File

@ -105,7 +105,7 @@ export default (resolvers = {}, config = {}) => {
const {
baseUrl,
batchMax = 10,
cacheConfig,
cacheConfig = { typePolicies: {}, possibleTypes: {} },
fetchPolicy = fetchPolicies.CACHE_FIRST,
typeDefs,
path = '/api/graphql',
@ -221,9 +221,15 @@ export default (resolvers = {}, config = {}) => {
typeDefs,
link: appLink,
cache: new InMemoryCache({
typePolicies,
possibleTypes,
...cacheConfig,
typePolicies: {
...typePolicies,
...cacheConfig.typePolicies,
},
possibleTypes: {
...possibleTypes,
...cacheConfig.possibleTypes,
},
}),
resolvers,
defaultOptions: {

View File

@ -107,7 +107,7 @@ export default {
<td v-if="error" class="js-error-lazy-load-diff diff-loading-error-block">
{{ __('Unable to load the diff') }}
<button
class="btn-link btn-link-retry gl-p-0 js-toggle-lazy-diff-retry-button"
class="gl-button btn-link btn-link-retry gl-p-0 js-toggle-lazy-diff-retry-button gl-reset-font-size!"
@click="fetchDiff"
>
{{ __('Try again') }}

View File

@ -58,7 +58,7 @@ export default {
<div class="issuable-note-warning" data-testid="email-participants-warning">
<gl-sprintf :message="message">
<template #andMore>
<button type="button" class="btn-transparent btn-link" @click="showMoreParticipants">
<button type="button" class="gl-button btn-link" @click="showMoreParticipants">
{{ moreLabel }}
</button>
</template>

View File

@ -72,7 +72,7 @@ export default {
{{ replies.length }} {{ n__('reply', 'replies', replies.length) }}
</gl-button>
{{ __('Last reply by') }}
<a :href="lastReply.author.path" class="btn btn-link author-link gl-mx-2">
<a :href="lastReply.author.path" class="btn btn-link author-link gl-mx-2 gl-button">
{{ lastReply.author.name }}
</a>
<time-ago-tooltip :time="lastReply.created_at" tooltip-placement="bottom" />

View File

@ -27,7 +27,7 @@ export default {
<div id="peek-view-add-request" class="view">
<form class="form-inline" @submit.prevent>
<button
class="btn-blank btn-link bold gl-text-blue-300"
class="btn-link bold gl-text-blue-300 gl-button"
type="button"
:title="__(`Add request manually`)"
@click="toggleInput"

View File

@ -150,7 +150,7 @@ export default {
<div id="js-peek" :class="env">
<div
v-if="currentRequest"
class="d-flex container-fluid container-limited justify-content-center"
class="d-flex container-fluid container-limited justify-content-center gl-align-items-center"
data-qa-selector="performance_bar"
>
<div id="peek-view-host" class="view">

View File

@ -55,7 +55,12 @@ export default {
{{ __('None') }}
<template v-if="editable">
-
<button type="button" class="btn-link" data-testid="assign-yourself" @click="assignSelf">
<button
type="button"
class="gl-button btn-link gl-reset-color!"
data-testid="assign-yourself"
@click="assignSelf"
>
{{ __('assign yourself') }}
</button>
</template>

View File

@ -26,7 +26,7 @@ export default {
};
</script>
<template>
<button type="button" class="btn-link">
<button type="button" class="gl-button btn-link">
<assignee-avatar :user="user" :img-size="24" :issuable-type="issuableType" />
<user-name-with-status
:name="user.name"

View File

@ -123,7 +123,7 @@ export default {
:user="user"
:issuable-type="issuableType"
/>
<button v-if="hasMoreThanTwoAssignees" class="btn-link" type="button">
<button v-if="hasMoreThanTwoAssignees" class="btn-link gl-button" type="button">
<span
class="avatar-counter sidebar-avatar-counter gl-display-flex gl-align-items-center gl-pl-3"
>

View File

@ -120,7 +120,7 @@ export default {
<div v-if="renderShowMoreSection" class="user-list-more gl-hover-text-blue-800">
<button
type="button"
class="btn-link"
class="btn-link gl-button gl-reset-color!"
data-qa-selector="more_assignees_link"
@click="toggleShowLess"
>

View File

@ -17,7 +17,7 @@ export default {
</script>
<template>
<button type="button" class="btn-link">
<button type="button" class="btn-link gl-button">
<reviewer-avatar :user="user" :img-size="24" />
<span class="author"> {{ user.name }} </span>
</button>

View File

@ -95,7 +95,7 @@ export default {
>
<gl-icon v-if="hasNoUsers" name="user" :aria-label="__('None')" />
<collapsed-reviewer v-for="user in collapsedUsers" :key="user.id" :user="user" />
<button v-if="hasMoreThanTwoReviewers" class="btn-link" type="button">
<button v-if="hasMoreThanTwoReviewers" class="btn-link gl-button" type="button">
<span
class="avatar-counter sidebar-avatar-counter gl-display-flex gl-align-items-center gl-pl-3"
>

View File

@ -2,6 +2,7 @@ import produce from 'immer';
import VueApollo from 'vue-apollo';
import getIssueStateQuery from '~/issues/show/queries/get_issue_state.query.graphql';
import createDefaultClient from '~/lib/graphql';
import { temporaryConfig } from '~/work_items/graphql/provider';
const resolvers = {
Mutation: {
@ -15,7 +16,12 @@ const resolvers = {
},
};
export const defaultClient = createDefaultClient(resolvers);
export const defaultClient = createDefaultClient(
resolvers,
// should be removed with the rollout of work item assignees FF
// https://gitlab.com/gitlab-org/gitlab/-/issues/363030
temporaryConfig,
);
export const apolloProvider = new VueApollo({
defaultClient,

View File

@ -17,7 +17,7 @@ const ERROR_HTML = `<div class="nothing-here-block">${spriteIcon(
's16',
)} Could not load diff</div>`;
const COLLAPSED_HTML =
'<div class="nothing-here-block diff-collapsed">This diff is collapsed. <button class="click-to-expand btn btn-link">Click to expand it.</button></div>';
'<div class="nothing-here-block diff-collapsed">This diff is collapsed. <button class="click-to-expand btn btn-link gl-button">Click to expand it.</button></div>';
export default class SingleFileDiff {
constructor(file) {

View File

@ -1,4 +1,4 @@
import { __ } from '~/locale';
import { __, s__ } from '~/locale';
export const DEBOUNCE_DELAY = 500;
export const MAX_RECENT_TOKENS_SIZE = 3;
@ -46,11 +46,13 @@ export const SortDirection = {
export const FILTERED_SEARCH_LABELS = 'labels';
export const FILTERED_SEARCH_TERM = 'filtered-search-term';
export const TOKEN_TITLE_AUTHOR = __('Author');
export const TOKEN_TITLE_ASSIGNEE = __('Assignee');
export const TOKEN_TITLE_MILESTONE = __('Milestone');
export const TOKEN_TITLE_LABEL = __('Label');
export const TOKEN_TITLE_TYPE = __('Type');
export const TOKEN_TITLE_RELEASE = __('Release');
export const TOKEN_TITLE_MY_REACTION = __('My-Reaction');
export const TOKEN_TITLE_AUTHOR = __('Author');
export const TOKEN_TITLE_CONFIDENTIAL = __('Confidential');
export const TOKEN_TITLE_CONTACT = s__('Crm|Contact');
export const TOKEN_TITLE_LABEL = __('Label');
export const TOKEN_TITLE_MILESTONE = __('Milestone');
export const TOKEN_TITLE_MY_REACTION = __('My-Reaction');
export const TOKEN_TITLE_ORGANIZATION = s__('Crm|Organization');
export const TOKEN_TITLE_RELEASE = __('Release');
export const TOKEN_TITLE_TYPE = __('Type');

View File

@ -22,10 +22,6 @@ export default {
type: Object,
required: true,
},
statusBadgeClass: {
type: String,
required: true,
},
statusIcon: {
type: String,
required: true,
@ -162,7 +158,6 @@ export default {
<template v-else>
<issuable-title
:issuable="issuable"
:status-badge-class="statusBadgeClass"
:status-icon="statusIcon"
:enable-edit="enableEdit"
@edit-issuable="$emit('edit-issuable', $event)"

View File

@ -40,11 +40,6 @@ export default {
required: false,
default: '',
},
statusBadgeClass: {
type: String,
required: false,
default: '',
},
statusIcon: {
type: String,
required: false,
@ -113,11 +108,7 @@ export default {
<template>
<div class="detail-page-header">
<div class="detail-page-header-body">
<gl-badge
class="issuable-status-badge gl-mr-3"
:class="statusBadgeClass"
:variant="badgeVariant"
>
<gl-badge class="issuable-status-badge gl-mr-3" :variant="badgeVariant">
<gl-icon v-if="statusIcon" :name="statusIcon" :class="statusIconClass" />
<span class="gl-display-none gl-sm-display-block"><slot name="status-badge"></slot></span>
</gl-badge>

View File

@ -17,11 +17,6 @@ export default {
type: Object,
required: true,
},
statusBadgeClass: {
type: String,
required: false,
default: '',
},
statusIcon: {
type: String,
required: false,
@ -108,7 +103,6 @@ export default {
<div class="issuable-show-container" data-qa-selector="issuable_show_container">
<issuable-header
:issuable-state="issuable.state"
:status-badge-class="statusBadgeClass"
:status-icon="statusIcon"
:status-icon-class="statusIconClass"
:blocked="issuable.blocked"
@ -127,7 +121,6 @@ export default {
<issuable-body
:issuable="issuable"
:status-badge-class="statusBadgeClass"
:status-icon="statusIcon"
:status-icon-class="statusIconClass"
:enable-edit="enableEdit"

View File

@ -29,10 +29,6 @@ export default {
type: Object,
required: true,
},
statusBadgeClass: {
type: String,
required: true,
},
statusIcon: {
type: String,
required: true,
@ -92,11 +88,7 @@ export default {
<div
class="issue-sticky-header-text gl-display-flex gl-align-items-center gl-mx-auto gl-px-5"
>
<gl-badge
class="gl-white-space-nowrap gl-mr-3"
:class="statusBadgeClass"
:variant="badgeVariant"
>
<gl-badge class="gl-white-space-nowrap gl-mr-3" :variant="badgeVariant">
<gl-icon v-if="statusIcon" class="gl-sm-display-none" :name="statusIcon" />
<span class="gl-display-none gl-sm-display-block">
<slot name="status-badge"></slot>

View File

@ -0,0 +1,42 @@
<script>
import { GlAvatar, GlLink } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
export default {
components: {
GlAvatar,
GlLink,
},
props: {
assignees: {
type: Array,
required: true,
},
},
methods: {
getUserId(id) {
return getIdFromGraphQLId(id);
},
},
};
</script>
<template>
<div class="gl-display-flex">
<span class="gl-font-weight-bold gl-w-15 gl-pt-1">{{ __('Assignee(s)') }}</span>
<div class="gl-mb-4">
<gl-link
v-for="user in assignees"
:key="user.id"
:href="user.webUrl"
:title="`test`"
:data-user-id="getUserId(user.id)"
data-placement="top"
class="gl-text-decoration-none! gl-text-black-normal! gl-display-flex gl-md-display-inline-flex! gl-align-items-center gl-mb-4 gl-md-mb-0 gl-mr-4 js-user-link"
>
<gl-avatar :size="24" :src="user.avatarUrl" />
<span class="gl-pl-2">{{ user.name }}</span>
</gl-link>
</div>
</div>
</template>

View File

@ -1,23 +1,27 @@
<script>
import { GlAlert, GlSkeletonLoader } from '@gitlab/ui';
import { i18n } from '../constants';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { i18n, WIDGET_TYPE_ASSIGNEE } from '../constants';
import workItemQuery from '../graphql/work_item.query.graphql';
import workItemTitleSubscription from '../graphql/work_item_title.subscription.graphql';
import WorkItemActions from './work_item_actions.vue';
import WorkItemState from './work_item_state.vue';
import WorkItemTitle from './work_item_title.vue';
import WorkItemLinks from './work_item_links/work_item_links.vue';
import WorkItemAssignees from './work_item_assignees.vue';
export default {
i18n,
components: {
GlAlert,
GlSkeletonLoader,
WorkItemAssignees,
WorkItemActions,
WorkItemTitle,
WorkItemState,
WorkItemLinks,
},
mixins: [glFeatureFlagMixin()],
props: {
workItemId: {
type: String,
@ -68,6 +72,12 @@ export default {
canDelete() {
return this.workItem?.userPermissions?.deleteWorkItem;
},
workItemAssigneesEnabled() {
return this.glFeatures.workItemAssignees;
},
workItemAssignees() {
return this.workItem?.mockWidgets?.find((widget) => widget.type === WIDGET_TYPE_ASSIGNEE);
},
},
};
</script>
@ -102,6 +112,10 @@ export default {
@error="error = $event"
/>
</div>
<work-item-assignees
v-if="workItemAssigneesEnabled && workItemAssignees"
:assignees="workItemAssignees.nodes"
/>
<work-item-state
:work-item="workItem"
@error="error = $event"

View File

@ -12,3 +12,5 @@ export const i18n = {
};
export const DEFAULT_MODAL_TYPE = 'Task';
export const WIDGET_TYPE_ASSIGNEE = 'ASSIGNEES';

View File

@ -1,11 +1,57 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import typeDefs from './typedefs.graphql';
export const temporaryConfig = {
typeDefs,
cacheConfig: {
possibleTypes: {
LocalWorkItemWidget: ['LocalWorkItemAssignees'],
},
typePolicies: {
WorkItem: {
fields: {
mockWidgets: {
read() {
return [
{
__typename: 'LocalWorkItemAssignees',
type: 'ASSIGNEES',
nodes: [
{
__typename: 'UserCore',
id: 'gid://gitlab/User/1',
avatarUrl: '',
webUrl: '',
// eslint-disable-next-line @gitlab/require-i18n-strings
name: 'John Doe',
username: 'doe_I',
},
{
__typename: 'UserCore',
id: 'gid://gitlab/User/2',
avatarUrl: '',
webUrl: '',
// eslint-disable-next-line @gitlab/require-i18n-strings
name: 'Marcus Rutherford',
username: 'ruthfull',
},
],
},
];
},
},
},
},
},
},
};
export function createApolloProvider() {
Vue.use(VueApollo);
const defaultClient = createDefaultClient();
const defaultClient = createDefaultClient({}, temporaryConfig);
return new VueApollo({
defaultClient,

View File

@ -0,0 +1,16 @@
enum LocalWidgetType {
ASSIGNEES
}
interface LocalWorkItemWidget {
type: LocalWidgetType!
}
type LocalWorkItemAssignees implements LocalWorkItemWidget {
type: LocalWidgetType!
nodes: [UserCore]
}
extend type WorkItem {
mockWidgets: [LocalWorkItemWidget]
}

View File

@ -3,5 +3,17 @@
query workItem($id: WorkItemID!) {
workItem(id: $id) {
...WorkItem
mockWidgets @client {
... on LocalWorkItemAssignees {
type
nodes {
id
avatarUrl
name
username
webUrl
}
}
}
}
}

View File

@ -24,7 +24,6 @@
@import 'framework/kbd';
@import 'framework/header';
@import 'framework/highlight';
@import 'framework/issue_box';
@import 'framework/lists';
@import 'framework/logo';
@import 'framework/job_log';

View File

@ -357,25 +357,6 @@
}
}
.btn-link {
padding: 0;
background-color: transparent;
color: $blue-600;
font-weight: normal;
border-radius: 0;
border-color: transparent;
border-width: 0;
&:hover,
&:active,
&:focus {
color: $blue-800;
text-decoration: underline;
background-color: transparent;
border-color: transparent;
}
}
// The .btn-svg class is available for legacy icon buttons to
// preserve a 34px height and have 16x16 icons at the same time.
// Once a button is migrated (to the current 32px height)

View File

@ -1,40 +0,0 @@
/**
* Issue box for showing Open/Closed state:
* Used for Issue#show page, MergeRequest#show page etc
*
*/
.status-box {
padding: 0 $gl-btn-padding;
border-radius: $border-radius-default;
display: block;
float: left;
margin-right: $gl-padding-8;
color: $white;
font-size: $gl-font-size;
line-height: $gl-line-height-24;
&.status-box-closed,
&.status-box-mr-closed {
background-color: $red-500;
}
&.status-box-issue-closed,
&.status-box-alert-resolved,
&.status-box-mr-merged {
background-color: $blue-500;
}
&.status-box-open {
background-color: $green-500;
}
&.status-box-expired {
background-color: $orange-500;
}
&.status-box-upcoming {
background: $gl-text-color-secondary;
}
}

View File

@ -1,3 +1,14 @@
.status-box {
padding: 0 $gl-btn-padding;
border-radius: $border-radius-default;
display: block;
float: left;
margin-right: $gl-padding-8;
color: $white;
font-size: $gl-font-size;
line-height: $gl-line-height-24;
}
.issuable-warning-icon {
background-color: $orange-50;
border-radius: $border-radius-default;

View File

@ -50,6 +50,7 @@ class Projects::IssuesController < Projects::ApplicationController
push_frontend_feature_flag(:paginated_issue_discussions, project)
push_frontend_feature_flag(:realtime_labels, project)
push_force_frontend_feature_flag(:work_items, project&.work_items_feature_flag_enabled?)
push_frontend_feature_flag(:work_item_assignees)
end
around_action :allow_gitaly_ref_name_caching, only: [:discussions]

View File

@ -3,6 +3,7 @@
class Projects::WorkItemsController < Projects::ApplicationController
before_action do
push_force_frontend_feature_flag(:work_items, project&.work_items_feature_flag_enabled?)
push_frontend_feature_flag(:work_item_assignees)
end
feature_category :team_planning

View File

@ -42,6 +42,7 @@ class ProjectsController < Projects::ApplicationController
push_licensed_feature(:file_locks) if @project.present? && @project.licensed_feature_available?(:file_locks)
push_licensed_feature(:security_orchestration_policies) if @project.present? && @project.licensed_feature_available?(:security_orchestration_policies)
push_force_frontend_feature_flag(:work_items, @project&.work_items_feature_flag_enabled?)
push_frontend_feature_flag(:work_item_assignees)
end
layout :determine_layout

View File

@ -86,6 +86,12 @@ module Types
field :version, GraphQL::Types::String, null: true,
description: 'Version of the runner.'
markdown_field :maintenance_note_html, null: true
def maintenance_note_html_resolver
::MarkupHelper.markdown(object.maintenance_note, context.to_h.dup)
end
def job_count
# We limit to 1 above the JOB_COUNT_LIMIT to indicate that more items exist after JOB_COUNT_LIMIT
runner.builds.limit(JOB_COUNT_LIMIT + 1).count

View File

@ -31,15 +31,15 @@ module IssuesHelper
updated_mr_header_enabled = Feature.enabled?(:updated_mr_header, @project)
if item.try(:expired?)
'status-box-expired'
'gl-bg-orange-500'
elsif item.try(:merged?)
updated_mr_header_enabled ? 'badge-info' : 'status-box-mr-merged'
updated_mr_header_enabled ? 'badge-info' : 'gl-bg-blue-500'
elsif item.closed?
item.is_a?(MergeRequest) && updated_mr_header_enabled ? 'badge-danger' : 'status-box-mr-closed'
item.is_a?(MergeRequest) && updated_mr_header_enabled ? 'badge-danger' : 'gl-bg-red-500'
elsif item.try(:upcoming?)
'status-box-upcoming'
'gl-bg-gray-500'
else
item.is_a?(MergeRequest) && updated_mr_header_enabled ? 'badge-success' : 'status-box-open'
item.is_a?(MergeRequest) && updated_mr_header_enabled ? 'badge-success' : 'gl-bg-green-500'
end
end
@ -218,6 +218,8 @@ module IssuesHelper
can_bulk_update: can?(current_user, :admin_issue, project).to_s,
can_edit: can?(current_user, :admin_project, project).to_s,
can_import_issues: can?(current_user, :import_issues, @project).to_s,
can_read_crm_contact: can?(current_user, :read_crm_contact, project.group).to_s,
can_read_crm_organization: can?(current_user, :read_crm_organization, project.group).to_s,
email: current_user&.notification_email_or_default,
emails_help_page_path: help_page_path('development/emails', anchor: 'email-namespace'),
export_csv_path: export_csv_project_issues_path(project),
@ -238,6 +240,8 @@ module IssuesHelper
def group_issues_list_data(group, current_user)
common_issues_list_data(group, current_user).merge(
can_read_crm_contact: can?(current_user, :read_crm_contact, group).to_s,
can_read_crm_organization: can?(current_user, :read_crm_organization, group).to_s,
has_any_issues: @has_issues.to_s,
has_any_projects: @has_projects.to_s
)

View File

@ -100,17 +100,22 @@ module TodosHelper
def todo_target_state_pill(todo)
return unless show_todo_state?(todo)
type =
case todo.target
when MergeRequest
'mr'
when Issue
'issue'
when AlertManagement::Alert
'alert'
end
state = todo.target.state.to_s
tag.span class: "gl-my-0 gl-px-2 status-box status-box-#{type}-#{todo.target.state.to_s.dasherize}" do
case todo.target
when MergeRequest
if state == 'closed'
background_class = 'gl-bg-red-500'
elsif state == 'merged'
background_class = 'gl-bg-blue-500'
end
when Issue
background_class = 'gl-bg-blue-500' if state == 'closed'
when AlertManagement::Alert
background_class = 'gl-bg-blue-500' if state == 'resolved'
end
tag.span class: "gl-my-0 gl-px-2 status-box #{background_class}" do
todo.target.state.to_s.capitalize
end
end

View File

@ -38,11 +38,12 @@ module Packages
raise GoZipSizeError, "#{version.mod.name}@#{version.name}.#{type} exceeds size limit" if file.size > project.actual_limits.golang_max_file_size
digests = {
md5: Digest::MD5.hexdigest(content),
sha1: Digest::SHA1.hexdigest(content),
sha256: Digest::SHA256.hexdigest(content)
}
digests[:md5] = Digest::MD5.hexdigest(content) unless Gitlab::FIPS.enabled?
[file, digests]
end

View File

@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350322
milestone: '14.8'
type: development
group: group::pipeline execution
default_enabled: false
default_enabled: true

View File

@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/357869
milestone: '14.10'
type: development
group: group::sharding
default_enabled: false
default_enabled: true

View File

@ -1,8 +1,8 @@
---
name: ci_show_all_projects_with_usage_sorted_descending
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83680
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/362331
milestone: '15.0'
name: work_item_assignees
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88003
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/363030
milestone: '15.1'
type: development
group: group::pipeline execution
group: group::project management
default_enabled: false

View File

@ -99,8 +99,6 @@
- 1
- - cronjob
- 1
- - dast_site_validation
- 1
- - default
- 1
- - delete_diff_files

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
class TempIndexForProjectNamespaceMemberBackfill < Gitlab::Database::Migration[1.0]
class TempIndexForProjectNamespaceMemberBackfill < Gitlab::Database::Migration[2.0]
INDEX_NAME = 'tmp_index_for_namespace_id_migration_on_project_members'
disable_ddl_transaction!

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true
class ScheduleBackfillProjectMemberNamespaceId < Gitlab::Database::Migration[1.0]
class ScheduleBackfillProjectMemberNamespaceId < Gitlab::Database::Migration[2.0]
restrict_gitlab_migration gitlab_schema: :gitlab_main
MIGRATION = 'BackfillProjectMemberNamespaceId'
INTERVAL = 2.minutes
BATCH_SIZE = 1_000

View File

@ -101,7 +101,7 @@ explorer. GraphiQL explorer is available for:
1. Open the [GraphiQL explorer tool](https://gitlab.com/-/graphql-explorer).
1. Paste the `query` listed above into the left window of your GraphiQL explorer tool.
1. Click Play to get the result shown here:
1. Select **Play** to get the result shown here:
![GraphiQL explorer search for boards](img/user_query_example_v13_2.png)

View File

@ -81,7 +81,7 @@ explorer. GraphiQL explorer is available for:
1. Open the [GraphiQL explorer tool](https://gitlab.com/-/graphql-explorer).
1. Paste the `query` listed above into the left window of your GraphiQL explorer tool.
1. Click Play to get the result shown here:
1. Select **Play** to get the result shown here:
![GraphiQL explore custom emoji query](img/custom_emoji_query_example.png)

View File

@ -9609,6 +9609,7 @@ Represents the total number of issues and their weights for a particular day.
| <a id="cirunnerjobcount"></a>`jobCount` | [`Int`](#int) | Number of jobs processed by the runner (limited to 1000, plus one to indicate that more items exist). |
| <a id="cirunnerlocked"></a>`locked` | [`Boolean`](#boolean) | Indicates the runner is locked. |
| <a id="cirunnermaintenancenote"></a>`maintenanceNote` | [`String`](#string) | Runner's maintenance notes. |
| <a id="cirunnermaintenancenotehtml"></a>`maintenanceNoteHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `maintenance_note`. |
| <a id="cirunnermaximumtimeout"></a>`maximumTimeout` | [`Int`](#int) | Maximum timeout (in seconds) for jobs processed by the runner. |
| <a id="cirunnerpaused"></a>`paused` | [`Boolean!`](#boolean) | Indicates the runner is paused and not available to run jobs. |
| <a id="cirunnerplatformname"></a>`platformName` | [`String`](#string) | Platform provided by the runner. |

View File

@ -73,7 +73,7 @@ explorer. GraphiQL explorer is available for:
1. Open the [GraphiQL explorer tool](https://gitlab.com/-/graphql-explorer).
1. Paste the `query` listed above into the left window of your GraphiQL explorer tool.
1. Click Play to get the result shown here:
1. Select **Play** to get the result shown here:
![GraphiQL explorer search for boards](img/users_query_example_v13_8.png)

View File

@ -11,7 +11,7 @@ file, as well as information and history about our changelog process.
## Overview
Each bullet point, or **entry**, in our
Each list item, or **entry**, in our
[`CHANGELOG.md`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/CHANGELOG.md)
file is generated from the subject line of a Git commit. Commits are included
when they contain the `Changelog` [Git trailer](https://git-scm.com/docs/git-interpret-trailers).

View File

@ -429,7 +429,7 @@ ALTER TABLE ONLY vulnerability_occurrence_pipelines
In this example we expect to delete all associated `vulnerability_occurrence_pipelines` records
whenever we delete the `ci_pipelines` record associated with them. In this case
you might end up with some vulnerability page in GitLab which shows an occurrence
of a vulnerability. However, when you try to click a link to the pipeline, you get
of a vulnerability. However, when you try to select a link to the pipeline, you get
a 404, because the pipeline is deleted. Then, when you navigate back you might find the
occurrence has disappeared too.

View File

@ -87,7 +87,7 @@ The easiest way to access tracing from a GDK environment is through the
[performance-bar](../administration/monitoring/performance/performance_bar.md). This can be shown
by typing `p` `b` in the browser window.
Once the performance bar is enabled, click on the **Trace** link in the performance bar to go to
Once the performance bar is enabled, select **Trace** in the performance bar to go to
the Jaeger UI.
The Jaeger search UI returns a query for the `Correlation-ID` of the current request. Normally,

View File

@ -114,12 +114,12 @@ pipeline in the main `gitlab` repository as well as in `gitlab-docs`. Create an
a different name first and test it to ensure you do not break the pipelines.
1. In [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs), go to **{rocket}** **CI/CD > Pipelines**.
1. Click the **Run pipeline** button.
1. Select **Run pipeline**.
1. See that a new pipeline is running. The jobs that build the images are in the first
stage, `build-images`. You can click the pipeline number to see the larger pipeline
graph, or click the first (`build-images`) stage in the mini pipeline graph to
stage, `build-images`. You can select the pipeline number to see the larger pipeline
graph, or select the first (`build-images`) stage in the mini pipeline graph to
expose the jobs that build the images.
1. Click the **play** (**{play}**) button next to the images you want to rebuild.
1. Select the **play** (**{play}**) button next to the images you want to rebuild.
- Normally, you do not need to rebuild the `image:gitlab-docs-base` image, as it
rarely changes. If it does need to be rebuilt, be sure to only run `image:docs-lint`
after it is finished rebuilding.
@ -133,7 +133,7 @@ and deploys it to <https://docs.gitlab.com>.
To build and deploy the site immediately (must have the Maintainer role):
1. In [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs), go to **{rocket}** **CI/CD > Schedules**.
1. For the `Build docs.gitlab.com every 4 hours` scheduled pipeline, click the **play** (**{play}**) button.
1. For the `Build docs.gitlab.com every 4 hours` scheduled pipeline, select the **play** (**{play}**) button.
Read more about [documentation deployments](deployment_process.md).

View File

@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Testing experiments with RSpec
In the course of working with experiments, you'll probably want to utilize the RSpec
In the course of working with experiments, you'll probably want to use the RSpec
tooling that's built in. This happens automatically for files in `spec/experiments`, but
for other files and specs you want to include it in, you can specify the `:experiment` type:

View File

@ -15,7 +15,7 @@ This document lists the different implementations of CSV export in GitLab codeba
| As email attachment | - Asynchronously process the query with background job.<br>- Email uses the export as an attachment. | - Asynchronous processing. | - Requires users use a different app (email) to download the CSV.<br>- Email providers may limit attachment size. | - [Export issues](../user/project/issues/csv_export.md)<br>- [Export merge requests](../user/project/merge_requests/csv_export.md) |
| As downloadable link in email (*) | - Asynchronously process the query with background job.<br>- Email uses an export link. | - Asynchronous processing.<br>- Bypasses email provider attachment size limit. | - Requires users use a different app (email).<br>- Requires additional storage and cleanup. | [Export User Permissions](https://gitlab.com/gitlab-org/gitlab/-/issues/1772) |
| Polling (non-persistent state) | - Asynchronously processes the query with the background job.<br>- Frontend(FE) polls every few seconds to check if CSV file is ready. | - Asynchronous processing.<br>- Automatically downloads to local machine on completion.<br>- In-app solution. | - Non-persistable request - request expires when user navigates to a different page.<br>- API is processed for each polling request. | [Export Vulnerabilities](../user/application_security/vulnerability_report/#export-vulnerability-details) |
| Polling (persistent state) (*) | - Asynchronously processes the query with background job.<br>- Backend (BE) maintains the export state<br>- FE polls every few seconds to check status.<br>- FE shows 'Download link' when export is ready.<br>- User can download or regenerate a new report. | - Asynchronous processing.<br>- No database calls made during the polling requests (HTTP 304 status is returned until export status changes).<br>- Does not require user to stay on page until export is complete.<br>- In-app solution.<br>- Can be expanded into a generic CSV feature (such as dashboard / CSV API). | - Requires to maintain export states in DB.<br>- Does not automatically download the CSV export to local machine, requires users to click 'Download' button. | [Export Merge Commits Report](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43055) |
| Polling (persistent state) (*) | - Asynchronously processes the query with background job.<br>- Backend (BE) maintains the export state<br>- FE polls every few seconds to check status.<br>- FE shows 'Download link' when export is ready.<br>- User can download or regenerate a new report. | - Asynchronous processing.<br>- No database calls made during the polling requests (HTTP 304 status is returned until export status changes).<br>- Does not require user to stay on page until export is complete.<br>- In-app solution.<br>- Can be expanded into a generic CSV feature (such as dashboard / CSV API). | - Requires to maintain export states in DB.<br>- Does not automatically download the CSV export to local machine, requires users to select 'Download'. | [Export Merge Commits Report](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43055) |
NOTE:
Export types marked as * are currently work in progress.

View File

@ -189,10 +189,10 @@ To see what polyfills are being used:
1. Navigate to your merge request.
1. In the secondary menu below the title of the merge request, click **Pipelines**, then
click the pipeline you want to view, to display the jobs in that pipeline.
1. Click the [`compile-production-assets`](https://gitlab.com/gitlab-org/gitlab/-/jobs/641770154) job.
1. In the right-hand sidebar, scroll to **Job Artifacts**, and click **Browse**.
1. Click the **webpack-report** folder to open it, and click **index.html**.
1. In the upper left corner of the page, click the right arrow **{angle-right}**
1. Select the [`compile-production-assets`](https://gitlab.com/gitlab-org/gitlab/-/jobs/641770154) job.
1. In the right-hand sidebar, scroll to **Job Artifacts**, and select **Browse**.
1. Select the **webpack-report** folder to open it, and select **index.html**.
1. In the upper left corner of the page, select the right arrow **{angle-right}**
to display the explorer.
1. In the **Search modules** field, enter `gitlab/node_modules/core-js` to see
which polyfills are being loaded and where:

View File

@ -64,7 +64,7 @@ main pieces of the desired UI and UX of a registry page. The most important comp
- `code-instruction`: represents a copyable box containing code. Supports multiline and single line
code boxes. Snowplow tracks the code copy event.
- `details-row`: represents a row of details. Used to add additional info in the details area of
- `details-row`: represents a row of details. Used to add additional information in the details area of
the `list-item` component.
- `history-item`: represents a history list item used to build a timeline.
- `list-item`: represents a list element in the registry. It supports: left action, left primary and

View File

@ -67,7 +67,7 @@ maintaining deterministic output for given input, while masking any relation to
#### How events are pseudonymized
Pseudonymization uses an allowlist that provides privacy by default. Therefore, each
attribute received as part of a Snowplow event is pseudonymized unless the attribute
attribute received as part of a Snowplow event is pseudonymized unless the attribute
is an allowed exception.
Pseudonymization is done using the HMAC-SHA256 keyed hash algorithm.

View File

@ -83,8 +83,8 @@ As we'll be using [Amazon S3 object storage](#amazon-s3-object-storage), our EC2
### Create an IAM Policy
1. Navigate to the IAM dashboard and click on **Policies** in the left menu.
1. Click **Create policy**, select the `JSON` tab, and add a policy. We want to [follow security best practices and grant _least privilege_](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege), giving our role only the permissions needed to perform the required actions.
1. Navigate to the IAM dashboard and select **Policies** in the left menu.
1. Select **Create policy**, select the `JSON` tab, and add a policy. We want to [follow security best practices and grant _least privilege_](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege), giving our role only the permissions needed to perform the required actions.
1. Assuming you prefix the S3 bucket names with `gl-` as shown in the diagram, add the following policy:
```json
@ -114,17 +114,17 @@ As we'll be using [Amazon S3 object storage](#amazon-s3-object-storage), our EC2
}
```
1. Click **Review policy**, give your policy a name (we'll use `gl-s3-policy`), and click **Create policy**.
1. Select **Review policy**, give your policy a name (we'll use `gl-s3-policy`), and select **Create policy**.
### Create an IAM Role
1. Still on the IAM dashboard, click on **Roles** in the left menu, and
click **Create role**.
1. Create a new role by selecting **AWS service > EC2**, then click
1. Still on the IAM dashboard, select **Roles** in the left menu, and
select **Create role**.
1. Create a new role by selecting **AWS service > EC2**, then select
**Next: Permissions**.
1. In the policy filter, search for the `gl-s3-policy` we created above, select it, and click **Tags**.
1. Add tags if needed and click **Review**.
1. Give the role a name (we'll use `GitLabS3Access`) and click **Create Role**.
1. In the policy filter, search for the `gl-s3-policy` we created above, select it, and select **Tags**.
1. Add tags if needed and select **Review**.
1. Give the role a name (we'll use `GitLabS3Access`) and select **Create Role**.
We'll use this role when we [create a launch configuration](#create-a-launch-configuration) later on.
@ -140,14 +140,14 @@ Internet Gateway.
We'll now create a VPC, a virtual networking environment that you'll control:
1. Sign in to [Amazon Web Services](https://console.aws.amazon.com/vpc/home).
1. Select **Your VPCs** from the left menu and then click **Create VPC**.
1. Select **Your VPCs** from the left menu and then select **Create VPC**.
At the "Name tag" enter `gitlab-vpc` and at the "IPv4 CIDR block" enter
`10.0.0.0/16`. If you don't require dedicated hardware, you can leave
"Tenancy" as default. Click **Yes, Create** when ready.
"Tenancy" as default. Select **Yes, Create** when ready.
![Create VPC](img/create_vpc.png)
1. Select the VPC, click **Actions**, click **Edit DNS resolution**, and enable DNS resolution. Hit **Save** when done.
1. Select the VPC, select **Actions**, select **Edit DNS resolution**, and enable DNS resolution. Hit **Save** when done.
### Subnets
@ -160,7 +160,7 @@ We will create private and public subnets to match load balancers and
RDS instances as well:
1. Select **Subnets** from the left menu.
1. Click **Create subnet**. Give it a descriptive name tag based on the IP,
1. Select **Create subnet**. Give it a descriptive name tag based on the IP,
for example `gitlab-public-10.0.0.0`, select the VPC we created previously, select an availability zone (we'll use `us-west-2a`),
and at the IPv4 CIDR block let's give it a 24 subnet `10.0.0.0/24`:
@ -176,7 +176,7 @@ RDS instances as well:
| `gitlab-private-10.0.3.0` | private | `us-west-2b` | `10.0.3.0/24` |
1. Once all the subnets are created, enable **Auto-assign IPv4** for the two public subnets:
1. Select each public subnet in turn, click **Actions**, and click **Modify auto-assign IP settings**. Enable the option and save.
1. Select each public subnet in turn, select **Actions**, and select **Modify auto-assign IP settings**. Enable the option and save.
### Internet Gateway
@ -184,8 +184,8 @@ Now, still on the same dashboard, go to Internet Gateways and
create a new one:
1. Select **Internet Gateways** from the left menu.
1. Click **Create internet gateway**, give it the name `gitlab-gateway` and
click **Create**.
1. Select **Create internet gateway**, give it the name `gitlab-gateway` and
select **Create**.
1. Select it from the table, and then under the **Actions** dropdown choose
"Attach to VPC".
@ -197,12 +197,12 @@ create a new one:
Instances deployed in our private subnets need to connect to the internet for updates, but should not be reachable from the public internet. To achieve this, we'll make use of [NAT Gateways](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html) deployed in each of our public subnets:
1. Navigate to the VPC dashboard and click on **NAT Gateways** in the left menu bar.
1. Click **Create NAT Gateway** and complete the following:
1. Navigate to the VPC dashboard and select **NAT Gateways** in the left menu bar.
1. Select **Create NAT Gateway** and complete the following:
1. **Subnet**: Select `gitlab-public-10.0.0.0` from the dropdown.
1. **Elastic IP Allocation ID**: Enter an existing Elastic IP or click **Allocate Elastic IP address** to allocate a new IP to your NAT gateway.
1. **Elastic IP Allocation ID**: Enter an existing Elastic IP or select **Allocate Elastic IP address** to allocate a new IP to your NAT gateway.
1. Add tags if needed.
1. Click **Create NAT Gateway**.
1. Select **Create NAT Gateway**.
Create a second NAT gateway but this time place it in the second public subnet, `gitlab-public-10.0.2.0`.
@ -215,23 +215,23 @@ We need to create a route table for our public subnets to reach the internet via
On the VPC dashboard:
1. Select **Route Tables** from the left menu.
1. Click **Create Route Table**.
1. Select **Create Route Table**.
1. At the "Name tag" enter `gitlab-public` and choose `gitlab-vpc` under "VPC".
1. Click **Create**.
1. Select **Create**.
We now need to add our internet gateway as a new target and have
it receive traffic from any destination.
1. Select **Route Tables** from the left menu and select the `gitlab-public`
route to show the options at the bottom.
1. Select the **Routes** tab, click **Edit routes > Add route** and set `0.0.0.0/0`
1. Select the **Routes** tab, select **Edit routes > Add route** and set `0.0.0.0/0`
as the destination. In the target column, select the `gitlab-gateway` we created previously.
Hit **Save routes** once done.
Next, we must associate the **public** subnets to the route table:
1. Select the **Subnet Associations** tab and click **Edit subnet associations**.
1. Check only the public subnets and click **Save**.
1. Select the **Subnet Associations** tab and select **Edit subnet associations**.
1. Check only the public subnets and select **Save**.
#### Private Route Tables
@ -251,7 +251,7 @@ We'll create a load balancer to evenly distribute inbound traffic on ports `80`
On the EC2 dashboard, look for Load Balancer in the left navigation bar:
1. Click the **Create Load Balancer** button.
1. Select **Create Load Balancer**.
1. Choose the **Classic Load Balancer**.
1. Give it a name (we'll use `gitlab-loadbalancer`) and for the **Create LB Inside** option, select `gitlab-vpc` from the dropdown menu.
1. In the **Listeners** section, set the following listeners:
@ -259,10 +259,10 @@ On the EC2 dashboard, look for Load Balancer in the left navigation bar:
- TCP port 22 for both load balancer and instance protocols and ports
- HTTPS port 443 for load balancer protocol and ports, forwarding to HTTP port 80 on the instance (we will configure GitLab to listen on port 80 [later in the guide](#add-support-for-proxied-ssl))
1. In the **Select Subnets** section, select both public subnets from the list so that the load balancer can route traffic to both availability zones.
1. We'll add a security group for our load balancer to act as a firewall to control what traffic is allowed through. Click **Assign Security Groups** and select **Create a new security group**, give it a name
1. We'll add a security group for our load balancer to act as a firewall to control what traffic is allowed through. Select **Assign Security Groups** and select **Create a new security group**, give it a name
(we'll use `gitlab-loadbalancer-sec-group`) and description, and allow both HTTP and HTTPS traffic
from anywhere (`0.0.0.0/0, ::/0`). Also allow SSH traffic, select a custom source, and add a single trusted IP address or an IP address range in CIDR notation. This will allow users to perform Git actions over SSH.
1. Click **Configure Security Settings** and set the following:
1. Select **Configure Security Settings** and set the following:
1. Select an SSL/TLS certificate from ACM or upload a certificate to IAM.
1. Under **Select a Cipher**, pick a predefined security policy from the dropdown. You can see a breakdown of [Predefined SSL Security Policies for Classic Load Balancers](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html) in the AWS docs. Check the GitLab codebase for a list of [supported SSL ciphers and protocols](https://gitlab.com/gitlab-org/gitlab/-/blob/9ee7ad433269b37251e0dd5b5e00a0f00d8126b4/lib/support/nginx/gitlab-ssl#L97-99).
1. Click **Configure Health Check** and set up a health check for your EC2 instances.
@ -270,9 +270,9 @@ On the EC2 dashboard, look for Load Balancer in the left navigation bar:
1. For **Ping Port**, enter 80.
1. For **Ping Path** - we recommend that you [use the Readiness check endpoint](../../administration/load_balancer.md#readiness-check). You'll need to add [the VPC IP Address Range (CIDR)](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-groups.html#elb-vpc-nacl) to the [IP Allowlist](../../administration/monitoring/ip_whitelist.md) for the [Health Check endpoints](../../user/admin_area/monitoring/health_check.md)
1. Keep the default **Advanced Details** or adjust them according to your needs.
1. Click **Add EC2 Instances** - don't add anything as we will create an Auto Scaling Group later to manage instances for us.
1. Click **Add Tags** and add any tags you need.
1. Click **Review and Create**, review all your settings, and click **Create** if you're happy.
1. Select **Add EC2 Instances** - don't add anything as we will create an Auto Scaling Group later to manage instances for us.
1. Select **Add Tags** and add any tags you need.
1. Select **Review and Create**, review all your settings, and select **Create** if you're happy.
After the Load Balancer is up and running, you can revisit your Security
Groups to refine the access only through the ELB and any other requirements
@ -280,19 +280,19 @@ you might have.
### Configure DNS for Load Balancer
On the Route 53 dashboard, click **Hosted zones** in the left navigation bar:
On the Route 53 dashboard, select **Hosted zones** in the left navigation bar:
1. Select an existing hosted zone or, if you do not already have one for your domain, click **Create Hosted Zone**, enter your domain name, and click **Create**.
1. Click **Create Record Set** and provide the following values:
1. Select **Create Record Set** and provide the following values:
1. **Name:** Use the domain name (the default value) or enter a subdomain.
1. **Type:** Select **A - IPv4 address**.
1. **Alias:** Defaults to **No**. Select **Yes**.
1. **Alias Target:** Find the **ELB Classic Load Balancers** section and select the classic load balancer we created earlier.
1. **Routing Policy:** We'll use **Simple** but you can choose a different policy based on your use case.
1. **Evaluate Target Health:** We'll set this to **No** but you can choose to have the load balancer route traffic based on target health.
1. Click **Create**.
1. Select **Create**.
1. If you registered your domain through Route 53, you're done. If you used a different domain registrar, you need to update your DNS records with your domain registrar. You'll need to:
1. Click on **Hosted zones** and select the domain you added above.
1. Select **Hosted zones** and select the domain you added above.
1. You'll see a list of `NS` records. From your domain registrar's administrator panel, add each of these as `NS` records to your domain's DNS records. These steps may vary between domain registrars. If you're stuck, Google **"name of your registrar" add DNS records** and you should find a help article specific to your domain registrar.
The steps for doing this vary depending on which registrar you use and is beyond the scope of this guide.
@ -308,22 +308,22 @@ create the actual RDS instance.
We need a security group for our database that will allow inbound traffic from the instances we'll deploy in our `gitlab-loadbalancer-sec-group` later on:
1. From the EC2 dashboard, select **Security Groups** from the left menu bar.
1. Click **Create security group**.
1. Select **Create security group**.
1. Give it a name (we'll use `gitlab-rds-sec-group`), a description, and select the `gitlab-vpc` from the **VPC** dropdown.
1. In the **Inbound rules** section, click **Add rule** and set the following:
1. In the **Inbound rules** section, select **Add rule** and set the following:
1. **Type:** search for and select the **PostgreSQL** rule.
1. **Source type:** set as "Custom".
1. **Source:** select the `gitlab-loadbalancer-sec-group` we created earlier.
1. When done, click **Create security group**.
1. When done, select **Create security group**.
### RDS Subnet Group
1. Navigate to the RDS dashboard and select **Subnet Groups** from the left menu.
1. Click on **Create DB Subnet Group**.
1. Select **Create DB Subnet Group**.
1. Under **Subnet group details**, enter a name (we'll use `gitlab-rds-group`), a description, and choose the `gitlab-vpc` from the VPC dropdown.
1. From the **Availability Zones** dropdown, select the Availability Zones that include the subnets you've configured. In our case, we'll add `eu-west-2a` and `eu-west-2b`.
1. From the **Subnets** dropdown, select the two private subnets (`10.0.1.0/24` and `10.0.3.0/24`) as we defined them in the [subnets section](#subnets).
1. Click **Create** when ready.
1. Select **Create** when ready.
### Create the database
@ -332,7 +332,7 @@ Avoid using burstable instances (t class instances) for the database as this cou
Now, it's time to create the database:
1. Navigate to the RDS dashboard, select **Databases** from the left menu, and click **Create database**.
1. Navigate to the RDS dashboard, select **Databases** from the left menu, and select **Create database**.
1. Select **Standard Create** for the database creation method.
1. Select **PostgreSQL** as the database engine and select the minimum PostgreSQL version as defined for your GitLab version in our [database requirements](../../install/requirements.md#postgresql-requirements).
1. Since this is a production server, let's choose **Production** from the **Templates** section.
@ -355,7 +355,7 @@ Now, it's time to create the database:
1. Configure your preferred backup settings.
1. The only other change we'll make here is to disable auto minor version updates under **Maintenance**.
1. Leave all the other settings as is or tweak according to your needs.
1. Once you're happy, click **Create database**.
1. Once you're happy, select **Create database**.
Now that the database is created, let's move on to setting up Redis with ElastiCache.
@ -368,24 +368,24 @@ persistence and is used to store session data, temporary cache information, and
1. Navigate to the EC2 dashboard.
1. Select **Security Groups** from the left menu.
1. Click **Create security group** and fill in the details. Give it a name (we'll use `gitlab-redis-sec-group`),
1. Select **Create security group** and fill in the details. Give it a name (we'll use `gitlab-redis-sec-group`),
add a description, and choose the VPC we created previously
1. In the **Inbound rules** section, click **Add rule** and add a **Custom TCP** rule, set port `6379`, and set the "Custom" source as the `gitlab-loadbalancer-sec-group` we created earlier.
1. When done, click **Create security group**.
1. In the **Inbound rules** section, select **Add rule** and add a **Custom TCP** rule, set port `6379`, and set the "Custom" source as the `gitlab-loadbalancer-sec-group` we created earlier.
1. When done, select **Create security group**.
### Redis Subnet Group
1. Navigate to the ElastiCache dashboard from your AWS console.
1. Go to **Subnet Groups** in the left menu, and create a new subnet group (we'll name ours `gitlab-redis-group`).
Make sure to select our VPC and its [private subnets](#subnets). Click
**Create** when ready.
Make sure to select our VPC and its [private subnets](#subnets).
1. Select **Create** when ready.
![ElastiCache subnet](img/ec_subnet.png)
### Create the Redis Cluster
1. Navigate back to the ElastiCache dashboard.
1. Select **Redis** on the left menu and click **Create** to create a new
1. Select **Redis** on the left menu and select **Create** to create a new
Redis cluster. Do not enable **Cluster Mode** as it is [not supported](../../administration/redis/replication_and_failover_external.md#requirements). Even without cluster mode on, you still get the
chance to deploy Redis in multiple availability zones.
1. In the settings section:
@ -404,7 +404,7 @@ persistence and is used to store session data, temporary cache information, and
1. In the security settings, edit the security groups and choose the
`gitlab-redis-sec-group` we had previously created.
1. Leave the rest of the settings to their default values or edit to your liking.
1. When done, click **Create**.
1. When done, select **Create**.
## Setting up Bastion Hosts
@ -418,29 +418,29 @@ If you do not want to maintain bastion hosts, you can set up [AWS Systems Manage
### Create Bastion Host A
1. Navigate to the EC2 Dashboard and click on **Launch instance**.
1. Navigate to the EC2 Dashboard and select **Launch instance**.
1. Select the **Ubuntu Server 18.04 LTS (HVM)** AMI.
1. Choose an instance type. We'll use a `t2.micro` as we'll only use the bastion host to SSH into our other instances.
1. Click **Configure Instance Details**.
1. Select **Configure Instance Details**.
1. Under **Network**, select the `gitlab-vpc` from the dropdown menu.
1. Under **Subnet**, select the public subnet we created earlier (`gitlab-public-10.0.0.0`).
1. Double check that under **Auto-assign Public IP** you have **Use subnet setting (Enable)** selected.
1. Leave everything else as default and click **Add Storage**.
1. Leave everything else as default and select **Add Storage**.
1. For storage, we'll leave everything as default and only add an 8GB root volume. We won't store anything on this instance.
1. Click **Add Tags** and on the next screen click **Add Tag**.
1. Select **Add Tags** and on the next screen select **Add Tag**.
1. We'll only set `Key: Name` and `Value: Bastion Host A`.
1. Click **Configure Security Group**.
1. Select **Configure Security Group**.
1. Select **Create a new security group**, enter a **Security group name** (we'll use `bastion-sec-group`), and add a description.
1. We'll enable SSH access from anywhere (`0.0.0.0/0`). If you want stricter security, specify a single IP address or an IP address range in CIDR notation.
1. Click **Review and Launch**
1. Review all your settings and, if you're happy, click **Launch**.
1. Acknowledge that you have access to an existing key pair or create a new one. Click **Launch Instance**.
1. Select **Review and Launch**
1. Review all your settings and, if you're happy, select **Launch**.
1. Acknowledge that you have access to an existing key pair or create a new one. Select **Launch Instance**.
Confirm that you can SSH into the instance:
1. On the EC2 Dashboard, click on **Instances** in the left menu.
1. On the EC2 Dashboard, select **Instances** in the left menu.
1. Select **Bastion Host A** from your list of instances.
1. Click **Connect** and follow the connection instructions.
1. Select **Connect** and follow the connection instructions.
1. If you are able to connect successfully, let's move on to setting up our second bastion host for redundancy.
### Create Bastion Host B
@ -466,16 +466,16 @@ From the EC2 dashboard:
1. Use the section below titled "[Find official GitLab-created AMI IDs on AWS](#find-official-gitlab-created-ami-ids-on-aws)" to find the correct AMI to launch.
1. After clicking **Launch** on the desired AMI, select an instance type based on your workload. Consult the [hardware requirements](../../install/requirements.md#hardware-requirements) to choose one that fits your needs (at least `c5.xlarge`, which is sufficient to accommodate 100 users).
1. Click **Configure Instance Details**:
1. Select **Configure Instance Details**:
1. In the **Network** dropdown, select `gitlab-vpc`, the VPC we created earlier.
1. In the **Subnet** dropdown, select `gitlab-private-10.0.1.0` from the list of subnets we created earlier.
1. Double check that **Auto-assign Public IP** is set to `Use subnet setting (Disable)`.
1. Click **Add Storage**.
1. Select **Add Storage**.
1. The root volume is 8GiB by default and should be enough given that we won't store any data there.
1. Click **Add Tags** and add any tags you may need. In our case, we'll only set `Key: Name` and `Value: GitLab`.
1. Click **Configure Security Group**. Check **Select an existing security group** and select the `gitlab-loadbalancer-sec-group` we created earlier.
1. Click **Review and launch** followed by **Launch** if you're happy with your settings.
1. Finally, acknowledge that you have access to the selected private key file or create a new one. Click **Launch Instances**.
1. Select **Add Tags** and add any tags you may need. In our case, we'll only set `Key: Name` and `Value: GitLab`.
1. Select **Configure Security Group**. Check **Select an existing security group** and select the `gitlab-loadbalancer-sec-group` we created earlier.
1. Select **Review and launch** followed by **Launch** if you're happy with your settings.
1. Finally, acknowledge that you have access to the selected private key file or create a new one. Select **Launch Instances**.
### Add custom configuration
@ -501,7 +501,7 @@ Since we're adding our SSL certificate at the load balancer, we do not need the
From your GitLab instance, connect to the RDS instance to verify access and to install the required `pg_trgm` and `btree_gist` extensions.
To find the host or endpoint, navigate to **Amazon RDS > Databases** and click on the database you created earlier. Look for the endpoint under the **Connectivity & security** tab.
To find the host or endpoint, navigate to **Amazon RDS > Databases** and select the database you created earlier. Look for the endpoint under the **Connectivity & security** tab.
Do not to include the colon and port number:
@ -580,23 +580,23 @@ It should be enabled and configured on a separate EC2 instance in one of the
Let's create an EC2 instance where we'll install Gitaly:
1. From the EC2 dashboard, click **Launch instance**.
1. From the EC2 dashboard, select **Launch instance**.
1. Choose an AMI. In this example, we'll select the **Ubuntu Server 18.04 LTS (HVM), SSD Volume Type**.
1. Choose an instance type. We'll pick a `c5.xlarge`.
1. Click **Configure Instance Details**.
1. Select **Configure Instance Details**.
1. In the **Network** dropdown, select `gitlab-vpc`, the VPC we created earlier.
1. In the **Subnet** dropdown, select `gitlab-private-10.0.1.0` from the list of subnets we created earlier.
1. Double check that **Auto-assign Public IP** is set to `Use subnet setting (Disable)`.
1. Click **Add Storage**.
1. Select **Add Storage**.
1. Increase the Root volume size to `20 GiB` and change the **Volume Type** to `Provisioned IOPS SSD (io1)`. (This is an arbitrary size. Create a volume big enough for your repository storage requirements.)
1. For **IOPS** set `1000` (20 GiB x 50 IOPS). You can provision up to 50 IOPS per GiB. If you select a larger volume, increase the IOPS accordingly. Workloads where many small files are written in a serialized manner, like `git`, requires performant storage, hence the choice of `Provisioned IOPS SSD (io1)`.
1. Click on **Add Tags** and add your tags. In our case, we'll only set `Key: Name` and `Value: Gitaly`.
1. Click on **Configure Security Group** and let's **Create a new security group**.
1. Select **Add Tags** and add your tags. In our case, we'll only set `Key: Name` and `Value: Gitaly`.
1. Select **Configure Security Group** and let's **Create a new security group**.
1. Give your security group a name and description. We'll use `gitlab-gitaly-sec-group` for both.
1. Create a **Custom TCP** rule and add port `8075` to the **Port Range**. For the **Source**, select the `gitlab-loadbalancer-sec-group`.
1. Also add an inbound rule for SSH from the `bastion-sec-group` so that we can connect using [SSH Agent Forwarding](#use-ssh-agent-forwarding) from the Bastion hosts.
1. Click **Review and launch** followed by **Launch** if you're happy with your settings.
1. Finally, acknowledge that you have access to the selected private key file or create a new one. Click **Launch Instances**.
1. Select **Review and launch** followed by **Launch** if you're happy with your settings.
1. Finally, acknowledge that you have access to the selected private key file or create a new one. Select **Launch Instances**.
NOTE:
Instead of storing configuration _and_ repository data on the root volume, you can also choose to add an additional EBS volume for repository storage. Follow the same guidance as above. See the [Amazon EBS pricing](https://aws.amazon.com/ebs/pricing/). We do not recommend using EFS as it may negatively impact the performance of GitLab. You can review the [relevant documentation](../../administration/nfs.md#avoid-using-cloud-based-file-systems) for more details.
@ -679,9 +679,9 @@ When our [auto scaling group](#create-an-auto-scaling-group) spins up new instan
On the EC2 dashboard:
1. Select the `GitLab` instance we [created earlier](#install-gitlab).
1. Click on **Actions**, scroll down to **Image** and click **Create Image**.
1. Select **Actions**, scroll down to **Image** and select **Create Image**.
1. Give your image a name and description (we'll use `GitLab-Source` for both).
1. Leave everything else as default and click **Create Image**
1. Leave everything else as default and select **Create Image**
Now we have a custom AMI that we'll use to create our launch configuration the next step.
@ -691,17 +691,17 @@ Now we have a custom AMI that we'll use to create our launch configuration the n
From the EC2 dashboard:
1. Select **Launch Configurations** from the left menu and click **Create launch configuration**.
1. Select **Launch Configurations** from the left menu and select **Create launch configuration**.
1. Select **My AMIs** from the left menu and select the `GitLab` custom AMI we created above.
1. Select an instance type best suited for your needs (at least a `c5.xlarge`) and click **Configure details**.
1. Select an instance type best suited for your needs (at least a `c5.xlarge`) and select **Configure details**.
1. Enter a name for your launch configuration (we'll use `gitlab-ha-launch-config`).
1. **Do not** check **Request Spot Instance**.
1. From the **IAM Role** dropdown, pick the `GitLabAdmin` instance role we [created earlier](#create-an-iam-ec2-instance-role-and-profile).
1. Leave the rest as defaults and click **Add Storage**.
1. The root volume is 8GiB by default and should be enough given that we won't store any data there. Click **Configure Security Group**.
1. Leave the rest as defaults and select **Add Storage**.
1. The root volume is 8GiB by default and should be enough given that we won't store any data there. Select **Configure Security Group**.
1. Check **Select and existing security group** and select the `gitlab-loadbalancer-sec-group` we created earlier.
1. Click **Review**, review your changes, and click **Create launch configuration**.
1. Acknowledge that you have access to the private key or create a new one. Click **Create launch configuration**.
1. Select **Review**, review your changes, and select **Create launch configuration**.
1. Acknowledge that you have access to the private key or create a new one. Select **Create launch configuration**.
### Create an auto scaling group
@ -713,7 +713,7 @@ From the EC2 dashboard:
1. Expand the **Advanced Details** section and check the **Receive traffic from one or more load balancers** option.
1. From the **Classic Load Balancers** dropdown, select the load balancer we created earlier.
1. For **Health Check Type**, select **ELB**.
1. We'll leave our **Health Check Grace Period** as the default `300` seconds. Click **Configure scaling policies**.
1. We'll leave our **Health Check Grace Period** as the default `300` seconds. Select **Configure scaling policies**.
1. Check **Use scaling policies to adjust the capacity of this group**.
1. For this group we'll scale between 2 and 4 instances where one instance will be added if CPU
utilization is greater than 60% and one instance is removed if it falls

View File

@ -114,7 +114,7 @@ to the end of the Bitbucket authorization callback URL.
if you installed from source.
On the sign-in page there should now be a Bitbucket icon below the regular
sign-in form. Click the icon to begin the authentication process. Bitbucket asks
sign-in form. Select the icon to begin the authentication process. Bitbucket asks
the user to sign in and authorize the GitLab application. If successful, the user
is returned to GitLab and signed in.

View File

@ -108,6 +108,6 @@ Facebook. Facebook generates an app ID and secret key for you to use.
installed GitLab via Omnibus or from source respectively.
On the sign in page there should now be a Facebook icon below the regular sign
in form. Click the icon to begin the authentication process. Facebook asks the
in form. Select the icon to begin the authentication process. Facebook asks the
user to sign in and authorize the GitLab application. If everything goes well
the user is returned to GitLab and signed in.

View File

@ -50,7 +50,7 @@ In Google's side:
To do so you should:
1. Go to the [Google API Console](https://console.developers.google.com/apis/dashboard).
1. Click on **ENABLE APIS AND SERVICES** button at the top of the page.
1. Select **ENABLE APIS AND SERVICES** at the top of the page.
1. Find each of the above APIs. On the page for the API, press the **ENABLE** button.
It may take a few minutes for the API to be fully functional.
@ -123,6 +123,6 @@ On your GitLab server:
respectively.
On the sign in page there should now be a Google icon below the regular sign in
form. Click the icon to begin the authentication process. Google asks the
form. Select the icon to begin the authentication process. Google asks the
user to sign in and authorize the GitLab application. If everything goes well
the user is returned to GitLab and is signed in.

View File

@ -15,7 +15,7 @@ To get the credentials (a pair of Client ID and Client Secret), you must [create
1. Sign in to [Salesforce](https://login.salesforce.com/).
1. In Setup, enter `App Manager` in the Quick Find box, click **App Manager**, then click **New Connected App**.
1. In Setup, enter `App Manager` in the Quick Find box, select **App Manager**, then select **New Connected App**.
1. Fill in the application details into the following fields:
- **Connected App Name** and **API Name**: Set to any value but consider something like `<Organization>'s GitLab`, `<Your Name>'s GitLab`, or something else that is descriptive.
@ -24,14 +24,14 @@ To get the credentials (a pair of Client ID and Client Secret), you must [create
![Salesforce App Details](img/salesforce_app_details.png)
1. Select **API (Enable OAuth Settings)** and click on **Enable OAuth Settings**.
1. Select **API (Enable OAuth Settings)** and select **Enable OAuth Settings**.
1. Fill in the application details into the following fields:
- **Callback URL**: The callback URL of your GitLab installation. For example, `https://gitlab.example.com/users/auth/salesforce/callback`.
- **Selected OAuth Scopes**: Move `Access your basic information (id, profile, email, address, phone)` and `Allow access to your unique identifier (openid)` to the right column.
![Salesforce OAuth App Details](img/salesforce_oauth_app_details.png)
1. Click **Save**.
1. Select **Save**.
1. On your GitLab server, open the configuration file.
@ -86,7 +86,7 @@ To get the credentials (a pair of Client ID and Client Secret), you must [create
to take effect if you installed GitLab via Omnibus or from source respectively.
On the sign in page, there should now be a Salesforce icon below the regular sign in form.
Click the icon to begin the authentication process. Salesforce asks the user to sign in and authorize the GitLab application.
Select the icon to begin the authentication process. Salesforce asks the user to sign in and authorize the GitLab application.
If everything goes well, the user is returned to GitLab and is signed in.
NOTE:

View File

@ -160,7 +160,7 @@ At a minimum the IdP *must* provide a claim containing the user's email address
See [the assertions list](#assertions) for other available claims.
On the sign in page there should now be a SAML button below the regular sign in form.
Click the icon to begin the authentication process. If everything goes well the user
Select the icon to begin the authentication process. If everything goes well the user
is returned to GitLab and signed in.
### Use multiple SAML identity providers
@ -486,7 +486,7 @@ In addition to the changes in GitLab, make sure that your IdP is returning the
### `auto_sign_in_with_provider`
You can add this setting to your GitLab configuration to automatically redirect you
to your SAML server for authentication. This removes the requirement to click a button
to your SAML server for authentication. This removes the requirement to select a button
before actually signing in.
For Omnibus package:
@ -812,7 +812,7 @@ The following guidance is based on this Okta article, on adding a [SAML Applicat
1. The last part of the configuration is the feedback section where you can
just say you're a customer and creating an app for internal use.
1. When you have your app you can see a few tabs on the top of the app's
profile. Click on the SAML 2.0 configuration instructions button.
profile. Select the SAML 2.0 configuration instructions button.
1. On the screen that comes up take note of the
**Identity Provider Single Sign-On URL** which you can use for the
`idp_sso_target_url` on your GitLab configuration file.

View File

@ -88,4 +88,4 @@ Twitter. Twitter generates a client ID and secret key for you to use.
1. [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect if you
installed GitLab via Omnibus or from source respectively.
On the sign in page there should now be a Twitter icon below the regular sign in form. Click the icon to begin the authentication process. Twitter asks the user to sign in and authorize the GitLab application. If everything goes well the user is returned to GitLab and signed in.
On the sign in page there should now be a Twitter icon below the regular sign in form. Select the icon to begin the authentication process. Twitter asks the user to sign in and authorize the GitLab application. If everything goes well the user is returned to GitLab and signed in.

View File

@ -98,11 +98,11 @@ The following assumes you already have Vault installed and running.
1. Go to your Vault UI (example: [http://127.0.0.1:8200/ui/vault/auth?with=oidc](http://127.0.0.1:8200/ui/vault/auth?with=oidc)).
1. If the `OIDC` method is not currently selected, open the dropdown and select it.
1. Click the **Sign in With GitLab** button, which opens a modal window:
1. Select **Sign in With GitLab**, which opens a modal window:
![Sign into Vault with GitLab](img/sign_into_vault_with_gitlab_v12_6.png)
1. Click **Authorize** on the modal to allow Vault to sign in through GitLab. This redirects you back to your Vault UI as a signed-in user.
1. Select **Authorize** to allow Vault to sign in through GitLab. This redirects you back to your Vault UI as a signed-in user.
![Authorize Vault to connect with GitLab](img/authorize_vault_with_gitlab_v12_6.png)
@ -127,7 +127,7 @@ The following assumes you already have Vault installed and running.
[Redirect URIs](https://www.vaultproject.io/docs/auth/jwt#redirect-uris).
After running the command, it presents a link in the terminal.
Click the link in the terminal and a browser tab opens that confirms you're signed into Vault via OIDC:
Select the link in the terminal and a browser tab opens that confirms you're signed into Vault via OIDC:
![Signed into Vault via OIDC](img/signed_into_vault_via_oidc_v12_6.png)

View File

@ -321,8 +321,8 @@ You can [cancel the subscription](#enable-or-disable-automatic-renewal) to disab
1. From either your personal homepage or the group's page, go to **Settings > Usage Quotas**.
1. For each locked project, total by how much its **Usage** exceeds the free quota and purchased
storage. You must purchase the storage increment that exceeds this total.
1. Click **Purchase more storage** and you are taken to the Customers Portal.
1. Click **Add new subscription**.
1. Select **Purchase more storage** and you are taken to the Customers Portal.
1. Select **Add new subscription**.
1. Scroll to **Purchase add-on subscriptions** and select **Buy storage subscription**.
1. In the **Subscription details** section select the name of the user or group from the dropdown.
1. Enter the desired quantity of storage packs.

View File

@ -39,8 +39,7 @@ containing a CRON expression for when the scans will be run.
```yaml
starboard:
vulnerability_report:
cadence: '0 0 * * *' # Daily at 00:00 (Kubernetes cluster time)
cadence: '0 0 * * *' # Daily at 00:00 (Kubernetes cluster time)
```
The `cadence` field is required. GitLab supports the following types of CRON syntax for the cadence field:
@ -58,8 +57,8 @@ namespaces, you can use this configuration:
```yaml
starboard:
cadence: '0 0 * * *'
vulnerability_report:
cadence: '0 0 * * *'
namespaces:
- development
- staging

View File

@ -69,6 +69,14 @@ Example response without attribute `select`:
}
```
Example request with attribute `select = package_file`:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" \
--upload-file path/to/file.txt \
"https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt?select=package_file"
```
Example response with attribute `select = package_file`:
```json

View File

@ -1455,7 +1455,7 @@ msgstr[1] ""
msgid "1-9 contributions"
msgstr ""
msgid "1. Effective June 1, 2022, all free tier public projects will be %{minutes_quota_link}."
msgid "1. Effective June 1, 2022, all GitLab Free tier public projects will be %{minutes_quota_link}."
msgstr ""
msgid "10-19 contributions"
@ -1470,7 +1470,7 @@ msgstr ""
msgid "1st contribution!"
msgstr ""
msgid "2. Before July 1, 2022, all free tier public open source projects must %{enrollment_link} to continue to receive GitLab Ultimate benefits."
msgid "2. Before July 1, 2022, all GitLab Free tier public open source projects must %{enrollment_link} to continue to receive GitLab Ultimate benefits."
msgstr ""
msgid "20-29 contributions"
@ -7407,7 +7407,7 @@ msgstr ""
msgid "Changes the title to \"%{title_param}\"."
msgstr ""
msgid "Changes to free tier public projects"
msgid "Changes to GitLab Free tier public projects"
msgstr ""
msgid "Changes to the title have not been saved"
@ -10849,6 +10849,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
msgid "Crm|Contact"
msgstr ""
msgid "Crm|Contact has been added."
msgstr ""

View File

@ -29,20 +29,14 @@ module QA
start_pipeline_via_api_with_variable(i + 1)
wait_for_pipelines
# Is inheritable when true
expect(child1_pipeline).to have_variable(key: key, value: value),
"Expected to find `{key: 'TEST_VAR', value: 'This is great!'}`" \
" but got #{child1_pipeline.pipeline_variables}"
# When forward:pipeline_variables is true
expect_downstream_pipeline_to_inherit_variable
# Is not inheritable when false
expect(child2_pipeline).not_to have_variable(key: key, value: value),
"Did not expect to find `{key: 'TEST_VAR', value: 'This is great!'}`" \
" but got #{child2_pipeline.pipeline_variables}"
# When forward:pipeline_variables is false
expect_downstream_pipeline_not_to_inherit_variable(upstream_project, 'child2_trigger')
# Is not inheritable by default
expect(downstream1_pipeline).not_to have_variable(key: key, value: value),
"Did not expect to find `{key: 'TEST_VAR', value: 'This is great!'}`" \
" but got #{downstream1_pipeline.pipeline_variables}"
# When forward:pipeline_variables is default
expect_downstream_pipeline_not_to_inherit_variable(downstream1_project, 'downstream1_trigger')
end
end
@ -84,6 +78,20 @@ module QA
YAML
}
end
def expect_downstream_pipeline_to_inherit_variable
pipeline = downstream_pipeline(upstream_project, 'child1_trigger')
expect(pipeline).to have_variable(key: key, value: value),
"Expected to find `{key: 'TEST_VAR', value: 'This is great!'}`" \
" but got #{pipeline.pipeline_variables}"
end
def expect_downstream_pipeline_not_to_inherit_variable(project, bridge_name)
pipeline = downstream_pipeline(project, bridge_name)
expect(pipeline).not_to have_variable(key: key, value: value),
"Did not expect to find `{key: 'TEST_VAR', value: 'This is great!'}`" \
" but got #{pipeline.pipeline_variables}"
end
end
end
end

View File

@ -66,7 +66,8 @@ module QA
def wait_for_pipelines
Support::Waiter.wait_until(max_duration: 300, sleep_interval: 10) do
upstream_pipeline.status == 'success' && downstream1_pipeline.status == 'success'
upstream_pipeline.status == 'success' &&
downstream_pipeline(downstream1_project, 'downstream1_trigger').status == 'success'
end
end
@ -106,31 +107,10 @@ module QA
end
end
def child1_pipeline
def downstream_pipeline(project, bridge_name)
Resource::Pipeline.fabricate_via_api! do |pipeline|
pipeline.project = upstream_project
pipeline.id = upstream_pipeline.downstream_pipeline_id(bridge_name: 'child1_trigger')
end
end
def child2_pipeline
Resource::Pipeline.fabricate_via_api! do |pipeline|
pipeline.project = upstream_project
pipeline.id = upstream_pipeline.downstream_pipeline_id(bridge_name: 'child2_trigger')
end
end
def downstream1_pipeline
Resource::Pipeline.fabricate_via_api! do |pipeline|
pipeline.project = downstream1_project
pipeline.id = upstream_pipeline.downstream_pipeline_id(bridge_name: 'downstream1_trigger')
end
end
def downstream2_pipeline
Resource::Pipeline.fabricate_via_api! do |pipeline|
pipeline.project = downstream2_project
pipeline.id = upstream_pipeline.downstream_pipeline_id(bridge_name: 'downstream2_trigger')
pipeline.project = project
pipeline.id = upstream_pipeline.downstream_pipeline_id(bridge_name: bridge_name)
end
end

View File

@ -122,8 +122,8 @@ RSpec.describe 'Milestone' do
click_link 'Reopen Milestone'
expect(page).not_to have_selector('.status-box-closed')
expect(page).to have_selector('.status-box-open')
expect(page).not_to have_selector('.gl-bg-red-500')
expect(page).to have_selector('.gl-bg-green-500')
end
end
@ -133,8 +133,8 @@ RSpec.describe 'Milestone' do
click_link 'Reopen Milestone'
expect(page).not_to have_selector('.status-box-closed')
expect(page).to have_selector('.status-box-open')
expect(page).not_to have_selector('.gl-bg-red-500')
expect(page).to have_selector('.gl-bg-green-500')
end
end
end

View File

@ -36,9 +36,11 @@ import {
TOKEN_TYPE_ASSIGNEE,
TOKEN_TYPE_AUTHOR,
TOKEN_TYPE_CONFIDENTIAL,
TOKEN_TYPE_CONTACT,
TOKEN_TYPE_LABEL,
TOKEN_TYPE_MILESTONE,
TOKEN_TYPE_MY_REACTION,
TOKEN_TYPE_ORGANIZATION,
TOKEN_TYPE_RELEASE,
TOKEN_TYPE_TYPE,
urlSortParams,
@ -65,6 +67,8 @@ describe('CE IssuesListApp component', () => {
autocompleteAwardEmojisPath: 'autocomplete/award/emojis/path',
calendarPath: 'calendar/path',
canBulkUpdate: false,
canReadCrmContact: false,
canReadCrmOrganization: false,
emptyStateSvgPath: 'empty-state.svg',
exportCsvPath: 'export/csv/path',
fullPath: 'path/to/project',
@ -589,6 +593,21 @@ describe('CE IssuesListApp component', () => {
});
});
describe('when user does not have CRM enabled', () => {
beforeEach(() => {
wrapper = mountComponent({
provide: { canReadCrmContact: false, canReadCrmOrganization: false },
});
});
it('does not render Contact or Organization tokens', () => {
expect(findIssuableList().props('searchTokens')).not.toMatchObject([
{ type: TOKEN_TYPE_CONTACT },
{ type: TOKEN_TYPE_ORGANIZATION },
]);
});
});
describe('when all tokens are available', () => {
const originalGon = window.gon;
@ -601,7 +620,13 @@ describe('CE IssuesListApp component', () => {
current_user_avatar_url: mockCurrentUser.avatar_url,
};
wrapper = mountComponent({ provide: { isSignedIn: true } });
wrapper = mountComponent({
provide: {
canReadCrmContact: true,
canReadCrmOrganization: true,
isSignedIn: true,
},
});
});
afterEach(() => {
@ -617,9 +642,11 @@ describe('CE IssuesListApp component', () => {
{ type: TOKEN_TYPE_ASSIGNEE, preloadedAuthors },
{ type: TOKEN_TYPE_AUTHOR, preloadedAuthors },
{ type: TOKEN_TYPE_CONFIDENTIAL },
{ type: TOKEN_TYPE_CONTACT },
{ type: TOKEN_TYPE_LABEL },
{ type: TOKEN_TYPE_MILESTONE },
{ type: TOKEN_TYPE_MY_REACTION },
{ type: TOKEN_TYPE_ORGANIZATION },
{ type: TOKEN_TYPE_RELEASE },
{ type: TOKEN_TYPE_TYPE },
]);

View File

@ -159,7 +159,6 @@ describe('IssuableBody', () => {
expect(titleEl.exists()).toBe(true);
expect(titleEl.props()).toMatchObject({
issuable: issuableBodyProps.issuable,
statusBadgeClass: issuableBodyProps.statusBadgeClass,
statusIcon: issuableBodyProps.statusIcon,
enableEdit: issuableBodyProps.enableEdit,
});

View File

@ -47,7 +47,6 @@ describe('IssuableShowRoot', () => {
describe('template', () => {
const {
statusBadgeClass,
statusIcon,
statusIconClass,
enableEdit,
@ -69,7 +68,6 @@ describe('IssuableShowRoot', () => {
expect(issuableHeader.exists()).toBe(true);
expect(issuableHeader.props()).toMatchObject({
issuableState: state,
statusBadgeClass,
statusIcon,
statusIconClass,
blocked,
@ -91,7 +89,6 @@ describe('IssuableShowRoot', () => {
expect(issuableBody.exists()).toBe(true);
expect(issuableBody.props()).toMatchObject({
issuable: mockIssuable,
statusBadgeClass,
statusIcon,
enableEdit,
enableAutocomplete,

View File

@ -98,9 +98,6 @@ describe('IssuableTitle', () => {
expect(stickyHeaderEl.exists()).toBe(true);
expect(stickyHeaderEl.findComponent(GlBadge).props('variant')).toBe('success');
expect(stickyHeaderEl.findComponent(GlBadge).classes()).toContain(
mockIssuableShowProps.statusBadgeClass,
);
expect(stickyHeaderEl.findComponent(GlIcon).props('name')).toBe(
issuableTitleProps.statusIcon,
);

View File

@ -36,7 +36,6 @@ export const mockIssuableShowProps = {
enableTaskList: true,
enableEdit: true,
showFieldTitle: false,
statusBadgeClass: 'issuable-status-badge-open',
statusIcon: 'issues',
statusIconClass: 'gl-sm-display-none',
taskCompletionStatus: {

View File

@ -0,0 +1,42 @@
import { shallowMount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
import WorkItemAssignees from '~/work_items/components/work_item_assignees.vue';
const mockAssignees = [
{
__typename: 'UserCore',
id: 'gid://gitlab/User/1',
avatarUrl: '',
webUrl: '',
name: 'John Doe',
username: 'doe_I',
},
{
__typename: 'UserCore',
id: 'gid://gitlab/User/2',
avatarUrl: '',
webUrl: '',
name: 'Marcus Rutherford',
username: 'ruthfull',
},
];
describe('WorkItemAssignees component', () => {
let wrapper;
const findAssigneeLinks = () => wrapper.findAllComponents(GlLink);
const createComponent = () => {
wrapper = shallowMount(WorkItemAssignees, {
propsData: {
assignees: mockAssignees,
},
});
};
it('should pass the correct data-user-id attribute', () => {
createComponent();
expect(findAssigneeLinks().at(0).attributes('data-user-id')).toBe('1');
});
});

View File

@ -7,9 +7,11 @@ import waitForPromises from 'helpers/wait_for_promises';
import WorkItemDetail from '~/work_items/components/work_item_detail.vue';
import WorkItemState from '~/work_items/components/work_item_state.vue';
import WorkItemTitle from '~/work_items/components/work_item_title.vue';
import WorkItemAssignees from '~/work_items/components/work_item_assignees.vue';
import { i18n } from '~/work_items/constants';
import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
import workItemTitleSubscription from '~/work_items/graphql/work_item_title.subscription.graphql';
import { temporaryConfig } from '~/work_items/graphql/provider';
import { workItemTitleSubscriptionResponse, workItemQueryResponse } from '../mock_data';
describe('WorkItemDetail component', () => {
@ -24,18 +26,32 @@ describe('WorkItemDetail component', () => {
const findSkeleton = () => wrapper.findComponent(GlSkeletonLoader);
const findWorkItemTitle = () => wrapper.findComponent(WorkItemTitle);
const findWorkItemState = () => wrapper.findComponent(WorkItemState);
const findWorkItemAssignees = () => wrapper.findComponent(WorkItemAssignees);
const createComponent = ({
workItemId = workItemQueryResponse.data.workItem.id,
handler = successHandler,
subscriptionHandler = initialSubscriptionHandler,
assigneesEnabled = false,
includeAssigneesWidget = false,
} = {}) => {
wrapper = shallowMount(WorkItemDetail, {
apolloProvider: createMockApollo([
[workItemQuery, handler],
[workItemTitleSubscription, subscriptionHandler],
]),
apolloProvider: createMockApollo(
[
[workItemQuery, handler],
[workItemTitleSubscription, subscriptionHandler],
],
{},
{
typePolicies: includeAssigneesWidget ? temporaryConfig.cacheConfig.typePolicies : {},
},
),
propsData: { workItemId },
provide: {
glFeatures: {
workItemAssignees: assigneesEnabled,
},
},
});
};
@ -118,4 +134,33 @@ describe('WorkItemDetail component', () => {
expect(wrapper.emitted('workItemUpdated')).toEqual([[], []]);
});
describe('when assignees feature flag is enabled', () => {
it('renders assignees component when assignees widget is returned from the API', async () => {
createComponent({
assigneesEnabled: true,
includeAssigneesWidget: true,
});
await waitForPromises();
expect(findWorkItemAssignees().exists()).toBe(true);
});
it('does not render assignees component when assignees widget is not returned from the API', async () => {
createComponent({
assigneesEnabled: true,
includeAssigneesWidget: false,
});
await waitForPromises();
expect(findWorkItemAssignees().exists()).toBe(false);
});
});
it('does not render assignees component when assignees feature flag is disabled', async () => {
createComponent();
await waitForPromises();
expect(findWorkItemAssignees().exists()).toBe(false);
});
});

View File

@ -12,7 +12,7 @@ RSpec.describe GitlabSchema.types['CiRunner'] do
id description created_at contacted_at maximum_timeout access_level active paused status
version short_sha revision locked run_untagged ip_address runner_type tag_list
project_count job_count admin_url edit_admin_url user_permissions executor_name architecture_name platform_name
maintenance_note groups projects jobs token_expires_at
maintenance_note maintenance_note_html groups projects jobs token_expires_at
]
expect(described_class).to include_graphql_fields(*expected_fields)

View File

@ -440,6 +440,90 @@ RSpec.describe IssuesHelper do
end
end
describe '#status_box_class' do
context 'when updated_mr_header feature flag is enabled' do
before do
stub_feature_flags(updated_mr_header: true)
end
context 'when object is expired' do
it 'returns orange background' do
milestone = build(:milestone, due_date: Date.today.prev_month)
expect(helper.status_box_class(milestone)).to eq('gl-bg-orange-500')
end
end
context 'when object is merged' do
it 'returns blue background' do
merge_request = build(:merge_request, :merged)
expect(helper.status_box_class(merge_request)).to eq('badge-info')
end
end
context 'when object is closed' do
it 'returns red background' do
merge_request = build(:merge_request, :closed)
expect(helper.status_box_class(merge_request)).to eq('badge-danger')
end
end
context 'when object is upcoming' do
it 'returns gray background' do
milestone = build(:milestone, start_date: Date.today.next_month)
expect(helper.status_box_class(milestone)).to eq('gl-bg-gray-500')
end
end
context 'when object is opened' do
it 'returns green background' do
merge_request = build(:merge_request, :opened)
expect(helper.status_box_class(merge_request)).to eq('badge-success')
end
end
end
context 'when updated_mr_header feature flag is disabled' do
before do
stub_feature_flags(updated_mr_header: false)
end
context 'when object is expired' do
it 'returns orange background' do
milestone = build(:milestone, due_date: Date.today.prev_month)
expect(helper.status_box_class(milestone)).to eq('gl-bg-orange-500')
end
end
context 'when object is merged' do
it 'returns blue background' do
merge_request = build(:merge_request, :merged)
expect(helper.status_box_class(merge_request)).to eq('gl-bg-blue-500')
end
end
context 'when object is closed' do
it 'returns red background' do
merge_request = build(:merge_request, :closed)
expect(helper.status_box_class(merge_request)).to eq('gl-bg-red-500')
end
end
context 'when object is upcoming' do
it 'returns gray background' do
milestone = build(:milestone, start_date: Date.today.next_month)
expect(helper.status_box_class(milestone)).to eq('gl-bg-gray-500')
end
end
context 'when object is opened' do
it 'returns green background' do
merge_request = build(:merge_request, :opened)
expect(helper.status_box_class(merge_request)).to eq('gl-bg-green-500')
end
end
end
end
describe '#issue_hidden?' do
context 'when issue is hidden' do
let_it_be(:banned_user) { build(:user, :banned) }

View File

@ -152,7 +152,7 @@ RSpec.describe TodosHelper do
shared_examples 'a rendered state pill' do |attr|
it 'returns expected html' do
aggregate_failures do
expect(subject).to have_css(".status-box-#{attr[:type]}-#{attr[:state].dasherize}")
expect(subject).to have_css(attr[:css])
expect(subject).to have_content(attr[:state].capitalize)
end
end
@ -167,12 +167,20 @@ RSpec.describe TodosHelper do
it_behaves_like 'no state pill'
context 'closed MR' do
before do
todo.target.update!(state: 'closed')
end
it_behaves_like 'a rendered state pill', css: '.gl-bg-red-500', state: 'closed'
end
context 'merged MR' do
before do
todo.target.update!(state: 'merged')
end
it_behaves_like 'a rendered state pill', type: 'mr', state: 'merged'
it_behaves_like 'a rendered state pill', css: '.gl-bg-blue-500', state: 'merged'
end
end
@ -186,7 +194,7 @@ RSpec.describe TodosHelper do
todo.target.update!(state: 'closed')
end
it_behaves_like 'a rendered state pill', type: 'issue', state: 'closed'
it_behaves_like 'a rendered state pill', css: '.gl-bg-blue-500', state: 'closed'
end
end
@ -200,7 +208,7 @@ RSpec.describe TodosHelper do
todo.target.resolve!
end
it_behaves_like 'a rendered state pill', type: 'alert', state: 'resolved'
it_behaves_like 'a rendered state pill', css: '.gl-bg-blue-500', state: 'resolved'
end
end
end

View File

@ -12,7 +12,7 @@ RSpec.describe 'Query.runner(id)' do
create(:ci_runner, :instance, description: 'Runner 1', contacted_at: 2.hours.ago,
active: true, version: 'adfe156', revision: 'a', locked: true, ip_address: '127.0.0.1', maximum_timeout: 600,
access_level: 0, tag_list: %w[tag1 tag2], run_untagged: true, executor_type: :custom,
maintenance_note: 'Test maintenance note')
maintenance_note: '**Test maintenance note**')
end
let_it_be(:inactive_instance_runner) do
@ -66,6 +66,8 @@ RSpec.describe 'Query.runner(id)' do
'architectureName' => runner.architecture,
'platformName' => runner.platform,
'maintenanceNote' => runner.maintenance_note,
'maintenanceNoteHtml' =>
runner.maintainer_note.present? ? a_string_including('<strong>Test maintenance note</strong>') : '',
'jobCount' => 0,
'jobs' => a_hash_including("count" => 0, "nodes" => [], "pageInfo" => anything),
'projectCount' => nil,

View File

@ -35,6 +35,22 @@ RSpec.describe Packages::Go::CreatePackageService do
expect(file.file_sha1).not_to be_nil
expect(file.file_sha256).not_to be_nil
end
context 'with FIPS mode', :fips_mode do
it 'does not generate file_md5' do
file_name = "#{version.name}.#{type}"
expect(subject.package_files.map { |f| f.file_name }).to include(file_name)
file = subject.package_files.with_file_name(file_name).first
expect(file).not_to be_nil
expect(file.file).not_to be_nil
expect(file.size).to eq(file.file.size)
expect(file.file_name).to eq(file_name)
expect(file.file_md5).to be_nil
expect(file.file_sha1).not_to be_nil
expect(file.file_sha256).not_to be_nil
end
end
end
describe '#execute' do

View File

@ -192,7 +192,6 @@ RSpec.describe 'Every Sidekiq worker' do
'CreateGithubWebhookWorker' => 3,
'CreateNoteDiffFileWorker' => 3,
'CreatePipelineWorker' => 3,
'DastSiteValidationWorker' => 3,
'DeleteContainerRepositoryWorker' => 3,
'DeleteDiffFilesWorker' => 3,
'DeleteMergedBranchesWorker' => 3,