Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
af5193aa3c
commit
3d8ebbb15d
|
|
@ -3,3 +3,5 @@ export const getModifierKey = (removeSuffix = false) => {
|
|||
const winKey = `Ctrl${removeSuffix ? '' : '+'}`;
|
||||
return window.gl?.client?.isMac ? '⌘' : winKey;
|
||||
};
|
||||
|
||||
export const PRELOAD_THROTTLE_TIMEOUT_MS = 4000;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import GfmAutoComplete, { defaultAutocompleteConfig } from 'ee_else_ce/gfm_auto_
|
|||
import { disableButtonIfEmptyField } from '~/lib/utils/common_utils';
|
||||
import dropzoneInput from './dropzone_input';
|
||||
import { addMarkdownListeners, removeMarkdownListeners } from './lib/utils/text_markdown';
|
||||
import { PRELOAD_THROTTLE_TIMEOUT_MS } from './constants';
|
||||
|
||||
export default class GLForm {
|
||||
/**
|
||||
|
|
@ -17,10 +18,11 @@ export default class GLForm {
|
|||
* By default, the backend embeds these in the global object gl.GfmAutocomplete.dataSources.
|
||||
* Use this param to override them.
|
||||
*/
|
||||
constructor(form, enableGFM = {}, forceNew = false, gfmDataSources = {}) {
|
||||
constructor(form, enableGFM = {}, forceNew = false, gfmDataSources = {}, preloadMembers = false) {
|
||||
this.form = form;
|
||||
this.textarea = this.form.find('textarea.js-gfm-input');
|
||||
this.enableGFM = { ...defaultAutocompleteConfig, ...enableGFM };
|
||||
this.preloadMembers = preloadMembers;
|
||||
|
||||
// Disable autocomplete for keywords which do not have dataSources available
|
||||
let dataSources = (gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources) || {};
|
||||
|
|
@ -68,6 +70,21 @@ export default class GLForm {
|
|||
);
|
||||
this.autoComplete = new GfmAutoComplete(dataSources);
|
||||
this.autoComplete.setup(this.form.find('.js-gfm-input'), this.enableGFM);
|
||||
|
||||
if (this.preloadMembers && dataSources?.members) {
|
||||
// for now the preload is only implemented for the members
|
||||
// timeout helping to trottle the preloads in the case content_editor
|
||||
// is set as main comment editor and support for rspec tests
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/issues/427437
|
||||
|
||||
requestIdleCallback(() =>
|
||||
setTimeout(
|
||||
() => this.autoComplete?.fetchData($('.js-gfm-input'), '@'),
|
||||
PRELOAD_THROTTLE_TIMEOUT_MS,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
this.formDropzone = dropzoneInput(this.form, { parallelUploads: 1 });
|
||||
|
||||
if (this.form.is(':not(.js-no-autosize)')) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import discussionNavigator from '../notes/components/discussion_navigator.vue';
|
|||
import NotesApp from '../notes/components/notes_app.vue';
|
||||
import { getNotesFilterData } from '../notes/utils/get_notes_filter_data';
|
||||
import initWidget from '../vue_merge_request_widget';
|
||||
import { MERGE_REQUEST_NOTEABLE_TYPE } from '../notes/constants';
|
||||
|
||||
export default () => {
|
||||
requestIdleCallback(
|
||||
|
|
@ -45,6 +46,9 @@ export default () => {
|
|||
newCommentTemplatePath: notesDataset.newCommentTemplatePath,
|
||||
mrFilter: true,
|
||||
newCustomEmojiPath: notesDataset.newCustomEmojiPath,
|
||||
preloadMembers:
|
||||
notesDataset?.noteableType === MERGE_REQUEST_NOTEABLE_TYPE &&
|
||||
gon?.features?.preloadAutocompleteMembersIssuesMrs,
|
||||
},
|
||||
data() {
|
||||
const noteableData = JSON.parse(notesDataset.noteableData);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { getLocationHash } from '~/lib/utils/url_utility';
|
|||
import NotesApp from './components/notes_app.vue';
|
||||
import { store } from './stores';
|
||||
import { getNotesFilterData } from './utils/get_notes_filter_data';
|
||||
import { ISSUE_NOTEABLE_TYPE } from './constants';
|
||||
|
||||
export default ({ editorAiActions = [] } = {}) => {
|
||||
const el = document.getElementById('js-vue-notes');
|
||||
|
|
@ -63,6 +64,9 @@ export default ({ editorAiActions = [] } = {}) => {
|
|||
resourceGlobalId: convertToGraphQLId(noteableData.noteableType, noteableData.id),
|
||||
editorAiActions: editorAiActions.map((factory) => factory(noteableData)),
|
||||
newCustomEmojiPath: notesDataset.newCustomEmojiPath,
|
||||
preloadMembers:
|
||||
notesDataset.noteableType === ISSUE_NOTEABLE_TYPE &&
|
||||
gon?.features?.preloadAutocompleteMembersIssuesMrs,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,13 @@ export default {
|
|||
GlTooltip: GlTooltipDirective,
|
||||
},
|
||||
mixins: [glFeatureFlagsMixin()],
|
||||
inject: {
|
||||
preloadMembers: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
props: {
|
||||
/**
|
||||
* This prop should be bound to the value of the `<textarea>` element
|
||||
|
|
@ -278,6 +285,7 @@ export default {
|
|||
},
|
||||
true,
|
||||
this.autocompleteDataSources,
|
||||
this.preloadMembers,
|
||||
);
|
||||
|
||||
markdownEditorEventHub.$emit(MARKDOWN_EDITOR_READY_EVENT);
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
push_force_frontend_feature_flag(:linked_work_items, project.linked_work_items_feature_flag_enabled?)
|
||||
push_frontend_feature_flag(:notifications_todos_buttons, current_user)
|
||||
push_frontend_feature_flag(:mention_autocomplete_backend_filtering, project)
|
||||
push_frontend_feature_flag(:preload_autocomplete_members_issues_mrs, current_user)
|
||||
end
|
||||
|
||||
around_action :allow_gitaly_ref_name_caching, only: [:discussions]
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
|
|||
push_frontend_feature_flag(:mention_autocomplete_backend_filtering, project)
|
||||
push_frontend_feature_flag(:pinned_file, project)
|
||||
push_frontend_feature_flag(:merge_request_diff_generated_subscription, project)
|
||||
push_frontend_feature_flag(:preload_autocomplete_members_issues_mrs, current_user)
|
||||
end
|
||||
|
||||
around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :diffs, :discussions]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: preload_autocomplete_members_issues_mrs
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139085
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/435698
|
||||
milestone: '16.8'
|
||||
type: development
|
||||
group: group::global search
|
||||
default_enabled: false
|
||||
|
|
@ -8,3 +8,5 @@ description: TODO
|
|||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/5b0954759cc24bdba97be89bb117c5440174f859
|
||||
milestone: '9.4'
|
||||
gitlab_schema: gitlab_ci
|
||||
sharding_key:
|
||||
group_id: namespaces
|
||||
|
|
|
|||
|
|
@ -8,3 +8,5 @@ description: TODO
|
|||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77886
|
||||
milestone: '14.7'
|
||||
gitlab_schema: gitlab_ci
|
||||
sharding_key:
|
||||
project_id: projects
|
||||
|
|
|
|||
|
|
@ -8,3 +8,5 @@ description: TODO
|
|||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/046b28312704f3131e72dcd2dbdacc5264d4aa62
|
||||
milestone: '8.0'
|
||||
gitlab_schema: gitlab_ci
|
||||
sharding_key:
|
||||
project_id: projects
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
1383d7d49981bdb5fa5eeb54dd83520f4bd2de1e8f0cc227c1397d0bc48a66f4
|
||||
f6e40be8eac5b255458e32b33755b9404ede064add99f0f13998647eea1dfbb7
|
||||
|
|
@ -178,12 +178,13 @@ including:
|
|||
- Snippets
|
||||
- [Group wikis](../../user/project/wiki/group.md)
|
||||
- Project-level Secure Files ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121142) in GitLab 16.1)
|
||||
- Merge request diffs (Helm chart installation only)
|
||||
|
||||
Backups do not include:
|
||||
|
||||
- [Mattermost data](https://docs.mattermost.com/administration/config-settings.html#file-storage)
|
||||
- [Mattermost data](../../integration/mattermost/index.md#back-up-gitlab-mattermost)
|
||||
- Redis (and thus Sidekiq jobs)
|
||||
- [Object storage](#object-storage)
|
||||
- [Object storage](#object-storage) on Linux package (Omnibus) / Docker / Self-compiled installations
|
||||
|
||||
WARNING:
|
||||
GitLab does not back up any configuration files (`/etc/gitlab`), TLS keys and certificates, or system
|
||||
|
|
@ -208,7 +209,7 @@ system. If you installed GitLab:
|
|||
### Backup command
|
||||
|
||||
WARNING:
|
||||
The backup command does not back up items in [object storage](#object-storage).
|
||||
The backup command does not back up items in [object storage](#object-storage) on Linux package (Omnibus) / Docker / Self-compiled installations.
|
||||
|
||||
WARNING:
|
||||
The backup command requires [additional parameters](#back-up-and-restore-for-installations-using-pgbouncer) when
|
||||
|
|
@ -239,8 +240,6 @@ Run the backup task by using `kubectl` to run the `backup-utility` script on the
|
|||
|
||||
Run the backup from the host.
|
||||
|
||||
- GitLab 12.2 or later:
|
||||
|
||||
```shell
|
||||
docker exec -t <container name> gitlab-backup create
|
||||
```
|
||||
|
|
@ -439,28 +438,45 @@ on all distributions. To verify that it's available in your distribution, run
|
|||
sudo gitlab-backup create BACKUP=dump GZIP_RSYNCABLE=yes
|
||||
```
|
||||
|
||||
#### Excluding specific directories from the backup
|
||||
#### Excluding specific data from the backup
|
||||
|
||||
You can exclude specific directories from the backup by adding the environment variable `SKIP`, whose values are a comma-separated list of the following options:
|
||||
Depending on your installation type, slightly different components can be skipped on backup creation.
|
||||
|
||||
::Tabs
|
||||
|
||||
:::Tab Title Linux package (Omnibus) / Docker / Self-compiled
|
||||
|
||||
<!-- source: https://gitlab.com/gitlab-org/gitlab/-/blob/31c3df7ebb65768208772da3e20d32688a6c90ef/lib/backup/manager.rb#L126 -->
|
||||
|
||||
- `db` (database)
|
||||
- `repositories` (Git repositories data, including wikis)
|
||||
- `uploads` (attachments)
|
||||
- `builds` (CI job output logs)
|
||||
- `artifacts` (CI job artifacts)
|
||||
- `pages` (Pages content)
|
||||
- `lfs` (LFS objects)
|
||||
- `terraform_state` (Terraform states)
|
||||
- `registry` (Container registry images)
|
||||
- `pages` (Pages content)
|
||||
- `repositories` (Git repositories data)
|
||||
- `packages` (Packages)
|
||||
- `ci_secure_files` (Project-level Secure Files)
|
||||
|
||||
NOTE:
|
||||
When [backing up and restoring Helm Charts](https://docs.gitlab.com/charts/architecture/backup-restore.html), there is an additional option `packages`, which refers to any packages managed by the GitLab [package registry](../../user/packages/package_registry/index.md).
|
||||
For more information see [command line arguments](https://docs.gitlab.com/charts/architecture/backup-restore.html#command-line-arguments).
|
||||
:::TabTitle Helm chart (Kubernetes)
|
||||
|
||||
All wikis are backed up as part of the `repositories` group. Non-existent
|
||||
wikis are skipped during a backup.
|
||||
<!-- source: https://gitlab.com/gitlab-org/build/CNG/-/blob/068e146db915efcd875414e04403410b71a2e70c/gitlab-toolbox/scripts/bin/backup-utility#L19 -->
|
||||
|
||||
- `db` (database)
|
||||
- `repositories` (Git repositories data, including wikis)
|
||||
- `uploads` (attachments)
|
||||
- `artifacts` (CI job artifacts and output logs)
|
||||
- `pages` (Pages content)
|
||||
- `lfs` (LFS objects)
|
||||
- `terraform_state` (Terraform states)
|
||||
- `registry` (Container registry images)
|
||||
- `packages` (Package registry)
|
||||
- `ci_secure_files` (Project-level Secure Files)
|
||||
- `external_diffs` (Merge request diffs)
|
||||
|
||||
::EndTabs
|
||||
|
||||
::Tabs
|
||||
|
||||
|
|
@ -470,6 +486,10 @@ wikis are skipped during a backup.
|
|||
sudo gitlab-backup create SKIP=db,uploads
|
||||
```
|
||||
|
||||
:::TabTitle Helm chart (Kubernetes)
|
||||
|
||||
See [Skipping components](https://docs.gitlab.com/charts/backup-restore/backup.html#skipping-components) in charts backup documentation.
|
||||
|
||||
:::TabTitle Self-compiled
|
||||
|
||||
```shell
|
||||
|
|
@ -1341,7 +1361,7 @@ If you have a specific reason to change the path, it can be configured in the Li
|
|||
|
||||
Because every deployment may have different capabilities, you should first review [what data needs to be backed up](#what-data-needs-to-be-backed-up) to better understand if, and how, you can leverage them.
|
||||
|
||||
For example, if you use Amazon RDS, you might choose to use its built-in backup and restore features to handle your GitLab [PostgreSQL data](#postgresql-databases), and [exclude PostgreSQL data](#excluding-specific-directories-from-the-backup) when using the [backup command](#backup-command).
|
||||
For example, if you use Amazon RDS, you might choose to use its built-in backup and restore features to handle your GitLab [PostgreSQL data](#postgresql-databases), and [exclude PostgreSQL data](#excluding-specific-data-from-the-backup) when using the [backup command](#backup-command).
|
||||
|
||||
In the following cases, consider using file system data transfer or snapshots as part of your backup strategy:
|
||||
|
||||
|
|
@ -1381,7 +1401,7 @@ practical use.
|
|||
|
||||
### Back up repository data separately
|
||||
|
||||
First, ensure you back up existing GitLab data while [skipping repositories](#excluding-specific-directories-from-the-backup):
|
||||
First, ensure you back up existing GitLab data while [skipping repositories](#excluding-specific-data-from-the-backup):
|
||||
|
||||
::Tabs
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ the container registry on the primary site and restore it onto the secondary
|
|||
site:
|
||||
|
||||
1. On your primary site, back up only the registry and
|
||||
[exclude specific directories from the backup](../../../administration/backup_restore/backup_gitlab.md#excluding-specific-directories-from-the-backup):
|
||||
[exclude specific directories from the backup](../../../administration/backup_restore/backup_gitlab.md#excluding-specific-data-from-the-backup):
|
||||
|
||||
```shell
|
||||
# Create a backup in the /var/opt/gitlab/backups folder
|
||||
|
|
|
|||
|
|
@ -985,3 +985,44 @@ to run the following command:
|
|||
```ruby
|
||||
Feature.disable(:s3_multithreaded_uploads)
|
||||
```
|
||||
|
||||
### Manual testing through Rails Console
|
||||
|
||||
In some situations, it may be helpful to test object storage settings using the Rails Console. The following example tests a given set of connection settings, attempts to write a test object, and finally read it.
|
||||
|
||||
1. Start a [Rails console](operations/rails_console.md).
|
||||
1. Set up the object storage connection, using the same parameters you set up in `/etc/gitlab/gitlab.rb`, in the following example format:
|
||||
|
||||
Example connection using access keys:
|
||||
|
||||
```ruby
|
||||
connection = Fog::Storage.new(
|
||||
{
|
||||
provider: 'AWS',
|
||||
region: `eu-central-1`,
|
||||
aws_access_key_id: '<AWS_ACCESS_KEY_ID>',
|
||||
aws_secret_access_key: '<AWS_SECRET_ACCESS_KEY>'
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
Example connection using AWS IAM Profiles:
|
||||
|
||||
```ruby
|
||||
connection = Fog::Storage.new(
|
||||
{
|
||||
provider: 'AWS',
|
||||
use_iam_profile: true,
|
||||
region: 'us-east-1'
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
1. Specify the bucket name to test against, write, and finally read a test file.
|
||||
|
||||
```ruby
|
||||
dir = connection.directories.new(key: '<bucket-name-here>')
|
||||
f = dir.files.create(key: 'test.txt', body: 'test')
|
||||
pp f
|
||||
pp dir.files.head('test.txt')
|
||||
```
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ can result from directly accessing and copying Gitaly files using tools like `rs
|
|||
- From GitLab 13.3, backup performance can be improved by
|
||||
[processing multiple repositories concurrently](../../administration/backup_restore/backup_gitlab.md#back-up-git-repositories-concurrently).
|
||||
- Backups can be created of just the repositories using the
|
||||
[skip feature](../../administration/backup_restore/backup_gitlab.md#excluding-specific-directories-from-the-backup).
|
||||
[skip feature](../../administration/backup_restore/backup_gitlab.md#excluding-specific-data-from-the-backup).
|
||||
|
||||
No other method works for Gitaly Cluster targets.
|
||||
|
||||
|
|
|
|||
|
|
@ -307,6 +307,41 @@ Example response:
|
|||
|
||||
```
|
||||
|
||||
## Get the sequence of a commit
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/438151) in GitLab 16.9.
|
||||
|
||||
Get the sequence number of a commit in a project by following the parent links from the given commit.
|
||||
|
||||
This API provides essentially the same features as the `git rev-list --count` command for a given commit SHA.
|
||||
|
||||
```plaintext
|
||||
GET /projects/:id/repository/commits/:sha/sequence
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| -------------- | -------------- | -------- | ----------- |
|
||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding) owned by the authenticated user. |
|
||||
| `sha` | string | yes | The commit hash. |
|
||||
| `first_parent` | boolean | no | Follow only the first parent commit upon seeing a merge commit. |
|
||||
|
||||
Example request:
|
||||
|
||||
```shell
|
||||
curl --header "PRIVATE-TOKEN: <your_access_token>" \
|
||||
--url "https://gitlab.example.com/api/v4/projects/5/repository/commits/5937ac0a7beb003549fc5fd26fc247adbce4a52e/sequence"
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"count": 632
|
||||
}
|
||||
```
|
||||
|
||||
## Cherry-pick a commit
|
||||
|
||||
Cherry-picks a commit to a given branch.
|
||||
|
|
|
|||
|
|
@ -804,6 +804,25 @@ Returns [`RunnerSetup`](#runnersetup).
|
|||
| <a id="queryrunnersetupplatform"></a>`platform` | [`String!`](#string) | Platform to generate the instructions for. |
|
||||
| <a id="queryrunnersetupprojectid"></a>`projectId` **{warning-solid}** | [`ProjectID`](#projectid) | **Deprecated** in 13.11. No longer used. |
|
||||
|
||||
### `Query.runnerUsageByProject`
|
||||
|
||||
Runner usage by project.
|
||||
|
||||
WARNING:
|
||||
**Introduced** in 16.9.
|
||||
This feature is an Experiment. It can be changed or removed at any time.
|
||||
|
||||
Returns [`[RunnerUsageByProject!]`](#runnerusagebyproject).
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="queryrunnerusagebyprojectfromdate"></a>`fromDate` | [`Date`](#date) | Start of the requested date frame. Defaults to the start of the previous calendar month. |
|
||||
| <a id="queryrunnerusagebyprojectprojectslimit"></a>`projectsLimit` | [`Int`](#int) | Maximum number of projects to return.Other projects will be aggregated to a `project: null` entry.Can not be larger than 500. Defaults to 5. |
|
||||
| <a id="queryrunnerusagebyprojectrunnertype"></a>`runnerType` | [`CiRunnerType`](#cirunnertype) | Filter jobs by the type of runner that executed them. |
|
||||
| <a id="queryrunnerusagebyprojecttodate"></a>`toDate` | [`Date`](#date) | End of the requested date frame. Defaults to the end of the previous calendar month. |
|
||||
|
||||
### `Query.runners`
|
||||
|
||||
Get all runners in the GitLab instance (project and shared). Access is restricted to users with administrator access.
|
||||
|
|
@ -26845,6 +26864,18 @@ Counts of requirements by their state.
|
|||
| <a id="runnersetupinstallinstructions"></a>`installInstructions` | [`String!`](#string) | Instructions for installing the runner on the specified architecture. |
|
||||
| <a id="runnersetupregisterinstructions"></a>`registerInstructions` | [`String`](#string) | Instructions for registering the runner. The actual registration tokens are not included in the commands. Instead, a placeholder `$REGISTRATION_TOKEN` is shown. |
|
||||
|
||||
### `RunnerUsageByProject`
|
||||
|
||||
Runner usage in minutes by project.
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="runnerusagebyprojectcibuildcount"></a>`ciBuildCount` | [`Int!`](#int) | Amount of builds executed during the selected period. |
|
||||
| <a id="runnerusagebyprojectciminutesused"></a>`ciMinutesUsed` | [`Int!`](#int) | Amount of minutes used during the selected period. |
|
||||
| <a id="runnerusagebyprojectproject"></a>`project` | [`Project`](#project) | Project that the usage refers to. Null means "Other projects". |
|
||||
|
||||
### `SastCiConfiguration`
|
||||
|
||||
Represents a CI configuration of SAST.
|
||||
|
|
|
|||
|
|
@ -766,7 +766,7 @@ Some important things to know:
|
|||
must [configure this yourself](../../administration/backup_restore/backup_gitlab.md#storing-configuration-files).
|
||||
- By default, the backup files are stored locally, but you can
|
||||
[backup GitLab using S3](../../administration/backup_restore/backup_gitlab.md#using-amazon-s3).
|
||||
- You can [exclude specific directories form the backup](../../administration/backup_restore/backup_gitlab.md#excluding-specific-directories-from-the-backup).
|
||||
- You can [exclude specific directories form the backup](../../administration/backup_restore/backup_gitlab.md#excluding-specific-data-from-the-backup).
|
||||
|
||||
### Backing up GitLab
|
||||
|
||||
|
|
|
|||
|
|
@ -184,10 +184,7 @@ separation of duties is:
|
|||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/356791) in GitLab 16.4 [with a flag](../../../administration/feature_flags.md) named `compliance_violation_csv_export`. Disabled by default.
|
||||
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/424447) in GitLab 16.5.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is available. To hide the feature, an administrator can [disable the feature flag](../../../administration/feature_flags.md) named
|
||||
`compliance_violation_csv_export`. On GitLab.com, this feature is available.
|
||||
> - [Feature flag `compliance_violation_csv_export`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142568) removed in GitLab 16.9.
|
||||
|
||||
Export a report of merge request compliance violations on merge requests belonging to projects in a group. Reports:
|
||||
|
||||
|
|
|
|||
|
|
@ -309,6 +309,27 @@ module API
|
|||
present paginate(notes), with: Entities::CommitNote
|
||||
end
|
||||
|
||||
desc 'Get the sequence count of a commit SHA' do
|
||||
success code: 200, model: Entities::CommitSequence
|
||||
tags %w[commits]
|
||||
failure [
|
||||
{ code: 404, message: 'Not found' }
|
||||
]
|
||||
end
|
||||
params do
|
||||
requires :sha, type: String, desc: 'A commit SHA'
|
||||
optional :first_parent, type: Boolean, desc: 'Only include the first parent of merges', default: false
|
||||
end
|
||||
get ':id/repository/commits/:sha/sequence', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
|
||||
commit = user_project.commit(params[:sha])
|
||||
|
||||
not_found! 'Commit' unless commit
|
||||
count = user_project.repository.count_commits(ref: params[:sha], first_parent: params[:first_parent])
|
||||
count_hash = { count: count }
|
||||
|
||||
present count_hash, with: Entities::CommitSequence
|
||||
end
|
||||
|
||||
desc 'Cherry pick commit into a branch' do
|
||||
detail 'This feature was introduced in GitLab 8.15'
|
||||
success code: 200, model: Entities::Commit
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module API
|
||||
module Entities
|
||||
class CommitSequence < Grape::Entity
|
||||
expose :count, documentation: { type: 'integer', example: 1 }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -85,7 +85,7 @@ module QA
|
|||
|
||||
def click_boards_dropdown_button
|
||||
# The dropdown button comes from the `GlDropdown` component of `@gitlab/ui`,
|
||||
# so it wasn't possible to add a `data-qa-selector` to it.
|
||||
# so it wasn't possible to add a `data-testid` to it.
|
||||
find_element('boards-dropdown').find('button').click
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# VSCode WebIDE is built off an iFrame application therefore we are unable to use `qa-selectors`
|
||||
# VSCode WebIDE is built off an iFrame application therefore we are unable to use `testids`
|
||||
module QA
|
||||
module Page
|
||||
module Project
|
||||
|
|
|
|||
|
|
@ -92,7 +92,9 @@ RSpec.describe 'User comments on a merge request', :js, feature_category: :code_
|
|||
end
|
||||
|
||||
wait_for_requests
|
||||
expect(page.html).to include('Are you sure you want to cancel creating this comment?')
|
||||
page.within('.modal-dialog') do
|
||||
expect(page).to have_content('Are you sure you want to cancel creating this comment?')
|
||||
end
|
||||
end
|
||||
|
||||
it 'loads new comment' do
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import autosize from 'autosize';
|
||||
import $ from 'jquery';
|
||||
import GLForm from '~/gl_form';
|
||||
import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
|
||||
import '~/lib/utils/text_utility';
|
||||
import '~/lib/utils/common_utils';
|
||||
|
||||
|
|
@ -46,6 +47,43 @@ describe('GLForm', () => {
|
|||
expect(setupFormSpy).toHaveBeenCalledWith(customDataSources, false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GfmAutoComplete', () => {
|
||||
let autocompleteDataFetchSpy;
|
||||
const updatedMockGl = { ...mockGl };
|
||||
|
||||
updatedMockGl.GfmAutoComplete.dataSources = {
|
||||
...updatedMockGl.GfmAutoComplete.dataSources,
|
||||
members: '/group/projects/-/autocomplete_sources/members',
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(window, 'requestIdleCallback').mockImplementation((cb) => cb());
|
||||
|
||||
// We need to mock implement fetchData to prevent
|
||||
// the axios call which is not subject of this test
|
||||
autocompleteDataFetchSpy = jest
|
||||
.spyOn(GfmAutoComplete.prototype, 'fetchData')
|
||||
.mockImplementation(() => 'test');
|
||||
|
||||
testContext.form = $('<form class="gfm-form"><textarea class="js-gfm-input"></form>');
|
||||
testContext.textarea = testContext.form.find('textarea');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.requestIdleCallback.mockRestore();
|
||||
autocompleteDataFetchSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('will call fetchdata if preloadMembers is enabled', () => {
|
||||
window.gl = { ...updatedMockGl };
|
||||
|
||||
testContext.glForm = new GLForm(testContext.form, {}, true, {}, true);
|
||||
jest.runAllTimers();
|
||||
expect(autocompleteDataFetchSpy).toHaveBeenCalledTimes(1);
|
||||
expect(autocompleteDataFetchSpy).toHaveBeenCalledWith(expect.any(Object), '@');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when instantiated', () => {
|
||||
|
|
|
|||
|
|
@ -67,6 +67,9 @@ describe('Markdown field component', () => {
|
|||
showContentEditorSwitcher,
|
||||
supportsQuickActions: true,
|
||||
},
|
||||
provide: {
|
||||
preloadMembers: true,
|
||||
},
|
||||
mocks: {
|
||||
$apollo: {
|
||||
queries: {
|
||||
|
|
@ -93,6 +96,9 @@ describe('Markdown field component', () => {
|
|||
showContentEditorSwitcher: false,
|
||||
autocompleteDataSources,
|
||||
},
|
||||
provide: {
|
||||
preloadMembers: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -131,6 +137,10 @@ describe('Markdown field component', () => {
|
|||
commands: '/foobar/-/autocomplete_sources',
|
||||
});
|
||||
});
|
||||
|
||||
it('initializes GlForm with autocomplete data sources and preload memebers', () => {
|
||||
expect(findGlForm().preloadMembers).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('renders textarea inside backdrop', () => {
|
||||
|
|
|
|||
|
|
@ -1864,6 +1864,46 @@ RSpec.describe API::Commits, feature_category: :source_code_management do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'GET /projects/:id/repository/commits/:sha/sequence' do
|
||||
let(:current_user) { user }
|
||||
let(:commit) { project.repository.commit }
|
||||
let(:commit_id) { commit.id }
|
||||
let(:route) { "/projects/#{project_id}/repository/commits/#{commit_id}/sequence" }
|
||||
|
||||
context 'when commit does not exist' do
|
||||
let(:commit_id) { 'unknown' }
|
||||
|
||||
it_behaves_like '404 response' do
|
||||
let(:request) { get api(route, current_user) }
|
||||
let(:message) { '404 Commit Not Found' }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when commit exists' do
|
||||
it 'returns correct JSON' do
|
||||
expected_count = project.repository.count_commits(ref: commit_id, first_parent: false)
|
||||
|
||||
get api(route, current_user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response['count']).to eq(expected_count)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when commit exists first-parent' do
|
||||
let(:route) { "/projects/#{project_id}/repository/commits/#{commit_id}/sequence?first_parent=true" }
|
||||
|
||||
it 'returns correct JSON' do
|
||||
expected_count = project.repository.count_commits(ref: commit_id, first_parent: true)
|
||||
|
||||
get api(route, current_user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response['count']).to eq(expected_count)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST :id/repository/commits/:sha/cherry_pick' do
|
||||
let(:project) { create(:project, :repository, creator: user, path: 'my.project') }
|
||||
let(:commit) { project.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') }
|
||||
|
|
|
|||
|
|
@ -125,7 +125,6 @@ type testServer struct {
|
|||
writer *multipart.Writer
|
||||
buffer *bytes.Buffer
|
||||
fileWriter io.Writer
|
||||
cleanup func()
|
||||
}
|
||||
|
||||
func setupWithTmpPath(t *testing.T, filename string, includeFormat bool, format string, authResponse *api.Response, bodyProcessor func(w http.ResponseWriter, r *http.Request)) *testServer {
|
||||
|
|
@ -143,10 +142,10 @@ func setupWithTmpPath(t *testing.T, filename string, includeFormat bool, format
|
|||
require.NotNil(t, fileWriter)
|
||||
require.NoError(t, err)
|
||||
|
||||
cleanup := func() {
|
||||
t.Cleanup(func() {
|
||||
ts.Close()
|
||||
require.NoError(t, writer.Close())
|
||||
}
|
||||
})
|
||||
|
||||
qs := ""
|
||||
|
||||
|
|
@ -154,7 +153,7 @@ func setupWithTmpPath(t *testing.T, filename string, includeFormat bool, format
|
|||
qs = fmt.Sprintf("?%s=%s", ArtifactFormatKey, format)
|
||||
}
|
||||
|
||||
return &testServer{url: ts.URL + Path + qs, writer: writer, buffer: &buffer, fileWriter: fileWriter, cleanup: cleanup}
|
||||
return &testServer{url: ts.URL + Path + qs, writer: writer, buffer: &buffer, fileWriter: fileWriter}
|
||||
}
|
||||
|
||||
func testUploadArtifacts(t *testing.T, contentType, url string, body io.Reader) *httptest.ResponseRecorder {
|
||||
|
|
@ -211,7 +210,6 @@ func TestUploadHandlerAddingMetadata(t *testing.T) {
|
|||
require.Contains(t, r.PostForm, "metadata.gitlab-workhorse-upload")
|
||||
},
|
||||
)
|
||||
defer s.cleanup()
|
||||
|
||||
archive := zip.NewWriter(s.fileWriter)
|
||||
file, err := archive.Create("test.file")
|
||||
|
|
@ -241,7 +239,6 @@ func TestUploadHandlerTarArtifact(t *testing.T) {
|
|||
require.Contains(t, r.PostForm, "file.gitlab-workhorse-upload")
|
||||
},
|
||||
)
|
||||
defer s.cleanup()
|
||||
|
||||
file, err := os.Open("../../testdata/tarfile.tar")
|
||||
require.NoError(t, err)
|
||||
|
|
@ -258,7 +255,6 @@ func TestUploadHandlerTarArtifact(t *testing.T) {
|
|||
|
||||
func TestUploadHandlerForUnsupportedArchive(t *testing.T) {
|
||||
s := setupWithTmpPath(t, "file", true, "other", nil, nil)
|
||||
defer s.cleanup()
|
||||
require.NoError(t, s.writer.Close())
|
||||
|
||||
response := testUploadArtifacts(t, s.writer.FormDataContentType(), s.url, s.buffer)
|
||||
|
|
@ -268,7 +264,6 @@ func TestUploadHandlerForUnsupportedArchive(t *testing.T) {
|
|||
|
||||
func TestUploadHandlerForMultipleFiles(t *testing.T) {
|
||||
s := setupWithTmpPath(t, "file", true, "", nil, nil)
|
||||
defer s.cleanup()
|
||||
|
||||
file, err := s.writer.CreateFormFile("file", "my.file")
|
||||
require.NotNil(t, file)
|
||||
|
|
@ -281,7 +276,6 @@ func TestUploadHandlerForMultipleFiles(t *testing.T) {
|
|||
|
||||
func TestUploadFormProcessing(t *testing.T) {
|
||||
s := setupWithTmpPath(t, "metadata", true, "", nil, nil)
|
||||
defer s.cleanup()
|
||||
require.NoError(t, s.writer.Close())
|
||||
|
||||
response := testUploadArtifacts(t, s.writer.FormDataContentType(), s.url, s.buffer)
|
||||
|
|
@ -292,7 +286,6 @@ func TestLsifFileProcessing(t *testing.T) {
|
|||
tempPath := t.TempDir()
|
||||
|
||||
s := setupWithTmpPath(t, "file", true, "zip", &api.Response{TempPath: tempPath, ProcessLsif: true}, nil)
|
||||
defer s.cleanup()
|
||||
|
||||
file, err := os.Open("../../testdata/lsif/valid.lsif.zip")
|
||||
require.NoError(t, err)
|
||||
|
|
@ -311,7 +304,6 @@ func TestInvalidLsifFileProcessing(t *testing.T) {
|
|||
tempPath := t.TempDir()
|
||||
|
||||
s := setupWithTmpPath(t, "file", true, "zip", &api.Response{TempPath: tempPath, ProcessLsif: true}, nil)
|
||||
defer s.cleanup()
|
||||
|
||||
file, err := os.Open("../../testdata/lsif/invalid.lsif.zip")
|
||||
require.NoError(t, err)
|
||||
|
|
|
|||
Loading…
Reference in New Issue