Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a84995f457
commit
6b5d8b17e2
|
|
@ -1 +1 @@
|
|||
93762b621c011fe570339c1c247d5197c2cfefcc
|
||||
2106629e3af3e8949b23f20825d6bfee62c10992
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
14.3.0
|
||||
14.3.1
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://gitlab.com/.gitlab-ci.yml",
|
||||
"title": "Gitlab CI configuration",
|
||||
"description": "Gitlab has a built-in solution for doing CI called Gitlab CI. It is configured by supplying a file called `.gitlab-ci.yml`, which will list all the jobs that are going to run for the project. A full list of all options can be found at https://docs.gitlab.com/ee/ci/yaml/. You can read more about Gitlab CI at https://docs.gitlab.com/ee/ci/README.html.",
|
||||
"markdownDescription": "Gitlab has a built-in solution for doing CI called Gitlab CI. It is configured by supplying a file called `.gitlab-ci.yml`, which will list all the jobs that are going to run for the project. A full list of all options can be found [here](https://docs.gitlab.com/ee/ci/yaml). [Learn More](https://docs.gitlab.com/ee/ci/index.html).",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"$schema": {
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
},
|
||||
"stages": {
|
||||
"type": "array",
|
||||
"description": "Groups jobs into stages. All jobs in one stage must complete before next stage is executed. Defaults to ['build', 'test', 'deploy'].",
|
||||
"markdownDescription": "Groups jobs into stages. All jobs in one stage must complete before next stage is executed. Defaults to ['build', 'test', 'deploy']. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#stages).",
|
||||
"default": ["build", "test", "deploy"],
|
||||
"items": {
|
||||
"type": "string"
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
"minItems": 1
|
||||
},
|
||||
"include": {
|
||||
"description": "Can be `IncludeItem` or `IncludeItem[]`. Each `IncludeItem` will be a string, or an object with properties for the method if including external YAML file. The external content will be fetched, included and evaluated along the `.gitlab-ci.yml`.",
|
||||
"markdownDescription": "Can be `IncludeItem` or `IncludeItem[]`. Each `IncludeItem` will be a string, or an object with properties for the method if including external YAML file. The external content will be fetched, included and evaluated along the `.gitlab-ci.yml`. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#include).",
|
||||
"oneOf": [
|
||||
{ "$ref": "#/definitions/include_item" },
|
||||
{
|
||||
|
|
@ -53,7 +53,7 @@
|
|||
},
|
||||
"pages": {
|
||||
"$ref": "#/definitions/job",
|
||||
"description": "A special job used to upload static sites to Gitlab pages. Requires a `public/` directory with `artifacts.path` pointing to it."
|
||||
"markdownDescription": "A special job used to upload static sites to Gitlab pages. Requires a `public/` directory with `artifacts.path` pointing to it. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#pages)."
|
||||
},
|
||||
"workflow": {
|
||||
"type": "object",
|
||||
|
|
@ -93,12 +93,12 @@
|
|||
"definitions": {
|
||||
"artifacts": {
|
||||
"type": "object",
|
||||
"description": "Used to specify a list of files and directories that should be attached to the job if it succeeds. Artifacts are sent to Gitlab where they can be downloaded.",
|
||||
"markdownDescription": "Used to specify a list of files and directories that should be attached to the job if it succeeds. Artifacts are sent to Gitlab where they can be downloaded. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#artifacts).",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"paths": {
|
||||
"type": "array",
|
||||
"description": "A list of paths to files/folders that should be included in the artifact.",
|
||||
"markdownDescription": "A list of paths to files/folders that should be included in the artifact. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#artifactspaths).",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -106,7 +106,7 @@
|
|||
},
|
||||
"exclude": {
|
||||
"type": "array",
|
||||
"description": "A list of paths to files/folders that should be excluded in the artifact.",
|
||||
"markdownDescription": "A list of paths to files/folders that should be excluded in the artifact. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#artifactsexclude).",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -114,19 +114,19 @@
|
|||
},
|
||||
"expose_as": {
|
||||
"type": "string",
|
||||
"description": "Can be used to expose job artifacts in the merge request UI. GitLab will add a link <expose_as> to the relevant merge request that points to the artifact."
|
||||
"markdownDescription": "Can be used to expose job artifacts in the merge request UI. GitLab will add a link <expose_as> to the relevant merge request that points to the artifact. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#artifactsexpose_as)."
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name for the archive created on job success. Can use variables in the name, e.g. '$CI_JOB_NAME'"
|
||||
"markdownDescription": "Name for the archive created on job success. Can use variables in the name, e.g. '$CI_JOB_NAME' [Learn More](https://docs.gitlab.com/ee/ci/yaml/#artifactsname)."
|
||||
},
|
||||
"untracked": {
|
||||
"type": "boolean",
|
||||
"description": "Whether to add all untracked files (along with 'artifacts.paths') to the artifact.",
|
||||
"markdownDescription": "Whether to add all untracked files (along with 'artifacts.paths') to the artifact. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#artifactsuntracked).",
|
||||
"default": false
|
||||
},
|
||||
"when": {
|
||||
"description": "Configure when artifacts are uploaded depended on job status.",
|
||||
"markdownDescription": "Configure when artifacts are uploaded depended on job status. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#artifactswhen).",
|
||||
"default": "on_success",
|
||||
"oneOf": [
|
||||
{
|
||||
|
|
@ -145,12 +145,12 @@
|
|||
},
|
||||
"expire_in": {
|
||||
"type": "string",
|
||||
"description": "How long artifacts should be kept. They are saved 30 days by default. Artifacts that have expired are removed periodically via cron job. Supports a wide variety of formats, e.g. '1 week', '3 mins 4 sec', '2 hrs 20 min', '2h20min', '6 mos 1 day', '47 yrs 6 mos and 4d', '3 weeks and 2 days'.",
|
||||
"markdownDescription": "How long artifacts should be kept. They are saved 30 days by default. Artifacts that have expired are removed periodically via cron job. Supports a wide variety of formats, e.g. '1 week', '3 mins 4 sec', '2 hrs 20 min', '2h20min', '6 mos 1 day', '47 yrs 6 mos and 4d', '3 weeks and 2 days'. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#artifactsexpire_in).",
|
||||
"default": "30 days"
|
||||
},
|
||||
"reports": {
|
||||
"type": "object",
|
||||
"description": "Reports will be uploaded as artifacts, and often displayed in the Gitlab UI, such as in Merge Requests.",
|
||||
"markdownDescription": "Reports will be uploaded as artifacts, and often displayed in the Gitlab UI, such as in Merge Requests. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#artifactsreports).",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"junit": {
|
||||
|
|
@ -367,11 +367,11 @@
|
|||
"required": ["name"]
|
||||
}
|
||||
],
|
||||
"description": "Specifies the docker image to use for the job or globally for all jobs. Job configuration takes precedence over global setting. Requires a certain kind of Gitlab runner executor."
|
||||
"markdownDescription": "Specifies the docker image to use for the job or globally for all jobs. Job configuration takes precedence over global setting. Requires a certain kind of Gitlab runner executor. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#image)."
|
||||
},
|
||||
"services": {
|
||||
"type": "array",
|
||||
"description": "Similar to `image` property, but will link the specified services to the `image` container.",
|
||||
"markdownDescription": "Similar to `image` property, but will link the specified services to the `image` container. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#services).",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
|
|
@ -418,7 +418,7 @@
|
|||
},
|
||||
"secrets": {
|
||||
"type": "object",
|
||||
"description": "Defines secrets to be injected as environment variables",
|
||||
"markdownDescription": "Defines secrets to be injected as environment variables. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#secrets).",
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"description": "Environment variable name",
|
||||
|
|
@ -453,7 +453,7 @@
|
|||
},
|
||||
"before_script": {
|
||||
"type": "array",
|
||||
"description": "Defines scripts that should run *before* the job. Can be set globally or per job.",
|
||||
"markdownDescription": "Defines scripts that should run *before* the job. Can be set globally or per job. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#before_script).",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
|
@ -470,7 +470,7 @@
|
|||
},
|
||||
"after_script": {
|
||||
"type": "array",
|
||||
"description": "Defines scripts that should run *after* the job. Can be set globally or per job.",
|
||||
"markdownDescription": "Defines scripts that should run *after* the job. Can be set globally or per job. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#after_script).",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
|
@ -487,7 +487,7 @@
|
|||
},
|
||||
"rules": {
|
||||
"type": "array",
|
||||
"description": "Rules allows for an array of individual rule objects to be evaluated in order, until one matches and dynamically provides attributes to the job.",
|
||||
"markdownDescription": "Rules allows for an array of individual rule objects to be evaluated in order, until one matches and dynamically provides attributes to the job. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#rules).",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
|
|
@ -503,7 +503,7 @@
|
|||
}
|
||||
},
|
||||
"globalVariables": {
|
||||
"description": "Defines environment variables globally. Job level property overrides global variables. If a job sets `variables: {}`, all global variables are turned off. You can use the value and description keywords to define variables that are prefilled when running a pipeline manually.",
|
||||
"markdownDescription": "Defines environment variables globally. Job level property overrides global variables. If a job sets `variables: {}`, all global variables are turned off. You can use the value and description keywords to define variables that are prefilled when running a pipeline manually. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#variables).",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"anyOf": [
|
||||
|
|
@ -523,41 +523,41 @@
|
|||
},
|
||||
"if": {
|
||||
"type": "string",
|
||||
"description": "Expression to evaluate whether additional attributes should be provided to the job"
|
||||
"markdownDescription": "Expression to evaluate whether additional attributes should be provided to the job. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#rulesif)."
|
||||
},
|
||||
"changes": {
|
||||
"type": "array",
|
||||
"description": "Additional attributes will be provided to job if any of the provided paths matches a modified file",
|
||||
"markdownDescription": "Additional attributes will be provided to job if any of the provided paths matches a modified file. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#ruleschanges).",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"exists": {
|
||||
"type": "array",
|
||||
"description": "Additional attributes will be provided to job if any of the provided paths matches an existing file in the repository",
|
||||
"markdownDescription": "Additional attributes will be provided to job if any of the provided paths matches an existing file in the repository. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#rulesexists).",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"type": "object",
|
||||
"description": "Defines environment variables for specific jobs. Job level property overrides global variables. If a job sets `variables: {}`, all global variables are turned off.",
|
||||
"markdownDescription": "Defines environment variables for specific jobs. Job level property overrides global variables. If a job sets `variables: {}`, all global variables are turned off. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#rulesvariables).",
|
||||
"additionalProperties": {
|
||||
"type": ["string", "integer"]
|
||||
}
|
||||
},
|
||||
"timeout": {
|
||||
"type": "string",
|
||||
"description": "Allows you to configure a timeout for a specific job (e.g. `1 minute`, `1h 30m 12s`). Read more: https://docs.gitlab.com/ee/ci/yaml/README.html#timeout",
|
||||
"markdownDescription": "Allows you to configure a timeout for a specific job (e.g. `1 minute`, `1h 30m 12s`). [Learn More](https://docs.gitlab.com/ee/ci/yaml/index.html#timeout).",
|
||||
"minLength": 1
|
||||
},
|
||||
"start_in": {
|
||||
"type": "string",
|
||||
"description": "Used in conjunction with 'when: delayed' to set how long to delay before starting a job. e.g. '5', 5 seconds, 30 minutes, 1 week, etc. Read more: https://docs.gitlab.com/ee/ci/jobs/job_control.html#run-a-job-after-a-delay",
|
||||
"markdownDescription": "Used in conjunction with 'when: delayed' to set how long to delay before starting a job. e.g. '5', 5 seconds, 30 minutes, 1 week, etc. [Learn More](https://docs.gitlab.com/ee/ci/jobs/job_control.html#run-a-job-after-a-delay).",
|
||||
"minLength": 1
|
||||
},
|
||||
"allow_failure": {
|
||||
"description": "Allow job to fail. A failed job does not cause the pipeline to fail.",
|
||||
"markdownDescription": "Allow job to fail. A failed job does not cause the pipeline to fail. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#allow_failure).",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Setting this option to true will allow the job to fail while still letting the pipeline pass.",
|
||||
|
|
@ -594,7 +594,7 @@
|
|||
]
|
||||
},
|
||||
"when": {
|
||||
"description": "Describes the conditions for when to run the job. Defaults to 'on_success'.",
|
||||
"markdownDescription": "Describes the conditions for when to run the job. Defaults to 'on_success'.",
|
||||
"default": "on_success",
|
||||
"oneOf": [
|
||||
{
|
||||
|
|
@ -611,11 +611,11 @@
|
|||
},
|
||||
{
|
||||
"enum": ["manual"],
|
||||
"description": "Execute the job manually from Gitlab UI or API. Read more: https://docs.gitlab.com/ee/ci/yaml/#when-manual"
|
||||
"markdownDescription": "Execute the job manually from Gitlab UI or API. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#when)."
|
||||
},
|
||||
{
|
||||
"enum": ["delayed"],
|
||||
"description": "Execute a job after the time limit in 'start_in' expires. Read more: https://docs.gitlab.com/ee/ci/yaml/#when-delayed"
|
||||
"markdownDescription": "Execute a job after the time limit in 'start_in' expires. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#when)."
|
||||
},
|
||||
{
|
||||
"enum": ["never"],
|
||||
|
|
@ -626,7 +626,7 @@
|
|||
"cache": {
|
||||
"properties": {
|
||||
"when": {
|
||||
"description": "Defines when to save the cache, based on the status of the job.",
|
||||
"markdownDescription": "Defines when to save the cache, based on the status of the job. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#cachewhen).",
|
||||
"default": "on_success",
|
||||
"oneOf": [
|
||||
{
|
||||
|
|
@ -778,7 +778,7 @@
|
|||
},
|
||||
"variables": {
|
||||
"type": "array",
|
||||
"description": "Filter job by checking comparing values of environment variables. Read more about variable expressions: https://docs.gitlab.com/ee/ci/variables/README.html#variables-expressions",
|
||||
"markdownDescription": "Filter job by checking comparing values of CI/CD variables. [Learn More](https://docs.gitlab.com/ee/ci/jobs/job_control.html#cicd-variable-expressions).",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
|
|
@ -795,7 +795,7 @@
|
|||
]
|
||||
},
|
||||
"retry": {
|
||||
"description": "Retry a job if it fails. Can be a simple integer or object definition.",
|
||||
"markdownDescription": "Retry a job if it fails. Can be a simple integer or object definition. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#retry).",
|
||||
"oneOf": [
|
||||
{ "$ref": "#/definitions/retry_max" },
|
||||
{
|
||||
|
|
@ -804,7 +804,7 @@
|
|||
"properties": {
|
||||
"max": { "$ref": "#/definitions/retry_max" },
|
||||
"when": {
|
||||
"description": "Either a single or array of error types to trigger job retry.",
|
||||
"markdownDescription": "Either a single or array of error types to trigger job retry. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#retrywhen).",
|
||||
"oneOf": [
|
||||
{ "$ref": "#/definitions/retry_errors" },
|
||||
{
|
||||
|
|
@ -884,7 +884,7 @@
|
|||
},
|
||||
"interruptible": {
|
||||
"type": "boolean",
|
||||
"description": "Interruptible is used to indicate that a job should be canceled if made redundant by a newer pipeline run.",
|
||||
"markdownDescription": "Interruptible is used to indicate that a job should be canceled if made redundant by a newer pipeline run. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#interruptible).",
|
||||
"default": false
|
||||
},
|
||||
"job": {
|
||||
|
|
@ -1241,11 +1241,11 @@
|
|||
"description": "Limit job concurrency. Can be used to ensure that the Runner will not run certain jobs simultaneously."
|
||||
},
|
||||
"trigger": {
|
||||
"description": "Trigger allows you to define downstream pipeline trigger. When a job created from trigger definition is started by GitLab, a downstream pipeline gets created. Read more: https://docs.gitlab.com/ee/ci/yaml/README.html#trigger",
|
||||
"markdownDescription": "Trigger allows you to define downstream pipeline trigger. When a job created from trigger definition is started by GitLab, a downstream pipeline gets created. [Learn More](https://docs.gitlab.com/ee/ci/yaml/index.html#trigger).",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"description": "Trigger a multi-project pipeline. Read more: https://docs.gitlab.com/ee/ci/pipelines/multi_project_pipelines.html#specify-a-downstream-pipeline-branch",
|
||||
"markdownDescription": "Trigger a multi-project pipeline. [Learn More](https://docs.gitlab.com/ee/ci/pipelines/multi_project_pipelines.html#specify-a-downstream-pipeline-branch).",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"project": {
|
||||
|
|
@ -1287,7 +1287,7 @@
|
|||
},
|
||||
{
|
||||
"type": "object",
|
||||
"description": "Trigger a child pipeline. Read more: https://docs.gitlab.com/ee/ci/pipelines/parent_child_pipelines.html",
|
||||
"description": "Trigger a child pipeline. [Learn More](https://docs.gitlab.com/ee/ci/pipelines/parent_child_pipelines.html).",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"include": {
|
||||
|
|
@ -1398,7 +1398,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"description": "Path to the project, e.g. `group/project`, or `group/sub-group/project`. Read more: https://docs.gitlab.com/ee/ci/pipelines/multi_project_pipelines.html#define-multi-project-pipelines-in-your-gitlab-ciyml-file",
|
||||
"markdownDescription": "Path to the project, e.g. `group/project`, or `group/sub-group/project`. [Learn More](https://docs.gitlab.com/ee/ci/pipelines/multi_project_pipelines.html#define-multi-project-pipelines-in-your-gitlab-ciyml-file).",
|
||||
"type": "string",
|
||||
"pattern": "\\S/\\S"
|
||||
}
|
||||
|
|
@ -1406,10 +1406,10 @@
|
|||
},
|
||||
"inherit": {
|
||||
"type": "object",
|
||||
"description": "Controls inheritance of globally-defined defaults and variables. Boolean values control inheritance of all default: or variables: keywords. To inherit only a subset of default: or variables: keywords, specify what you wish to inherit. Anything not listed is not inherited.",
|
||||
"markdownDescription": "Controls inheritance of globally-defined defaults and variables. Boolean values control inheritance of all default: or variables: keywords. To inherit only a subset of default: or variables: keywords, specify what you wish to inherit. Anything not listed is not inherited. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#inherit).",
|
||||
"properties": {
|
||||
"default": {
|
||||
"description": "Whether to inherit all globally-defined defaults or not. Or subset of inherited defaults",
|
||||
"markdownDescription": "Whether to inherit all globally-defined defaults or not. Or subset of inherited defaults. [Learn more](https://docs.gitlab.com/ee/ci/yaml/#inheritdefault).",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
|
|
@ -1435,7 +1435,7 @@
|
|||
]
|
||||
},
|
||||
"variables": {
|
||||
"description": "Whether to inherit all globally-defined variables or not. Or subset of inherited variables",
|
||||
"markdownDescription": "Whether to inherit all globally-defined variables or not. Or subset of inherited variables. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#inheritvariables).",
|
||||
"oneOf": [
|
||||
{ "type": "boolean" },
|
||||
{
|
||||
|
|
@ -1470,7 +1470,7 @@
|
|||
},
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"description": "Used to select runners from the list of available runners. A runner must have all tags listed here to run the job.",
|
||||
"markdownDescription": "Used to select runners from the list of available runners. A runner must have all tags listed here to run the job. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#tags).",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ function getFallbackKey() {
|
|||
|
||||
export default class IssuableForm {
|
||||
constructor(form) {
|
||||
if (form.length === 0) {
|
||||
return;
|
||||
}
|
||||
this.form = form;
|
||||
this.toggleWip = this.toggleWip.bind(this);
|
||||
this.renderWipExplanation = this.renderWipExplanation.bind(this);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import CsvImportExportButtons from '~/issuable/components/csv_import_export_butt
|
|||
import IssuableByEmail from '~/issuable/components/issuable_by_email.vue';
|
||||
import { IssuableStatus } from '~/issues/constants';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { isPositiveInteger } from '~/lib/utils/number_utils';
|
||||
import { scrollUp } from '~/lib/utils/scroll_utils';
|
||||
import { getParameterByName, joinPaths } from '~/lib/utils/url_utility';
|
||||
import {
|
||||
|
|
@ -45,6 +46,8 @@ import {
|
|||
ISSUE_REFERENCE,
|
||||
MAX_LIST_SIZE,
|
||||
PAGE_SIZE,
|
||||
PARAM_FIRST_PAGE_SIZE,
|
||||
PARAM_LAST_PAGE_SIZE,
|
||||
PARAM_PAGE_AFTER,
|
||||
PARAM_PAGE_BEFORE,
|
||||
PARAM_SORT,
|
||||
|
|
@ -390,12 +393,14 @@ export default {
|
|||
},
|
||||
urlParams() {
|
||||
return {
|
||||
page_after: this.pageParams.afterCursor,
|
||||
page_before: this.pageParams.beforeCursor,
|
||||
search: this.searchQuery,
|
||||
sort: urlSortParams[this.sortKey],
|
||||
state: this.state,
|
||||
...this.urlFilterParams,
|
||||
first_page_size: this.pageParams.firstPageSize,
|
||||
last_page_size: this.pageParams.lastPageSize,
|
||||
page_after: this.pageParams.afterCursor,
|
||||
page_before: this.pageParams.beforeCursor,
|
||||
};
|
||||
},
|
||||
hasCrmParameter() {
|
||||
|
|
@ -632,6 +637,8 @@ export default {
|
|||
this.showBulkEditSidebar = showBulkEditSidebar;
|
||||
},
|
||||
updateData(sortValue) {
|
||||
const firstPageSize = getParameterByName(PARAM_FIRST_PAGE_SIZE);
|
||||
const lastPageSize = getParameterByName(PARAM_LAST_PAGE_SIZE);
|
||||
const pageAfter = getParameterByName(PARAM_PAGE_AFTER);
|
||||
const pageBefore = getParameterByName(PARAM_PAGE_BEFORE);
|
||||
const state = getParameterByName(PARAM_STATE);
|
||||
|
|
@ -660,7 +667,13 @@ export default {
|
|||
|
||||
this.exportCsvPathWithQuery = this.getExportCsvPathWithQuery();
|
||||
this.filterTokens = isSearchDisabled ? [] : getFilterTokens(window.location.search);
|
||||
this.pageParams = getInitialPageParams(sortKey, pageAfter, pageBefore);
|
||||
this.pageParams = getInitialPageParams(
|
||||
sortKey,
|
||||
isPositiveInteger(firstPageSize) ? parseInt(firstPageSize, 10) : undefined,
|
||||
isPositiveInteger(lastPageSize) ? parseInt(lastPageSize, 10) : undefined,
|
||||
pageAfter,
|
||||
pageBefore,
|
||||
);
|
||||
this.sortKey = sortKey;
|
||||
this.state = state || IssuableStates.Opened;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ export const MAX_LIST_SIZE = 10;
|
|||
export const PAGE_SIZE = 20;
|
||||
export const PAGE_SIZE_MANUAL = 100;
|
||||
export const PARAM_ASSIGNEE_ID = 'assignee_id';
|
||||
export const PARAM_FIRST_PAGE_SIZE = 'first_page_size';
|
||||
export const PARAM_LAST_PAGE_SIZE = 'last_page_size';
|
||||
export const PARAM_PAGE_AFTER = 'page_after';
|
||||
export const PARAM_PAGE_BEFORE = 'page_before';
|
||||
export const PARAM_SORT = 'sort';
|
||||
|
|
|
|||
|
|
@ -46,8 +46,15 @@ import {
|
|||
WEIGHT_DESC,
|
||||
} from './constants';
|
||||
|
||||
export const getInitialPageParams = (sortKey, afterCursor, beforeCursor) => ({
|
||||
firstPageSize: sortKey === RELATIVE_POSITION_ASC ? PAGE_SIZE_MANUAL : PAGE_SIZE,
|
||||
export const getInitialPageParams = (
|
||||
sortKey,
|
||||
firstPageSize = sortKey === RELATIVE_POSITION_ASC ? PAGE_SIZE_MANUAL : PAGE_SIZE,
|
||||
lastPageSize,
|
||||
afterCursor,
|
||||
beforeCursor,
|
||||
) => ({
|
||||
firstPageSize: lastPageSize ? undefined : firstPageSize,
|
||||
lastPageSize,
|
||||
afterCursor,
|
||||
beforeCursor,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import {
|
|||
NOT_AVAILABLE_TEXT,
|
||||
NOT_AVAILABLE_SIZE,
|
||||
MORE_ACTIONS_TEXT,
|
||||
COPY_IMAGE_PATH_TITLE,
|
||||
} from '../../constants/index';
|
||||
|
||||
export default {
|
||||
|
|
@ -72,6 +73,7 @@ export default {
|
|||
CONFIGURATION_DETAILS_ROW_TEST,
|
||||
MISSING_MANIFEST_WARNING_TOOLTIP,
|
||||
MORE_ACTIONS_TEXT,
|
||||
COPY_IMAGE_PATH_TITLE,
|
||||
},
|
||||
computed: {
|
||||
formattedSize() {
|
||||
|
|
@ -138,7 +140,7 @@ export default {
|
|||
|
||||
<clipboard-button
|
||||
v-if="tag.location"
|
||||
:title="tag.location"
|
||||
:title="$options.i18n.COPY_IMAGE_PATH_TITLE"
|
||||
:text="tag.location"
|
||||
category="tertiary"
|
||||
:disabled="disabled"
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import {
|
|||
IMAGE_FAILED_DELETED_STATUS,
|
||||
IMAGE_MIGRATING_STATE,
|
||||
ROOT_IMAGE_TEXT,
|
||||
COPY_IMAGE_PATH_TITLE,
|
||||
} from '../../constants/index';
|
||||
import DeleteButton from '../delete_button.vue';
|
||||
import CleanupStatus from './cleanup_status.vue';
|
||||
|
|
@ -52,6 +53,7 @@ export default {
|
|||
i18n: {
|
||||
REMOVE_REPOSITORY_LABEL,
|
||||
ROW_SCHEDULED_FOR_DELETION,
|
||||
COPY_IMAGE_PATH_TITLE,
|
||||
},
|
||||
computed: {
|
||||
disabledDelete() {
|
||||
|
|
@ -115,7 +117,7 @@ export default {
|
|||
v-if="item.location"
|
||||
:disabled="deleting"
|
||||
:text="item.location"
|
||||
:title="item.location"
|
||||
:title="$options.i18n.COPY_IMAGE_PATH_TITLE"
|
||||
category="tertiary"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ export const EMPTY_RESULT_MESSAGE = s__(
|
|||
'ContainerRegistry|To widen your search, change or remove the filters above.',
|
||||
);
|
||||
|
||||
export const COPY_IMAGE_PATH_TITLE = s__('ContainerRegistry|Copy image path');
|
||||
|
||||
// Parameters
|
||||
|
||||
export const IMAGE_DELETE_SCHEDULED_STATUS = 'DELETE_SCHEDULED';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<script>
|
||||
import { GlButton } from '@gitlab/ui';
|
||||
import getAppStatus from '~/pipeline_editor/graphql/queries/client/app_status.query.graphql';
|
||||
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import { EDITOR_APP_STATUS_EMPTY, EDITOR_APP_STATUS_LOADING } from '../../constants';
|
||||
import FileTreePopover from '../popovers/file_tree_popover.vue';
|
||||
import BranchSwitcher from './branch_switcher.vue';
|
||||
|
|
@ -12,7 +11,6 @@ export default {
|
|||
FileTreePopover,
|
||||
GlButton,
|
||||
},
|
||||
mixins: [glFeatureFlagMixin()],
|
||||
props: {
|
||||
hasUnsavedChanges: {
|
||||
type: Boolean,
|
||||
|
|
@ -43,11 +41,7 @@ export default {
|
|||
return this.appStatus === EDITOR_APP_STATUS_LOADING;
|
||||
},
|
||||
showFileTreeToggle() {
|
||||
return (
|
||||
this.glFeatures.pipelineEditorFileTree &&
|
||||
!this.isNewCiConfigFile &&
|
||||
this.appStatus !== EDITOR_APP_STATUS_EMPTY
|
||||
);
|
||||
return !this.isNewCiConfigFile && this.appStatus !== EDITOR_APP_STATUS_EMPTY;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<script>
|
||||
import { GlModal } from '@gitlab/ui';
|
||||
import { __ } from '~/locale';
|
||||
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import CommitSection from './components/commit/commit_section.vue';
|
||||
import PipelineEditorDrawer from './components/drawer/pipeline_editor_drawer.vue';
|
||||
import PipelineEditorFileNav from './components/file_nav/pipeline_editor_file_nav.vue';
|
||||
|
|
@ -34,7 +33,6 @@ export default {
|
|||
PipelineEditorHeader,
|
||||
PipelineEditorTabs,
|
||||
},
|
||||
mixins: [glFeatureFlagMixin()],
|
||||
props: {
|
||||
ciConfigData: {
|
||||
type: Object,
|
||||
|
|
@ -76,9 +74,6 @@ export default {
|
|||
includesFiles() {
|
||||
return this.ciConfigData?.includes || [];
|
||||
},
|
||||
isFileTreeVisible() {
|
||||
return this.showFileTree && this.glFeatures.pipelineEditorFileTree;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.showFileTree = JSON.parse(localStorage.getItem(FILE_TREE_DISPLAY_KEY)) || false;
|
||||
|
|
@ -140,7 +135,7 @@ export default {
|
|||
/>
|
||||
<div class="gl-display-flex gl-w-full gl-sm-flex-direction-column">
|
||||
<pipeline-editor-file-tree
|
||||
v-if="isFileTreeVisible"
|
||||
v-if="showFileTree"
|
||||
class="gl-flex-shrink-0"
|
||||
:includes="includesFiles"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -98,10 +98,10 @@ export default {
|
|||
|
||||
<template>
|
||||
<div data-qa-selector="approvals_summary_content">
|
||||
<strong>{{ approvalLeftMessage }}</strong>
|
||||
<span class="gl-font-weight-bold">{{ approvalLeftMessage }}</span>
|
||||
<template v-if="hasApprovers">
|
||||
<span v-if="approvalLeftMessage">{{ message }}</span>
|
||||
<strong v-else>{{ message }}</strong>
|
||||
<span v-else class="gl-font-weight-bold">{{ message }}</span>
|
||||
<user-avatar-list
|
||||
class="gl-display-inline-block gl-vertical-align-middle"
|
||||
:img-size="24"
|
||||
|
|
|
|||
|
|
@ -234,6 +234,8 @@
|
|||
|
||||
.navbar-sub-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
margin: 0 0 0 6px;
|
||||
|
||||
.dropdown-chevron {
|
||||
|
|
|
|||
|
|
@ -439,7 +439,7 @@ $browser-scrollbar-size: 10px;
|
|||
/*
|
||||
* Misc
|
||||
*/
|
||||
$header-height: var(--header-height, 40px);
|
||||
$header-height: var(--header-height, 48px);
|
||||
$header-zindex: 1000;
|
||||
$zindex-dropdown-menu: 300;
|
||||
$suggestion-header-height: 46px;
|
||||
|
|
|
|||
|
|
@ -755,7 +755,7 @@ input {
|
|||
padding: 0 16px;
|
||||
z-index: 1000;
|
||||
margin-bottom: 0;
|
||||
min-height: var(--header-height, 40px);
|
||||
min-height: var(--header-height, 48px);
|
||||
border: 0;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
|
@ -771,7 +771,7 @@ input {
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
min-height: var(--header-height, 40px);
|
||||
min-height: var(--header-height, 48px);
|
||||
padding-left: 0;
|
||||
}
|
||||
.navbar-gitlab .header-content .title {
|
||||
|
|
@ -787,9 +787,6 @@ input {
|
|||
.navbar-gitlab .header-content .title img {
|
||||
height: 24px;
|
||||
}
|
||||
.navbar-gitlab .header-content .title img + .logo-text {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.navbar-gitlab .header-content .title a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -915,6 +912,8 @@ input {
|
|||
}
|
||||
.navbar-sub-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
margin: 0 0 0 6px;
|
||||
}
|
||||
.caret-down,
|
||||
|
|
@ -1034,7 +1033,7 @@ input {
|
|||
left: 0;
|
||||
z-index: 600;
|
||||
width: 220px;
|
||||
top: var(--header-height, 40px);
|
||||
top: var(--header-height, 48px);
|
||||
background-color: #303030;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
|
@ -2044,19 +2043,9 @@ body.gl-dark {
|
|||
.gl-display-none {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.gl-lg-display-none\! {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.gl-display-flex {
|
||||
display: flex;
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.gl-lg-display-flex {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.gl-sm-display-block {
|
||||
display: block;
|
||||
|
|
|
|||
|
|
@ -740,7 +740,7 @@ input {
|
|||
padding: 0 16px;
|
||||
z-index: 1000;
|
||||
margin-bottom: 0;
|
||||
min-height: var(--header-height, 40px);
|
||||
min-height: var(--header-height, 48px);
|
||||
border: 0;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
|
@ -756,7 +756,7 @@ input {
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
min-height: var(--header-height, 40px);
|
||||
min-height: var(--header-height, 48px);
|
||||
padding-left: 0;
|
||||
}
|
||||
.navbar-gitlab .header-content .title {
|
||||
|
|
@ -772,9 +772,6 @@ input {
|
|||
.navbar-gitlab .header-content .title img {
|
||||
height: 24px;
|
||||
}
|
||||
.navbar-gitlab .header-content .title img + .logo-text {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.navbar-gitlab .header-content .title a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -900,6 +897,8 @@ input {
|
|||
}
|
||||
.navbar-sub-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
margin: 0 0 0 6px;
|
||||
}
|
||||
.caret-down,
|
||||
|
|
@ -1019,7 +1018,7 @@ input {
|
|||
left: 0;
|
||||
z-index: 600;
|
||||
width: 220px;
|
||||
top: var(--header-height, 40px);
|
||||
top: var(--header-height, 48px);
|
||||
background-color: #f0f0f0;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
|
@ -1704,19 +1703,9 @@ svg.s16 {
|
|||
.gl-display-none {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.gl-lg-display-none\! {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.gl-display-flex {
|
||||
display: flex;
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.gl-lg-display-flex {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.gl-sm-display-block {
|
||||
display: block;
|
||||
|
|
|
|||
|
|
@ -419,7 +419,7 @@ body.navless {
|
|||
}
|
||||
}
|
||||
.navless-container {
|
||||
margin-top: var(--header-height, 40px);
|
||||
margin-top: var(--header-height, 48px);
|
||||
padding-top: 32px;
|
||||
}
|
||||
.btn {
|
||||
|
|
@ -506,7 +506,7 @@ label.label-bold {
|
|||
}
|
||||
.navbar-empty {
|
||||
justify-content: center;
|
||||
height: var(--header-height, 40px);
|
||||
height: var(--header-height, 48px);
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #dbdbdb;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Mailgun
|
||||
class WebhooksController < ApplicationController
|
||||
respond_to :json
|
||||
|
||||
skip_before_action :authenticate_user!
|
||||
skip_before_action :verify_authenticity_token
|
||||
|
||||
before_action :ensure_feature_enabled!
|
||||
before_action :authenticate_signature!
|
||||
|
||||
feature_category :team_planning
|
||||
|
||||
WEBHOOK_PROCESSORS = [
|
||||
::Members::Mailgun::ProcessWebhookService
|
||||
].freeze
|
||||
|
||||
def process_webhook
|
||||
WEBHOOK_PROCESSORS.each do |processor_class|
|
||||
processor = processor_class.new(params['event-data'] || {})
|
||||
processor.execute if processor.should_process?
|
||||
end
|
||||
|
||||
head :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensure_feature_enabled!
|
||||
render_406 unless Gitlab::CurrentSettings.mailgun_events_enabled?
|
||||
end
|
||||
|
||||
def authenticate_signature!
|
||||
access_denied! unless valid_signature?
|
||||
end
|
||||
|
||||
def valid_signature?
|
||||
return false if Gitlab::CurrentSettings.mailgun_signing_key.blank?
|
||||
|
||||
# per this guide: https://documentation.mailgun.com/en/latest/user_manual.html#webhooks
|
||||
digest = OpenSSL::Digest.new('SHA256')
|
||||
data = [params.dig(:signature, :timestamp), params.dig(:signature, :token)].join
|
||||
|
||||
hmac_digest = OpenSSL::HMAC.hexdigest(digest, Gitlab::CurrentSettings.mailgun_signing_key, data)
|
||||
|
||||
ActiveSupport::SecurityUtils.secure_compare(params.dig(:signature, :signature), hmac_digest)
|
||||
end
|
||||
|
||||
def render_406
|
||||
# failure to stop retries per https://documentation.mailgun.com/en/latest/user_manual.html#webhooks
|
||||
head :not_acceptable
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Members
|
||||
module Mailgun
|
||||
class PermanentFailuresController < ApplicationController
|
||||
respond_to :json
|
||||
|
||||
skip_before_action :authenticate_user!
|
||||
skip_before_action :verify_authenticity_token
|
||||
|
||||
before_action :ensure_feature_enabled!
|
||||
before_action :authenticate_signature!
|
||||
before_action :validate_invite_email!
|
||||
|
||||
feature_category :authentication_and_authorization
|
||||
|
||||
def create
|
||||
webhook_processor.execute
|
||||
|
||||
head :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensure_feature_enabled!
|
||||
render_406 unless Gitlab::CurrentSettings.mailgun_events_enabled?
|
||||
end
|
||||
|
||||
def authenticate_signature!
|
||||
access_denied! unless valid_signature?
|
||||
end
|
||||
|
||||
def valid_signature?
|
||||
return false if Gitlab::CurrentSettings.mailgun_signing_key.blank?
|
||||
|
||||
# per this guide: https://documentation.mailgun.com/en/latest/user_manual.html#webhooks
|
||||
digest = OpenSSL::Digest.new('SHA256')
|
||||
data = [params.dig(:signature, :timestamp), params.dig(:signature, :token)].join
|
||||
|
||||
hmac_digest = OpenSSL::HMAC.hexdigest(digest, Gitlab::CurrentSettings.mailgun_signing_key, data)
|
||||
|
||||
ActiveSupport::SecurityUtils.secure_compare(params.dig(:signature, :signature), hmac_digest)
|
||||
end
|
||||
|
||||
def validate_invite_email!
|
||||
# permanent_failures webhook does not provide a way to filter failures, so we'll get them all on this endpoint
|
||||
# and we only care about our invite_emails
|
||||
render_406 unless payload[:tags]&.include?(::Members::Mailgun::INVITE_EMAIL_TAG)
|
||||
end
|
||||
|
||||
def webhook_processor
|
||||
::Members::Mailgun::ProcessWebhookService.new(payload)
|
||||
end
|
||||
|
||||
def payload
|
||||
@payload ||= params.permit!['event-data']
|
||||
end
|
||||
|
||||
def render_406
|
||||
# failure to stop retries per https://documentation.mailgun.com/en/latest/user_manual.html#webhooks
|
||||
head :not_acceptable
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -4,7 +4,6 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController
|
|||
before_action :check_can_collaborate!
|
||||
before_action do
|
||||
push_frontend_feature_flag(:schema_linting, @project)
|
||||
push_frontend_feature_flag(:pipeline_editor_file_tree, @project)
|
||||
end
|
||||
|
||||
feature_category :pipeline_authoring
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ module ResolvesMergeRequests
|
|||
security_auto_fix: [:author],
|
||||
head_pipeline: [:merge_request_diff, { head_pipeline: [:merge_request] }],
|
||||
timelogs: [:timelogs],
|
||||
pipelines: [:merge_request_diffs], # used by `recent_diff_head_shas` to load pipelines
|
||||
committers: [merge_request_diff: [:merge_request_diff_commits]]
|
||||
}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -21,8 +21,9 @@ module Resolvers
|
|||
super
|
||||
end
|
||||
|
||||
def query_for(args)
|
||||
resolve_pipelines(project, args).merge(merge_request.all_pipelines)
|
||||
def query_for(input)
|
||||
mr, args = input
|
||||
resolve_pipelines(mr.source_project, args).merge(mr.all_pipelines)
|
||||
end
|
||||
|
||||
def model_class
|
||||
|
|
@ -30,7 +31,7 @@ module Resolvers
|
|||
end
|
||||
|
||||
def query_input(**args)
|
||||
args
|
||||
[merge_request, args]
|
||||
end
|
||||
|
||||
def project
|
||||
|
|
|
|||
|
|
@ -1696,7 +1696,12 @@ class MergeRequest < ApplicationRecord
|
|||
service_class.new(project, current_user, id: id, report_type: report_type).execute(comparison_base_pipeline(identifier), actual_head_pipeline)
|
||||
end
|
||||
|
||||
def recent_diff_head_shas(limit = 100)
|
||||
MAX_RECENT_DIFF_HEAD_SHAS = 100
|
||||
|
||||
def recent_diff_head_shas(limit = MAX_RECENT_DIFF_HEAD_SHAS)
|
||||
# see MergeRequestDiff.recent
|
||||
return merge_request_diffs.to_a.sort_by(&:id).reverse.first(limit).pluck(:head_commit_sha) if merge_request_diffs.loaded?
|
||||
|
||||
merge_request_diffs.recent(limit).pluck(:head_commit_sha)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ module Members
|
|||
Gitlab::ErrorTracking.track_exception(e)
|
||||
end
|
||||
|
||||
def should_process?
|
||||
payload['event'] == 'failed' && payload['severity'] == 'permanent' && payload['tags']&.include?(::Members::Mailgun::INVITE_EMAIL_TAG)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :payload, :member
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ module Projects
|
|||
|
||||
validate_state!
|
||||
validate_max_size!
|
||||
validate_public_folder!
|
||||
validate_max_entries!
|
||||
|
||||
build.artifacts_file.use_file do |artifacts_path|
|
||||
|
|
@ -180,6 +181,10 @@ module Projects
|
|||
end
|
||||
end
|
||||
|
||||
def validate_public_folder!
|
||||
raise InvalidStateError, 'Error: The `public/` folder is missing, or not declared in `.gitlab-ci.yml`.' unless total_size > 0
|
||||
end
|
||||
|
||||
def entries_count
|
||||
# we're using the full archive and pages daemon needs to read it
|
||||
# so we want the total count from entries, not only "public/" directory
|
||||
|
|
|
|||
|
|
@ -9,10 +9,7 @@
|
|||
%h1.title
|
||||
%span.gl-sr-only GitLab
|
||||
= link_to root_path, title: _('Dashboard'), id: 'logo', **tracking_attrs('main_navigation', 'click_gitlab_logo_link', 'navigation') do
|
||||
%span{ :class => "gl-display-none gl-lg-display-flex" }
|
||||
= brand_header_logo({add_gitlab_white_text: true})
|
||||
%span{ :class => "gl-lg-display-none! gl-display-flex" }
|
||||
= brand_header_logo
|
||||
= brand_header_logo
|
||||
- if Gitlab.com_and_canary?
|
||||
= link_to Gitlab::Saas.canary_toggle_com_url, class: 'canary-badge bg-transparent', data: { qa_selector: 'canary_badge_link' }, target: :_blank, rel: 'noopener noreferrer' do
|
||||
= gl_badge_tag({ variant: :success, size: :sm }) do
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
- page_title _('Edit Release')
|
||||
- add_to_breadcrumbs _('Releases'), project_releases_path(@project)
|
||||
- add_to_breadcrumbs @release.name, project_release_path(@project, @release)
|
||||
|
||||
#js-edit-release-page{ data: data_for_edit_release_page }
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ module Database
|
|||
|
||||
include ApplicationWorker
|
||||
include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
LEASE_TIMEOUT_MULTIPLIER = 3
|
||||
MINIMUM_LEASE_TIMEOUT = 10.minutes.freeze
|
||||
|
|
@ -44,6 +45,15 @@ module Database
|
|||
return
|
||||
end
|
||||
|
||||
if shares_db_config?
|
||||
Sidekiq.logger.info(
|
||||
class: self.class.name,
|
||||
database: self.class.tracking_database,
|
||||
message: 'skipping migration execution for database that shares database configuration with another database')
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
Gitlab::Database::SharedModel.using_connection(base_model.connection) do
|
||||
break unless self.class.enabled? && active_migration
|
||||
|
||||
|
|
@ -63,7 +73,7 @@ module Database
|
|||
private
|
||||
|
||||
def active_migration
|
||||
@active_migration ||= Gitlab::Database::BackgroundMigration::BatchedMigration.active_migration
|
||||
@active_migration ||= Gitlab::Database::BackgroundMigration::BatchedMigration.active_migration(connection: base_model.connection)
|
||||
end
|
||||
|
||||
def run_active_migration
|
||||
|
|
@ -71,7 +81,13 @@ module Database
|
|||
end
|
||||
|
||||
def base_model
|
||||
@base_model ||= Gitlab::Database.database_base_models[self.class.tracking_database]
|
||||
strong_memoize(:base_model) do
|
||||
Gitlab::Database.database_base_models[self.class.tracking_database]
|
||||
end
|
||||
end
|
||||
|
||||
def shares_db_config?
|
||||
base_model && Gitlab::Database.db_config_share_with(base_model.connection_db_config).present?
|
||||
end
|
||||
|
||||
def with_exclusive_lease(interval)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ module Namespaces
|
|||
urgency :high
|
||||
|
||||
idempotent!
|
||||
deduplicate :until_executing
|
||||
deduplicate :until_executed
|
||||
|
||||
def perform
|
||||
results = ::Ci::ProcessSyncEventsService.new(
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ module Projects
|
|||
urgency :high
|
||||
|
||||
idempotent!
|
||||
deduplicate :until_executing
|
||||
deduplicate :until_executed
|
||||
|
||||
def perform
|
||||
results = ::Ci::ProcessSyncEventsService.new(
|
||||
|
|
|
|||
|
|
@ -16,6 +16,14 @@ production:
|
|||
username: git
|
||||
password: "secure password"
|
||||
host: localhost
|
||||
geo:
|
||||
adapter: postgresql
|
||||
encoding: unicode
|
||||
database: gitlabhq_geo_production
|
||||
username: git
|
||||
password: "secure password"
|
||||
host: localhost
|
||||
|
||||
#
|
||||
# Development specific
|
||||
#
|
||||
|
|
@ -38,6 +46,13 @@ development:
|
|||
host: localhost
|
||||
variables:
|
||||
statement_timeout: 15s
|
||||
geo:
|
||||
adapter: postgresql
|
||||
encoding: unicode
|
||||
database: gitlabhq_geo_development
|
||||
username: postgres
|
||||
password: "secure password"
|
||||
host: localhost
|
||||
|
||||
# Warning: The database defined as "test" will be erased and
|
||||
# re-generated from your development database when you run "rake".
|
||||
|
|
@ -63,3 +78,10 @@ test: &test
|
|||
prepared_statements: false
|
||||
variables:
|
||||
statement_timeout: 15s
|
||||
geo:
|
||||
adapter: postgresql
|
||||
encoding: unicode
|
||||
database: gitlabhq_geo_test
|
||||
username: postgres
|
||||
password:
|
||||
host: localhost
|
||||
|
|
|
|||
|
|
@ -18,6 +18,13 @@ production:
|
|||
# port: 8600
|
||||
# record: secondary.postgresql.service.consul
|
||||
# interval: 300
|
||||
geo:
|
||||
adapter: postgresql
|
||||
encoding: unicode
|
||||
database: gitlabhq_geo_production
|
||||
username: git
|
||||
password: "secure password"
|
||||
host: localhost
|
||||
|
||||
#
|
||||
# Development specific
|
||||
|
|
@ -32,6 +39,13 @@ development:
|
|||
host: localhost
|
||||
variables:
|
||||
statement_timeout: 15s
|
||||
geo:
|
||||
adapter: postgresql
|
||||
encoding: unicode
|
||||
database: gitlabhq_geo_development
|
||||
username: postgres
|
||||
password: "secure password"
|
||||
host: localhost
|
||||
|
||||
#
|
||||
# Staging specific
|
||||
|
|
@ -44,6 +58,13 @@ staging:
|
|||
username: git
|
||||
password: "secure password"
|
||||
host: localhost
|
||||
geo:
|
||||
adapter: postgresql
|
||||
encoding: unicode
|
||||
database: gitlabhq_geo_staging
|
||||
username: git
|
||||
password: "secure password"
|
||||
host: localhost
|
||||
|
||||
# Warning: The database defined as "test" will be erased and
|
||||
# re-generated from your development database when you run "rake".
|
||||
|
|
@ -59,3 +80,10 @@ test: &test
|
|||
prepared_statements: false
|
||||
variables:
|
||||
statement_timeout: 15s
|
||||
geo:
|
||||
adapter: postgresql
|
||||
encoding: unicode
|
||||
database: gitlabhq_geo_test
|
||||
username: postgres
|
||||
password:
|
||||
host: localhost
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
#
|
||||
# PRODUCTION
|
||||
#
|
||||
production:
|
||||
adapter: postgresql
|
||||
encoding: unicode
|
||||
database: gitlabhq_geo_production
|
||||
username: git
|
||||
password: "secure password"
|
||||
host: localhost
|
||||
|
||||
#
|
||||
# Development specific
|
||||
#
|
||||
development:
|
||||
adapter: postgresql
|
||||
encoding: unicode
|
||||
database: gitlabhq_geo_development
|
||||
username: postgres
|
||||
password: "secure password"
|
||||
host: localhost
|
||||
|
||||
#
|
||||
# Staging specific
|
||||
#
|
||||
staging:
|
||||
adapter: postgresql
|
||||
encoding: unicode
|
||||
database: gitlabhq_geo_staging
|
||||
username: git
|
||||
password: "secure password"
|
||||
host: localhost
|
||||
|
||||
# Warning: The database defined as "test" will be erased and
|
||||
# re-generated from your development database when you run "rake".
|
||||
# Do not set this db to the same as development or production.
|
||||
test: &test
|
||||
adapter: postgresql
|
||||
encoding: unicode
|
||||
database: gitlabhq_geo_test
|
||||
username: postgres
|
||||
password:
|
||||
host: localhost
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
name: pipeline_editor_file_tree
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83910
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/357219
|
||||
name: ci_show_all_projects_with_usage_sorted_descending
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83680
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/362331
|
||||
milestone: '15.0'
|
||||
type: development
|
||||
group: group::pipeline authoring
|
||||
group: group::pipeline execution
|
||||
default_enabled: false
|
||||
|
|
@ -711,7 +711,7 @@ Gitlab.ee do
|
|||
Settings.cron_jobs['ldap_sync_worker']['job_class'] = 'LdapSyncWorker'
|
||||
Settings.cron_jobs['free_user_cap_data_remediation'] ||= Settingslogic.new({})
|
||||
Settings.cron_jobs['free_user_cap_data_remediation']['cron'] ||= '17 6,10,14,18 * * *'
|
||||
Settings.cron_jobs['free_user_cap_data_remediation']['job_class'] = 'Namespaces::FreeUserCapWorker'
|
||||
Settings.cron_jobs['free_user_cap_data_remediation']['job_class'] = 'Namespaces::FreeUserCap::RemediationWorker'
|
||||
Settings.cron_jobs['update_max_seats_used_for_gitlab_com_subscriptions_worker'] ||= Settingslogic.new({})
|
||||
Settings.cron_jobs['update_max_seats_used_for_gitlab_com_subscriptions_worker']['cron'] ||= '0 12 * * *'
|
||||
Settings.cron_jobs['update_max_seats_used_for_gitlab_com_subscriptions_worker']['job_class'] = 'UpdateMaxSeatsUsedForGitlabComSubscriptionsWorker'
|
||||
|
|
|
|||
|
|
@ -1,14 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Gitlab.ee do
|
||||
# We need to initialize the Geo database before
|
||||
# setting the Geo DB connection pool size.
|
||||
if File.exist?(Rails.root.join('config/database_geo.yml'))
|
||||
Rails.application.configure do
|
||||
config.geo_database = config_for(:database_geo)
|
||||
end
|
||||
end
|
||||
|
||||
if Gitlab::Runtime.sidekiq? && Gitlab::Geo.geo_database_configured?
|
||||
# The Geo::TrackingBase model does not yet use connects_to. So,
|
||||
# this will not properly support geo: from config/databse.yml
|
||||
|
|
|
|||
|
|
@ -228,7 +228,12 @@ Rails.application.routes.draw do
|
|||
|
||||
draw :snippets
|
||||
draw :profile
|
||||
draw :members
|
||||
|
||||
post '/mailgun/webhooks' => 'mailgun/webhooks#process_webhook'
|
||||
|
||||
# Deprecated route for permanent failures
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/362606
|
||||
post '/members/mailgun/permanent_failures' => 'mailgun/webhooks#process_webhook'
|
||||
|
||||
# Product analytics collector
|
||||
match '/collector/i', to: ProductAnalytics::CollectorApp.new, via: :all
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
namespace :members do
|
||||
namespace :mailgun do
|
||||
resources :permanent_failures, only: [:create]
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddGitlabSchemaToBatchedBackgroundMigrations < Gitlab::Database::Migration[2.0]
|
||||
# rubocop:disable Migration/AddLimitToTextColumns
|
||||
# limit is added in 20220503035437_add_text_limit_to_batched_background_migrations_gitlab_schema
|
||||
def change
|
||||
add_column :batched_background_migrations, :gitlab_schema, :text, null: false, default: :gitlab_main
|
||||
change_column_default(:batched_background_migrations, :gitlab_schema, from: :gitlab_main, to: nil)
|
||||
end
|
||||
# rubocop:enable Migration/AddLimitToTextColumns
|
||||
end
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddTextLimitToBatchedBackgroundMigrationsGitlabSchema < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_text_limit :batched_background_migrations, :gitlab_schema, 255
|
||||
end
|
||||
|
||||
def down
|
||||
remove_text_limit :batched_background_migrations, :gitlab_schema
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class IndexBatchedMigrationsOnGitlabSchemaAndConfiguration < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
TABLE_NAME = :batched_background_migrations
|
||||
INDEX_NAME = 'index_batched_migrations_on_gl_schema_and_unique_configuration'
|
||||
|
||||
def up
|
||||
add_concurrent_index TABLE_NAME,
|
||||
%i[gitlab_schema job_class_name table_name column_name job_arguments],
|
||||
unique: true,
|
||||
name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name TABLE_NAME, INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -16,8 +16,6 @@ class BackfillIntegrationsTypeNew < ActiveRecord::Migration[6.1]
|
|||
end
|
||||
|
||||
def down
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :integrations, :id, [])
|
||||
.delete_all
|
||||
delete_batched_background_migration(MIGRATION, :integrations, :id, [])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ class BackfillUserNamespace < Gitlab::Database::Migration[1.0]
|
|||
end
|
||||
|
||||
def down
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :namespaces, :id, [])
|
||||
.delete_all
|
||||
delete_batched_background_migration(MIGRATION, :namespaces, :id, [])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ class BackfillIssueSearchData < Gitlab::Database::Migration[1.0]
|
|||
end
|
||||
|
||||
def down
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :issues, :id, [])
|
||||
.delete_all
|
||||
delete_batched_background_migration(MIGRATION, :issues, :id, [])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ class BackfillProjectNamespacesForGroup < Gitlab::Database::Migration[1.0]
|
|||
def down
|
||||
return unless Gitlab.com? || Gitlab.staging?
|
||||
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :projects, :id, [GROUP_ID, 'up']).delete_all
|
||||
delete_batched_background_migration(MIGRATION, :projects, :id, [GROUP_ID, 'up'])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ class BackfillNamespaceIdForNamespaceRoutes < Gitlab::Database::Migration[1.0]
|
|||
end
|
||||
|
||||
def down
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :routes, :id, [])
|
||||
.delete_all
|
||||
delete_batched_background_migration(MIGRATION, :routes, :id, [])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ class BackfillMemberNamespaceIdForGroupMembers < Gitlab::Database::Migration[1.0
|
|||
end
|
||||
|
||||
def down
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :members, :id, [])
|
||||
.delete_all
|
||||
delete_batched_background_migration(MIGRATION, :members, :id, [])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ class ScheduleNullifyOrphanRunnerIdOnCiBuilds < Gitlab::Database::Migration[1.0]
|
|||
end
|
||||
|
||||
def down
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :ci_builds, :id, [])
|
||||
.delete_all
|
||||
delete_batched_background_migration(MIGRATION, :ci_builds, :id, [])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ class BackfillAllProjectNamespaces < Gitlab::Database::Migration[1.0]
|
|||
end
|
||||
|
||||
def down
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :projects, :id, [nil, 'up']).delete_all
|
||||
delete_batched_background_migration(MIGRATION, :projects, :id, [nil, 'up'])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ class BackfillGroupFeatures < Gitlab::Database::Migration[1.0]
|
|||
end
|
||||
|
||||
def down
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :namespaces, :id, [BATCH_SIZE])
|
||||
.delete_all
|
||||
delete_batched_background_migration(MIGRATION, :namespaces, :id, [BATCH_SIZE])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ class BackfillNamespaceIdForProjectRoutes < Gitlab::Database::Migration[1.0]
|
|||
end
|
||||
|
||||
def down
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :routes, :id, [])
|
||||
.delete_all
|
||||
delete_batched_background_migration(MIGRATION, :routes, :id, [])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@ class ScheduleBackfillProjectSettings < Gitlab::Database::Migration[1.0]
|
|||
end
|
||||
|
||||
def down
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :projects, :id, [])
|
||||
.delete_all
|
||||
delete_batched_background_migration(MIGRATION, :projects, :id, [])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveThreatMonitoringAlerts < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
def up
|
||||
execute("DELETE FROM alert_management_alerts WHERE domain = 1")
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveWebHooksWebHookLogsWebHookIdFk < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
PARENT_TABLE_NAME = :web_hook_logs
|
||||
FK_NAME = "fk_rails_bb3355782d"
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
execute('LOCK web_hooks, web_hook_logs IN ACCESS EXCLUSIVE MODE') if transaction_open?
|
||||
|
||||
remove_foreign_key_if_exists(:web_hook_logs, :web_hooks, name: FK_NAME)
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
fk_attrs = {
|
||||
name: FK_NAME, # Note we need the same name for every partition
|
||||
column: :web_hook_id,
|
||||
target_column: :id,
|
||||
on_delete: :cascade
|
||||
}
|
||||
|
||||
# Must add child FK's first, then to the partitioned table.
|
||||
child_tables.each do |tbl|
|
||||
add_concurrent_foreign_key(
|
||||
tbl, :web_hooks,
|
||||
# This embeds the lock table statement in the with_lock_retries inside add_concurrent_foreign_key
|
||||
reverse_lock_order: true,
|
||||
**fk_attrs)
|
||||
end
|
||||
|
||||
with_lock_retries do
|
||||
execute("LOCK web_hooks, #{PARENT_TABLE_NAME} IN ACCESS EXCLUSIVE MODE") if transaction_open?
|
||||
add_foreign_key(:web_hook_logs, :web_hooks, **fk_attrs)
|
||||
end
|
||||
end
|
||||
|
||||
# This table is partitioned: we need to apply the index changes to each
|
||||
# partition separately.
|
||||
def child_tables
|
||||
@child_tables ||= execute(<<~SQL.squish).pluck("child")
|
||||
SELECT inhrelid::regclass AS child
|
||||
FROM pg_catalog.pg_inherits
|
||||
WHERE inhparent = '#{PARENT_TABLE_NAME}'::regclass
|
||||
ORDER BY inhrelid ASC
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
|
@ -10,9 +10,7 @@ class RescheduleExpireOAuthTokens < Gitlab::Database::Migration[2.0]
|
|||
|
||||
def up
|
||||
# remove the original migration from db/post_migrate/20220428133724_schedule_expire_o_auth_tokens.rb
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :oauth_access_tokens, :id, [])
|
||||
.delete_all
|
||||
delete_batched_background_migration(MIGRATION, :oauth_access_tokens, :id, [])
|
||||
|
||||
# reschedule
|
||||
queue_batched_background_migration(
|
||||
|
|
@ -24,8 +22,6 @@ class RescheduleExpireOAuthTokens < Gitlab::Database::Migration[2.0]
|
|||
end
|
||||
|
||||
def down
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :oauth_access_tokens, :id, [])
|
||||
.delete_all
|
||||
delete_batched_background_migration(MIGRATION, :oauth_access_tokens, :id, [])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateConfidentialNotesIndexSynchronously < Gitlab::Database::Migration[2.0]
|
||||
INDEX_NAME = 'index_notes_on_confidential'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_index :notes, :confidential, where: 'confidential = true', name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :notes, name: INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class MigrateFreeUserCapRemediation < Gitlab::Database::Migration[2.0]
|
||||
def up
|
||||
sidekiq_queue_migrate 'cronjob:namespaces_free_user_cap', to: 'cronjob:namespaces_free_user_cap_remediation'
|
||||
end
|
||||
|
||||
def down
|
||||
sidekiq_queue_migrate 'cronjob:namespaces_free_user_cap_remediation', to: 'cronjob:namespaces_free_user_cap'
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
0eeb96f26d8f8372c70f9aef59e976c4d403ec6aec01ad8784d31a7594bbaee2
|
||||
|
|
@ -0,0 +1 @@
|
|||
78306ca94e5f8e595d496efff983ed4749ee841ca8e2633afdb0cc5cb077e96a
|
||||
|
|
@ -0,0 +1 @@
|
|||
6f77ac586d48274a8f88384808b56ecad33a8ce00488595c0f82a074b45d5634
|
||||
|
|
@ -0,0 +1 @@
|
|||
16071cd85b772d86242ced867ba2f8c5e317222f6c3297e15dd456de13b4926e
|
||||
|
|
@ -0,0 +1 @@
|
|||
bbd6be6772f4fc5aecf393d6c043c1fdc38fdde6efd1586ba4be08ddbb5886dd
|
||||
|
|
@ -0,0 +1 @@
|
|||
74585dbb76b6744533a1df5dc995b461798fe8d0e0cd37fb6f9d52958f87a403
|
||||
|
|
@ -0,0 +1 @@
|
|||
eadee7b8b85cce48f48dbdab2f5e0b8cd633ef4ef8363960b7de1eb73a6fe1aa
|
||||
|
|
@ -11767,6 +11767,8 @@ CREATE TABLE batched_background_migrations (
|
|||
max_batch_size integer,
|
||||
started_at timestamp with time zone,
|
||||
on_hold_until timestamp with time zone,
|
||||
gitlab_schema text NOT NULL,
|
||||
CONSTRAINT check_0406d9776f CHECK ((char_length(gitlab_schema) <= 255)),
|
||||
CONSTRAINT check_5bb0382d6f CHECK ((char_length(column_name) <= 63)),
|
||||
CONSTRAINT check_6b6a06254a CHECK ((char_length(table_name) <= 63)),
|
||||
CONSTRAINT check_batch_size_in_range CHECK ((batch_size >= sub_batch_size)),
|
||||
|
|
@ -26911,6 +26913,8 @@ CREATE INDEX index_batched_jobs_by_batched_migration_id_and_id ON batched_backgr
|
|||
|
||||
CREATE INDEX index_batched_jobs_on_batched_migration_id_and_status ON batched_background_migration_jobs USING btree (batched_background_migration_id, status);
|
||||
|
||||
CREATE UNIQUE INDEX index_batched_migrations_on_gl_schema_and_unique_configuration ON batched_background_migrations USING btree (gitlab_schema, job_class_name, table_name, column_name, job_arguments);
|
||||
|
||||
CREATE INDEX index_board_assignees_on_assignee_id ON board_assignees USING btree (assignee_id);
|
||||
|
||||
CREATE UNIQUE INDEX index_board_assignees_on_board_id_and_assignee_id ON board_assignees USING btree (board_id, assignee_id);
|
||||
|
|
@ -28425,6 +28429,8 @@ CREATE INDEX index_notes_on_author_id_and_created_at_and_id ON notes USING btree
|
|||
|
||||
CREATE INDEX index_notes_on_commit_id ON notes USING btree (commit_id);
|
||||
|
||||
CREATE INDEX index_notes_on_confidential ON notes USING btree (confidential) WHERE (confidential = true);
|
||||
|
||||
CREATE INDEX index_notes_on_created_at ON notes USING btree (created_at);
|
||||
|
||||
CREATE INDEX index_notes_on_discussion_id ON notes USING btree (discussion_id);
|
||||
|
|
@ -33118,9 +33124,6 @@ ALTER TABLE ONLY approval_project_rules_users
|
|||
ALTER TABLE ONLY lists
|
||||
ADD CONSTRAINT fk_rails_baed5f39b7 FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE web_hook_logs
|
||||
ADD CONSTRAINT fk_rails_bb3355782d FOREIGN KEY (web_hook_id) REFERENCES web_hooks(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY security_findings
|
||||
ADD CONSTRAINT fk_rails_bb63863cf1 FOREIGN KEY (scan_id) REFERENCES security_scans(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
|
|||
|
|
@ -203,6 +203,8 @@ successfully, you must replicate their data using some other means.
|
|||
|[External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | **Yes** (14.6) | Via Object Storage provider if supported. Native Geo support (Beta). | Replication is behind the feature flag `geo_merge_request_diff_replication`, enabled by default. Verification was behind the feature flag `geo_merge_request_diff_verification`, removed in 14.7.|
|
||||
|[Versioned snippets](../../../user/snippets.md#versioned-snippets) | [**Yes** (13.7)](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [**Yes** (14.2)](https://gitlab.com/groups/gitlab-org/-/epics/2810) | No | Verification was implemented behind the feature flag `geo_snippet_repository_verification` in 13.11, and the feature flag was removed in 14.2. |
|
||||
|[GitLab Pages](../../pages/index.md) | [**Yes** (14.3)](https://gitlab.com/groups/gitlab-org/-/epics/589) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (14.6) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_pages_deployment_replication`, enabled by default. Verification was behind the feature flag `geo_pages_deployment_verification`, removed in 14.7. |
|
||||
|[Incident Metric Images](../../../operations/incident_management/incidents.md#metrics) | [Planned](https://gitlab.com/gitlab-org/gitlab/-/issues/352326) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/362561) | No | |
|
||||
|[Alert Metric Images](../../../operations/incident_management/alerts.md#metrics-tab) | [Planned](https://gitlab.com/gitlab-org/gitlab/-/issues/352326) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/362561) | No | |
|
||||
|[Server-side Git hooks](../../server_hooks.md) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/1867) | No | No | Not planned because of current implementation complexity, low customer interest, and availability of alternatives to hooks. |
|
||||
|[Elasticsearch integration](../../../integration/elasticsearch.md) | [Not planned](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No | No | Not planned because further product discovery is required and Elasticsearch (ES) clusters can be rebuilt. Secondaries use the same ES cluster as the primary. |
|
||||
|[Dependency proxy images](../../../user/packages/dependency_proxy/index.md) | [Not planned](https://gitlab.com/gitlab-org/gitlab/-/issues/259694) | No | No | Blocked by [Geo: Secondary Mimicry](https://gitlab.com/groups/gitlab-org/-/epics/1528). Replication of this cache is not needed for disaster recovery purposes because it can be recreated from external sources. |
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
stage: Growth
|
||||
group: Expansion
|
||||
stage: Plan
|
||||
group: Project Management
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
||||
type: reference, howto
|
||||
---
|
||||
|
|
@ -9,26 +9,37 @@ type: reference, howto
|
|||
|
||||
When you use Mailgun to send emails for your GitLab instance and [Mailgun](https://www.mailgun.com/)
|
||||
integration is enabled and configured in GitLab, you can receive their webhook for
|
||||
permanent invite email failures. To set up the integration, you must:
|
||||
tracking delivery failures. To set up the integration, you must:
|
||||
|
||||
1. [Configure your Mailgun domain](#configure-your-mailgun-domain).
|
||||
1. [Enable Mailgun integration](#enable-mailgun-integration).
|
||||
|
||||
After completing the integration, Mailgun `permanent_failure` webhooks are sent to your GitLab instance.
|
||||
After completing the integration, Mailgun `temporary_failure` and `permanent_failure` webhooks are sent to your GitLab instance.
|
||||
|
||||
## Configure your Mailgun domain
|
||||
|
||||
Before you can enable Mailgun in GitLab, set up your own Mailgun permanent failure endpoint to receive the webhooks.
|
||||
> [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/359113) the `/-/members/mailgun/permanent_failures` URL in GitLab 15.0.
|
||||
> [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/359113) the URL to handle both temporary and permanent failures in GitLab 15.0.
|
||||
|
||||
Before you can enable Mailgun in GitLab, set up your own Mailgun endpoints to receive the webhooks.
|
||||
|
||||
Using the [Mailgun webhook guide](https://www.mailgun.com/blog/a-guide-to-using-mailguns-webhooks/):
|
||||
|
||||
1. Add a webhook with the **Event type** set to **Permanent Failure**.
|
||||
1. Fill in the URL of your instance and include the `/-/members/mailgun/permanent_failures` path.
|
||||
- Example: `https://myinstance.gitlab.com/-/members/mailgun/permanent_failures`
|
||||
1. Enter the URL of your instance and include the `/-/mailgun/webhooks` path.
|
||||
|
||||
For example:
|
||||
|
||||
```plaintext
|
||||
https://myinstance.gitlab.com/-/mailgun/webhooks
|
||||
```
|
||||
|
||||
1. Add another webhook with the **Event type** set to **Temporary Failure**.
|
||||
1. Enter the URL of your instance and use the same `/-/mailgun/webhooks` path.
|
||||
|
||||
## Enable Mailgun integration
|
||||
|
||||
After configuring your Mailgun domain for the permanent failures endpoint,
|
||||
After configuring your Mailgun domain for the webhook endpoints,
|
||||
you're ready to enable the Mailgun integration:
|
||||
|
||||
1. Sign in to GitLab as an [Administrator](../../user/permissions.md) user.
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ alternatives to server hooks include:
|
|||
|
||||
- [Webhooks](../user/project/integrations/webhooks.md).
|
||||
- [GitLab CI/CD](../ci/index.md).
|
||||
- [Push rules](../push_rules/push_rules.md), for a user-configurable Git hook interface.
|
||||
- [Push rules](../user/project/repository/push_rules.md), for a user-configurable Git hook interface.
|
||||
|
||||
[Geo](geo/index.md) doesn't replicate server hooks to secondary nodes.
|
||||
|
||||
|
|
|
|||
|
|
@ -619,92 +619,56 @@ Parameters:
|
|||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"iid": 1,
|
||||
"project_id": 3,
|
||||
"title": "test1",
|
||||
"description": "fixed login page css paddings",
|
||||
"state": "merged",
|
||||
"created_at": "2017-04-29T08:46:00Z",
|
||||
"updated_at": "2017-04-29T08:46:00Z",
|
||||
"id": 155016530,
|
||||
"iid": 133,
|
||||
"project_id": 15513260,
|
||||
"title": "Manual job rules",
|
||||
"description": "",
|
||||
"state": "opened",
|
||||
"created_at": "2022-05-13T07:26:38.402Z",
|
||||
"updated_at": "2022-05-14T03:38:31.354Z",
|
||||
"merged_by": null, // Deprecated and will be removed in API v5, use `merge_user` instead
|
||||
"merge_user": null,
|
||||
"merged_at": null,
|
||||
"closed_by": null,
|
||||
"closed_at": null,
|
||||
"target_branch": "master",
|
||||
"source_branch": "test1",
|
||||
"source_branch": "manual-job-rules",
|
||||
"user_notes_count": 0,
|
||||
"upvotes": 0,
|
||||
"downvotes": 0,
|
||||
"author": {
|
||||
"id": 1,
|
||||
"name": "Administrator",
|
||||
"username": "admin",
|
||||
"id": 4155490,
|
||||
"username": "marcel.amirault",
|
||||
"name": "Marcel Amirault",
|
||||
"state": "active",
|
||||
"avatar_url": null,
|
||||
"web_url" : "https://gitlab.example.com/admin"
|
||||
"avatar_url": "https://gitlab.com/uploads/-/system/user/avatar/4155490/avatar.png",
|
||||
"web_url": "https://gitlab.com/marcel.amirault"
|
||||
},
|
||||
"user" : {
|
||||
"can_merge" : false
|
||||
},
|
||||
"assignee": {
|
||||
"id": 1,
|
||||
"name": "Administrator",
|
||||
"username": "admin",
|
||||
"state": "active",
|
||||
"avatar_url": null,
|
||||
"web_url" : "https://gitlab.example.com/admin"
|
||||
},
|
||||
"assignees": [{
|
||||
"name": "Miss Monserrate Beier",
|
||||
"username": "axel.block",
|
||||
"id": 12,
|
||||
"state": "active",
|
||||
"avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
|
||||
"web_url": "https://gitlab.example.com/axel.block"
|
||||
}],
|
||||
"reviewers": [{
|
||||
"id": 2,
|
||||
"name": "Sam Bauch",
|
||||
"username": "kenyatta_oconnell",
|
||||
"state": "active",
|
||||
"avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon",
|
||||
"web_url": "http://gitlab.example.com//kenyatta_oconnell"
|
||||
}],
|
||||
"source_project_id": 2,
|
||||
"target_project_id": 3,
|
||||
"labels": [
|
||||
"Community contribution",
|
||||
"Manage"
|
||||
],
|
||||
"assignees": [],
|
||||
"assignee": null,
|
||||
"reviewers": [],
|
||||
"source_project_id": 15513260,
|
||||
"target_project_id": 15513260,
|
||||
"labels": [],
|
||||
"draft": false,
|
||||
"work_in_progress": false,
|
||||
"milestone": {
|
||||
"id": 5,
|
||||
"iid": 1,
|
||||
"project_id": 3,
|
||||
"title": "v2.0",
|
||||
"description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
|
||||
"state": "closed",
|
||||
"created_at": "2015-02-02T19:49:26.013Z",
|
||||
"updated_at": "2015-02-02T19:49:26.013Z",
|
||||
"due_date": "2018-09-22",
|
||||
"start_date": "2018-08-08",
|
||||
"web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
|
||||
},
|
||||
"merge_when_pipeline_succeeds": true,
|
||||
"milestone": null,
|
||||
"merge_when_pipeline_succeeds": false,
|
||||
"merge_status": "can_be_merged",
|
||||
"merge_error": null,
|
||||
"sha": "8888888888888888888888888888888888888888",
|
||||
"sha": "e82eb4a098e32c796079ca3915e07487fc4db24c",
|
||||
"merge_commit_sha": null,
|
||||
"squash_commit_sha": null,
|
||||
"user_notes_count": 1,
|
||||
"discussion_locked": null,
|
||||
"should_remove_source_branch": true,
|
||||
"force_remove_source_branch": false,
|
||||
"allow_collaboration": false,
|
||||
"allow_maintainer_to_push": false,
|
||||
"web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
|
||||
"should_remove_source_branch": null,
|
||||
"force_remove_source_branch": true,
|
||||
"reference": "!133",
|
||||
"references": {
|
||||
"short": "!1",
|
||||
"relative": "!1",
|
||||
"full": "my-group/my-project!1"
|
||||
"short": "!133",
|
||||
"relative": "!133",
|
||||
"full": "marcel.amirault/test-project!133"
|
||||
},
|
||||
"web_url": "https://gitlab.com/marcel.amirault/test-project/-/merge_requests/133",
|
||||
"time_stats": {
|
||||
"time_estimate": 0,
|
||||
"total_time_spent": 0,
|
||||
|
|
@ -712,51 +676,80 @@ Parameters:
|
|||
"human_total_time_spent": null
|
||||
},
|
||||
"squash": false,
|
||||
"subscribed": false,
|
||||
"changes_count": "1",
|
||||
"merged_by": { // Deprecated and will be removed in API v5, use `merge_user` instead
|
||||
"id": 87854,
|
||||
"name": "Douwe Maan",
|
||||
"username": "DouweM",
|
||||
"state": "active",
|
||||
"avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
|
||||
"web_url": "https://gitlab.com/DouweM"
|
||||
},
|
||||
"merge_user": {
|
||||
"id": 87854,
|
||||
"name": "Douwe Maan",
|
||||
"username": "DouweM",
|
||||
"state": "active",
|
||||
"avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
|
||||
"web_url": "https://gitlab.com/DouweM"
|
||||
},
|
||||
"merged_at": "2018-09-07T11:16:17.520Z",
|
||||
"closed_by": null,
|
||||
"closed_at": null,
|
||||
"latest_build_started_at": "2018-09-07T07:27:38.472Z",
|
||||
"latest_build_finished_at": "2018-09-07T08:07:06.012Z",
|
||||
"first_deployed_to_production_at": null,
|
||||
"pipeline": {
|
||||
"id": 29626725,
|
||||
"sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
|
||||
"ref": "patch-28",
|
||||
"status": "success",
|
||||
"web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725"
|
||||
},
|
||||
"diff_refs": {
|
||||
"base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00",
|
||||
"head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
|
||||
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
|
||||
},
|
||||
"diverged_commits_count": 2,
|
||||
"rebase_in_progress": false,
|
||||
"first_contribution": false,
|
||||
"task_completion_status":{
|
||||
"count":0,
|
||||
"completed_count":0
|
||||
"task_completion_status": {
|
||||
"count": 0,
|
||||
"completed_count": 0
|
||||
},
|
||||
"has_conflicts": false,
|
||||
"blocking_discussions_resolved": true
|
||||
"blocking_discussions_resolved": true,
|
||||
"approvals_before_merge": null,
|
||||
"subscribed": true,
|
||||
"changes_count": "1",
|
||||
"latest_build_started_at": "2022-05-13T09:46:50.032Z",
|
||||
"latest_build_finished_at": null,
|
||||
"first_deployed_to_production_at": null,
|
||||
"pipeline": { // Old parameter, use `head_pipeline` instead.
|
||||
"id": 538317940,
|
||||
"iid": 1877,
|
||||
"project_id": 15513260,
|
||||
"sha": "1604b0c46c395822e4e9478777f8e54ac99fe5b9",
|
||||
"ref": "refs/merge-requests/133/merge",
|
||||
"status": "failed",
|
||||
"source": "merge_request_event",
|
||||
"created_at": "2022-05-13T09:46:39.560Z",
|
||||
"updated_at": "2022-05-13T09:47:20.706Z",
|
||||
"web_url": "https://gitlab.com/marcel.amirault/test-project/-/pipelines/538317940"
|
||||
},
|
||||
"head_pipeline": {
|
||||
"id": 538317940,
|
||||
"iid": 1877,
|
||||
"project_id": 15513260,
|
||||
"sha": "1604b0c46c395822e4e9478777f8e54ac99fe5b9",
|
||||
"ref": "refs/merge-requests/133/merge",
|
||||
"status": "failed",
|
||||
"source": "merge_request_event",
|
||||
"created_at": "2022-05-13T09:46:39.560Z",
|
||||
"updated_at": "2022-05-13T09:47:20.706Z",
|
||||
"web_url": "https://gitlab.com/marcel.amirault/test-project/-/pipelines/538317940",
|
||||
"before_sha": "1604b0c46c395822e4e9478777f8e54ac99fe5b9",
|
||||
"tag": false,
|
||||
"yaml_errors": null,
|
||||
"user": {
|
||||
"id": 4155490,
|
||||
"username": "marcel.amirault",
|
||||
"name": "Marcel Amirault",
|
||||
"state": "active",
|
||||
"avatar_url": "https://gitlab.com/uploads/-/system/user/avatar/4155490/avatar.png",
|
||||
"web_url": "https://gitlab.com/marcel.amirault"
|
||||
},
|
||||
"started_at": "2022-05-13T09:46:50.032Z",
|
||||
"finished_at": "2022-05-13T09:47:20.697Z",
|
||||
"committed_at": null,
|
||||
"duration": 30,
|
||||
"queued_duration": 10,
|
||||
"coverage": null,
|
||||
"detailed_status": {
|
||||
"icon": "status_failed",
|
||||
"text": "failed",
|
||||
"label": "failed",
|
||||
"group": "failed",
|
||||
"tooltip": "failed",
|
||||
"has_details": true,
|
||||
"details_path": "/marcel.amirault/test-project/-/pipelines/538317940",
|
||||
"illustration": null,
|
||||
"favicon": "/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png"
|
||||
}
|
||||
},
|
||||
"diff_refs": {
|
||||
"base_sha": "1162f719d711319a2efb2a35566f3bfdadee8bab",
|
||||
"head_sha": "e82eb4a098e32c796079ca3915e07487fc4db24c",
|
||||
"start_sha": "1162f719d711319a2efb2a35566f3bfdadee8bab"
|
||||
},
|
||||
"merge_error": null,
|
||||
"first_contribution": false,
|
||||
"user": {
|
||||
"can_merge": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -53,12 +53,8 @@ reflected in the CI lint. It displays the same results as the existing [CI Lint
|
|||
|
||||
## View included CI/CD configuration
|
||||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/7064) in GitLab 15.0 [with a flag](../../administration/feature_flags.md) named `pipeline_editor_file_tree`. Disabled by default.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available,
|
||||
ask an administrator to [enable the feature flag](../../administration/feature_flags.md)
|
||||
named `pipeline_editor_file_tree`.
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/7064) in GitLab 15.0 [with a flag](../../administration/feature_flags.md) named `pipeline_editor_file_tree`. Disabled by default.
|
||||
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/357219) in GitLab 15.1.
|
||||
|
||||
You can review configuration added with the [`include`](../yaml/index.md#include)
|
||||
keyword in the pipeline editor. In the top right, select the file tree (**{file-tree}**)
|
||||
|
|
|
|||
|
|
@ -193,9 +193,12 @@ The cost factor for a job running on a shared runner is:
|
|||
|
||||
### Additional costs on GitLab SaaS
|
||||
|
||||
On GitLab SaaS, shared runners can have different cost factors depending on the cost involved
|
||||
in executing the runner. For example, a high spec shared runner could be set to have a cost factor of `2`.
|
||||
Conversely, a shared runner that executes jobs for public projects could have a low cost factor, like `0.008`.
|
||||
GitLab SaaS shared runners have different cost factors, depending on the runner type (Linux, Windows, macOS) and the virtual machine configuration.
|
||||
|
||||
| GitLab SaaS runner type | Virtual machine configuration | CI/CD minutes cost factor |
|
||||
| :--------- | :------------------- | :--------- |
|
||||
| Linux OS + Docker executor| 1 vCPU, 3.75 GB RAM |1|
|
||||
| macOS + shell executor | 4 vCPU, 10 GB RAM| 6 |
|
||||
|
||||
### Monthly reset of CI/CD minutes
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
---
|
||||
stage: Verify
|
||||
group: Runner
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
# Code signing for SaaS runners on macOS
|
||||
|
||||
> Introduced in GitLab 15.0.
|
||||
|
||||
Before you can integrate GitLab with Apple services, install to a device, or deploy to the Apple App Store, you must [code sign](https://developer.apple.com/support/code-signing/) your application.
|
||||
|
||||
To code sign an iOS project, you need the following files:
|
||||
|
||||
- A certifcate issued by Apple.
|
||||
- A provisioning profile.
|
||||
|
||||
## Code signing iOS Projects with fastlane
|
||||
|
||||
When you use SaaS runners on macOS, each job runs on a VM. Included in each VM is [fastlane](https://fastlane.tools/),
|
||||
an open-source solution aimed at simplifying mobile app deployment.
|
||||
|
||||
These steps outline the minimal setup required to use fastlane to code sign your application. Refer to the fastlane [getting started guide](https://docs.fastlane.tools/), [best practices for integrating with GitLab CI](https://docs.fastlane.tools/best-practices/continuous-integration/gitlab/) and the [fastlane code signing getting started guide](https://docs.fastlane.tools/codesigning/getting-started/) for installation instructions, and an overview of how to use fastlane to handle code signing.
|
||||
|
||||
To use fastlane to code sign your application:
|
||||
|
||||
1. At the root of your project repository, on your local development system, run this command:
|
||||
|
||||
```plaintext
|
||||
fastlane match init
|
||||
```
|
||||
|
||||
This command creates the `fastlane` directory and adds two files: `Fastfile` and `Appfile`.
|
||||
|
||||
1. Open `Appfile` and edit it to include your Apple ID and app ID.
|
||||
|
||||
```plaintext
|
||||
app_identifier("APP IDENTIFIER") # The bundle identifier of your app
|
||||
|
||||
apple_id("APPLE ID") # Your Apple email address
|
||||
```
|
||||
|
||||
1. Open `Fastfile`, which includes the fastlane build steps.
|
||||
In the following snippet, the steps `get_certificates`, `get_provisioning_profile,match`, `gym`, and
|
||||
`upload_to_testflight` are fastlane [actions](https://docs.fastlane.tools/actions/).
|
||||
|
||||
```plaintext
|
||||
# This file contains the fastlane.tools configuration
|
||||
# You can find the documentation at https://docs.fastlane.tools
|
||||
|
||||
default_platform(:ios)
|
||||
|
||||
platform :ios do
|
||||
desc "Build the application"
|
||||
lane :beta do
|
||||
increment_build_number(
|
||||
build_number: latest_testflight_build_number + 1,
|
||||
xcodeproj: "${PROJECT_NAME}.xcodeproj"
|
||||
)
|
||||
get_certificates
|
||||
get_provisioning_profile
|
||||
# match(type: "appstore",read_only: true)
|
||||
gym
|
||||
upload_to_testflight
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
The example configuration also includes an optional `Gymfile`. This file stores configuration
|
||||
parameters and is used by the fastlane [`gym`](https://docs.fastlane.tools/actions/gym/) action.
|
||||
|
||||
## Using fastlane match
|
||||
|
||||
To simplify the code signing process and implement the
|
||||
[Code Signing Best Practices Guide](https://codesigning.guide/) recommendations,
|
||||
use [fastlane match](https://docs.fastlane.tools/actions/match/).
|
||||
|
||||
- Use one code signing identity shared across your team.
|
||||
- Store the required certificates and provisioning profiles in a separate GitLab project repository.
|
||||
|
||||
Match automatically syncs iOS and macOS keys and provisioning profiles across all team members with access to the GitLab project. Each team member with access to the project can use the credentials for code signing.
|
||||
|
||||
To use fastlane match:
|
||||
|
||||
1. Initialize match in the project repository:
|
||||
|
||||
```shell
|
||||
bundle exec fastlane match init
|
||||
```
|
||||
|
||||
1. Select `git` as your storage node.
|
||||
1. Enter the URL of the GitLab project you plan to use to store your code signing identities.
|
||||
1. Optional. To create a new certificate and provisioning profile, run:
|
||||
|
||||
```shell
|
||||
bundle exec fastlane match development
|
||||
```
|
||||
|
||||
For different code signing identities' storage options, and for a complete step-by-step guide for using match,
|
||||
refer to the [match documentation](https://docs.fastlane.tools/actions/match/#usage).
|
||||
|
||||
### Environment variables and authentication
|
||||
|
||||
To complete the setup, you must configure environment variables to use with fastlane. The required variables are outlined in the [fastlane documentation](https://docs.fastlane.tools/best-practices/continuous-integration/#environment-variables-to-set).
|
||||
|
||||
To support Apple's two factor authentication requirement, configure these variables:
|
||||
|
||||
- `FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD` and
|
||||
- `FASTLANE_SESSION`
|
||||
|
||||
To authenticate fastlane with the App Store for the TestFlight upload, configure these variables:
|
||||
|
||||
- `FASTLANE_USER` and
|
||||
- `FASTLANE_PASSWORD`
|
||||
|
||||
View the [fastlane authentication with Apple Services guide](https://docs.fastlane.tools/getting-started/ios/authentication/) for an overview of authentication options.
|
||||
|
||||
## Related topics
|
||||
|
||||
- [Apple Developer Support - Code Signing](https://developer.apple.com/support/code-signing/)
|
||||
- [Code Signing Best Practice Guide](https://codesigning.guide/)
|
||||
|
|
@ -20,7 +20,7 @@ Each time you run a job that requires tooling or dependencies not available in t
|
|||
GitLab SaaS provides macOS build machines on Apple servers with Intel x86-64 processors.
|
||||
The expectation is that virtual machines running on the Apple M1 chip will be available in the second half of 2022.
|
||||
|
||||
For the [Beta](../../../../policy/alpha-beta-support.md#beta-features), there is only one available machine type, `gbc-macos-large`.
|
||||
At this time there is only one available machine type offered, `gbc-macos-large`.
|
||||
|
||||
| Instance type | vCPUS | Memory (GB) |
|
||||
| --------- | --- | ------- |
|
||||
|
|
|
|||
|
|
@ -4,10 +4,9 @@ group: Runner
|
|||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
# SaaS runners on macOS (beta) **(PREMIUM SAAS)**
|
||||
# SaaS runners on macOS (Limited Availability) **(PREMIUM SAAS)**
|
||||
|
||||
SaaS runners on macOS are in [Beta](../../../policy/alpha-beta-support.md#beta-features)
|
||||
and shouldn't be relied upon for mission-critical production jobs.
|
||||
SaaS runners on macOS are now in [Limited Availability](../../../policy/alpha-beta-support.md#beta-features) for approved open source programs and customers in Premium and Ultimate plans.
|
||||
|
||||
SaaS runners on macOS provide an on-demand macOS build environment integrated with
|
||||
GitLab SaaS [CI/CD](../../../ci/index.md).
|
||||
|
|
@ -15,11 +14,17 @@ Use these runners to build, test, and deploy apps for the Apple ecosystem (macOS
|
|||
of all the capabilities of the GitLab single DevOps platform and not have to manage or operate a
|
||||
build environment.
|
||||
|
||||
CI/CD minutes used on GitLab SaaS macOS runners are included in your CI/CD minute consumption totals. CI jobs that run on macOS **will** consume CI minutes at a faster rate than CI jobs on the GitLab SaaS runners on Linux.
|
||||
|
||||
Refer to the CI/CD minutes [cost factor](../../../ci/pipelines/cicd_minutes.md#cost-factor) for the cost factor applied to the GitLab SaaS macOS runners.
|
||||
|
||||
## Quickstart
|
||||
|
||||
To start using SaaS runners on macOS, you must submit an access request [issue](https://gitlab.com/gitlab-com/macos-buildcloud-runners-beta/-/issues/new?issuable_template=beta_access_request). After your
|
||||
access has been granted and your build environment configured, you must configure your
|
||||
`.gitlab-ci.yml` pipeline file:
|
||||
To start using SaaS runners on macOS, you must be an active GitLab SaaS Premium or Ultimate customer. Participants in the GitLab Open Source program are also eligible to use the service.
|
||||
|
||||
### Configuring your pipeline
|
||||
|
||||
To start using the SaaS runners on macOS to run your CI jobs, you must configure your `.gitlab-ci.yml` file:
|
||||
|
||||
1. Add a `.gitlab-ci.yml` file to your project repository.
|
||||
1. Specify the [image](macos/environment.md#vm-images) you want to use.
|
||||
|
|
@ -27,7 +32,7 @@ access has been granted and your build environment configured, you must configur
|
|||
|
||||
The runners automatically run your build.
|
||||
|
||||
## Example `.gitlab-ci.yml` file
|
||||
### Example `.gitlab-ci.yml` file
|
||||
|
||||
The following sample `.gitlab-ci.yml` file shows how to start using the SaaS runners on macOS:
|
||||
|
||||
|
|
@ -42,7 +47,7 @@ stages:
|
|||
- test
|
||||
|
||||
before_script:
|
||||
- echo "started by ${GITLAB_USER_NAME}"
|
||||
- echo "started by ${GITLAB_USER_NAME}"
|
||||
|
||||
build:
|
||||
extends:
|
||||
|
|
@ -60,4 +65,13 @@ test:
|
|||
```
|
||||
|
||||
NOTE:
|
||||
During the Beta period, the architecture of this solution will change. Rather than the jobs running on a specific VM instance, they will run on an ephemeral VM instance that is created by an autoscaling instance, known as the Runner Manager. We will notify all Beta participants of any downtime required to do this work.
|
||||
You can specify a different Xcode image to run a job. To do so, replace the value for the `image` keyword with the value of the [virtual machine image name](macos/environment.md#vm-images) from the list of available images.
|
||||
|
||||
## SaaS runners on macOS service level objective
|
||||
|
||||
In SaaS runners on macOS, the objective is to make 90% of CI jobs start executing in 120 seconds or less. The error rate should be less than 0.5%.
|
||||
|
||||
## Known Limitations and Usage Constraints
|
||||
|
||||
- If the VM image does not include the specific software version you need for your job, then the job execution time will increase as the required software needs to be fetched and installed.
|
||||
- At this time, it is not possible to bring your own OS image.
|
||||
|
|
|
|||
|
|
@ -152,9 +152,7 @@ When you start the second post-deployment migration, delete the
|
|||
previously batched migration with the provided code:
|
||||
|
||||
```ruby
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION_NAME, TABLE_NAME, COLUMN, JOB_ARGUMENTS)
|
||||
.delete_all
|
||||
delete_batched_background_migration(MIGRATION_NAME, TABLE_NAME, COLUMN, JOB_ARGUMENTS)
|
||||
```
|
||||
|
||||
## Cleaning up
|
||||
|
|
@ -261,8 +259,7 @@ background migration.
|
|||
end
|
||||
|
||||
def down
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(MIGRATION, :routes, :id, []).delete_all
|
||||
delete_batched_background_migration(MIGRATION_NAME, :routes, :id, [])
|
||||
end
|
||||
end
|
||||
```
|
||||
|
|
|
|||
|
|
@ -191,6 +191,8 @@ GitLab documentation should be clear and easy to understand.
|
|||
|
||||
### Capitalization
|
||||
|
||||
As a company, we tend toward lowercase.
|
||||
|
||||
#### Headings
|
||||
|
||||
Use sentence case. For example:
|
||||
|
|
@ -589,6 +591,10 @@ Consider installing a plugin or extension in your editor for formatting tables:
|
|||
- [Markdown Table Formatter](https://packagecontrol.io/packages/Markdown%20Table%20Formatter) for Sublime Text
|
||||
- [Markdown Table Formatter](https://atom.io/packages/markdown-table-formatter) for Atom
|
||||
|
||||
### Table headings
|
||||
|
||||
Use sentence case for table headings. For example, `Keyword value` or `Project name`.
|
||||
|
||||
### Feature tables
|
||||
|
||||
When creating tables of lists of features (such the features
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ Guidelines:
|
|||
- Consider notifying `#support_gitlab-com` beforehand. So in case if the feature has any side effects on user experience, they can mitigate and disable the feature flag to reduce some impact.
|
||||
- If the feature meets the requirements for creating a [Change Management](https://about.gitlab.com/handbook/engineering/infrastructure/change-management/#feature-flags-and-the-change-management-process) issue, create a Change Management issue per [criticality guidelines](https://about.gitlab.com/handbook/engineering/infrastructure/change-management/#change-request-workflows).
|
||||
- For simple, low-risk, easily reverted features, proceed and [enable the feature in `#production`](#process).
|
||||
- For support requests to toggle feature flags for specific groups or projects, please follow the process outlined in the [support workflows](https://about.gitlab.com/handbook/support/workflows/saas_feature_flags.html).
|
||||
|
||||
#### Process
|
||||
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ needs to be applied to the tracking database on each **secondary** site.
|
|||
|
||||
### Configuration
|
||||
|
||||
The database configuration is set in [`config/database_geo.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/database_geo.yml.postgresql).
|
||||
The database configuration is set in [`config/database.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/database.yml.postgresql).
|
||||
The directory [`ee/db/geo`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/db/geo)
|
||||
contains the schema and migrations for this database.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../user/project/repository/push_rules.md'
|
||||
remove_date: '2022-05-10'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../user/project/repository/push_rules.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2022-05-10>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -409,6 +409,7 @@ applications.
|
|||
| `AUTO_DEVOPS_BUILD_IMAGE_CNB_BUILDER` | The builder used when building with Cloud Native Buildpacks. The default builder is `heroku/buildpacks:18`. [More details](stages.md#auto-build-using-cloud-native-buildpacks). |
|
||||
| `AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` | Extra arguments to be passed to the `docker build` command. Note that using quotes doesn't prevent word splitting. [More details](#passing-arguments-to-docker-build). |
|
||||
| `AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` | A [comma-separated list of CI/CD variable names](#forward-cicd-variables-to-the-build-environment) to be forwarded to the build environment (the buildpack builder or `docker build`). |
|
||||
| `AUTO_DEVOPS_BUILD_IMAGE_CNB_PORT` | In GitLab 15.0 and later, port exposed by the generated Docker image. Set to `false` to prevent exposing any ports. Defaults to `5000`. |
|
||||
| `AUTO_DEVOPS_CHART` | Helm Chart used to deploy your apps. Defaults to the one [provided by GitLab](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app). |
|
||||
| `AUTO_DEVOPS_CHART_REPOSITORY` | Helm Chart repository used to search for charts. Defaults to `https://charts.gitlab.io`. |
|
||||
| `AUTO_DEVOPS_CHART_REPOSITORY_NAME` | Used to set the name of the Helm repository. Defaults to `gitlab`. |
|
||||
|
|
|
|||
|
|
@ -156,6 +156,9 @@ gemnasium-python-dependency_scanning:
|
|||
|
||||
bundler-audit-dependency_scanning:
|
||||
extends: .ds-analyzer
|
||||
variables:
|
||||
DS_ANALYZER_NAME: "bundler-audit"
|
||||
DS_MAJOR_VERSION: 2
|
||||
script:
|
||||
- echo "This job was deprecated in GitLab 14.8 and removed in GitLab 15.0"
|
||||
- echo "For more information see https://gitlab.com/gitlab-org/gitlab/-/issues/347491"
|
||||
|
|
@ -165,6 +168,9 @@ bundler-audit-dependency_scanning:
|
|||
|
||||
retire-js-dependency_scanning:
|
||||
extends: .ds-analyzer
|
||||
variables:
|
||||
DS_ANALYZER_NAME: "retire.js"
|
||||
DS_MAJOR_VERSION: 2
|
||||
script:
|
||||
- echo "This job was deprecated in GitLab 14.8 and removed in GitLab 15.0"
|
||||
- echo "For more information see https://gitlab.com/gitlab-org/gitlab/-/issues/289830"
|
||||
|
|
|
|||
|
|
@ -30,9 +30,23 @@ module Gitlab
|
|||
|
||||
scope :created_after, ->(time) { where('created_at > ?', time) }
|
||||
|
||||
scope :for_configuration, ->(job_class_name, table_name, column_name, job_arguments) do
|
||||
where(job_class_name: job_class_name, table_name: table_name, column_name: column_name)
|
||||
scope :for_configuration, ->(gitlab_schema, job_class_name, table_name, column_name, job_arguments) do
|
||||
relation = where(job_class_name: job_class_name, table_name: table_name, column_name: column_name)
|
||||
.where("job_arguments = ?", job_arguments.to_json) # rubocop:disable Rails/WhereEquals
|
||||
|
||||
# This method is called from migrations older than the gitlab_schema column,
|
||||
# check and add this filter only if the column exists.
|
||||
relation = relation.for_gitlab_schema(gitlab_schema) if gitlab_schema_column_exists?
|
||||
|
||||
relation
|
||||
end
|
||||
|
||||
def self.gitlab_schema_column_exists?
|
||||
column_names.include?('gitlab_schema')
|
||||
end
|
||||
|
||||
scope :for_gitlab_schema, ->(gitlab_schema) do
|
||||
where(gitlab_schema: gitlab_schema)
|
||||
end
|
||||
|
||||
state_machine :status, initial: :paused do
|
||||
|
|
@ -73,12 +87,13 @@ module Gitlab
|
|||
state_machine.states.map(&:name)
|
||||
end
|
||||
|
||||
def self.find_for_configuration(job_class_name, table_name, column_name, job_arguments)
|
||||
for_configuration(job_class_name, table_name, column_name, job_arguments).first
|
||||
def self.find_for_configuration(gitlab_schema, job_class_name, table_name, column_name, job_arguments)
|
||||
for_configuration(gitlab_schema, job_class_name, table_name, column_name, job_arguments).first
|
||||
end
|
||||
|
||||
def self.active_migration
|
||||
executable.queue_order.first
|
||||
def self.active_migration(connection:)
|
||||
for_gitlab_schema(Gitlab::Database.gitlab_schemas_for_connection(connection))
|
||||
.executable.queue_order.first
|
||||
end
|
||||
|
||||
def self.successful_rows_counts(migrations)
|
||||
|
|
|
|||
|
|
@ -54,7 +54,10 @@ module Gitlab
|
|||
# in order to prevent it being picked up by the background worker. Perform all pending jobs,
|
||||
# then keep running until migration is finished.
|
||||
def finalize(job_class_name, table_name, column_name, job_arguments)
|
||||
migration = BatchedMigration.find_for_configuration(job_class_name, table_name, column_name, job_arguments)
|
||||
migration = BatchedMigration.find_for_configuration(
|
||||
Gitlab::Database.gitlab_schemas_for_connection(connection),
|
||||
job_class_name, table_name, column_name, job_arguments
|
||||
)
|
||||
|
||||
configuration = {
|
||||
job_class_name: job_class_name,
|
||||
|
|
|
|||
|
|
@ -945,8 +945,13 @@ module Gitlab
|
|||
end
|
||||
|
||||
def ensure_batched_background_migration_is_finished(job_class_name:, table_name:, column_name:, job_arguments:, finalize: true)
|
||||
migration = Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(job_class_name, table_name, column_name, job_arguments).first
|
||||
Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.require_dml_mode!
|
||||
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration.reset_column_information
|
||||
migration = Gitlab::Database::BackgroundMigration::BatchedMigration.find_for_configuration(
|
||||
Gitlab::Database.gitlab_schemas_for_connection(connection),
|
||||
job_class_name, table_name, column_name, job_arguments
|
||||
)
|
||||
|
||||
configuration = {
|
||||
job_class_name: job_class_name,
|
||||
|
|
|
|||
|
|
@ -67,10 +67,16 @@ module Gitlab
|
|||
batch_class_name: BATCH_CLASS_NAME,
|
||||
batch_size: BATCH_SIZE,
|
||||
max_batch_size: nil,
|
||||
sub_batch_size: SUB_BATCH_SIZE
|
||||
sub_batch_size: SUB_BATCH_SIZE,
|
||||
gitlab_schema: nil
|
||||
)
|
||||
Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.require_dml_mode!
|
||||
|
||||
if Gitlab::Database::BackgroundMigration::BatchedMigration.for_configuration(job_class_name, batch_table_name, batch_column_name, job_arguments).exists?
|
||||
gitlab_schema ||= gitlab_schema_from_context
|
||||
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration.reset_column_information
|
||||
|
||||
if Gitlab::Database::BackgroundMigration::BatchedMigration.for_configuration(gitlab_schema, job_class_name, batch_table_name, batch_column_name, job_arguments).exists?
|
||||
Gitlab::AppLogger.warn "Batched background migration not enqueued because it already exists: " \
|
||||
"job_class_name: #{job_class_name}, table_name: #{batch_table_name}, column_name: #{batch_column_name}, " \
|
||||
"job_arguments: #{job_arguments.inspect}"
|
||||
|
|
@ -119,11 +125,17 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
if migration.respond_to?(:gitlab_schema)
|
||||
migration.gitlab_schema = gitlab_schema
|
||||
end
|
||||
|
||||
migration.save!
|
||||
migration
|
||||
end
|
||||
|
||||
def finalize_batched_background_migration(job_class_name:, table_name:, column_name:, job_arguments:)
|
||||
Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.require_dml_mode!
|
||||
|
||||
database_name = Gitlab::Database.db_config_name(connection)
|
||||
|
||||
unless ActiveRecord::Base.configurations.primary?(database_name)
|
||||
|
|
@ -132,12 +144,47 @@ module Gitlab
|
|||
'https://docs.gitlab.com/ee/development/database/migrations_for_multiple_databases.html'
|
||||
end
|
||||
|
||||
migration = Gitlab::Database::BackgroundMigration::BatchedMigration.find_for_configuration(job_class_name, table_name, column_name, job_arguments)
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration.reset_column_information
|
||||
|
||||
migration = Gitlab::Database::BackgroundMigration::BatchedMigration.find_for_configuration(
|
||||
gitlab_schema_from_context, job_class_name, table_name, column_name, job_arguments)
|
||||
|
||||
raise 'Could not find batched background migration' if migration.nil?
|
||||
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigrationRunner.finalize(job_class_name, table_name, column_name, job_arguments, connection: connection)
|
||||
end
|
||||
|
||||
# Deletes batched background migration for the given configuration.
|
||||
#
|
||||
# job_class_name - The background migration job class as a string
|
||||
# table_name - The name of the table the migration iterates over
|
||||
# column_name - The name of the column the migration will batch over
|
||||
# job_arguments - Migration arguments
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# delete_batched_background_migration(
|
||||
# 'CopyColumnUsingBackgroundMigrationJob',
|
||||
# :events,
|
||||
# :id,
|
||||
# ['column1', 'column2'])
|
||||
def delete_batched_background_migration(job_class_name, table_name, column_name, job_arguments)
|
||||
Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.require_dml_mode!
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration.reset_column_information
|
||||
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
.for_configuration(
|
||||
gitlab_schema_from_context, job_class_name, table_name, column_name, job_arguments
|
||||
).delete_all
|
||||
end
|
||||
|
||||
def gitlab_schema_from_context
|
||||
if respond_to?(:allowed_gitlab_schemas) # Gitlab::Database::Migration::V2_0
|
||||
Array(allowed_gitlab_schemas).first
|
||||
else # Gitlab::Database::Migration::V1_0
|
||||
:gitlab_main
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,77 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# The purpose of this code is to transform legacy `database.yml`
|
||||
# into a `database.yml` containing `main:` as a name of a first database
|
||||
#
|
||||
# This should be removed once all places using legacy `database.yml`
|
||||
# are fixed. The likely moment to remove this check is the %14.0.
|
||||
#
|
||||
# This converts the following syntax:
|
||||
#
|
||||
# production:
|
||||
# adapter: postgresql
|
||||
# database: gitlabhq_production
|
||||
# username: git
|
||||
# password: "secure password"
|
||||
# host: localhost
|
||||
#
|
||||
# Into:
|
||||
#
|
||||
# production:
|
||||
# main:
|
||||
# adapter: postgresql
|
||||
# database: gitlabhq_production
|
||||
# username: git
|
||||
# password: "secure password"
|
||||
# host: localhost
|
||||
#
|
||||
|
||||
# The purpose of this code is to set the migrations path
|
||||
# for the Geo tracking database.
|
||||
module Gitlab
|
||||
module Patch
|
||||
module DatabaseConfig
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def load_database_yaml
|
||||
return super unless Gitlab.ee?
|
||||
|
||||
super.deep_merge(load_geo_database_yaml)
|
||||
end
|
||||
|
||||
# This method is taken from Rails to load a database YAML file without
|
||||
# evaluating ERB. This allows us to create the rake tasks for the Geo
|
||||
# tracking database without filling in the configuration values or
|
||||
# loading the environment. To be removed when we start configure Geo
|
||||
# tracking database in database.yml instead of custom database_geo.yml
|
||||
#
|
||||
# https://github.com/rails/rails/blob/v6.1.4/railties/lib/rails/application/configuration.rb#L255
|
||||
def load_geo_database_yaml
|
||||
path = Rails.root.join("config/database_geo.yml")
|
||||
return {} unless File.exist?(path)
|
||||
|
||||
require "rails/application/dummy_erb_compiler"
|
||||
|
||||
yaml = DummyERB.new(Pathname.new(path).read).result
|
||||
config = YAML.load(yaml) || {} # rubocop:disable Security/YAMLLoad
|
||||
|
||||
config.to_h do |env, configs|
|
||||
# This check is taken from Rails where the transformation
|
||||
# of a flat database.yml is done into `primary:`
|
||||
# https://github.com/rails/rails/blob/v6.1.4/activerecord/lib/active_record/database_configurations.rb#L169
|
||||
if configs.is_a?(Hash) && !configs.all? { |_, v| v.is_a?(Hash) }
|
||||
configs = { "geo" => configs }
|
||||
end
|
||||
|
||||
[env, configs]
|
||||
end
|
||||
end
|
||||
|
||||
def database_configuration
|
||||
super.to_h do |env, configs|
|
||||
if Gitlab.ee?
|
||||
if !configs.key?("geo") && File.exist?(Rails.root.join("config/database_geo.yml"))
|
||||
configs["geo"] = Rails.application.config_for(:database_geo).stringify_keys
|
||||
end
|
||||
|
||||
if configs.key?("geo")
|
||||
migrations_paths = Array(configs["geo"]["migrations_paths"])
|
||||
migrations_paths << "ee/db/geo/migrate" if migrations_paths.empty?
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ unless Rails.env.production?
|
|||
# expected.
|
||||
cop_names = args.to_a
|
||||
|
||||
todo_dir = RuboCop::TodoDir.new(RuboCop::TodoDir::DEFAULT_TODO_DIR)
|
||||
todo_dir = RuboCop::TodoDir.new(RuboCop::Formatter::TodoFormatter.base_directory)
|
||||
|
||||
if cop_names.any?
|
||||
# We are sorting the cop names to benefit from RuboCop cache which
|
||||
|
|
|
|||
|
|
@ -9671,6 +9671,9 @@ msgstr ""
|
|||
msgid "ContainerRegistry|Copy build command"
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|Copy image path"
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|Copy login command"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -16850,6 +16853,9 @@ msgstr ""
|
|||
msgid "Geo|Shards to synchronize"
|
||||
msgstr ""
|
||||
|
||||
msgid "Geo|Show more"
|
||||
msgstr ""
|
||||
|
||||
msgid "Geo|Site name can't be blank"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -40792,6 +40798,12 @@ msgstr ""
|
|||
msgid "UsageQuota|This namespace has no projects which use shared runners"
|
||||
msgstr ""
|
||||
|
||||
msgid "UsageQuota|This namespace has no projects which used shared runners in the current period"
|
||||
msgstr ""
|
||||
|
||||
msgid "UsageQuota|This table omits projects that used 0 CI/CD minutes or 0 shared runners duration"
|
||||
msgstr ""
|
||||
|
||||
msgid "UsageQuota|Total excess storage used"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -14,13 +14,6 @@ module RuboCop
|
|||
# For example, this formatter stores offenses for `RSpec/VariableName`
|
||||
# in `.rubocop_todo/rspec/variable_name.yml`.
|
||||
class TodoFormatter < BaseFormatter
|
||||
# Disable a cop which exceeds this limit. This way we ensure that we
|
||||
# don't enable a cop by accident when moving it from
|
||||
# .rubocop_todo.yml to .rubocop_todo/.
|
||||
# We keep the cop disabled if it has been disabled previously explicitly
|
||||
# via `Enabled: false` in .rubocop_todo.yml or .rubocop_todo/.
|
||||
MAX_OFFENSE_COUNT = 15
|
||||
|
||||
class Todo
|
||||
attr_reader :cop_name, :files, :offense_count
|
||||
|
||||
|
|
@ -41,12 +34,20 @@ module RuboCop
|
|||
end
|
||||
end
|
||||
|
||||
def initialize(output, options = {})
|
||||
directory = options.delete(:rubocop_todo_dir) || TodoDir::DEFAULT_TODO_DIR
|
||||
DEFAULT_BASE_DIRECTORY = File.expand_path('../../.rubocop_todo', __dir__)
|
||||
|
||||
class << self
|
||||
attr_accessor :base_directory
|
||||
end
|
||||
|
||||
self.base_directory = DEFAULT_BASE_DIRECTORY
|
||||
|
||||
def initialize(output, _options = {})
|
||||
@directory = self.class.base_directory
|
||||
@todos = Hash.new { |hash, cop_name| hash[cop_name] = Todo.new(cop_name) }
|
||||
@todo_dir = TodoDir.new(directory)
|
||||
@config_inspect_todo_dir = load_config_inspect_todo_dir(directory)
|
||||
@config_old_todo_yml = load_config_old_todo_yml(directory)
|
||||
@config_inspect_todo_dir = load_config_inspect_todo_dir
|
||||
@config_old_todo_yml = load_config_old_todo_yml
|
||||
check_multiple_configurations!
|
||||
|
||||
super
|
||||
|
|
@ -71,10 +72,21 @@ module RuboCop
|
|||
end
|
||||
end
|
||||
|
||||
def self.with_base_directory(directory)
|
||||
old = base_directory
|
||||
self.base_directory = directory
|
||||
|
||||
yield
|
||||
ensure
|
||||
self.base_directory = old
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :directory
|
||||
|
||||
def relative_path(path)
|
||||
parent = File.expand_path('..', @todo_dir.directory)
|
||||
parent = File.expand_path('..', directory)
|
||||
path.delete_prefix("#{parent}/")
|
||||
end
|
||||
|
||||
|
|
@ -84,7 +96,7 @@ module RuboCop
|
|||
yaml << '# Cop supports --auto-correct.' if todo.autocorrectable?
|
||||
yaml << "#{todo.cop_name}:"
|
||||
|
||||
if previously_disabled?(todo) && offense_count_exceeded?(todo)
|
||||
if previously_disabled?(todo)
|
||||
yaml << " # Offense count: #{todo.offense_count}"
|
||||
yaml << ' # Temporarily disabled due to too many offenses'
|
||||
yaml << ' Enabled: false'
|
||||
|
|
@ -99,10 +111,6 @@ module RuboCop
|
|||
yaml.join("\n")
|
||||
end
|
||||
|
||||
def offense_count_exceeded?(todo)
|
||||
todo.offense_count > MAX_OFFENSE_COUNT
|
||||
end
|
||||
|
||||
def check_multiple_configurations!
|
||||
cop_names = @config_inspect_todo_dir.keys & @config_old_todo_yml.keys
|
||||
return if cop_names.empty?
|
||||
|
|
@ -121,7 +129,7 @@ module RuboCop
|
|||
config['Enabled'] == false
|
||||
end
|
||||
|
||||
def load_config_inspect_todo_dir(directory)
|
||||
def load_config_inspect_todo_dir
|
||||
@todo_dir.list_inspect.each_with_object({}) do |path, combined|
|
||||
config = YAML.load_file(path)
|
||||
combined.update(config) if Hash === config
|
||||
|
|
@ -130,7 +138,7 @@ module RuboCop
|
|||
|
||||
# Load YAML configuration from `.rubocop_todo.yml`.
|
||||
# We consider this file already old, obsolete, and to be removed soon.
|
||||
def load_config_old_todo_yml(directory)
|
||||
def load_config_old_todo_yml
|
||||
path = File.expand_path(File.join(directory, '../.rubocop_todo.yml'))
|
||||
config = YAML.load_file(path) if File.exist?(path)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,22 +6,36 @@ require 'active_support/inflector/inflections'
|
|||
module RuboCop
|
||||
# Helper class to manage file access to RuboCop TODOs in .rubocop_todo directory.
|
||||
class TodoDir
|
||||
DEFAULT_TODO_DIR = File.expand_path('../.rubocop_todo', __dir__)
|
||||
# Suffix a TODO file.
|
||||
SUFFIX_YAML = '.yml'
|
||||
|
||||
# Suffix to indicate TODOs being inspected right now.
|
||||
SUFFIX_INSPECT = '.inspect'
|
||||
|
||||
attr_reader :directory
|
||||
|
||||
# Instantiates a TodoDir.
|
||||
#
|
||||
# @param directory [String] base directory where all TODO YAML files are written to.
|
||||
# @param inflector [ActiveSupport::Inflector, #underscore] an object which supports
|
||||
# converting a string to its underscored version.
|
||||
def initialize(directory, inflector: ActiveSupport::Inflector)
|
||||
@directory = directory
|
||||
@inflector = inflector
|
||||
end
|
||||
|
||||
def read(cop_name, suffix = nil)
|
||||
read_suffixed(cop_name)
|
||||
# Reads content of TODO YAML for given +cop_name+.
|
||||
#
|
||||
# @param cop_name [String] name of the cop rule
|
||||
#
|
||||
# @return [String, nil] content of the TODO YAML file if it exists
|
||||
def read(cop_name)
|
||||
path = path_for(cop_name)
|
||||
|
||||
File.read(path) if File.exist?(path)
|
||||
end
|
||||
|
||||
# Saves +content+ for given +cop_name+ to TODO YAML file.
|
||||
#
|
||||
# @return [String] path of the written TODO YAML file
|
||||
def write(cop_name, content)
|
||||
path = path_for(cop_name)
|
||||
|
||||
|
|
@ -31,6 +45,10 @@ module RuboCop
|
|||
path
|
||||
end
|
||||
|
||||
# Marks a TODO YAML file for inspection by renaming the original TODO YAML
|
||||
# and appending the suffix +.inspect+ to it.
|
||||
#
|
||||
# @return [Boolean] +true+ a file was marked for inspection successfully.
|
||||
def inspect(cop_name)
|
||||
path = path_for(cop_name)
|
||||
|
||||
|
|
@ -42,38 +60,47 @@ module RuboCop
|
|||
end
|
||||
end
|
||||
|
||||
# Marks all TODO YAML files for inspection.
|
||||
#
|
||||
# @return [Integer] number of renamed YAML TODO files.
|
||||
#
|
||||
# @see inspect
|
||||
def inspect_all
|
||||
pattern = File.join(@directory, '**/*.yml')
|
||||
pattern = File.join(@directory, "**/*#{SUFFIX_YAML}")
|
||||
|
||||
Dir.glob(pattern).count do |path|
|
||||
FileUtils.mv(path, "#{path}#{SUFFIX_INSPECT}")
|
||||
end
|
||||
end
|
||||
|
||||
# Returns a list of TODO YAML files which are marked for inspection.
|
||||
#
|
||||
# @return [Array<String>] list of paths
|
||||
#
|
||||
# @see inspect
|
||||
# @see inspect_all
|
||||
def list_inspect
|
||||
pattern = File.join(@directory, "**/*.yml.inspect")
|
||||
pattern = File.join(@directory, "**/*#{SUFFIX_YAML}#{SUFFIX_INSPECT}")
|
||||
|
||||
Dir.glob(pattern)
|
||||
end
|
||||
|
||||
# Deletes a list of TODO yaml files which were marked for inspection.
|
||||
#
|
||||
# @return [Integer] number of deleted YAML TODO files.
|
||||
#
|
||||
# @see #inspect
|
||||
# @see #inspect_all
|
||||
def delete_inspected
|
||||
pattern = File.join(@directory, '**/*.yml.inspect')
|
||||
|
||||
Dir.glob(pattern).count do |path|
|
||||
list_inspect.count do |path|
|
||||
File.delete(path)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def read_suffixed(cop_name, suffix = nil)
|
||||
path = path_for(cop_name, suffix)
|
||||
|
||||
File.read(path) if File.exist?(path)
|
||||
end
|
||||
|
||||
def path_for(cop_name, suffix = nil)
|
||||
todo_path = "#{@inflector.underscore(cop_name)}.yml#{suffix}"
|
||||
def path_for(cop_name)
|
||||
todo_path = "#{@inflector.underscore(cop_name)}#{SUFFIX_YAML}"
|
||||
|
||||
File.join(@directory, todo_path)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,13 +12,35 @@ module Glfm
|
|||
|
||||
def process
|
||||
output('Updating specification...')
|
||||
ghfm_spec_txt_lines = download_and_write_ghfm_spec_txt
|
||||
ghfm_spec_txt_lines = load_ghfm_spec_txt
|
||||
glfm_spec_txt_string = build_glfm_spec_txt(ghfm_spec_txt_lines)
|
||||
write_glfm_spec_txt(glfm_spec_txt_string)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_ghfm_spec_txt
|
||||
# We only re-download the GitHub Flavored Markdown specification if the
|
||||
# UPDATE_GHFM_SPEC_TXT environment variable is set to true, which should only
|
||||
# ever be done manually and locally, never in CI. This provides some security
|
||||
# protection against a possible injection attack vector, if the GitHub-hosted
|
||||
# version of the spec is ever temporarily compromised with an injection attack.
|
||||
#
|
||||
# This also avoids doing external network access to download the file
|
||||
# in CI jobs, which can avoid potentially flaky builds if the GitHub-hosted
|
||||
# version of the file is temporarily unavailable.
|
||||
if ENV['UPDATE_GHFM_SPEC_TXT'] == 'true'
|
||||
download_and_write_ghfm_spec_txt
|
||||
else
|
||||
read_existing_ghfm_spec_txt
|
||||
end
|
||||
end
|
||||
|
||||
def read_existing_ghfm_spec_txt
|
||||
output("Reading existing #{GHFM_SPEC_TXT_PATH}...")
|
||||
File.open(GHFM_SPEC_TXT_PATH).readlines
|
||||
end
|
||||
|
||||
def download_and_write_ghfm_spec_txt
|
||||
output("Downloading #{GHFM_SPEC_TXT_URI}...")
|
||||
ghfm_spec_txt_uri_io = URI.open(GHFM_SPEC_TXT_URI)
|
||||
|
|
|
|||
|
|
@ -17,8 +17,11 @@ else
|
|||
cp config/database.yml.postgresql config/database.yml
|
||||
fi
|
||||
|
||||
if [ -f config/database_geo.yml.postgresql ]; then
|
||||
cp config/database_geo.yml.postgresql config/database_geo.yml
|
||||
# Remove Geo database setting if `ee/` directory does not exist. When it does
|
||||
# not exist, it runs the GitLab test suite "as if FOSS", meaning the jobs run
|
||||
# in the context of gitlab-org/gitlab-foss where the Geo is not available.
|
||||
if [ ! -d "ee/" ] ; then
|
||||
sed -i '/geo:/,/^$/d' config/database.yml
|
||||
fi
|
||||
|
||||
# Set user to a non-superuser to ensure we test permissions
|
||||
|
|
@ -27,11 +30,6 @@ sed -i 's/username: root/username: gitlab/g' config/database.yml
|
|||
sed -i 's/localhost/postgres/g' config/database.yml
|
||||
sed -i 's/username: git/username: postgres/g' config/database.yml
|
||||
|
||||
if [ -f config/database_geo.yml ]; then
|
||||
sed -i 's/localhost/postgres/g' config/database_geo.yml
|
||||
sed -i 's/username: git/username: postgres/g' config/database_geo.yml
|
||||
fi
|
||||
|
||||
cp config/cable.yml.example config/cable.yml
|
||||
sed -i 's|url:.*$|url: redis://redis:6379|g' config/cable.yml
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,10 @@ RSpec.describe 'Database schema' do
|
|||
vulnerability_identifiers: %w[external_id],
|
||||
vulnerability_scanners: %w[external_id],
|
||||
security_scans: %w[pipeline_id], # foreign key is not added as ci_pipeline table will be moved into different db soon
|
||||
vulnerability_reads: %w[cluster_agent_id]
|
||||
vulnerability_reads: %w[cluster_agent_id],
|
||||
# See: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87584
|
||||
# Fixes performance issues with the deletion of web-hooks with many log entries
|
||||
web_hook_logs: %w[web_hook_id]
|
||||
}.with_indifferent_access.freeze
|
||||
|
||||
context 'for table' do
|
||||
|
|
|
|||
|
|
@ -95,10 +95,6 @@ FactoryBot.define do
|
|||
severity { 'unknown' }
|
||||
end
|
||||
|
||||
trait :threat_monitoring do
|
||||
domain { :threat_monitoring }
|
||||
end
|
||||
|
||||
trait :prometheus do
|
||||
monitoring_tool { Gitlab::AlertManagement::Payload::MONITORING_TOOLS[:prometheus] }
|
||||
payload do
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ FactoryBot.define do
|
|||
sequence(:job_arguments) { |n| [["column_#{n}"], ["column_#{n}_convert_to_bigint"]] }
|
||||
total_tuple_count { 10_000 }
|
||||
pause_ms { 100 }
|
||||
gitlab_schema { :gitlab_main }
|
||||
|
||||
trait(:paused) do
|
||||
status { 0 }
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ RSpec.describe 'Pipeline Editor', :js do
|
|||
let(:other_branch) { 'test' }
|
||||
|
||||
before do
|
||||
stub_feature_flags(pipeline_editor_file_tree: false)
|
||||
|
||||
sign_in(user)
|
||||
project.add_developer(user)
|
||||
|
||||
|
|
@ -70,14 +68,8 @@ RSpec.describe 'Pipeline Editor', :js do
|
|||
expect(page).to have_content('Pipeline Editor')
|
||||
end
|
||||
|
||||
describe 'Branch Switcher (pipeline_editor_file_tree disabled)' do
|
||||
it_behaves_like 'default branch switcher behavior'
|
||||
end
|
||||
|
||||
describe 'Branch Switcher (pipeline_editor_file_tree enabled)' do
|
||||
describe 'Branch Switcher' do
|
||||
before do
|
||||
stub_feature_flags(pipeline_editor_file_tree: true)
|
||||
|
||||
visit project_ci_pipeline_editor_path(project)
|
||||
wait_for_requests
|
||||
|
||||
|
|
|
|||
|
|
@ -30,10 +30,12 @@ RSpec.describe 'User edits Release', :js do
|
|||
|
||||
it 'renders the breadcrumbs' do
|
||||
within('.breadcrumbs') do
|
||||
expect(page).to have_content("#{project.creator.name} #{project.name} Edit Release")
|
||||
expect(page).to have_content("#{project.creator.name} #{project.name} Releases #{release.name} Edit Release")
|
||||
|
||||
expect(page).to have_link(project.creator.name, href: user_path(project.creator))
|
||||
expect(page).to have_link(project.name, href: project_path(project))
|
||||
expect(page).to have_link(_('Releases'), href: project_releases_path(project))
|
||||
expect(page).to have_link(release.name, href: project_release_path(project, release))
|
||||
expect(page).to have_link('Edit Release', href: edit_project_release_path(project, release))
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ const ajv = new Ajv({
|
|||
strictTuples: false,
|
||||
allowMatchingProperties: true,
|
||||
});
|
||||
ajv.addKeyword('markdownDescription');
|
||||
|
||||
AjvFormats(ajv);
|
||||
const schema = ajv.compile(CiSchema);
|
||||
|
|
|
|||
|
|
@ -301,17 +301,23 @@ describe('CE IssuesListApp component', () => {
|
|||
describe('initial url params', () => {
|
||||
describe('page', () => {
|
||||
it('page_after is set from the url params', () => {
|
||||
setWindowLocation('?page_after=randomCursorString');
|
||||
setWindowLocation('?page_after=randomCursorString&first_page_size=20');
|
||||
wrapper = mountComponent();
|
||||
|
||||
expect(wrapper.vm.$route.query).toMatchObject({ page_after: 'randomCursorString' });
|
||||
expect(wrapper.vm.$route.query).toMatchObject({
|
||||
page_after: 'randomCursorString',
|
||||
first_page_size: '20',
|
||||
});
|
||||
});
|
||||
|
||||
it('page_before is set from the url params', () => {
|
||||
setWindowLocation('?page_before=anotherRandomCursorString');
|
||||
setWindowLocation('?page_before=anotherRandomCursorString&last_page_size=20');
|
||||
wrapper = mountComponent();
|
||||
|
||||
expect(wrapper.vm.$route.query).toMatchObject({ page_before: 'anotherRandomCursorString' });
|
||||
expect(wrapper.vm.$route.query).toMatchObject({
|
||||
page_before: 'anotherRandomCursorString',
|
||||
last_page_size: '20',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -675,10 +681,10 @@ describe('CE IssuesListApp component', () => {
|
|||
});
|
||||
|
||||
describe.each`
|
||||
event | paramName | paramValue
|
||||
${'next-page'} | ${'page_after'} | ${'endCursor'}
|
||||
${'previous-page'} | ${'page_before'} | ${'startCursor'}
|
||||
`('when "$event" event is emitted by IssuableList', ({ event, paramName, paramValue }) => {
|
||||
event | params
|
||||
${'next-page'} | ${{ page_after: 'endCursor', page_before: undefined, first_page_size: 20, last_page_size: undefined }}
|
||||
${'previous-page'} | ${{ page_after: undefined, page_before: 'startCursor', first_page_size: undefined, last_page_size: 20 }}
|
||||
`('when "$event" event is emitted by IssuableList', ({ event, params }) => {
|
||||
beforeEach(() => {
|
||||
wrapper = mountComponent({
|
||||
data: {
|
||||
|
|
@ -697,9 +703,9 @@ describe('CE IssuesListApp component', () => {
|
|||
expect(scrollUp).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`updates url with "${paramName}" param`, () => {
|
||||
it(`updates url`, () => {
|
||||
expect(wrapper.vm.$router.push).toHaveBeenCalledWith({
|
||||
query: expect.objectContaining({ [paramName]: paramValue }),
|
||||
query: expect.objectContaining(params),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue