Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-09-23 22:34:10 +00:00
parent 5248069bd6
commit 96855c4214
79 changed files with 872 additions and 203 deletions

View File

@ -0,0 +1,32 @@
<script>
import { NodeViewWrapper, NodeViewContent } from '@tiptap/vue-2';
import { __ } from '~/locale';
export default {
name: 'FrontMatter',
components: {
NodeViewWrapper,
NodeViewContent,
},
props: {
node: {
type: Object,
required: true,
},
},
i18n: {
frontmatter: __('frontmatter'),
},
};
</script>
<template>
<node-view-wrapper class="gl-relative code highlight" as="pre">
<span
data-testid="frontmatter-label"
class="gl-absolute gl-top-0 gl-right-3"
contenteditable="false"
>{{ $options.i18n.frontmatter }}:{{ node.attrs.language }}</span
>
<node-view-content as="code" />
</node-view-wrapper>
</template>

View File

@ -11,7 +11,8 @@ export default CodeBlockLowlight.extend({
parseHTML: (element) => extractLanguage(element),
},
class: {
default: 'code highlight js-syntax-highlight',
// eslint-disable-next-line @gitlab/require-i18n-strings
default: 'code highlight',
},
};
},

View File

@ -0,0 +1,20 @@
import { VueNodeViewRenderer } from '@tiptap/vue-2';
import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
import FrontmatterWrapper from '../components/wrappers/frontmatter.vue';
import CodeBlockHighlight from './code_block_highlight';
export default CodeBlockHighlight.extend({
name: 'frontmatter',
parseHTML() {
return [
{
tag: 'pre[data-lang-params="frontmatter"]',
preserveWhitespace: 'full',
priority: PARSE_HTML_PRIORITY_HIGHEST,
},
];
},
addNodeView() {
return new VueNodeViewRenderer(FrontmatterWrapper);
},
});

View File

@ -0,0 +1,29 @@
import { Node, mergeAttributes, nodeInputRule } from '@tiptap/core';
export const inputRegex = /^<wbr>$/;
export default Node.create({
name: 'wordBreak',
inline: true,
group: 'inline',
selectable: false,
atom: true,
defaultOptions: {
HTMLAttributes: {
class: 'gl-display-inline-flex gl-px-1 gl-bg-blue-100 gl-rounded-base gl-font-sm',
},
},
parseHTML() {
return [{ tag: 'wbr' }];
},
renderHTML({ HTMLAttributes }) {
return ['span', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), '-'];
},
addInputRules() {
return [nodeInputRule(inputRegex, this.type)];
},
});

View File

@ -16,6 +16,7 @@ import Dropcursor from '../extensions/dropcursor';
import Emoji from '../extensions/emoji';
import Figure from '../extensions/figure';
import FigureCaption from '../extensions/figure_caption';
import Frontmatter from '../extensions/frontmatter';
import Gapcursor from '../extensions/gapcursor';
import HardBreak from '../extensions/hard_break';
import Heading from '../extensions/heading';
@ -43,6 +44,7 @@ import TaskItem from '../extensions/task_item';
import TaskList from '../extensions/task_list';
import Text from '../extensions/text';
import Video from '../extensions/video';
import WordBreak from '../extensions/word_break';
import { ContentEditor } from './content_editor';
import createMarkdownSerializer from './markdown_serializer';
import trackInputRulesAndShortcuts from './track_input_rules_and_shortcuts';
@ -85,6 +87,7 @@ export const createContentEditor = ({
Emoji,
Figure,
FigureCaption,
Frontmatter,
Gapcursor,
HardBreak,
Heading,
@ -112,6 +115,7 @@ export const createContentEditor = ({
TaskList,
Text,
Video,
WordBreak,
];
const allExtensions = [...builtInContentEditorExtensions, ...extensions];

View File

@ -15,6 +15,7 @@ import Division from '../extensions/division';
import Emoji from '../extensions/emoji';
import Figure from '../extensions/figure';
import FigureCaption from '../extensions/figure_caption';
import Frontmatter from '../extensions/frontmatter';
import HardBreak from '../extensions/hard_break';
import Heading from '../extensions/heading';
import HorizontalRule from '../extensions/horizontal_rule';
@ -39,6 +40,7 @@ import TaskItem from '../extensions/task_item';
import TaskList from '../extensions/task_list';
import Text from '../extensions/text';
import Video from '../extensions/video';
import WordBreak from '../extensions/word_break';
import {
isPlainURL,
renderHardBreak,
@ -136,6 +138,20 @@ const defaultSerializerConfig = {
state.write(`:${name}:`);
},
[Frontmatter.name]: (state, node) => {
const { language } = node.attrs;
const syntax = {
toml: '+++',
json: ';;;',
yaml: '---',
}[language];
state.write(`${syntax}\n`);
state.text(node.textContent, false);
state.ensureNewLine();
state.write(syntax);
state.closeBlock(node);
},
[Figure.name]: renderHTMLNode('figure'),
[FigureCaption.name]: renderHTMLNode('figcaption'),
[HardBreak.name]: renderHardBreak,
@ -166,6 +182,7 @@ const defaultSerializerConfig = {
},
[Text.name]: defaultMarkdownSerializer.nodes.text,
[Video.name]: renderPlayable,
[WordBreak.name]: (state) => state.write('<wbr>'),
},
};

View File

@ -1,6 +1,14 @@
<script>
import { GlButton, GlFormGroup, GlFormCheckbox, GlFormRadioGroup, GlFormRadio } from '@gitlab/ui';
import {
GlButton,
GlFormGroup,
GlFormCheckbox,
GlFormRadioGroup,
GlFormRadio,
GlFormInputGroup,
} from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import ErrorTrackingForm from './error_tracking_form.vue';
import ProjectDropdown from './project_dropdown.vue';
@ -12,7 +20,9 @@ export default {
GlFormGroup,
GlFormRadioGroup,
GlFormRadio,
GlFormInputGroup,
ProjectDropdown,
ClipboardButton,
},
props: {
initialApiHost: {
@ -46,6 +56,11 @@ export default {
type: String,
required: true,
},
gitlabDsn: {
type: String,
required: false,
default: null,
},
},
computed: {
...mapGetters([
@ -63,6 +78,9 @@ export default {
'settingsLoading',
'token',
]),
showGitlabDsnSetting() {
return this.integrated && this.enabled && this.gitlabDsn;
},
},
created() {
this.setInitialState({
@ -119,6 +137,17 @@ export default {
</gl-form-radio>
</gl-form-radio-group>
</gl-form-group>
<gl-form-group
v-if="showGitlabDsnSetting"
:label="__('Paste this DSN into your Sentry SDK')"
data-testid="gitlab-dsn-setting-form"
>
<gl-form-input-group readonly :value="gitlabDsn">
<template #append>
<clipboard-button :text="gitlabDsn" :title="__('Copy')" />
</template>
</gl-form-input-group>
</gl-form-group>
<div v-if="!integrated" class="js-sentry-setting-form" data-testid="sentry-setting-form">
<error-tracking-form />
<div class="form-group">

View File

@ -13,6 +13,7 @@ export default () => {
token,
listProjectsEndpoint,
operationsSettingsEndpoint,
gitlabDsn,
},
} = formContainerEl;
@ -29,6 +30,7 @@ export default () => {
initialToken: token,
listProjectsEndpoint,
operationsSettingsEndpoint,
gitlabDsn,
},
});
},

View File

@ -1,14 +1,13 @@
import { sprintf, n__, __ } from '../../../../locale';
import { __ } from '../../../../locale';
import { COMMIT_TO_NEW_BRANCH } from './constants';
const BRANCH_SUFFIX_COUNT = 5;
const createTranslatedTextForFiles = (files, text) => {
if (!files.length) return null;
return sprintf(n__('%{text} %{files}', '%{text} %{files} files', files.length), {
files: files.reduce((acc, val) => acc.concat(val.path), []).join(', '),
text,
});
const filesPart = files.reduce((acc, val) => acc.concat(val.path), []).join(', ');
return `${text} ${filesPart}`;
};
export const discardDraftButtonDisabled = (state) =>

View File

@ -136,7 +136,13 @@ export default {
<template>
<gl-button-group>
<template v-if="canReadJob">
<gl-button v-if="isActive" icon="cancel" :title="$options.CANCEL" @click="cancelJob()" />
<gl-button
v-if="isActive"
data-testid="cancel-button"
icon="cancel"
:title="$options.CANCEL"
@click="cancelJob()"
/>
<template v-else-if="isScheduled">
<gl-button icon="planning" disabled data-testid="countdown">
<gl-countdown :end-date-string="scheduledAt" />

View File

@ -4,7 +4,7 @@ class Admin::Serverless::DomainsController < Admin::ApplicationController
before_action :check_feature_flag
before_action :domain, only: [:update, :verify, :destroy]
feature_category :serverless
feature_category :not_owned
def index
@domain = PagesDomain.instance_serverless.first_or_initialize

View File

@ -5,7 +5,7 @@ module Projects
class FunctionsController < Projects::ApplicationController
before_action :authorize_read_cluster!
feature_category :serverless
feature_category :not_owned
def index
respond_to do |format|

View File

@ -46,6 +46,11 @@ module ErrorTracking
after_save :clear_reactive_cache!
# When a user enables the integrated error tracking
# we want to immediately provide them with a first
# working client key so they have a DSN for Sentry SDK.
after_save :create_client_key!
def sentry_enabled
enabled && !integrated_client?
end
@ -54,6 +59,12 @@ module ErrorTracking
integrated
end
def gitlab_dsn
strong_memoize(:gitlab_dsn) do
client_key&.sentry_dsn
end
end
def api_url=(value)
super
clear_memoization(:api_url_slugs)
@ -236,5 +247,19 @@ module ErrorTracking
errors.add(:project, 'is a required field')
end
end
def client_key
# Project can have multiple client keys.
# However for UI simplicity we render the first active one for user.
# In future we should make it possible to manage client keys from UI.
# Issue https://gitlab.com/gitlab-org/gitlab/-/issues/329596
project.error_tracking_client_keys.active.first
end
def create_client_key!
if enabled? && integrated_client? && !client_key
project.error_tracking_client_keys.create!
end
end
end
end

View File

@ -1,26 +1,9 @@
# frozen_string_literal: true
class NamespacePolicy < BasePolicy
rule { anonymous }.prevent_all
condition(:personal_project, scope: :subject) { @subject.kind == 'user' }
condition(:can_create_personal_project, scope: :user) { @user.can_create_project? }
condition(:owner) { @subject.owner == @user }
rule { owner | admin }.policy do
enable :owner_access
enable :create_projects
enable :admin_namespace
enable :read_namespace
enable :read_statistics
enable :create_jira_connect_subscription
enable :create_package_settings
enable :read_package_settings
end
rule { personal_project & ~can_create_personal_project }.prevent :create_projects
rule { (owner | admin) & can?(:create_projects) }.enable :transfer_projects
class NamespacePolicy < ::Namespaces::UserNamespacePolicy
# NamespacePolicy has been traditionally for user namespaces.
# So these policies have been moved into Namespaces::UserNamespacePolicy.
# Once the user namespace conversion is complete, we can look at
# either removing this file or locating common namespace policy items
# here.
end
NamespacePolicy.prepend_mod_with('NamespacePolicy')

View File

@ -0,0 +1,28 @@
# frozen_string_literal: true
module Namespaces
class UserNamespacePolicy < BasePolicy
rule { anonymous }.prevent_all
condition(:personal_project, scope: :subject) { @subject.kind == 'user' }
condition(:can_create_personal_project, scope: :user) { @user.can_create_project? }
condition(:owner) { @subject.owner == @user }
rule { owner | admin }.policy do
enable :owner_access
enable :create_projects
enable :admin_namespace
enable :read_namespace
enable :read_statistics
enable :create_jira_connect_subscription
enable :create_package_settings
enable :read_package_settings
end
rule { personal_project & ~can_create_personal_project }.prevent :create_projects
rule { (owner | admin) & can?(:create_projects) }.enable :transfer_projects
end
end
Namespaces::UserNamespacePolicy.prepend_mod_with('Namespaces::UserNamespacePolicy')

View File

@ -17,7 +17,7 @@ module Ci
def execute(build)
build.ensure_scheduling_type!
reprocess!(build).tap do |new_build|
clone!(build).tap do |new_build|
check_assignable_runners!(new_build)
next if new_build.failed?
@ -31,7 +31,7 @@ module Ci
end
# rubocop: disable CodeReuse/ActiveRecord
def reprocess!(build)
def clone!(build)
# Cloning a build requires a strict type check to ensure
# the attributes being used for the clone are taken straight
# from the model and not overridden by other abstractions.

View File

@ -9,17 +9,12 @@ module Ci
raise Gitlab::Access::AccessDeniedError
end
needs = Set.new
pipeline.ensure_scheduling_type!
builds_relation(pipeline).find_each do |build|
next unless can_be_retried?(build)
Ci::RetryBuildService.new(project, current_user)
.reprocess!(build)
needs += build.needs.map(&:name)
Ci::RetryBuildService.new(project, current_user).clone!(build)
end
pipeline.builds.latest.skipped.find_each do |skipped|

View File

@ -9,7 +9,7 @@
- if show_feed_buttons
= render 'shared/issuable/feed_buttons'
.js-csv-import-export-buttons{ data: { show_export_button: show_export_button.to_s, show_import_button: show_import_button.to_s, issuable_type: issuable_type, issuable_count: issuables_count_for_state(issuable_type.to_sym, params[:state]), email: notification_email, export_csv_path: export_csv_project_issues_path(@project, request.query_parameters), import_csv_issues_path: import_csv_namespace_project_issues_path, container_class: 'gl-mr-3', can_edit: can_edit.to_s, project_import_jira_path: project_import_jira_path(@project) } }
.js-csv-import-export-buttons{ data: { show_export_button: show_export_button.to_s, show_import_button: show_import_button.to_s, issuable_type: issuable_type, issuable_count: issuables_count_for_state(issuable_type.to_sym, params[:state]), email: notification_email, export_csv_path: export_csv_project_issues_path(@project, request.query_parameters), import_csv_issues_path: import_csv_namespace_project_issues_path, container_class: 'gl-mr-3', can_edit: can_edit.to_s, project_import_jira_path: project_import_jira_path(@project), max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes) } }
- if @can_bulk_update
= button_tag _("Edit issues"), class: "gl-button btn btn-default gl-mr-3 js-bulk-update-toggle"

View File

@ -18,4 +18,5 @@
api_host: setting.api_host,
enabled: setting.enabled.to_json,
integrated: setting.integrated.to_json,
gitlab_dsn: setting.gitlab_dsn,
token: setting.token.present? ? '*' * 12 : nil } }

View File

@ -33,6 +33,7 @@
- continuous_integration_scaling
- database
- dataops
- delivery
- delivery_management
- dependency_firewall
- dependency_proxy
@ -53,16 +54,15 @@
- five_minute_production_app
- foundations
- fuzz_testing
- gdk
- geo_replication
- git_lfs
- gitaly
- gitlab_docs
- global_search
- helm_chart_registry
- horse
- importers
- incident_management
- infrastructure
- infrastructure_as_code
- insider_threat
- integrations
@ -103,12 +103,12 @@
- roadmaps
- runbooks
- runner
- scalability
- secret_detection
- secrets_management
- security_benchmarking
- security_orchestration
- self_monitoring
- serverless
- service_desk
- service_ping
- sharding

View File

@ -0,0 +1,8 @@
---
name: vulnerability_location_image_filter
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69867
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340915
milestone: '14.4'
type: development
group: group::container security
default_enabled: false

View File

@ -0,0 +1,10 @@
# frozen_string_literal: true
class DropInt4ColumnsForCiJobArtifacts < Gitlab::Database::Migration[1.0]
enable_lock_retries!
def change
remove_column :ci_job_artifacts, :id_convert_to_bigint, :integer, null: false, default: 0
remove_column :ci_job_artifacts, :job_id_convert_to_bigint, :integer, null: false, default: 0
end
end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class DropInt4ColumnForEvents < Gitlab::Database::Migration[1.0]
enable_lock_retries!
def change
remove_column :events, :id_convert_to_bigint, :integer, null: false, default: 0
end
end

View File

@ -0,0 +1 @@
1d18e061cb5bcdaa7d3fcea93e58d65a6f2c8b557fe53ba461b6cfa570f565be

View File

@ -0,0 +1 @@
011b714ee5d4389a5a172ae687eea3a814915fb39a5e5eae38b6ee423a903eaf

View File

@ -11506,9 +11506,7 @@ CREATE SEQUENCE ci_instance_variables_id_seq
ALTER SEQUENCE ci_instance_variables_id_seq OWNED BY ci_instance_variables.id;
CREATE TABLE ci_job_artifacts (
id_convert_to_bigint integer DEFAULT 0 NOT NULL,
project_id integer NOT NULL,
job_id_convert_to_bigint integer DEFAULT 0 NOT NULL,
file_type integer NOT NULL,
size bigint,
created_at timestamp with time zone NOT NULL,
@ -13705,7 +13703,6 @@ CREATE SEQUENCE error_tracking_errors_id_seq
ALTER SEQUENCE error_tracking_errors_id_seq OWNED BY error_tracking_errors.id;
CREATE TABLE events (
id_convert_to_bigint integer DEFAULT 0 NOT NULL,
project_id integer,
author_id integer NOT NULL,
target_id integer,

View File

@ -67,7 +67,7 @@ message is logged to:
- `log/file_hook.log` in a source installation.
NOTE:
Before 14.0 release, the file name was `plugin.log`
Before 14.0 release, the filename was `plugin.log`
## Creating file hooks

View File

@ -199,7 +199,7 @@ then make the following modifications:
## `application_role` already enables this. You only need this line if
## you selectively enable individual services that depend on Rails, like
## `puma`, `sidekiq`, `geo-logcursor`, etc.
## `puma`, `sidekiq`, `geo-logcursor`, and so on.
gitlab_rails['enable'] = true
##

View File

@ -41,7 +41,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
### Configuring GitLab
- [Adjust your instance's timezone](timezone.md): Customize the default time zone of GitLab.
- [Adjust your instance's time zone](timezone.md): Customize the default time zone of GitLab.
- [System hooks](../system_hooks/system_hooks.md): Notifications when users, projects and keys are changed.
- [Security](../security/index.md): Learn what you can do to further secure your GitLab instance.
- [Usage statistics, version check, and Service Ping](../user/admin_area/settings/usage_statistics.md): Enable or disable information about your instance to be sent to GitLab, Inc.

View File

@ -146,9 +146,9 @@ a background job archives the job log. The log is moved to `/var/opt/gitlab/gitl
by default, or to object storage if configured.
In a [scaled-out architecture](reference_architectures/index.md) with Rails and Sidekiq running on more than one
server, these two locations on the filesystem have to be shared using NFS.
server, these two locations on the file system have to be shared using NFS.
To eliminate both filesystem requirements:
To eliminate both file system requirements:
- [Enable the incremental logging feature](#enable-or-disable-incremental-logging), which uses Redis instead of disk space for temporary caching of job logs.
- Configure [object storage](job_artifacts.md#object-storage-settings) for storing archived job logs.

View File

@ -60,7 +60,7 @@ We should aim to not remove sensitive configuration in the *next major* release
See the table below for some examples:
| Config. type | Deprecation announced | Final minor release | Remove |
| Configuration type | Deprecation announced | Final minor release | Remove |
| -------- | -------- | -------- | -------- |
| Sensitive | 10.1.0 | 10.9.0 | 11.0.0 |
| Sensitive | 10.7.0 | 10.9.0 | 12.0.0 |
@ -90,6 +90,6 @@ the feature will continue working the same way as if you had `gitlab_rails['bett
However, setting the old version of configuration will print out a deprecation
notice at the end of installation/upgrade/reconfigure run.
With GitLab 11, `gitlab_rails['configuration'] = true` will no longer work and you will have to manually change the configuration in `/etc/gitlab/gitlab.rb` to the new valid config.
With GitLab 11, `gitlab_rails['configuration'] = true` will no longer work and you will have to manually change the configuration in `/etc/gitlab/gitlab.rb` to the new valid configuration.
**Note** If this configuration option is sensitive and can put integrity of the installation or
data in danger, installation/upgrade will be aborted.

View File

@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21811) in GitLab 12.9.
Get a list of all deploy tokens across the GitLab instance. This endpoint requires administrator access.
Get a list of all deploy tokens across the GitLab instance. This endpoint requires the Administrator role.
```plaintext
GET /deploy_tokens

View File

@ -94,7 +94,7 @@ POST /projects/:id/freeze_periods
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
| `freeze_start` | string | yes | Start of the Freeze Period in [cron](https://crontab.guru/) format. |
| `freeze_end` | string | yes | End of the Freeze Period in [cron](https://crontab.guru/) format. |
| `cron_timezone` | string | no | The timezone for the cron fields, defaults to UTC if not provided. |
| `cron_timezone` | string | no | The time zone for the cron fields, defaults to UTC if not provided. |
Example request:
@ -131,7 +131,7 @@ PUT /projects/:id/freeze_periods/:freeze_period_id
| `freeze_period_id` | integer or string | yes | The database ID of the Freeze Period. |
| `freeze_start` | string | no | Start of the Freeze Period in [cron](https://crontab.guru/) format. |
| `freeze_end` | string | no | End of the Freeze Period in [cron](https://crontab.guru/) format. |
| `cron_timezone` | string | no | The timezone for the cron fields. |
| `cron_timezone` | string | no | The time zone for the cron fields. |
Example request:

View File

@ -469,6 +469,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="queryvulnerabilitieshasissues"></a>`hasIssues` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have linked issues. |
| <a id="queryvulnerabilitieshasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have been resolved on default branch. |
| <a id="queryvulnerabilitiesimage"></a>`image` | [`[String!]`](#string) | Filter vulnerabilities by location image. When this filter is present, the response only matches entries for a `reportType` that includes `container_scanning`, `cluster_image_scanning`. |
| <a id="queryvulnerabilitiesprojectid"></a>`projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
| <a id="queryvulnerabilitiesreporttype"></a>`reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
| <a id="queryvulnerabilitiesscanner"></a>`scanner` | [`[String!]`](#string) | Filter vulnerabilities by VulnerabilityScanner.externalId. |
@ -10527,6 +10528,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="groupvulnerabilitieshasissues"></a>`hasIssues` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have linked issues. |
| <a id="groupvulnerabilitieshasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have been resolved on default branch. |
| <a id="groupvulnerabilitiesimage"></a>`image` | [`[String!]`](#string) | Filter vulnerabilities by location image. When this filter is present, the response only matches entries for a `reportType` that includes `container_scanning`, `cluster_image_scanning`. |
| <a id="groupvulnerabilitiesprojectid"></a>`projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
| <a id="groupvulnerabilitiesreporttype"></a>`reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
| <a id="groupvulnerabilitiesscanner"></a>`scanner` | [`[String!]`](#string) | Filter vulnerabilities by VulnerabilityScanner.externalId. |
@ -13203,6 +13205,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="projectvulnerabilitieshasissues"></a>`hasIssues` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have linked issues. |
| <a id="projectvulnerabilitieshasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have been resolved on default branch. |
| <a id="projectvulnerabilitiesimage"></a>`image` | [`[String!]`](#string) | Filter vulnerabilities by location image. When this filter is present, the response only matches entries for a `reportType` that includes `container_scanning`, `cluster_image_scanning`. |
| <a id="projectvulnerabilitiesprojectid"></a>`projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
| <a id="projectvulnerabilitiesreporttype"></a>`reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
| <a id="projectvulnerabilitiesscanner"></a>`scanner` | [`[String!]`](#string) | Filter vulnerabilities by VulnerabilityScanner.externalId. |

View File

@ -830,7 +830,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
## Transfer project to group
Transfer a project to the Group namespace. Available only to instance administrators, although an [alternative API endpoint](projects.md#transfer-a-project-to-a-new-namespace) is available which does not require instance administrator access. Transferring projects may fail when tagged packages exist in the project's repository.
Transfer a project to the Group namespace. Available only to instance administrators, although an [alternative API endpoint](projects.md#transfer-a-project-to-a-new-namespace) is available which does not require instance administrator role. Transferring projects may fail when tagged packages exist in the project's repository.
```plaintext
POST /groups/:id/projects/:project_id

View File

@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Instance-level Kubernetes clusters allow you to connect a Kubernetes cluster to the GitLab instance, which enables you to use the same cluster across multiple projects. [More information](../user/instance/clusters/index.md)
NOTE:
Users need administrator access to use these endpoints.
Users need the Administrator role to use these endpoints.
## List instance clusters

View File

@ -5,15 +5,15 @@ group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# GitLab as an OAuth 2.0 provider **(FREE)**
# OAuth 2.0 identity provider API **(FREE)**
This document covers using the [OAuth2](https://oauth.net/2/) protocol to allow
other services to access GitLab resources on user's behalf.
GitLab provides an API to allow third-party services to access GitLab resources on a user's behalf
with the [OAuth2](https://oauth.net/2/) protocol.
If you want GitLab to be an OAuth authentication service provider to sign into
other services, see the [OAuth2 authentication service provider](../integration/oauth_provider.md)
documentation. This functionality is based on the
[doorkeeper Ruby gem](https://github.com/doorkeeper-gem/doorkeeper).
To configure GitLab for this, see
[Configure GitLab as an OAuth 2.0 authentication identity provider](../integration/oauth_provider.md).
This functionality is based on the [doorkeeper Ruby gem](https://github.com/doorkeeper-gem/doorkeeper).
## Supported OAuth 2.0 flows
@ -25,7 +25,7 @@ GitLab supports the following authorization flows:
- **Authorization code:** Secure and common flow. Recommended option for secure
server-side apps.
- **Implicit grant:** Originally designed for user-agent only apps, such as
single page web apps running on GitLab Pages).
single page web apps running on GitLab Pages.
The [Internet Engineering Task Force (IETF)](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-09#section-2.1.2)
recommends against Implicit grant flow.
- **Resource owner password credentials:** To be used **only** for securely

View File

@ -78,7 +78,7 @@ GET projects/:id/packages/debian/pool/:distribution/:letter/:package_name/:packa
| `letter` | string | yes | The Debian Classification (first-letter or lib-first-letter). |
| `package_name` | string | yes | The source package name. |
| `package_version` | string | yes | The source package version. |
| `file_name` | string | yes | The file name. |
| `file_name` | string | yes | The filename. |
```shell
curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/pool/my-distro/a/my-pkg/1.0.0/example_1.0.0~alpha2_amd64.deb"
@ -92,7 +92,7 @@ curl --header "Private-Token: <personal_access_token>" \
--remote-name
```
This writes the downloaded file using the remote file name in the current directory.
This writes the downloaded file using the remote filename in the current directory.
## Route prefix
@ -150,7 +150,7 @@ curl --header "Private-Token: <personal_access_token>" \
--remote-name
```
This writes the downloaded file using the remote file name in the current directory.
This writes the downloaded file using the remote filename in the current directory.
## Download a signed distribution Release file
@ -178,7 +178,7 @@ curl --header "Private-Token: <personal_access_token>" \
--remote-name
```
This writes the downloaded file using the remote file name in the current directory.
This writes the downloaded file using the remote filename in the current directory.
## Download a release file signature
@ -206,7 +206,7 @@ curl --header "Private-Token: <personal_access_token>" \
--remote-name
```
This writes the downloaded file using the remote file name in the current directory.
This writes the downloaded file using the remote filename in the current directory.
## Download a binary file's index
@ -236,4 +236,4 @@ curl --header "Private-Token: <personal_access_token>" \
--remote-name
```
This writes the downloaded file using the remote file name in the current directory.
This writes the downloaded file using the remote filename in the current directory.

View File

@ -63,7 +63,7 @@ GET projects/:id/packages/helm/:channel/charts/:file_name.tgz
| ----------- | ------ | -------- | ----------- |
| `id` | string | yes | The ID or full path of the project. |
| `channel` | string | yes | Helm repository channel. |
| `file_name` | string | yes | Chart file name. |
| `file_name` | string | yes | Chart filename. |
```shell
curl --user <username>:<personal_access_token> \

View File

@ -115,7 +115,7 @@ POST /projects/:id/pipeline_schedules
| `description` | string | yes | The description of the pipeline schedule. |
| `ref` | string | yes | The branch or tag name that is triggered. |
| `cron` | string | yes | The [cron](https://en.wikipedia.org/wiki/Cron) schedule, for example: `0 1 * * *`. |
| `cron_timezone` | string | no | The timezone supported by `ActiveSupport::TimeZone`, for example: `Pacific Time (US & Canada)` (default: `UTC`). |
| `cron_timezone` | string | no | The time zone supported by `ActiveSupport::TimeZone`, for example: `Pacific Time (US & Canada)` (default: `UTC`). |
| `active` | boolean | no | The activation of pipeline schedule. If false is set, the pipeline schedule is initially deactivated (default: `true`). |
```shell
@ -162,7 +162,7 @@ PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id
| `description` | string | no | The description of the pipeline schedule. |
| `ref` | string | no | The branch or tag name that is triggered. |
| `cron` | string | no | The [cron](https://en.wikipedia.org/wiki/Cron) schedule, for example: `0 1 * * *`. |
| `cron_timezone` | string | no | The timezone supported by `ActiveSupport::TimeZone` (for example `Pacific Time (US & Canada)`), or `TZInfo::Timezone` (for example `America/Los_Angeles`). |
| `cron_timezone` | string | no | The time zone supported by `ActiveSupport::TimeZone` (for example `Pacific Time (US & Canada)`), or `TZInfo::Timezone` (for example `America/Los_Angeles`). |
| `active` | boolean | no | The activation of pipeline schedule. If false is set, the pipeline schedule is initially deactivated. |
```shell

View File

@ -14,7 +14,7 @@ The existing plans depend on the GitLab edition. In the Community Edition, only
is available. In the Enterprise Edition, additional plans are available as well.
NOTE:
Administrator access is required to use this API.
The Administrator role is required to use this API.
## Get current plan limits

View File

@ -729,3 +729,5 @@ Example response:
A release with a `released_at` attribute set to a future date is labeled
as an **Upcoming Release** [in the UI](../../user/project/releases/index.md#upcoming-releases).
Additionally, if a [release is requested from the API](#list-releases), for each release with a `release_at` attribute set to a future date, an additional attribute `upcoming_release` (set to true) will be returned as part of the response.

View File

@ -1161,7 +1161,7 @@ Blobs searches are performed on both filenames and contents. Search results:
times in the content.
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/6/search?scope=blobs&search=installation&ref=feature"
curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/6/search?scope=blobs&search=keyword%20filename:*.py
```
Example response:
@ -1175,7 +1175,7 @@ Example response:
"path": "README.md",
"filename": "README.md",
"id": null,
"ref": "feature",
"ref": "master",
"startline": 46,
"project_id": 6
}

View File

@ -514,7 +514,7 @@ Today, loading GraphQL requires a bunch of [dependencies](https://gitlab.com/git
GraphQL only needs to run in a specific context. If we could limit when it is being loaded we could effectively improve application efficiency, by reducing application load time and required memory. This, for example, is applicable for every size installation.
A potential challenge with GraphQL and Websockets is that at some point we might want to use Action Cable subscriptions and push GraphQL/API payload from Sidekiq to clients. This would likely utilize Redis to pass data through. Where Sidekiq would publish information on Redis and ActionCable Node would pass through that information to connected clients. This way of working is possible in the above model, but we would have to use GraphQL or API (over HTTP endpoint) to calculate what should be sent.
A potential challenge with GraphQL and Websockets is that at some point we might want to use Action Cable subscriptions and push GraphQL/API payload from Sidekiq to clients. This would likely use Redis to pass data through. Where Sidekiq would publish information on Redis and ActionCable Node would pass through that information to connected clients. This way of working is possible in the above model, but we would have to use GraphQL or API (over HTTP endpoint) to calculate what should be sent.
An alternative way is to use a notification system that would always make an `ActionCable` node (the one handling WebSockets) generate a payload based on a send query instead of performing passthrough. This could be applicable since `ActionCable` is the one handling a given connection for a client. This could have a downside of having to recalculate the same payload if many clients would be watching the same resource. However, this behavior of system might still be desired for security purposes, as generated payload might be dependent on permission of watching client (we would show different for anonymous, and different for the member of the project).

View File

@ -32,7 +32,7 @@ they all live on their own. A few more problems with this approach:
- Features are coupled to their container. In practice it is not straight
forward to decouple a feature from its container. The degree of coupling
varies across features.
- Naive duplication of features will result in a more complex and fragile code base.
- Naive duplication of features will result in a more complex and fragile codebase.
- Generalizing solutions across groups and projects may degrade system performance.
- The range of features span across many teams, and these changes will need to
manage development interference.

View File

@ -454,7 +454,8 @@ FLAG:
On self-managed GitLab, by default this feature is available. To hide the feature per project or for your entire instance, ask an administrator to [disable the `ci_include_rules` flag](../../administration/feature_flags.md). On GitLab.com, this feature is available.
You can use [`rules`](#rules) with `include` to conditionally include other configuration files.
You can only use `rules:if` in `include` with [certain variables](#variables-with-include).
You can only use [`if` rules](#rulesif) in `include`, and only with [certain variables](#variables-with-include).
`rules` keywords such as `changes` and `exists` are not supported.
```yaml
include:
@ -1178,6 +1179,7 @@ job:
all rules. You can't mix `when` at the job-level with `when` in rules.
- Unlike variables in [`script`](../variables/index.md#use-cicd-variables-in-job-scripts)
sections, variables in rules expressions are always formatted as `$VARIABLE`.
- You can use `rules:if` with `include` to [conditionally include other configuration files](#rules-with-include).
**Related topics**:

View File

@ -142,7 +142,7 @@ Nanoc layout), which is displayed at the top of the page if defined.
The `type` metadata parameter is deprecated but still exists in documentation
pages. You can safely remove the `type` metadata parameter and its values.
## Move or rename a page
## Move, rename, or delete a page
See [redirects](redirects.md).

View File

@ -15,13 +15,26 @@ description: Learn how to contribute to GitLab Documentation.
# Redirects in GitLab documentation
Moving or renaming a document is the same as changing its location. Be sure
to assign a technical writer to any merge request that renames or moves a page.
Technical Writers can help with any questions and can review your change.
When you move, rename, or delete a page, you must add a redirect. Redirects reduce
how often users get 404s when visiting the documentation site from out-of-date links, like:
When moving or renaming a page, you must redirect browsers to the new page.
This ensures users find the new page, and have the opportunity to update their
bookmarks.
- Bookmarks
- Links from external sites
- Links from old blog posts
- Links in the documentation site global navigation
Add a redirect to ensure:
- Users see the new page and can update or delete their bookmark.
- External sites can update their links, especially sites that have automation that
check for redirecting links.
- The documentation site global navigation does not link to a missing page.
The links in the global navigation are already tested in the `gitlab-docs` project.
If the redirect is missing, the `gitlab-docs` project's `main` branch might break.
Be sure to assign a technical writer to any merge request that moves, renames, or deletes a page.
Technical Writers can help with any questions and can review your change.
There are two types of redirects:

View File

@ -233,6 +233,11 @@ Any data or index cleanup needed to support migration retries should be handled
will re-enqueue itself with a delay which is set using the `throttle_delay` option described below. The batching
must be handled within the `migrate` method, this setting controls the re-enqueuing only.
- `batch_size` - Sets the number of documents modified during a `batched!` migration run. This size should be set to a value which allows the updates
enough time to finish. This can be tuned in combination with the `throttle_delay` option described below. The batching
must be handled within a custom `migrate` method or by using the [`Elastic::MigrationBackfillHelper`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/concerns/elastic/migration_backfill_helper.rb)
`migrate` method which uses this setting. Default value is 1000 documents.
- `throttle_delay` - Sets the wait time in between batch runs. This time should be set high enough to allow each migration batch
enough time to finish. Additionally, the time should be less than 30 minutes since that is how often the
[`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/elastic/migration_worker.rb)

View File

@ -534,15 +534,24 @@ affecting version `2.50.3-2+deb9u1` of Debian package `glib2.0`:
},
"version": "2.50.3-2+deb9u1",
"operating_system": "debian:9",
"image": "index.docker.io/library/nginx:1.18"
"image": "index.docker.io/library/nginx:1.18",
"kubernetes_resource": {
"namespace": "production",
"kind": "Deployment",
"name": "nginx-ingress",
"container": "nginx",
"agent_id": "1"
}
}
```
The affected package is found when scanning the image of the pod `index.docker.io/library/nginx:1.18`.
The affected package is found when scanning a deployment using the `index.docker.io/library/nginx:1.18` image.
The location fingerprint of a Cluster Image Scanning vulnerability combines the
`operating_system` and the package `name`, so these attributes are mandatory. The `image` is also
mandatory. All other attributes are optional.
`namespace`, `kind`, `name`, and `container` fields from the `kubernetes_resource`,
as well as the package `name`, so these fields are required. The `image` field is also mandatory.
The `cluster_id` and `agent_id` are mutually exclusive, and one of them must be present.
All other fields are optional.
#### SAST

View File

@ -103,7 +103,7 @@ sudo docker run --detach \
```
This will ensure that the Docker process has enough permissions to create the
config files in the mounted volumes.
configuration files in the mounted volumes.
If you're using the [Kerberos integration](../integration/kerberos.md) **(PREMIUM ONLY)**,
you must also publish your Kerberos port (for example, `--publish 8443:8443`).
@ -573,7 +573,7 @@ sudo docker restart gitlab
This error occurs when using Docker Toolbox with VirtualBox on Windows or Mac,
and making use of Docker volumes. The `/c/Users` volume is mounted as a
VirtualBox Shared Folder, and does not support the all POSIX filesystem features.
VirtualBox Shared Folder, and does not support the all POSIX file system features.
The directory ownership and permissions cannot be changed without remounting, and
GitLab fails.

View File

@ -52,7 +52,7 @@ installation.
Activate all GitLab Enterprise Edition functionality with a license.
- [Pricing](https://about.gitlab.com/pricing/): Pricing for the different tiers.
## Cross-repo Code Search
## Cross-repository Code Search
- [Advanced Search](../integration/elasticsearch.md): Leverage Elasticsearch for
faster, more advanced code search across your entire GitLab instance.

View File

@ -169,7 +169,7 @@ of GitLab Support or other GitLab engineers.
operations to manage partitioned tables.
- You should not modify the GitLab schema (for example, adding triggers or modifying tables).
Database migrations are tested against the schema definition in the GitLab code base. GitLab
Database migrations are tested against the schema definition in the GitLab codebase. GitLab
version upgrades may fail if the schema is modified.
## Puma settings

View File

@ -64,8 +64,8 @@ Grant a GitLab user access to the select GitLab projects.
1. Grant the user permission to the GitLab projects.
If you're integrating Jenkins with many GitLab projects, consider granting the user global
Administrator permission. Otherwise, add the user to each project, and grant the Developer role.
If you're integrating Jenkins with many GitLab projects, consider granting the user the global
Administrator role. Otherwise, add the user to each project, and grant the Developer role.
## Configure GitLab API access

View File

@ -4,18 +4,16 @@ group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# GitLab as an OAuth 2.0 authentication service provider
# Configure GitLab as an OAuth 2.0 authentication identity provider
This document describes how you can use GitLab as an OAuth 2.0
authentication service provider.
This document describes how you can use GitLab as an OAuth 2.0 authentication identity provider.
If you want to use:
- The [OAuth 2.0](https://oauth.net/2/) protocol to access GitLab resources on
a user's behalf, see [OAuth 2.0 provider](../api/oauth2.md).
- Other OAuth 2.0 authentication service providers to sign in to
GitLab, see the [OAuth 2.0 client documentation](omniauth.md).
- The related API, see [Applications API](../api/applications.md).
- OAuth 2 applications can be created and managed using the GitLab UI (described below)
or managed using the [Applications API](../api/applications.md).
- After an application is created, external services can manage access tokens using the
[OAuth 2 API](../api/oauth2.md).
- To allow users to sign in to GitLab using third-party OAuth 2 providers, see
[OmniAuth documentation](omniauth.md).
## Introduction to OAuth

View File

@ -31,7 +31,7 @@ To create an on-call schedule:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Monitor > On-call Schedules**.
1. Select **Add a schedule**.
1. Enter the schedule's name and description and select a timezone.
1. Enter the schedule's name and description and select a time zone.
1. Select **Add schedule**.
You now have an empty schedule with no rotations. This renders as an empty state, prompting you to

View File

@ -43,7 +43,7 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [Personal access tokens](../../api/index.md#personalproject-access-tokens)
- [Project access tokens](../../api/index.md#personalproject-access-tokens)
- [Impersonation tokens](../../api/index.md#impersonation-tokens)
- [GitLab as an OAuth2 provider](../../api/oauth2.md#gitlab-as-an-oauth-20-provider)
- [OAuth 2.0 identity provider API](../../api/oauth2.md)
## Third-party resources

View File

@ -13,10 +13,10 @@ Welcome to GitLab! We're glad to have you here!
As a GitLab user you have access to all the features
your [subscription](https://about.gitlab.com/pricing/)
includes, except [GitLab administrator](../administration/index.md)
settings, unless you have admin privileges to install, configure,
settings, unless you have administrator privileges to install, configure,
and upgrade your GitLab instance.
Admin privileges for [GitLab.com](https://gitlab.com/) are restricted to the GitLab team.
Administrator privileges for [GitLab.com](https://gitlab.com/) are restricted to the GitLab team.
For more information on configuring GitLab self-managed instances, see the [Administrator documentation](../administration/index.md).
@ -78,7 +78,7 @@ There are several types of users in GitLab:
- Regular users and GitLab.com users. <!-- Note: further description TBA -->
- [Groups](group/index.md) of users.
- GitLab [admin area](admin_area/index.md) user.
- GitLab [administrator area](admin_area/index.md) user.
- [GitLab Administrator](../administration/index.md) with full access to
self-managed instances' features and settings.
- [Internal users](../development/internal_users.md).

View File

@ -63,8 +63,9 @@ information.
Follow this step-by-step guide to configure an executable runbook in GitLab using
the components outlined above and the pre-loaded demo runbook.
1. Create an [OAuth Application for JupyterHub](../../../../integration/oauth_provider.md#gitlab-as-an-oauth-20-authentication-service-provider).
1. When [installing JupyterHub with Helm](https://zero-to-jupyterhub.readthedocs.io/en/latest/jupyterhub/installation.html), use the following values
1. Create an [OAuth application for JupyterHub](../../../../integration/oauth_provider.md).
1. When [installing JupyterHub with Helm](https://zero-to-jupyterhub.readthedocs.io/en/latest/jupyterhub/installation.html),
use the following values:
```yaml
#-----------------------------------------------------------------------------

View File

@ -61,6 +61,7 @@ module Gitlab
def self.databases
@databases ||= database_base_models
.transform_values { |connection_class| Connection.new(connection_class) }
.with_indifferent_access
.freeze
end

View File

@ -116,7 +116,7 @@ module Gitlab
def record_apdex_if_needed(elapsed)
return unless Gitlab::Metrics::RailsSlis.request_apdex_counters_enabled?
Gitlab::Metrics::Sli[:rails_request_apdex].increment(
Gitlab::Metrics::RailsSlis.request_apdex.increment(
labels: labels_from_context,
# hardcoded 1s here will be replaced by a per-endpoint value.
# https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1223

View File

@ -64,9 +64,9 @@ module Gitlab
Sidekiq.redis do |redis|
redis.multi do |multi|
redis.set(idempotency_key, jid, ex: expiry, nx: true)
read_wal_locations = check_existing_wal_locations!(redis, expiry)
read_jid = redis.get(idempotency_key)
multi.set(idempotency_key, jid, ex: expiry, nx: true)
read_wal_locations = check_existing_wal_locations!(multi, expiry)
read_jid = multi.get(idempotency_key)
end
end
@ -81,9 +81,9 @@ module Gitlab
return unless job_wal_locations.present?
Sidekiq.redis do |redis|
redis.multi do
redis.multi do |multi|
job_wal_locations.each do |connection_name, location|
redis.eval(LUA_SET_WAL_SCRIPT, keys: [wal_location_key(connection_name)], argv: [location, pg_wal_lsn_diff(connection_name).to_i, WAL_LOCATION_TTL])
multi.eval(LUA_SET_WAL_SCRIPT, keys: [wal_location_key(connection_name)], argv: [location, pg_wal_lsn_diff(connection_name).to_i, WAL_LOCATION_TTL])
end
end
end
@ -96,9 +96,9 @@ module Gitlab
read_wal_locations = {}
Sidekiq.redis do |redis|
redis.multi do
redis.multi do |multi|
job_wal_locations.keys.each do |connection_name|
read_wal_locations[connection_name] = redis.lindex(wal_location_key(connection_name), 0)
read_wal_locations[connection_name] = multi.lindex(wal_location_key(connection_name), 0)
end
end
end
@ -110,8 +110,8 @@ module Gitlab
def delete!
Sidekiq.redis do |redis|
redis.multi do |multi|
redis.del(idempotency_key)
delete_wal_locations!(redis)
multi.del(idempotency_key)
delete_wal_locations!(multi)
end
end
end
@ -147,7 +147,7 @@ module Gitlab
private
attr_accessor :existing_wal_locations
attr_writer :existing_wal_locations
attr_reader :queue_name, :job
attr_writer :existing_jid
@ -155,6 +155,31 @@ module Gitlab
@worker_klass ||= worker_class_name.to_s.safe_constantize
end
def delete_wal_locations!(redis)
job_wal_locations.keys.each do |connection_name|
redis.del(wal_location_key(connection_name))
redis.del(existing_wal_location_key(connection_name))
end
end
def check_existing_wal_locations!(redis, expiry)
read_wal_locations = {}
job_wal_locations.each do |connection_name, location|
key = existing_wal_location_key(connection_name)
redis.set(key, location, ex: expiry, nx: true)
read_wal_locations[connection_name] = redis.get(key)
end
read_wal_locations
end
def job_wal_locations
return {} unless preserve_wal_location?
job['wal_locations'] || {}
end
def pg_wal_lsn_diff(connection_name)
Gitlab::Database.databases[connection_name].pg_wal_lsn_diff(job_wal_locations[connection_name], existing_wal_locations[connection_name])
end
@ -179,12 +204,6 @@ module Gitlab
job['jid']
end
def job_wal_locations
return {} unless preserve_wal_location?
job['wal_locations'] || {}
end
def existing_wal_location_key(connection_name)
"#{idempotency_key}:#{connection_name}:existing_wal_location"
end
@ -209,23 +228,8 @@ module Gitlab
"#{worker_class_name}:#{Sidekiq.dump_json(arguments)}"
end
def delete_wal_locations!(redis)
job_wal_locations.keys.each do |connection_name|
redis.del(wal_location_key(connection_name))
redis.del(existing_wal_location_key(connection_name))
end
end
def check_existing_wal_locations!(redis, expiry)
read_wal_locations = {}
job_wal_locations.each do |connection_name, location|
key = existing_wal_location_key(connection_name)
redis.set(key, location, ex: expiry, nx: true)
read_wal_locations[connection_name] = redis.get(key)
end
read_wal_locations
def existing_wal_locations
@existing_wal_locations ||= {}
end
def preserve_wal_location?

View File

@ -4,11 +4,15 @@ module Gitlab
module SidekiqMiddleware
module DuplicateJobs
module Strategies
module DeduplicatesWhenScheduling
class DeduplicatesWhenScheduling < Base
extend ::Gitlab::Utils::Override
override :initialize
def initialize(duplicate_job)
@duplicate_job = duplicate_job
end
override :schedule
def schedule(job)
if deduplicatable_job? && check! && duplicate_job.duplicate?
job['duplicate-of'] = duplicate_job.existing_jid
@ -25,6 +29,7 @@ module Gitlab
yield
end
override :perform
def perform(job)
update_job_wal_location!(job)
end

View File

@ -7,11 +7,7 @@ module Gitlab
# This strategy takes a lock before scheduling the job in a queue and
# removes the lock after the job has executed preventing a new job to be queued
# while a job is still executing.
class UntilExecuted < Base
extend ::Gitlab::Utils::Override
include DeduplicatesWhenScheduling
class UntilExecuted < DeduplicatesWhenScheduling
override :perform
def perform(job)
super

View File

@ -7,11 +7,7 @@ module Gitlab
# This strategy takes a lock before scheduling the job in a queue and
# removes the lock before the job starts allowing a new job to be queued
# while a job is still executing.
class UntilExecuting < Base
extend ::Gitlab::Utils::Override
include DeduplicatesWhenScheduling
class UntilExecuting < DeduplicatesWhenScheduling
override :perform
def perform(job)
super

View File

@ -968,11 +968,6 @@ msgstr ""
msgid "%{template_project_id} is unknown or invalid"
msgstr ""
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
msgstr[1] ""
msgid "%{text} is available"
msgstr ""
@ -24460,6 +24455,9 @@ msgstr ""
msgid "Paste project path (i.e. gitlab-org/gitlab)"
msgstr ""
msgid "Paste this DSN into your Sentry SDK"
msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
msgstr ""
@ -39997,6 +39995,9 @@ msgid_plural "from %d jobs"
msgstr[0] ""
msgstr[1] ""
msgid "frontmatter"
msgstr ""
msgid "group"
msgstr ""

View File

@ -183,7 +183,7 @@ module QA
another_project.remove_via_api!
end
it 'pushes and pulls a Maven package via CI and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1627' do
it 'pushes and pulls a Maven package via CI and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1627', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/341414', type: :investigating } do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
@ -256,7 +256,7 @@ module QA
Page::Group::Settings::PackageRegistries.perform(&:set_allow_duplicates_disabled)
end
it 'prevents users from publishing duplicate Maven packages at the group level', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1830' do
it 'prevents users from publishing duplicate Maven packages at the group level', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1830', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/341209', type: :investigating } do
with_fixtures([pom_xml, settings_xml]) do |dir|
Service::DockerRun::Maven.new(dir).publish!
end
@ -301,7 +301,7 @@ module QA
Page::Group::Settings::PackageRegistries.perform(&:set_allow_duplicates_enabled)
end
it 'allows users to publish duplicate Maven packages at the group level', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1829' do
it 'allows users to publish duplicate Maven packages at the group level', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1829', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/341209', type: :investigating } do
with_fixtures([pom_xml, settings_xml]) do |dir|
Service::DockerRun::Maven.new(dir).publish!
end

View File

@ -2,36 +2,276 @@
require 'spec_helper'
def visit_jobs_page
visit(project_jobs_path(project))
wait_for_requests
end
RSpec.describe 'User browses jobs' do
let!(:build) { create(:ci_build, :coverage, pipeline: pipeline) }
let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') }
let(:project) { create(:project, :repository, namespace: user.namespace) }
let(:user) { create(:user) }
describe 'with jobs_table_vue feature flag turned off' do
let!(:build) { create(:ci_build, :coverage, pipeline: pipeline) }
let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') }
let(:project) { create(:project, :repository, namespace: user.namespace) }
let(:user) { create(:user) }
before do
stub_feature_flags(jobs_table_vue: false)
project.add_maintainer(user)
project.enable_ci
project.update_attribute(:build_coverage_regex, /Coverage (\d+)%/)
before do
stub_feature_flags(jobs_table_vue: false)
project.add_maintainer(user)
project.enable_ci
project.update_attribute(:build_coverage_regex, /Coverage (\d+)%/)
sign_in(user)
sign_in(user)
visit(project_jobs_path(project))
end
visit(project_jobs_path(project))
end
it 'shows the coverage' do
page.within('td.coverage') do
expect(page).to have_content('99.9%')
it 'shows the coverage' do
page.within('td.coverage') do
expect(page).to have_content('99.9%')
end
end
context 'with a failed job' do
let!(:build) { create(:ci_build, :coverage, :failed, pipeline: pipeline) }
it 'displays a tooltip with the failure reason' do
page.within('.ci-table') do
failed_job_link = page.find('.ci-failed')
expect(failed_job_link[:title]).to eq('Failed - (unknown failure)')
end
end
end
end
context 'with a failed job' do
let!(:build) { create(:ci_build, :coverage, :failed, pipeline: pipeline) }
describe 'with jobs_table_vue feature flag turned on', :js do
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
it 'displays a tooltip with the failure reason' do
page.within('.ci-table') do
failed_job_link = page.find('.ci-failed')
expect(failed_job_link[:title]).to eq('Failed - (unknown failure)')
before do
stub_feature_flags(jobs_table_vue: true)
project.add_maintainer(user)
project.enable_ci
sign_in(user)
end
describe 'header tabs' do
before do
visit_jobs_page
end
it 'shows a tab for All jobs and count' do
expect(page.find('[data-testid="jobs-all-tab"]').text).to include('All')
expect(page.find('[data-testid="jobs-all-tab"] .badge').text).to include('0')
end
it 'shows a tab for Pending jobs and count' do
expect(page.find('[data-testid="jobs-pending-tab"]').text).to include('Pending')
expect(page.find('[data-testid="jobs-pending-tab"] .badge').text).to include('0')
end
it 'shows a tab for Running jobs and count' do
expect(page.find('[data-testid="jobs-running-tab"]').text).to include('Running')
expect(page.find('[data-testid="jobs-running-tab"] .badge').text).to include('0')
end
it 'shows a tab for Finished jobs and count' do
expect(page.find('[data-testid="jobs-finished-tab"]').text).to include('Finished')
expect(page.find('[data-testid="jobs-finished-tab"] .badge').text).to include('0')
end
it 'updates the content when tab is clicked' do
page.find('[data-testid="jobs-finished-tab"]').click
wait_for_requests
expect(page).to have_content('No jobs to show')
end
end
describe 'Empty state' do
before do
visit_jobs_page
end
it 'renders an empty state' do
expect(page).to have_content 'Use jobs to automate your tasks'
expect(page).to have_content 'Create CI/CD configuration file'
end
end
describe 'Job actions' do
let!(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.id, ref: 'master') }
context 'when a job can be canceled' do
let!(:job) do
create(:ci_build, pipeline: pipeline,
stage: 'test')
end
before do
job.run
visit_jobs_page
end
it 'cancels a job successfully' do
page.find('[data-testid="cancel-button"]').click
wait_for_requests
expect(page).to have_selector('.ci-canceled')
end
end
context 'when a job can be retried' do
let!(:job) do
create(:ci_build, pipeline: pipeline,
stage: 'test')
end
before do
job.drop
visit_jobs_page
end
it 'retries a job successfully' do
page.find('[data-testid="retry"]').click
wait_for_requests
expect(page).to have_selector('.ci-pending')
end
end
context 'with a scheduled job' do
let!(:scheduled_job) { create(:ci_build, :scheduled, pipeline: pipeline, name: 'build') }
before do
visit_jobs_page
end
it 'plays a job successfully' do
page.find('[data-testid="play-scheduled"]').click
page.within '#play-job-modal' do
page.find_button('OK').click
end
wait_for_requests
expect(page).to have_selector('.ci-pending')
end
it 'unschedules a job successfully' do
page.find('[data-testid="unschedule"]').click
wait_for_requests
expect(page).to have_selector('.ci-manual')
end
end
context 'with downloadable artifacts' do
let!(:with_artifacts) do
build = create(:ci_build, :success,
pipeline: pipeline,
name: 'rspec tests',
stage: 'test')
create(:ci_job_artifact, :codequality, job: build)
end
before do
visit_jobs_page
end
it 'shows the download artifacts button' do
expect(page).to have_selector('[data-testid="download-artifacts"]')
end
end
context 'with artifacts expired' do
let!(:with_artifacts_expired) do
create(:ci_build, :expired, :success,
pipeline: pipeline,
name: 'rspec',
stage: 'test')
end
before do
visit_jobs_page
end
it 'does not show the download artifacts button' do
expect(page).not_to have_selector('[data-testid="download-artifacts"]')
end
end
end
describe 'Jobs table' do
let!(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.id, ref: 'master') }
context 'column links' do
let!(:job) do
create(:ci_build, pipeline: pipeline,
stage: 'test')
end
before do
job.run
visit_jobs_page
end
it 'contains a link to the pipeline' do
expect(page.find('[data-testid="pipeline-id"]')).to have_content "##{pipeline.id}"
end
it 'contains a link to the job sha' do
expect(page.find('[data-testid="job-sha"]')).to have_content "#{job.sha[0..7]}"
end
it 'contains a link to the job id' do
expect(page.find('[data-testid="job-id-link"]')).to have_content "#{job.id}"
end
it 'contains a link to the job ref' do
expect(page.find('[data-testid="job-ref"]')).to have_content "#{job.ref}"
end
end
end
describe 'when user is not logged in' do
before do
sign_out(user)
end
context 'when project is public' do
let(:public_project) { create(:project, :public, :repository) }
context 'without jobs' do
it 'shows an empty state' do
visit project_jobs_path(public_project)
wait_for_requests
expect(page).to have_content 'Use jobs to automate your tasks'
end
end
end
context 'when project is private' do
let(:private_project) { create(:project, :private, :repository) }
it 'redirects the user to sign_in and displays the flash alert' do
visit project_jobs_path(private_project)
wait_for_requests
expect(page).to have_content 'You need to sign in'
expect(page.current_path).to eq("/users/sign_in")
end
end
end
end

View File

@ -175,6 +175,12 @@ RSpec.describe 'Projects > Settings > For a forked project', :js do
wait_for_requests
assert_text('Your changes have been saved')
within '.js-error-tracking-settings' do
click_button('Expand')
end
expect(page).to have_content('Paste this DSN into your Sentry SDK')
end
end
end

View File

@ -0,0 +1,43 @@
import { NodeViewWrapper, NodeViewContent } from '@tiptap/vue-2';
import { shallowMount } from '@vue/test-utils';
import FrontmatterWrapper from '~/content_editor/components/wrappers/frontmatter.vue';
describe('content/components/wrappers/frontmatter', () => {
let wrapper;
const createWrapper = async (nodeAttrs = { language: 'yaml' }) => {
wrapper = shallowMount(FrontmatterWrapper, {
propsData: {
node: {
attrs: nodeAttrs,
},
},
});
};
afterEach(() => {
wrapper.destroy();
});
it('renders a node-view-wrapper as a pre element', () => {
createWrapper();
expect(wrapper.findComponent(NodeViewWrapper).props().as).toBe('pre');
expect(wrapper.findComponent(NodeViewWrapper).classes()).toContain('gl-relative');
});
it('renders a node-view-content as a code element', () => {
createWrapper();
expect(wrapper.findComponent(NodeViewContent).props().as).toBe('code');
});
it('renders label indicating that code block is frontmatter', () => {
createWrapper();
const label = wrapper.find('[data-testid="frontmatter-label"]');
expect(label.text()).toEqual('frontmatter:yaml');
expect(label.classes()).toEqual(['gl-absolute', 'gl-top-0', 'gl-right-3']);
});
});

View File

@ -1,7 +1,8 @@
import { GlFormRadioGroup, GlFormRadio } from '@gitlab/ui';
import { GlFormRadioGroup, GlFormRadio, GlFormInputGroup } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import Vuex from 'vuex';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { TEST_HOST } from 'helpers/test_constants';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import ErrorTrackingSettings from '~/error_tracking_settings/components/app.vue';
@ -12,6 +13,8 @@ import createStore from '~/error_tracking_settings/store';
const localVue = createLocalVue();
localVue.use(Vuex);
const TEST_GITLAB_DSN = 'https://gitlab.example.com/123456';
describe('error tracking settings app', () => {
let store;
let wrapper;
@ -29,6 +32,10 @@ describe('error tracking settings app', () => {
initialProject: null,
listProjectsEndpoint: TEST_HOST,
operationsSettingsEndpoint: TEST_HOST,
gitlabDsn: TEST_GITLAB_DSN,
},
stubs: {
GlFormInputGroup, // we need this non-shallow to query for a component within a slot
},
}),
);
@ -41,6 +48,12 @@ describe('error tracking settings app', () => {
findBackendSettingsRadioGroup().findAllComponents(GlFormRadio);
const findElementWithText = (wrappers, text) => wrappers.filter((item) => item.text() === text);
const findSentrySettings = () => wrapper.findByTestId('sentry-setting-form');
const findDsnSettings = () => wrapper.findByTestId('gitlab-dsn-setting-form');
const enableGitLabErrorTracking = async () => {
findBackendSettingsRadioGroup().vm.$emit('change', true);
await nextTick();
};
beforeEach(() => {
store = createStore();
@ -93,17 +106,35 @@ describe('error tracking settings app', () => {
expect(findElementWithText(findBackendSettingsRadioButtons(), 'GitLab')).toHaveLength(1);
});
it('toggles the sentry-settings section when sentry is selected as a tracking-backend', async () => {
it('hides the Sentry settings when GitLab is selected as a tracking-backend', async () => {
expect(findSentrySettings().exists()).toBe(true);
// set the "integrated" setting to "true"
findBackendSettingsRadioGroup().vm.$emit('change', true);
await nextTick();
await enableGitLabErrorTracking();
expect(findSentrySettings().exists()).toBe(false);
});
describe('GitLab DSN section', () => {
it('is visible when GitLab is selected as a tracking-backend and DSN is present', async () => {
expect(findDsnSettings().exists()).toBe(false);
await enableGitLabErrorTracking();
expect(findDsnSettings().exists()).toBe(true);
});
it('contains copy-to-clipboard functionality for the GitLab DSN string', async () => {
await enableGitLabErrorTracking();
const clipBoardInput = findDsnSettings().findComponent(GlFormInputGroup);
const clipBoardButton = findDsnSettings().findComponent(ClipboardButton);
expect(clipBoardInput.props('value')).toBe(TEST_GITLAB_DSN);
expect(clipBoardInput.attributes('readonly')).toBeTruthy();
expect(clipBoardButton.props('text')).toBe(TEST_GITLAB_DSN);
});
});
it.each([true, false])(
'calls the `updateIntegrated` action when the setting changes to `%s`',
(integrated) => {

View File

@ -219,3 +219,22 @@
# Sit amit
### I don't know
- name: word_break
markdown: Fernstraßen<wbr>bau<wbr>privat<wbr>finanzierungs<wbr>gesetz
- name: frontmatter_yaml
markdown: |-
---
title: Page title
---
- name: frontmatter_toml
markdown: |-
+++
title = "Page title"
+++
- name: frontmatter_json
markdown: |-
;;;
{
"title": "Page title"
}
;;;

View File

@ -126,7 +126,7 @@ describe('IDE commit module getters', () => {
);
expect(getters.preBuiltCommitMessage(state, null, rootState)).toBe(
'Update test-file, index.js files',
'Update test-file, index.js',
);
});

View File

@ -15,6 +15,13 @@ RSpec.describe Gitlab::Database do
end
end
describe '.databases' do
it 'stores connections as a HashWithIndifferentAccess' do
expect(described_class.databases.has_key?('main')).to be true
expect(described_class.databases.has_key?(:main)).to be true
end
end
describe '.default_pool_size' do
before do
allow(Gitlab::Runtime).to receive(:max_threads).and_return(7)

View File

@ -0,0 +1,23 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!('drop_int4_columns_for_ci_job_artifacts')
RSpec.describe DropInt4ColumnsForCiJobArtifacts do
let(:ci_job_artifacts) { table(:ci_job_artifacts) }
it 'correctly migrates up and down' do
reversible_migration do |migration|
migration.before -> {
expect(ci_job_artifacts.column_names).to include('id_convert_to_bigint')
expect(ci_job_artifacts.column_names).to include('job_id_convert_to_bigint')
}
migration.after -> {
ci_job_artifacts.reset_column_information
expect(ci_job_artifacts.column_names).not_to include('id_convert_to_bigint')
expect(ci_job_artifacts.column_names).not_to include('job_id_convert_to_bigint')
}
end
end
end

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!('drop_int4_column_for_events')
RSpec.describe DropInt4ColumnForEvents do
let(:events) { table(:events) }
it 'correctly migrates up and down' do
reversible_migration do |migration|
migration.before -> {
expect(events.column_names).to include('id_convert_to_bigint')
}
migration.after -> {
events.reset_column_information
expect(events.column_names).not_to include('id_convert_to_bigint')
}
end
end
end

View File

@ -79,6 +79,46 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
end
end
describe 'Callbacks' do
describe 'after_save :create_client_key!' do
subject { build(:project_error_tracking_setting, :integrated, project: project) }
context 'no client key yet' do
it 'creates a new client key' do
expect { subject.save! }.to change { ErrorTracking::ClientKey.count }.by(1)
end
context 'sentry backend' do
before do
subject.integrated = false
end
it 'does not create a new client key' do
expect { subject.save! }.not_to change { ErrorTracking::ClientKey.count }
end
end
context 'feature disabled' do
before do
subject.enabled = false
end
it 'does not create a new client key' do
expect { subject.save! }.not_to change { ErrorTracking::ClientKey.count }
end
end
end
context 'client key already exists' do
let!(:client_key) { create(:error_tracking_client_key, project: project) }
it 'does not create a new client key' do
expect { subject.save! }.not_to change { ErrorTracking::ClientKey.count }
end
end
end
end
describe '.extract_sentry_external_url' do
subject { described_class.extract_sentry_external_url(sentry_url) }
@ -494,4 +534,10 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
it { expect(subject.sentry_enabled).to eq(sentry_enabled) }
end
end
describe '#gitlab_dsn' do
let!(:client_key) { create(:error_tracking_client_key, project: project) }
it { expect(subject.gitlab_dsn).to eq(client_key.sentry_dsn) }
end
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe NamespacePolicy do
RSpec.describe Namespaces::UserNamespacePolicy do
let(:user) { create(:user) }
let(:owner) { create(:user) }
let(:admin) { create(:admin) }

View File

@ -277,15 +277,15 @@ RSpec.describe Ci::RetryBuildService do
end
end
describe '#reprocess' do
describe '#clone!' do
let(:new_build) do
travel_to(1.second.from_now) do
service.reprocess!(build)
service.clone!(build)
end
end
it 'raises an error when an unexpected class is passed' do
expect { service.reprocess!(create(:ci_build).present) }.to raise_error(TypeError)
expect { service.clone!(create(:ci_build).present) }.to raise_error(TypeError)
end
context 'when user has ability to execute build' do
@ -343,7 +343,7 @@ RSpec.describe Ci::RetryBuildService do
let(:user) { reporter }
it 'raises an error' do
expect { service.reprocess!(build) }
expect { service.clone!(build) }
.to raise_error Gitlab::Access::AccessDeniedError
end
end