Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-11-15 12:09:24 +00:00
parent 25fdad39f5
commit 7912017a13
51 changed files with 762 additions and 252 deletions

View File

@ -397,6 +397,8 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/data/removals/ @gl-docsteam
^[Documentation Pages]
# This block is managed by the rake script at lib/tasks/gitlab/tw/codeowners.rake, manual updates will be overwritten!
# Begin rake-managed-docs-block
/doc/administration/application_settings_cache.md @jglassman1
/doc/administration/audit_event_streaming.md @eread
/doc/administration/audit_events.md @eread
@ -1032,6 +1034,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/todos.md @msedlakjakubowski
/doc/user/usage_quotas.md @fneill
/doc/user/workspace/ @lciutacu
# End rake-managed-docs-block
[Authentication and Authorization]
/app/assets/javascripts/access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers

View File

@ -83,8 +83,8 @@
.if-merge-request-labels-group-global-search: &if-merge-request-labels-group-global-search
if: '$CI_MERGE_REQUEST_LABELS =~ /group::global search/'
.if-merge-request-labels-pipeline-revert: &if-merge-request-labels-pipeline-revert
if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:revert/'
.if-merge-request-labels-pipeline-expedite-master-fixing: &if-merge-request-labels-pipeline-expedite-master-fixing
if: '$CI_MERGE_REQUEST_LABELS =~ /master:(foss-)?broken/ && $CI_MERGE_REQUEST_LABELS =~ /pipeline:expedite-master-fixing/'
.if-merge-request-labels-frontend-and-feature-flag: &if-merge-request-labels-frontend-and-feature-flag
if: '$CI_MERGE_REQUEST_LABELS =~ /frontend/ && $CI_MERGE_REQUEST_LABELS =~ /feature flag/'
@ -993,7 +993,7 @@
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-labels-pipeline-revert
- <<: *if-merge-request-labels-pipeline-expedite-master-fixing
when: never
- <<: *if-merge-request
changes: *code-backstage-patterns
@ -1102,7 +1102,7 @@
when: never
- <<: *if-not-ee
when: never
- <<: *if-merge-request-labels-pipeline-revert
- <<: *if-merge-request-labels-pipeline-expedite-master-fixing
when: never
- <<: *if-merge-request-targeting-stable-branch
allow_failure: true
@ -1541,7 +1541,7 @@
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-labels-pipeline-revert
- <<: *if-merge-request-labels-pipeline-expedite-master-fixing
when: never
- <<: *if-merge-request
changes: *code-backstage-patterns
@ -1552,7 +1552,7 @@
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-labels-pipeline-revert
- <<: *if-merge-request-labels-pipeline-expedite-master-fixing
when: never
- <<: *if-merge-request-labels-skip-undercoverage
when: never
@ -1587,7 +1587,7 @@
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-labels-pipeline-revert
- <<: *if-merge-request-labels-pipeline-expedite-master-fixing
when: never
- if: '$SKIP_FLAKY_TESTS_AUTOMATICALLY == "true" || $RETRY_FAILED_TESTS_IN_NEW_PROCESS == "true"'
changes: *code-backstage-patterns
@ -1868,7 +1868,7 @@
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-labels-pipeline-revert
- <<: *if-merge-request-labels-pipeline-expedite-master-fixing
when: never
- <<: *if-merge-request-labels-run-review-app
- <<: *if-dot-com-gitlab-org-merge-request
@ -1933,7 +1933,7 @@
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-labels-pipeline-revert
- <<: *if-merge-request-labels-pipeline-expedite-master-fixing
when: never
- <<: *if-merge-request-labels-run-review-app
when: manual

View File

@ -2948,7 +2948,6 @@ Layout/LineLength:
- 'lib/api/feature_flags.rb'
- 'lib/api/files.rb'
- 'lib/api/generic_packages.rb'
- 'lib/api/go_proxy.rb'
- 'lib/api/group_clusters.rb'
- 'lib/api/group_import.rb'
- 'lib/api/group_labels.rb'

View File

@ -100,7 +100,6 @@ Style/StringConcatenation:
- 'ee/spec/support/shared_examples/models/geo_framework_registry_shared_examples.rb'
- 'ee/spec/tasks/gitlab/license_rake_spec.rb'
- 'lib/api/entities/tree_object.rb'
- 'lib/api/go_proxy.rb'
- 'lib/api/internal/kubernetes.rb'
- 'lib/backup/files.rb'
- 'lib/backup/manager.rb'

View File

@ -1 +1 @@
4b21b45f897007e0d3428353913edac8d1ecc422
cdc87c3fefb4386c150cb4d71fcb4530d2b0501b

View File

@ -393,7 +393,7 @@ export default {
v-else-if="conflictResolutionPath"
:message="
__(
'You can %{gitlabLinkStart}resolve conflicts on GitLab%{gitlabLinkEnd} or %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}.',
'You can %{gitlabLinkStart}resolve conflicts on GitLab%{gitlabLinkEnd} or %{resolveLocallyStart}resolve them locally%{resolveLocallyEnd}.',
)
"
>
@ -415,7 +415,7 @@ export default {
</gl-sprintf>
<gl-sprintf
v-else
:message="__('You can %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}.')"
:message="__('You can %{resolveLocallyStart}resolve them locally%{resolveLocallyEnd}.')"
>
<template #resolveLocally="{ content }">
<gl-button

View File

@ -62,10 +62,15 @@ export const generateTreeList = (files) => {
const split = file.new_path.split('/');
split.forEach((name, i) => {
const parent = acc.treeEntries[split.slice(0, i).join('/')];
let parent = acc.treeEntries[split.slice(0, i).join('/')];
const path = `${parent ? `${parent.path}/` : ''}${name}`;
const child = acc.treeEntries[path];
if (!acc.treeEntries[path]) {
if (parent && !parent.tree) {
parent = null;
}
if (!child || !child.tree) {
const type = path === file.new_path ? 'blob' : 'tree';
acc.treeEntries[path] = {
key: path,

View File

@ -260,7 +260,7 @@ export default class MergeRequestTabs {
}
}
tabShown(action, href) {
tabShown(action, href, shouldScroll = true) {
if (action !== this.currentTab && this.mergeRequestTabs) {
this.currentTab = action;
@ -336,7 +336,7 @@ export default class MergeRequestTabs {
$('.detail-page-description').renderGFM();
this.recallScroll(action);
if (shouldScroll) this.recallScroll(action);
} else if (action === this.currentAction) {
// ContentTop is used to handle anything at the top of the page before the main content
const mainContentContainer = document.querySelector('.content-wrapper');
@ -350,7 +350,7 @@ export default class MergeRequestTabs {
const scrollDestination = tabContentTop - mainContentTop - 51;
// scrollBehavior is only available in browsers that support scrollToOptions
if ('scrollBehavior' in document.documentElement.style) {
if ('scrollBehavior' in document.documentElement.style && shouldScroll) {
window.scrollTo({
top: scrollDestination,
behavior: 'smooth',

View File

@ -126,6 +126,9 @@ export default {
slotKeys() {
return this.sortDirDesc ? ['form', 'comments'] : ['comments', 'form'];
},
isAppReady() {
return !this.isLoading && !this.renderSkeleton && this.shouldShow;
},
},
watch: {
async isFetching() {
@ -149,6 +152,15 @@ export default {
this.discussionsCount.textContent = val;
}
},
isAppReady: {
handler(isReady) {
if (!isReady) return;
this.$nextTick(() => {
window.mrTabs?.eventHub.$emit('NotesAppReady');
});
},
immediate: true,
},
},
created() {
this.discussionsCount = document.querySelector('.js-discussions-count');

View File

@ -1,8 +1,12 @@
import { mapGetters, mapActions, mapState } from 'vuex';
import { scrollToElement, contentTop } from '~/lib/utils/common_utils';
function isOverviewPage() {
return window.mrTabs?.currentAction === 'show';
}
function getAllDiscussionElements() {
const containerEl = window.mrTabs?.currentAction === 'diffs' ? '.diffs' : '.tab-pane.notes';
const containerEl = isOverviewPage() ? '.tab-pane.notes' : '.diffs';
return Array.from(
document.querySelectorAll(
`${containerEl} div[data-discussion-id]:not([data-discussion-resolved])`,
@ -59,6 +63,14 @@ function getPreviousDiscussion() {
function handleJumpForBothPages(getDiscussion, ctx, fn, scrollOptions) {
const discussion = getDiscussion();
if (!isOverviewPage() && !discussion) {
window.mrTabs?.eventHub.$once('NotesAppReady', () => {
handleJumpForBothPages(getDiscussion, ctx, fn, scrollOptions);
});
window.mrTabs?.setCurrentAction('show');
window.mrTabs?.tabShown('show', undefined, false);
return;
}
const id = discussion.dataset.discussionId;
ctx.expandDiscussion({ discussionId: id });
scrollToElement(discussion, scrollOptions);

View File

@ -125,6 +125,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
@coverage_path = coverage_reports_project_merge_request_path(@project, @merge_request, format: :json) if @merge_request.has_coverage_reports?
@update_current_user_path = expose_path(api_v4_user_preferences_path)
@endpoint_metadata_url = endpoint_metadata_url(@project, @merge_request)
@endpoint_diff_batch_url = endpoint_diff_batch_url(@project, @merge_request)
set_pipeline_variables
@ -549,12 +550,23 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
return render_404 unless can?(current_user, :read_build, merge_request.actual_head_pipeline)
end
def show_whitespace
current_user&.show_whitespace_in_diffs ? '0' : '1'
end
def endpoint_metadata_url(project, merge_request)
params = request.query_parameters.merge(view: 'inline', diff_head: true, w: current_user&.show_whitespace_in_diffs ? '0' : '1')
params = request.query_parameters.merge(view: 'inline', diff_head: true, w: show_whitespace)
diffs_metadata_project_json_merge_request_path(project, merge_request, 'json', params)
end
def endpoint_diff_batch_url(project, merge_request)
per_page = current_user&.view_diffs_file_by_file ? '1' : '5'
params = request.query_parameters.merge(view: 'inline', diff_head: true, w: show_whitespace, page: '0', per_page: per_page)
diffs_batch_project_json_merge_request_path(project, merge_request, 'json', params)
end
def convert_date_to_epoch(date)
Date.strptime(date, "%Y-%m-%d")&.to_time&.to_i if date
rescue Date::Error, TypeError

View File

@ -144,8 +144,7 @@ class SearchController < ApplicationController
def check_single_commit_result?
return false if params[:force_search_results]
return false unless @project.present?
# download_code project policy grants user the read_commit ability
return false unless Ability.allowed?(current_user, :download_code, @project)
return false unless Ability.allowed?(current_user, :read_code, @project)
query = params[:search].strip.downcase
return false unless Commit.valid_hash?(query)

View File

@ -205,7 +205,7 @@ module SearchHelper
hash[:project] = { id: @project.id, name: @project.name }
hash[:project_metadata] = { issues_path: project_issues_path(@project), mr_path: project_merge_requests_path(@project) }
hash[:code_search] = search_scope.nil?
hash[:ref] = @ref if @ref && can?(current_user, :download_code, @project)
hash[:ref] = @ref if @ref && can?(current_user, :read_code, @project)
end
hash[:scope] = search_scope if search_has_project? || search_has_group?
@ -268,7 +268,7 @@ module SearchHelper
result = []
if can?(current_user, :download_code, @project)
if can?(current_user, :read_code, @project)
result.concat([
{ category: "In this project", label: _("Files"), url: project_tree_path(@project, ref) },
{ category: "In this project", label: _("Commits"), url: project_commits_path(@project, ref) }

View File

@ -2934,10 +2934,6 @@ class Project < ApplicationRecord
ci_cd_settings.keep_latest_artifact?
end
def runner_token_expiration_interval
ci_cd_settings&.runner_token_expiration_interval
end
def group_runners_enabled?
return false unless ci_cd_settings

View File

@ -3,5 +3,5 @@
class BlobPolicy < BasePolicy
delegate { @subject.project }
rule { can?(:download_code) }.enable :read_blob
rule { can?(:read_code) }.enable :read_blob
end

View File

@ -3,6 +3,6 @@
class CommitPolicy < BasePolicy
delegate { @subject.project }
rule { can?(:download_code) }.enable :read_commit
rule { can?(:read_code) }.enable :read_commit
rule { ~can?(:read_commit) }.prevent :create_note
end

View File

@ -15,6 +15,8 @@
- add_page_specific_style 'page_bundles/ci_status'
- add_page_startup_api_call @endpoint_metadata_url
- if mr_action == 'diffs'
- add_page_startup_api_call @endpoint_diff_batch_url
.merge-request{ data: { mr_action: mr_action, url: merge_request_path(@merge_request, format: :json), project_path: project_path(@merge_request.project), lock_version: @merge_request.lock_version } }
- if moved_mr_sidebar_enabled?

View File

@ -39,6 +39,8 @@ metadata:
description: Operations related to DevOps Research and Assessment (DORA) key metrics
- name: environments
description: Operations related to environments
- name: error_tracking_client_keys
description: Operations related to error tracking client keys
- name: error_tracking_project_settings
description: Operations related to error tracking project settings
- name: feature_flags_user_lists
@ -53,6 +55,8 @@ metadata:
description: Operations related to Geo
- name: geo_nodes
description: Operations related Geo Nodes
- name: go_proxy
description: Operations related to Go Proxy
- name: group_export
description: Operations related to exporting groups
- name: group_import

View File

@ -18,10 +18,12 @@
- [Bandit](https://gitlab.com/gitlab-org/security-products/analyzers/bandit) (Python)
NOTE:
This change was originally planned for GitLab 15.0 and has been postponed.
This change was originally planned for GitLab 15.0 and was postponed to GitLab 15.4.
See [the removal notice](./removals.md#sast-analyzer-consolidation-and-cicd-template-changes) for further details.
These analyzers will be removed from the [GitLab-managed SAST CI/CD template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml) and replaced with the [Semgrep-based analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep).
They will no longer receive routine updates, except for security issues.
Effective immediately, they will receive only security updates; other routine improvements or updates are not guaranteed.
After these analyzers reach End of Support, no further updates will be provided.
We will not delete container images previously published for these analyzers; any such change would be announced as a [deprecation, removal, or breaking change announcement](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations-removals-and-breaking-changes).
We will also remove Java from the scope of the [SpotBugs](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs) analyzer and replace it with the [Semgrep-based analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep).

View File

@ -25,6 +25,7 @@ exceptions:
- ARN
- ASCII
- ASG
- AST
- AWS
- BMP
- BSD

View File

@ -571,6 +571,7 @@ roadmap
roadmaps
rollout
rollouts
RSpec
rsync
rsynced
rsyncing

View File

@ -25,7 +25,7 @@ GET /projects/:id/jobs/:job_id/artifacts
Example request using the `PRIVATE-TOKEN` header:
```shell
curl --output artifacts.zip --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts"
curl --location --output artifacts.zip --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts"
```
To use this in a [`script` definition](../ci/yaml/index.md#script) inside
@ -90,7 +90,7 @@ Parameters
Example request using the `PRIVATE-TOKEN` header:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/main/download?job=test"
curl --location --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/main/download?job=test"
```
To use this in a [`script` definition](../ci/yaml/index.md#script) inside

View File

@ -1,6 +1,6 @@
---
stage: Verify
group: Runner
group: Runner SaaS
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---

View File

@ -7,31 +7,32 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Ruby style guide
This is a GitLab-specific style guide for Ruby code.
This is a GitLab-specific style guide for Ruby code. Everything documented in this page can be [reopened for discussion](https://about.gitlab.com/handbook/values/#disagree-commit-and-disagree).
Generally, if a style is not covered by [existing RuboCop rules or style guides](../contributing/style_guides.md#ruby-rails-rspec), it shouldn't be a blocker.
Before adding a new cop to enforce a given style, make sure to discuss it with your team.
When the style is approved by a backend EM or by a BE staff eng, add a new section to this page to
document the new rule. For every new guideline, add it in a new section and link the discussion from the section's
[version history note](../documentation/versions.md#add-a-version-history-item)
to provide context and serve as a reference.
We use [RuboCop](../rubocop_development_guide.md) to enforce Ruby style guide rules.
See also [guidelines for reusing abstractions](../reusing_abstractions.md).
Where a RuboCop rule is absent, refer to the following style guides as general guidelines to write idiomatic Ruby:
Everything listed here can be [reopened for discussion](https://about.gitlab.com/handbook/values/#disagree-commit-and-disagree).
- [Ruby Style Guide](https://github.com/rubocop/ruby-style-guide).
- [Rails Style Guide](https://github.com/rubocop/rails-style-guide).
- [RSpec Style Guide](https://github.com/rubocop/rspec-style-guide).
## String literals quoting
Generally, if a style is not covered by existing RuboCop rules or the above style guides, it shouldn't be a blocker.
Due to the sheer amount of work to rectify, we do not care whether string
literals are single, or double quoted.
Some styles we have decided [no one should not have a strong opinion on](#styles-we-have-no-opinion-on).
Previous discussions include:
See also:
- <https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44234>
- <https://gitlab.com/gitlab-org/gitlab-foss/-/issues/36076>
- <https://gitlab.com/gitlab-org/gitlab/-/issues/198046>
- [Guidelines for reusing abstractions](../reusing_abstractions.md).
- [Test-specific style guides and best practices](../testing_guide/index.md).
## Instance variable access using `attr_reader`
## Styles we have no rule for
These styles are not backed by a RuboCop rule.
For every style added to this section, link the discussion from the section's [version history note](../documentation/versions.md#add-a-version-history-item) to provide context and serve as a reference.
### Instance variable access using `attr_reader`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52351) in GitLab 14.1.
@ -84,11 +85,11 @@ Public attributes should only be used if they are accessed outside of the class.
There is not a strong opinion on what strategy is used when attributes are only
accessed internally, as long as there is consistency in related code.
## Newlines style guide
### Newlines style guide
This style guide recommends best practices for newlines in Ruby code.
In addition to the RuboCops `Layout/EmptyLinesAroundMethodBody` and `Cop/LineBreakAroundConditionalBlock` that enforce some newline styles, we have the following guidelines that are not backed by RuboCop.
### Rule: separate code with newlines only to group together related logic
#### Rule: separate code with newlines only to group together related logic
```ruby
# bad
@ -111,9 +112,7 @@ def method
end
```
### Rule: separate code and block with newlines
#### Newline before block
#### Rule: newline before block
```ruby
# bad
@ -136,35 +135,11 @@ def method
end
```
### Rule: Newline after block
##### Exception: no need for a newline when code block starts or ends right inside another code block
```ruby
# bad
def method
if issue.save
issue.send_email
end
render json: issue
end
```
```ruby
# good
def method
if issue.save
issue.send_email
end
render json: issue
end
```
#### Exception: no need for newline when code block starts or ends right inside another code block
```ruby
# bad
def method
if issue
if issue.valid?
@ -172,7 +147,6 @@ def method
end
end
end
```
@ -186,3 +160,18 @@ def method
end
end
```
## Styles we have no opinion on
If a RuboCop rule is proposed and we choose not to add it, we should document that decision in this guide so it is more discoverable and link the relevant discussion as a reference.
### Quoting string literals
Due to the sheer amount of work to rectify, we do not care whether string
literals are single or double-quoted.
Previous discussions include:
- <https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44234>
- <https://gitlab.com/gitlab-org/gitlab-foss/-/issues/36076>
- <https://gitlab.com/gitlab-org/gitlab/-/issues/198046>

View File

@ -108,117 +108,6 @@ pre-push:
For more information, check out [Lefthook documentation Skipping commands section](https://github.com/evilmartians/lefthook/blob/master/docs/full_guide.md#skipping-commands).
## Ruby, Rails, RSpec
Our codebase style is defined and enforced by [RuboCop](https://github.com/rubocop-hq/rubocop).
You can check for any offenses locally with `bundle exec rubocop --parallel`.
On the CI, this is automatically checked by the `static-analysis` jobs.
In addition, you can [integrate RuboCop](../developing_with_solargraph.md) into
supported IDEs using the [Solargraph](https://github.com/castwide/solargraph) gem.
For RuboCop rules that we have not taken a decision on yet, we follow the
[Ruby Style Guide](https://github.com/rubocop-hq/ruby-style-guide),
[Rails Style Guide](https://github.com/rubocop-hq/rails-style-guide), and
[RSpec Style Guide](https://github.com/rubocop-hq/rspec-style-guide) as general
guidelines to write idiomatic Ruby/Rails/RSpec, but reviewers/maintainers should
be tolerant and not too pedantic about style.
Similarly, some RuboCop rules are currently disabled, and for those,
reviewers/maintainers must not ask authors to use one style or the other, as both
are accepted. This isn't an ideal situation since this leaves space for
[bike-shedding](https://en.wiktionary.org/wiki/bikeshedding), and ideally we
should enable all RuboCop rules to avoid style-related
discussions/nitpicking/back-and-forth in reviews. There are some styles that
commonly come up in reviews that are not enforced, the
[GitLab Ruby style guide](../backend/ruby_style_guide.md) includes a non-exhaustive
list of these topics.
Additionally, we have a dedicated
[newlines style guide](../newlines_styleguide.md), as well as dedicated
[test-specific style guides and best practices](../testing_guide/index.md).
### Creating new RuboCop cops
Typically it is better for the linting rules to be enforced programmatically as it
reduces the aforementioned [bike-shedding](https://en.wiktionary.org/wiki/bikeshedding).
To that end, we encourage creation of new RuboCop rules in the codebase.
We maintain Cops across several Ruby code bases, and not all of them are
specific to the GitLab application.
When creating a new cop that could be applied to multiple applications, we encourage you
to add it to our [GitLab Styles](https://gitlab.com/gitlab-org/gitlab-styles) gem.
If the Cop targets rules that only apply to the main GitLab application,
it should be added to [GitLab](https://gitlab.com/gitlab-org/gitlab) instead.
### Cop grace period
A cop is in a "grace period" if it is enabled and has `Details: grace period` defined in its TODO YAML configuration.
On the default branch, all of the offenses from cops in the ["grace period"](../rake_tasks.md#run-rubocop-in-graceful-mode) will not fail the RuboCop CI job. The job will notify Slack in the `#f_rubocop` channel when offenses have been silenced in the scheduled pipeline. However, on merge request pipelines, the RuboCop job will fail.
A grace period can safely be lifted as soon as there are no warnings for 2 weeks in the `#f_rubocop` channel on Slack.
### Enabling a new cop
1. Enable the new cop in `.rubocop.yml` (if not already done via [`gitlab-styles`](https://gitlab.com/gitlab-org/ruby/gems/gitlab-styles)).
1. [Generate TODOs for the new cop](../rake_tasks.md#generate-initial-rubocop-todo-list).
1. [Set the new cop to "grace period"](#cop-grace-period).
1. Create an issue to fix TODOs and encourage Community contributions (via ~"good for new contributors" and/or ~"Seeking community contributions"). [See some examples](https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=created_date&state=opened&label_name%5B%5D=good%20for%20new%20contributors&label_name%5B%5D=static%20code%20analysis&first_page_size=20).
1. Create an issue to remove "grace period" after 2 weeks silence in `#f_rubocop` Slack channel. ([See an example](https://gitlab.com/gitlab-org/gitlab/-/issues/374903).)
### Silenced offenses
When offenses are silenced for cops in ["grace period"](#cop-grace-period),
the `#f_rubocop` Slack channel receives a notification message every two hours.
To fix this issue:
1. Find cops with silenced offenses in the linked CI job.
1. [Generate TODOs](../rake_tasks.md#generate-initial-rubocop-todo-list) for these cops.
#### RuboCop node pattern
When creating [node patterns](https://docs.rubocop.org/rubocop-ast/node_pattern.html) to match
Ruby's AST, you can use [`scripts/rubocop-parse`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/scripts/rubocop-parse)
to display the AST of a Ruby expression, to help you create the matcher.
See also [!97024](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97024).
### Resolving RuboCop exceptions
When the number of RuboCop exceptions exceed the default [`exclude-limit` of 15](https://docs.rubocop.org/rubocop/1.2/usage/basic_usage.html#command-line-flags),
we may want to resolve exceptions over multiple commits. To minimize confusion,
we should track our progress through the exception list.
The preferred way to [generate the initial list or a list for specific RuboCop rules](../rake_tasks.md#generate-initial-rubocop-todo-list)
is to run the Rake task `rubocop:todo:generate`:
```shell
# Initial list
bundle exec rake rubocop:todo:generate
# List for specific RuboCop rules
bundle exec rake 'rubocop:todo:generate[Gitlab/NamespacedClass,Lint/Syntax]'
```
This Rake task creates or updates the exception list in `.rubocop_todo/`. For
example, the configuration for the RuboCop rule `Gitlab/NamespacedClass` is
located in `.rubocop_todo/gitlab/namespaced_class.yml`.
Make sure to commit any changes in `.rubocop_todo/` after running the Rake task.
### Reveal existing RuboCop exceptions
To reveal existing RuboCop exceptions in the code that have been excluded via `.rubocop_todo.yml` and
`.rubocop_todo/**/*.yml`, set the environment variable `REVEAL_RUBOCOP_TODO` to `1`.
This allows you to reveal existing RuboCop exceptions during your daily work cycle and fix them along the way.
NOTE:
Define permanent `Exclude`s in `.rubocop.yml` instead of `.rubocop_todo/**/*.yml`.
## Database migrations
See the dedicated [Database Migrations Style Guide](../migration_style_guide.md).
@ -231,6 +120,10 @@ See the dedicated [JS Style Guide](../fe_guide/style/javascript.md).
See the dedicated [SCSS Style Guide](../fe_guide/style/scss.md).
## Ruby
See the dedicated [Ruby Style Guide](../backend/ruby_style_guide.md).
## Go
See the dedicated [Go standards and style guidelines](../go_guide/index.md).

View File

@ -197,6 +197,7 @@ The following integration guides are internal. Some integrations require access
- [Preventing transient bugs](transient/prevention-patterns.md)
- [GitLab Application SLIs](application_slis/index.md)
- [Spam protection and CAPTCHA development guide](spam_protection_and_captcha/index.md)
- [RuboCop development guide](rubocop_development_guide.md)
## Other GitLab Development Kit (GDK) guides

View File

@ -146,9 +146,9 @@ merge request. This prevents `rspec fail-fast` duration from exceeding the avera
This number can be overridden by setting a CI/CD variable named `RSPEC_FAIL_FAST_TEST_FILE_COUNT_THRESHOLD`.
## Faster feedback when reverting merge requests
## Faster feedback for merge requests that fix a broken `master`
When you need to revert a merge request, to get accelerated feedback, you can add the `~pipeline:revert` label to your merge request.
When you need to [fix a broken `master`](https://about.gitlab.com/handbook/engineering/workflow/#resolution-of-broken-master), you can add the `pipeline:expedite-master-fixing` label to expedite the pipelines that run on the merge request.
When this label is assigned, the following steps of the CI/CD pipeline are skipped:
@ -158,6 +158,8 @@ When this label is assigned, the following steps of the CI/CD pipeline are skipp
Apply the label to the merge request, and run a new pipeline for the MR.
Note that the merge request also needs to have the `master:broken` or `master:foss-broken` label set.
## Test jobs
We have dedicated jobs for each [testing level](../testing_guide/testing_levels.md) and each job runs depending on the

View File

@ -220,7 +220,7 @@ bundle exec rake rubocop:todo:generate\[Gitlab/NamespacedClass,Lint/Syntax\]
Some shells require brackets to be escaped or quoted.
See [Resolving RuboCop exceptions](contributing/style_guides.md#resolving-rubocop-exceptions)
See [Resolving RuboCop exceptions](../development/rubocop_development_guide.md#resolving-rubocop-exceptions)
on how to proceed from here.
### Run RuboCop in graceful mode

View File

@ -0,0 +1,114 @@
---
type: reference, dev
stage: none
group: Development
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# RuboCop rule development guide
Our codebase style is defined and enforced by [RuboCop](https://github.com/rubocop-hq/rubocop).
You can check for any offenses locally with `bundle exec rubocop --parallel`.
On the CI, this is automatically checked by the `static-analysis` jobs.
In addition, you can [integrate RuboCop](developing_with_solargraph.md) into
supported IDEs using the [Solargraph](https://github.com/castwide/solargraph) gem.
For RuboCop rules that we have not taken a decision on, follow the [Ruby style guide](backend/ruby_style_guide.md) to write idiomatic Ruby.
Reviewers/maintainers should be tolerant and not too pedantic about style.
Some RuboCop rules are disabled, and for those,
reviewers/maintainers must not ask authors to use one style or the other, as both
are accepted. This isn't an ideal situation because this leaves space for
[bike-shedding](https://en.wiktionary.org/wiki/bikeshedding). Ideally we
should enable all RuboCop rules to avoid style-related
discussions, nitpicking, or back-and-forth in reviews. The
[GitLab Ruby style guide](backend/ruby_style_guide.md) includes a non-exhaustive
list of styles that commonly come up in reviews and are not enforced.
Additionally, we have dedicated
[test-specific style guides and best practices](testing_guide/index.md).
## Creating new RuboCop cops
Typically it is better for the linting rules to be enforced programmatically as it
reduces the aforementioned [bike-shedding](https://en.wiktionary.org/wiki/bikeshedding).
To that end, we encourage creation of new RuboCop rules in the codebase.
Before adding a new cop to enforce a given style, make sure to discuss it with your team.
We maintain cops across several Ruby code bases, and not all of them are
specific to the GitLab application.
When creating a new cop that could be applied to multiple applications, we encourage you
to add it to our [`gitlab-styles`](https://gitlab.com/gitlab-org/gitlab-styles) gem.
If the cop targets rules that only apply to the main GitLab application,
it should be added to [GitLab](https://gitlab.com/gitlab-org/gitlab) instead.
## Cop grace period
A cop is in a _grace period_ if it is enabled and has `Details: grace period` defined in its TODO YAML configuration.
On the default branch, offenses from cops in the [grace period](rake_tasks.md#run-rubocop-in-graceful-mode) do not fail the RuboCop CI job. Instead, the job notifies the `#f_rubocop` Slack channel. However, on other branches, the RuboCop job fails.
A grace period can safely be lifted as soon as there are no warnings for 2 weeks in the `#f_rubocop` channel on Slack.
## Enabling a new cop
1. Enable the new cop in `.rubocop.yml` (if not already done via [`gitlab-styles`](https://gitlab.com/gitlab-org/ruby/gems/gitlab-styles)).
1. [Generate TODOs for the new cop](rake_tasks.md#generate-initial-rubocop-todo-list).
1. [Set the new cop to `grace period`](#cop-grace-period).
1. Create an issue to fix TODOs and encourage community contributions (via ~"good for new contributors" and/or ~"Seeking community contributions"). [See some examples](https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=created_date&state=opened&label_name%5B%5D=good%20for%20new%20contributors&label_name%5B%5D=static%20code%20analysis&first_page_size=20).
1. Create an issue to remove `grace period` after 2 weeks of silence in the `#f_rubocop` Slack channel. [See an example](https://gitlab.com/gitlab-org/gitlab/-/issues/374903).
## Silenced offenses
When offenses are silenced for cops in the [grace period](#cop-grace-period),
the `#f_rubocop` Slack channel receives a notification message every 2 hours.
To fix this issue:
1. Find cops with silenced offenses in the linked CI job.
1. [Generate TODOs](rake_tasks.md#generate-initial-rubocop-todo-list) for these cops.
### RuboCop node pattern
When creating [node patterns](https://docs.rubocop.org/rubocop-ast/node_pattern.html) to match
Ruby's AST, you can use [`scripts/rubocop-parse`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/scripts/rubocop-parse).
This displays the AST of a Ruby expression to help you create the matcher.
See also [!97024](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97024).
## Resolving RuboCop exceptions
When the number of RuboCop exceptions exceeds the default [`exclude-limit` of 15](https://docs.rubocop.org/rubocop/1.2/usage/basic_usage.html#command-line-flags),
we may want to resolve exceptions over multiple commits. To minimize confusion,
we should track our progress through the exception list.
The preferred way to [generate the initial list or a list for specific RuboCop rules](rake_tasks.md#generate-initial-rubocop-todo-list)
is to run the Rake task `rubocop:todo:generate`:
```shell
# Initial list
bundle exec rake rubocop:todo:generate
# List for specific RuboCop rules
bundle exec rake 'rubocop:todo:generate[Gitlab/NamespacedClass,Lint/Syntax]'
```
This Rake task creates or updates the exception list in `.rubocop_todo/`. For
example, the configuration for the RuboCop rule `Gitlab/NamespacedClass` is
located in `.rubocop_todo/gitlab/namespaced_class.yml`.
Make sure to commit any changes in `.rubocop_todo/` after running the Rake task.
## Reveal existing RuboCop exceptions
To reveal existing RuboCop exceptions in the code that have been excluded via `.rubocop_todo.yml` and
`.rubocop_todo/**/*.yml`, set the environment variable `REVEAL_RUBOCOP_TODO` to `1`.
This allows you to reveal existing RuboCop exceptions during your daily work cycle and fix them along the way.
NOTE:
Define permanent `Exclude`s in `.rubocop.yml` instead of `.rubocop_todo/**/*.yml`.

View File

@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/344059) in GitLab 15.2 [with a flag](../../administration/feature_flags.md) named `incident_timeline`. Enabled by default.
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/353426) in GitLab 15.3.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/353426) in GitLab 15.5. [Feature flag 'incident_timeline'](https://gitlab.com/gitlab-org/gitlab/-/issues/343386) removed.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/353426) in GitLab 15.5. [Feature flag `incident_timeline`](https://gitlab.com/gitlab-org/gitlab/-/issues/343386) removed.
Incident timelines are an important part of record keeping for incidents.
Timelines can show executives and external viewers what happened during an incident,

View File

@ -0,0 +1,119 @@
---
stage: Monitor
group: Respond
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Incident management for Slack **(FREE SAAS)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/8545) in GitLab 15.6.
Many teams receive alerts and collaborate in real time during incidents in Slack.
With the GitLab for Slack app:
- Create GitLab incidents from Slack.
- Receive incident notifications.
- Send important updates between Slack and GitLab incidents.
Incident management for Slack is initially only available for GitLab.com. Some of the functionality
described might be available for
[the self-managed Slack app](../../user/project/integrations/slack_slash_commands.md).
To stay up to date, follow [epic 1211](https://gitlab.com/groups/gitlab-org/-/epics/1211).
## Setup and configuration
To be able to manage incidents from Slack:
1. Install the [GitLab for Slack app](../../user/project/integrations/gitlab_slack_application.md).
Installing this application allows you to use slash commands in Slack to create and update GitLab incidents.
1. Enable [Slack notifications](../../user/project/integrations/slack.md). Be sure to enable
notifications for `Issue` events, and to define a Slack channel to receive the relevant notifications.
## Manage an incident from Slack
Use the following slash commands in Slack to manage incidents
| Command | Description |
| ---------------------------------- | ------------------------------------------ |
| `/gitlab incident declare` | Creates an incident in GitLab. |
| `/gitlab incident comment <text>` | Adds a comment on a GitLab incident. |
| `/gitlab incident timeline <text>` | Adds a timeline event to a GitLab incident. |
After the Slack app for GitLab is configured, you can also use any of the [existing slash commands for Slack](../../user/project/integrations/gitlab_slack_application.md).
### Declare an incident
After you've configured the GitLab for Slack app, create incidents in GitLab from Slack
with the `/gitlab incident declare` slash command.
To declare an incident:
1. In Slack, in any channel or DM, enter the `/gitlab incident declare` slash command.
1. From the modal, select the relevant incident details, including:
- The incident title and description.
- The project where the incident should be created.
- The severity of the incident.
If there is an existing [incident template](incidents.md#create-incidents-automatically) for your
project, that template is automatically applied to the description field. The template is applied
only if the description field is empty.
You can also include GitLab [quick actions](../../user/project/quick_actions.md) in the description field.
For example, typing `/link https://example.slack.com/archives/123456789 Dedicated Slack channel`
adds a dedicated Slack channel to the incident you create. For a more complete list of applicable
quick actions for incidents, see [Use GitLab quick actions](#use-gitlab-quick-actions).
1. Optional. Add a link to an existing Zoom meeting.
1. Select **Create**.
If the incident is successfully created, Slack shows a confirmation notification.
#### Use GitLab quick actions
Use [quick actions](../../user/project/quick_actions.md) in the description field when creating
an incident from Slack to take additional actions in GitLab. The following quick actions might be the most relevant to you:
| Command | Description |
| ------------------------ | ----------------------------------------- |
| `/assign @user1 @user2` | Adds an assignee to the GitLab incident. |
| `/label ~label1 ~label2` | Adds labels to the GitLab incident. |
| `/link <URL> <text>` | Adds a link to a dedicated Slack channel, a runbook, or to any relevant resource to the `Related resources` section of an incident. |
| `/zoom <URL>` | Adds a Zoom meeting link to the incident. |
### Comment on GitLab incidents
Comment on GitLab incidents from Slack with the `/gitlab incident comment <text>` slash command.
After you enter this slash command, Slack shows a prompt asking you to confirm which incident you'd
like to post your comment to.
### Add a timeline event
Add a [timeline event](incident_timeline_events.md) to a GitLab incident from Slack with the
`/gitlab incident timeline <text>` slash command.
After you enter this slash command, Slack shows a prompt asking you to confirm which incident you'd
like to add your timeline event to.
### Close an incident
When your incident is fully resolved, close your incident from Slack using the `/gitlab incident close`
slash command.
After you enter this slash command, Slack shows a prompt asking you to confirm which incident you'd
like to close.
## Send GitLab incident notifications to Slack
If you have [enabled notifications](#setup-and-configuration) for issues, you should receive
notifications to the selected Slack channel every time an incident is opened, closed, or updated.
## Troubleshooting
### No projects in the incident project dropdown list
If this happens, you might have not authorized GitLab to take actions on behalf of your Slack user.
Try executing a non-incident [Slack slash command](../../integration/slash_commands.md) to start the
authorization flow. For more context, visit [issue 377548](https://gitlab.com/gitlab-org/gitlab/-/issues/377548).

View File

@ -1255,10 +1255,12 @@ In GitLab 15.4, GitLab SAST will no longer use the following analyzers:
- [Bandit](https://gitlab.com/gitlab-org/security-products/analyzers/bandit) (Python)
NOTE:
This change was originally planned for GitLab 15.0 and has been postponed.
This change was originally planned for GitLab 15.0 and was postponed to GitLab 15.4.
See [the removal notice](./removals.md#sast-analyzer-consolidation-and-cicd-template-changes) for further details.
These analyzers will be removed from the [GitLab-managed SAST CI/CD template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml) and replaced with the [Semgrep-based analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep).
They will no longer receive routine updates, except for security issues.
Effective immediately, they will receive only security updates; other routine improvements or updates are not guaranteed.
After these analyzers reach End of Support, no further updates will be provided.
We will not delete container images previously published for these analyzers; any such change would be announced as a [deprecation, removal, or breaking change announcement](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations-removals-and-breaking-changes).
We will also remove Java from the scope of the [SpotBugs](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs) analyzer and replace it with the [Semgrep-based analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep).

View File

@ -74,7 +74,7 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/due <date>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Set due date. Examples of valid `<date>` include `in 2 days`, `this Friday` and `December 31st`. |
| `/duplicate <#issue>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Close this issue and mark as a duplicate of another issue. Also, mark both as related. |
| `/epic <epic>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Add to epic `<epic>`. The `<epic>` value should be in the format of `&epic`, `group&epic`, or a URL to an epic. |
| `/estimate <time>` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Set time estimate. For example, `/estimate 1mo 2w 3d 4h 5m`. Learn more about [time tracking](time_tracking.md). |
| `/estimate <time>` or `/estimate_time <time>` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Set time estimate. For example, `/estimate 1mo 2w 3d 4h 5m`. Learn more about [time tracking](time_tracking.md). Alias `/estimate_time` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16501) in GitLab 15.6. |
| `/health_status <value>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Set [health status](issues/managing_issues.md#health-status). Valid options for `<value>` are `on_track`, `needs_attention`, and `at_risk` ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213814) in GitLab 14.7). |
| `/invite_email email1 email2` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Add up to six email participants. This action is behind feature flag `issue_email_participants` and is not yet supported in issue templates. |
| `/iteration *iteration:"iteration name"` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Set iteration. For example, to set the `Late in July` iteration: `/iteration *iteration:"Late in July"` ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196795) in GitLab 13.1). |
@ -99,7 +99,7 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/remove_contacts [contact:email1@example.com] [contact:email2@example.com]` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Remove one or more [CRM contacts](../crm/index.md) ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73413) in GitLab 14.6). |
| `/remove_due_date` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Remove due date. |
| `/remove_epic` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Remove from epic. |
| `/remove_estimate` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Remove time estimate. |
| `/remove_estimate` or `/remove_time_estimate` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Remove time estimate. Alias `/remove_time_estimate` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16501) in GitLab 15.6. |
| `/remove_iteration` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Remove iteration ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196795) in GitLab 13.1). |
| `/remove_milestone` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Remove milestone. |
| `/remove_parent_epic` | **{dotted-circle}** No | **{dotted-circle}** No | **{check-circle}** Yes | Remove parent epic from epic ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10556) in GitLab 12.1). |
@ -108,7 +108,7 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/reopen` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Reopen. |
| `/severity <severity>` | **{check-circle}** Yes | **{check-circle}** No | **{check-circle}** No | Set the severity. Issue type must be `Incident`. Options for `<severity>` are `S1` ... `S4`, `critical`, `high`, `medium`, `low`, `unknown`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334045) in GitLab 14.2. |
| `/shrug <comment>` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Append the comment with `¯\_(ツ)_/¯`. |
| `/spend <time> [<date>]` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Add or subtract spent time. Optionally, specify the date that time was spent on. For example, `/spend 1mo 2w 3d 4h 5m 2018-08-26` or `/spend -1h 30m`. Learn more about [time tracking](time_tracking.md). |
| `/spend <time> [<date>]` or `/spend_time <time> [<date>]` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Add or subtract spent time. Optionally, specify the date that time was spent on. For example, `/spend 1mo 2w 3d 4h 5m 2018-08-26` or `/spend -1h 30m`. Learn more about [time tracking](time_tracking.md). Alias `/spend_time` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16501) in GitLab 15.6. |
| `/submit_review` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Submit a pending review ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8041) in GitLab 12.7). |
| `/subscribe` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Subscribe to notifications. |
| `/tableflip <comment>` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Append the comment with `(╯°□°)╯︵ ┻━┻`. |

Binary file not shown.

Before

Width:  |  Height:  |  Size: 444 KiB

View File

@ -62,8 +62,6 @@ to display, add a file to your repository.
To preview Markdown content in the Web Editor, select the **Preview** tab.
In this tab, you can see a live Markdown preview that updates as you type alongside your content.
![The Markdown Live Preview](img/web_editor_markdown_live_preview.png)
To close the preview panel, do one of the following:
- Select the **Write** tab.

View File

@ -196,6 +196,7 @@ module API
mount ::API::DeployTokens
mount ::API::Deployments
mount ::API::Environments
mount ::API::ErrorTracking::ClientKeys
mount ::API::ErrorTracking::ProjectSettings
mount ::API::FeatureFlags
mount ::API::FeatureFlagsUserLists
@ -203,6 +204,7 @@ module API
mount ::API::Files
mount ::API::FreezePeriods
mount ::API::Geo
mount ::API::GoProxy
mount ::API::GroupAvatar
mount ::API::GroupClusters
mount ::API::GroupExport
@ -278,11 +280,9 @@ module API
mount ::API::DebianGroupPackages
mount ::API::DebianProjectPackages
mount ::API::Discussions
mount ::API::ErrorTracking::ClientKeys
mount ::API::ErrorTracking::Collector
mount ::API::Events
mount ::API::GenericPackages
mount ::API::GoProxy
mount ::API::GroupBoards
mount ::API::GroupContainerRepositories
mount ::API::GroupDebianDistributions

View File

@ -18,10 +18,10 @@ module API
end
class ClientKey < Grape::Entity
expose :id
expose :active
expose :public_key
expose :sentry_dsn
expose :id, documentation: { type: 'integer', example: 1 }
expose :active, documentation: { type: 'boolean' }
expose :public_key, documentation: { type: 'string', example: 'glet_aa77551d849c083f76d0bc545ed053a3' }
expose :sentry_dsn, documentation: { type: 'string', example: 'https://glet_aa77551d849c083f76d0bc545ed053a3@gitlab.example.com/api/v4/error_tracking/collector/5' }
end
end
end

View File

@ -3,8 +3,8 @@
module API
module Entities
class GoModuleVersion < Grape::Entity
expose :name, as: 'Version'
expose :time, as: 'Time'
expose :name, as: 'Version', documentation: { type: 'string', example: 'v1.0.0' }
expose :time, as: 'Time', documentation: { type: 'string', example: '1617822312 -0600' }
end
end
end

View File

@ -4,11 +4,14 @@ module API
class ErrorTracking::ClientKeys < ::API::Base
before { authenticate! }
ERROR_TRACKING_CLIENT_KEYS_TAGS = %w[error_tracking_client_keys].freeze
feature_category :error_tracking
urgency :low
params do
requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project'
requires :id, types: [String, Integer],
desc: 'The ID or URL-encoded path of the project owned by the authenticated user'
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
@ -17,9 +20,11 @@ module API
authorize! :admin_operations, user_project
end
desc 'List all client keys' do
detail 'This feature was introduced in GitLab 14.3.'
desc 'List project client keys' do
detail 'List all client keys. This feature was introduced in GitLab 14.3.'
success Entities::ErrorTracking::ClientKey
is_array true
tags ERROR_TRACKING_CLIENT_KEYS_TAGS
end
get '/client_keys' do
collection = user_project.error_tracking_client_keys
@ -28,8 +33,10 @@ module API
end
desc 'Create a client key' do
detail 'This feature was introduced in GitLab 14.3.'
detail 'Creates a new client key for a project. The public key attribute is generated automatically.'\
'This feature was introduced in GitLab 14.3.'
success Entities::ErrorTracking::ClientKey
tags ERROR_TRACKING_CLIENT_KEYS_TAGS
end
post '/client_keys' do
key = user_project.error_tracking_client_keys.create!
@ -38,8 +45,14 @@ module API
end
desc 'Delete a client key' do
detail 'This feature was introduced in GitLab 14.3.'
detail 'Removes a client key from the project. This feature was introduced in GitLab 14.3.'
success Entities::ErrorTracking::ClientKey
failure [
{ code: 400, message: 'Bad request' },
{ code: 401, message: 'Unauthorized' },
{ code: 404, message: 'Not found' }
]
tags ERROR_TRACKING_CLIENT_KEYS_TAGS
end
delete '/client_keys/:key_id' do
key = user_project.error_tracking_client_keys.find(params[:key_id])

View File

@ -4,6 +4,8 @@ module API
helpers Gitlab::Golang
helpers ::API::Helpers::PackagesHelpers
GO_PROXY_TAGS = %w[go_proxy].freeze
feature_category :package_registry
urgency :low
@ -62,18 +64,21 @@ module API
end
params do
requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project'
requires :module_name, type: String, desc: 'Module name', coerce_with: ->(val) { CGI.unescape(val) }
requires :id, types: [String, Integer], desc: 'The project ID or full path of a project'
requires :module_name, type: String, desc: 'The name of the Go module', coerce_with: ->(val) { CGI.unescape(val) }
end
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, authenticate_non_public: true
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true,
authenticate_non_public: true
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do
authorize_read_package!(project)
end
namespace ':id/packages/go/*module_name/@v' do
desc 'Get all tagged versions for a given Go module' do
detail 'See `go help goproxy`, GET $GOPROXY/<module>/@v/list. This feature was introduced in GitLab 13.1.'
desc 'List' do
detail 'Get all tagged versions for a given Go module.'\
'See `go help goproxy`, GET $GOPROXY/<module>/@v/list. This feature was introduced in GitLab 13.1.'
tags GO_PROXY_TAGS
end
get 'list' do
mod = find_module
@ -82,12 +87,14 @@ module API
mod.versions.map { |t| t.name }.join("\n")
end
desc 'Get information about the given module version' do
detail 'See `go help goproxy`, GET $GOPROXY/<module>/@v/<version>.info. This feature was introduced in GitLab 13.1.'
desc 'Version metadata' do
detail 'Get all tagged versions for a given Go module.'\
'See `go help goproxy`, GET $GOPROXY/<module>/@v/<version>.info. This feature was introduced in GitLab 13.1'
success ::API::Entities::GoModuleVersion
tags GO_PROXY_TAGS
end
params do
requires :module_version, type: String, desc: 'Module version'
requires :module_version, type: String, desc: 'The version of the Go module'
end
get ':module_version.info', requirements: MODULE_VERSION_REQUIREMENTS do
ver = find_version
@ -95,11 +102,13 @@ module API
present ::Packages::Go::ModuleVersionPresenter.new(ver), with: ::API::Entities::GoModuleVersion
end
desc 'Get the module file of the given module version' do
detail 'See `go help goproxy`, GET $GOPROXY/<module>/@v/<version>.mod. This feature was introduced in GitLab 13.1.'
desc 'Download module file' do
detail 'Get the module file of a given module version.'\
'See `go help goproxy`, GET $GOPROXY/<module>/@v/<version>.mod. This feature was introduced in GitLab 13.1.'
tags GO_PROXY_TAGS
end
params do
requires :module_version, type: String, desc: 'Module version'
requires :module_version, type: String, desc: 'The version of the Go module'
end
get ':module_version.mod', requirements: MODULE_VERSION_REQUIREMENTS do
ver = find_version
@ -108,18 +117,21 @@ module API
ver.gomod
end
desc 'Get a zip of the source of the given module version' do
detail 'See `go help goproxy`, GET $GOPROXY/<module>/@v/<version>.zip. This feature was introduced in GitLab 13.1.'
desc 'Download module source' do
detail 'Get a zip of the source of the given module version.'\
'See `go help goproxy`, GET $GOPROXY/<module>/@v/<version>.zip. This feature was introduced in GitLab 13.1.'
tags GO_PROXY_TAGS
end
params do
requires :module_version, type: String, desc: 'Module version'
requires :module_version, type: String, desc: 'The version of the Go module'
end
get ':module_version.zip', requirements: MODULE_VERSION_REQUIREMENTS do
ver = find_version
content_type 'application/zip'
env['api.format'] = :binary
header['Content-Disposition'] = ActionDispatch::Http::ContentDisposition.format(disposition: 'attachment', filename: ver.name + '.zip')
header['Content-Disposition'] =
ActionDispatch::Http::ContentDisposition.format(disposition: 'attachment', filename: "#{ver.name}.zip")
header['Content-Transfer-Encoding'] = 'binary'
status :ok
body ver.archive.string

View File

@ -117,7 +117,7 @@ module Gitlab
end
def blobs(limit: count_limit)
return [] unless Ability.allowed?(@current_user, :download_code, @project)
return [] unless Ability.allowed?(@current_user, :read_code, @project)
@blobs ||= Gitlab::FileFinder.new(project, repository_project_ref).find(query, content_match_cutoff: limit)
end
@ -153,7 +153,7 @@ module Gitlab
end
def find_commits(query, limit:)
return [] unless Ability.allowed?(@current_user, :download_code, @project)
return [] unless Ability.allowed?(@current_user, :read_code, @project)
commits = find_commits_by_message(query, limit: limit)
commit_by_sha = find_commit_by_sha(query)

View File

@ -161,7 +161,7 @@ module Gitlab
parse_params do |raw_duration|
Gitlab::TimeTrackingFormatter.parse(raw_duration)
end
command :estimate do |time_estimate|
command :estimate, :estimate_time do |time_estimate|
if time_estimate
@updates[:time_estimate] = time_estimate
end
@ -184,7 +184,7 @@ module Gitlab
parse_params do |raw_time_date|
Gitlab::QuickActions::SpendTimeAndDateSeparator.new(raw_time_date).execute
end
command :spend, :spent do |time_spent, time_spent_date|
command :spend, :spent, :spend_time do |time_spent, time_spent_date|
if time_spent
@updates[:spend_time] = {
duration: time_spent,
@ -202,7 +202,7 @@ module Gitlab
quick_action_target.persisted? &&
current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
end
command :remove_estimate do
command :remove_estimate, :remove_time_estimate do
@updates[:time_estimate] = 0
end

View File

@ -81,6 +81,9 @@ namespace :tw do
CodeOwnerRule.new('Workspace', '@lciutacu')
].freeze
CODEOWNERS_BLOCK_BEGIN = "# Begin rake-managed-docs-block"
CODEOWNERS_BLOCK_END = "# End rake-managed-docs-block"
Document = Struct.new(:group, :redirect) do
def has_a_valid_group?
group && !redirect
@ -124,7 +127,17 @@ namespace :tw do
end
end
deduplicated_mappings.sort.each { |mapping| puts mapping }
new_docs_owners = deduplicated_mappings.sort.join("\n")
codeowners_path = Rails.root.join('.gitlab/CODEOWNERS')
current_codeowners_content = File.read(codeowners_path)
docs_replace_regex = Regexp.new("#{CODEOWNERS_BLOCK_BEGIN}\n[\\s\\S]*?\n#{CODEOWNERS_BLOCK_END}")
new_codeowners_content = current_codeowners_content
.gsub(docs_replace_regex, "#{CODEOWNERS_BLOCK_BEGIN}\n#{new_docs_owners}\n#{CODEOWNERS_BLOCK_END}")
File.write(codeowners_path, new_codeowners_content)
if errors.present?
puts "-----"

View File

@ -46510,10 +46510,10 @@ msgstr ""
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
msgid "You can %{gitlabLinkStart}resolve conflicts on GitLab%{gitlabLinkEnd} or %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}."
msgid "You can %{gitlabLinkStart}resolve conflicts on GitLab%{gitlabLinkEnd} or %{resolveLocallyStart}resolve them locally%{resolveLocallyEnd}."
msgstr ""
msgid "You can %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}."
msgid "You can %{resolveLocallyStart}resolve them locally%{resolveLocallyEnd}."
msgstr ""
msgid "You can adjust rules on auto-banning %{link_start}here%{link_end}."

View File

@ -80,11 +80,13 @@ class CreatePipelineFailureIncident
If you believe that there's an easy resolution by either:
- Reverting a particular merge request. Make sure to add the ~"pipeline:revert" label in that case, to speed up the revert pipeline.
- Reverting a particular merge request.
- Making a quick fix (for example, one line or a few similar simple changes in a few lines).
You can create a merge request, assign to any available maintainer, and ping people that were involved/related to the introduction of the failure.
Additionally, a message can be posted in `#backend_maintainers` or `#frontend_maintainers` to get a maintainer take a look at the fix ASAP.
In both cases, make sure to add the ~"pipeline:expedite-master-fixing" label, and `master:broken` or `master:foss-broken` label, to speed up the `master`-fixing pipelines.
### Resolution
Follow [the Resolution steps from the handbook](https://about.gitlab.com/handbook/engineering/workflow/#responsibilities-of-the-resolution-dri).

View File

@ -97,7 +97,7 @@ puts
if additional_flags.count > 0
puts "==================================================".green.bold
puts "There are feature flags that appears to be unknown".yellow
puts "There are feature flags that appear to be unknown".yellow
puts
puts "They appear to be used by CI, but we do lack their YAML definition".yellow
puts "This is likely expected, so feel free to ignore that list:".yellow
@ -110,7 +110,7 @@ end
if unused_flags.count > 0
puts "========================================".green.bold
puts "These feature flags appears to be UNUSED".red.bold
puts "These feature flags appear to be UNUSED".red.bold
puts
puts "If they are really no longer needed REMOVE their .yml definition".red
puts "If they are needed you need to ENSURE that their usage is covered with specs to continue.".red

View File

@ -0,0 +1,222 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Merge request > User sees discussions navigation', :js do
let_it_be(:project) { create(:project, :public, :repository) }
let_it_be(:user) { project.creator }
let_it_be(:merge_request) { create(:merge_request, source_project: project) }
before do
# FIXME: before removing this please fix discussions navigation with this flag enabled
stub_feature_flags(moved_mr_sidebar: false)
project.add_maintainer(user)
sign_in(user)
end
describe 'Code discussions' do
let!(:position) do
build(:text_diff_position, :added,
file: "files/images/wm.svg",
new_line: 1,
diff_refs: merge_request.diff_refs
)
end
let!(:first_discussion) do
create(:diff_note_on_merge_request,
noteable: merge_request,
project: project,
position: position
).to_discussion
end
let!(:second_discussion) do
create(:diff_note_on_merge_request,
noteable: merge_request,
project: project,
position: position
).to_discussion
end
let(:first_discussion_selector) { ".discussion[data-discussion-id='#{first_discussion.id}']" }
let(:second_discussion_selector) { ".discussion[data-discussion-id='#{second_discussion.id}']" }
shared_examples 'a page with a thread navigation' do
context 'with active threads' do
it 'navigates to the first thread' do
goto_next_thread
expect(page).to have_selector(first_discussion_selector, obscured: false)
end
it 'navigates to the last thread' do
goto_previous_thread
expect(page).to have_selector(second_discussion_selector, obscured: false)
end
it 'navigates through active threads' do
goto_next_thread
goto_next_thread
expect(page).to have_selector(second_discussion_selector, obscured: false)
end
it 'cycles back to the first thread' do
goto_next_thread
goto_next_thread
goto_next_thread
expect(page).to have_selector(first_discussion_selector, obscured: false)
end
it 'cycles back to the last thread' do
goto_previous_thread
goto_previous_thread
goto_previous_thread
expect(page).to have_selector(second_discussion_selector, obscured: false)
end
end
context 'with resolved threads' do
let!(:resolved_discussion) do
create(:diff_note_on_merge_request,
noteable: merge_request,
project: project,
position: position
).to_discussion
end
let(:resolved_discussion_selector) { ".discussion[data-discussion-id='#{resolved_discussion.id}']" }
before do
# :resolved attr doesn't actually resolve the thread but just collapses it
page.within(resolved_discussion_selector) do
click_button text: 'Resolve thread'
end
page.execute_script("window.scrollTo(0,0)")
end
it 'excludes resolved threads during navigation' do
goto_next_thread
goto_next_thread
goto_next_thread
expect(page).to have_selector(first_discussion_selector, obscured: false)
end
end
end
describe "Overview page discussions navigation" do
before do
visit project_merge_request_path(project, merge_request)
end
it_behaves_like 'a page with a thread navigation'
context 'with collapsed threads' do
before do
page.within(first_discussion_selector) do
click_button 'Hide thread'
end
end
it 'expands threads during navigation' do
goto_next_thread
expect(page).to have_selector "#note_#{first_discussion.first_note.id}"
end
end
end
describe "Changes page discussions navigation" do
before do
visit diffs_project_merge_request_path(project, merge_request)
end
it_behaves_like 'a page with a thread navigation'
end
end
describe 'Merge request discussions' do
shared_examples 'a page with no code discussions' do
let!(:first_discussion) do
create(:discussion_note_on_merge_request,
noteable: merge_request,
project: project
).to_discussion
end
let!(:second_discussion) do
create(:discussion_note_on_merge_request,
noteable: merge_request,
project: project
).to_discussion
end
let(:first_discussion_selector) { ".discussion[data-discussion-id='#{first_discussion.id}']" }
let(:second_discussion_selector) { ".discussion[data-discussion-id='#{second_discussion.id}']" }
describe "Changes page discussions navigation" do
it 'navigates to the first discussion on the Overview page' do
goto_next_thread
expect(page).to have_selector(first_discussion_selector, obscured: false)
end
it 'navigates to the last discussion on the Overview page' do
goto_previous_thread
expect(page).to have_selector(second_discussion_selector, obscured: false)
end
end
end
context 'on changes page' do
before do
visit diffs_project_merge_request_path(project, merge_request)
end
it_behaves_like 'a page with no code discussions'
end
context 'on commits page' do
before do
# we can't go directly to the commits page since it doesn't load discussions
visit project_merge_request_path(project, merge_request)
click_link 'Commits'
end
it_behaves_like 'a page with no code discussions'
end
context 'on pipelines page' do
before do
visit project_merge_request_path(project, merge_request)
click_link 'Pipelines'
end
it_behaves_like 'a page with no code discussions'
end
end
def goto_next_thread
begin
# this is required when moved_mr_sidebar is enabled
page.within('.issue-sticky-header') do
click_button 'Go to next unresolved thread'
end
rescue StandardError
click_button 'Go to next unresolved thread'
end
wait_for_scroll_end
end
def goto_previous_thread
begin
page.within('.issue-sticky-header') do
click_button 'Go to previous unresolved thread'
end
rescue StandardError
click_button 'Go to previous unresolved thread'
end
wait_for_scroll_end
end
def wait_for_scroll_end
sleep(1)
end
end

View File

@ -34,6 +34,23 @@ describe('~/diffs/utils/tree_worker_utils', () => {
added_lines: 0,
file_hash: 'test',
},
{
new_path: 'constructor/test/aFile.js',
deleted_file: false,
new_file: true,
removed_lines: 0,
added_lines: 42,
file_hash: 'test',
},
{
new_path: 'submodule @ abcdef123',
deleted_file: false,
new_file: true,
removed_lines: 0,
added_lines: 1,
submodule: true,
file_hash: 'test',
},
{
new_path: 'package.json',
deleted_file: true,
@ -66,6 +83,7 @@ describe('~/diffs/utils/tree_worker_utils', () => {
path: 'app/index.js',
removedLines: 10,
tempFile: false,
submodule: undefined,
type: 'blob',
tree: [],
},
@ -87,6 +105,7 @@ describe('~/diffs/utils/tree_worker_utils', () => {
path: 'app/test/index.js',
removedLines: 0,
tempFile: true,
submodule: undefined,
type: 'blob',
tree: [],
},
@ -101,6 +120,7 @@ describe('~/diffs/utils/tree_worker_utils', () => {
path: 'app/test/filepathneedstruncating.js',
removedLines: 0,
tempFile: true,
submodule: undefined,
type: 'blob',
tree: [],
},
@ -109,6 +129,45 @@ describe('~/diffs/utils/tree_worker_utils', () => {
],
opened: true,
},
{
key: 'constructor',
name: 'constructor/test',
opened: true,
path: 'constructor',
tree: [
{
addedLines: 42,
changed: true,
deleted: false,
fileHash: 'test',
key: 'constructor/test/aFile.js',
name: 'aFile.js',
parentPath: 'constructor/test/',
path: 'constructor/test/aFile.js',
removedLines: 0,
submodule: undefined,
tempFile: true,
tree: [],
type: 'blob',
},
],
type: 'tree',
},
{
key: 'submodule @ abcdef123',
parentPath: '/',
path: 'submodule @ abcdef123',
name: 'submodule @ abcdef123',
type: 'blob',
changed: true,
tempFile: true,
submodule: true,
deleted: false,
fileHash: 'test',
addedLines: 1,
removedLines: 0,
tree: [],
},
{
key: 'package.json',
parentPath: '/',
@ -117,6 +176,7 @@ describe('~/diffs/utils/tree_worker_utils', () => {
type: 'blob',
changed: true,
tempFile: false,
submodule: undefined,
deleted: true,
fileHash: 'test',
addedLines: 0,
@ -135,6 +195,10 @@ describe('~/diffs/utils/tree_worker_utils', () => {
'app/test',
'app/test/index.js',
'app/test/filepathneedstruncating.js',
'constructor',
'constructor/test',
'constructor/test/aFile.js',
'submodule @ abcdef123',
'package.json',
]);
});

View File

@ -195,7 +195,7 @@ RSpec.describe SearchHelper do
expect(search_autocomplete_opts("Network").size).to eq(1)
expect(search_autocomplete_opts("Graph").size).to eq(1)
allow(self).to receive(:can?).with(user, :download_code, @project).and_return(false)
allow(self).to receive(:can?).with(user, :read_code, @project).and_return(false)
expect(search_autocomplete_opts("Files").size).to eq(0)
expect(search_autocomplete_opts("Commits").size).to eq(0)

View File

@ -103,13 +103,17 @@ RSpec.describe SearchController, type: :request do
expect(response).not_to redirect_to(project_commit_path(project, sha))
end
it 'does not redirect if user cannot download_code from project' do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?).with(user, :download_code, project).and_return(false)
context 'when user cannot read_code' do
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?).with(user, :read_code, project).and_return(false)
end
send_search_request({ search: sha, project_id: project.id })
it 'does not redirect' do
send_search_request({ search: sha, project_id: project.id })
expect(response).not_to redirect_to(project_commit_path(project, sha))
expect(response).not_to redirect_to(project_commit_path(project, sha))
end
end
it 'does not redirect if commit sha not found in project' do

View File

@ -1450,6 +1450,11 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { issue }
end
it_behaves_like 'estimate command' do
let(:content) { '/estimate_time 1h' }
let(:issuable) { issue }
end
it_behaves_like 'failed command' do
let(:content) { '/estimate' }
let(:issuable) { issue }
@ -1470,6 +1475,11 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { issue }
end
it_behaves_like 'spend command' do
let(:content) { '/spend_time 1h' }
let(:issuable) { issue }
end
it_behaves_like 'spend command with negative time' do
let(:content) { '/spend -120m' }
let(:issuable) { issue }
@ -1537,6 +1547,11 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { issue }
end
it_behaves_like 'remove_estimate command' do
let(:content) { '/remove_time_estimate' }
let(:issuable) { issue }
end
it_behaves_like 'remove_time_spent command' do
let(:content) { '/remove_time_spent' }
let(:issuable) { issue }