diff --git a/app/assets/javascripts/reports/components/summary_row.vue b/app/assets/javascripts/reports/components/summary_row.vue index 1191e43d0d98e897d3f77a3e8aa792263de5c986..9cbe2a690a013c0607b9d92a19de6fda24043135 100644 --- a/app/assets/javascripts/reports/components/summary_row.vue +++ b/app/assets/javascripts/reports/components/summary_row.vue @@ -53,11 +53,19 @@ export default { /> -
-
{{ summary }}
- - +
+ {{ summary + }}  + +
+
+
+
diff --git a/app/assets/javascripts/static_site_editor/components/publish_toolbar.vue b/app/assets/javascripts/static_site_editor/components/publish_toolbar.vue index 83b50b2f8ebe9a1a2ddcb3d4c3f4e15bb45d6b4d..7f00fb71b0427c4645b4614c93b70fe15de339f9 100644 --- a/app/assets/javascripts/static_site_editor/components/publish_toolbar.vue +++ b/app/assets/javascripts/static_site_editor/components/publish_toolbar.vue @@ -1,9 +1,10 @@ diff --git a/app/assets/javascripts/static_site_editor/index.js b/app/assets/javascripts/static_site_editor/index.js index 22f96a60df06e150813f1d510dc6f0a86febba0a..3d40f3918a41f4e61700990cb4963e7f13ef18b6 100644 --- a/app/assets/javascripts/static_site_editor/index.js +++ b/app/assets/javascripts/static_site_editor/index.js @@ -6,7 +6,7 @@ const initStaticSiteEditor = el => { const { projectId, path: sourcePath } = el.dataset; const store = createStore({ - initialState: { projectId, sourcePath }, + initialState: { projectId, sourcePath, username: window.gon.current_username }, }); return new Vue({ diff --git a/app/assets/javascripts/static_site_editor/services/submit_content_changes.js b/app/assets/javascripts/static_site_editor/services/submit_content_changes.js new file mode 100644 index 0000000000000000000000000000000000000000..6b0d8c74ff735fffbe66cfad23ba9003672ac267 --- /dev/null +++ b/app/assets/javascripts/static_site_editor/services/submit_content_changes.js @@ -0,0 +1,4 @@ +// TODO implement +const submitContentChanges = () => new Promise(resolve => setTimeout(resolve, 1000)); + +export default submitContentChanges; diff --git a/app/assets/javascripts/static_site_editor/store/actions.js b/app/assets/javascripts/static_site_editor/store/actions.js index 141148de1e05f7fcb1ea55edde350d835e076d71..c57ef86f6efb6e0022ae4a45b1dc5ecf78a6f0ab 100644 --- a/app/assets/javascripts/static_site_editor/store/actions.js +++ b/app/assets/javascripts/static_site_editor/store/actions.js @@ -3,6 +3,7 @@ import { __ } from '~/locale'; import * as mutationTypes from './mutation_types'; import loadSourceContent from '~/static_site_editor/services/load_source_content'; +import submitContentChanges from '~/static_site_editor/services/submit_content_changes'; export const loadContent = ({ commit, state: { sourcePath, projectId } }) => { commit(mutationTypes.LOAD_CONTENT); @@ -19,4 +20,15 @@ export const setContent = ({ commit }, content) => { commit(mutationTypes.SET_CONTENT, content); }; +export const submitChanges = ({ state: { projectId, content, sourcePath, username }, commit }) => { + commit(mutationTypes.SUBMIT_CHANGES); + + return submitContentChanges({ content, projectId, sourcePath, username }) + .then(data => commit(mutationTypes.SUBMIT_CHANGES_SUCCESS, data)) + .catch(error => { + commit(mutationTypes.SUBMIT_CHANGES_ERROR); + createFlash(error.message); + }); +}; + export default () => {}; diff --git a/app/assets/javascripts/static_site_editor/store/mutation_types.js b/app/assets/javascripts/static_site_editor/store/mutation_types.js index 2bb201f5d247366ab474185303439ba9db929aa2..35eb35ebbe912d27fe5ea973ec6af0db37b6ded1 100644 --- a/app/assets/javascripts/static_site_editor/store/mutation_types.js +++ b/app/assets/javascripts/static_site_editor/store/mutation_types.js @@ -2,3 +2,6 @@ export const LOAD_CONTENT = 'loadContent'; export const RECEIVE_CONTENT_SUCCESS = 'receiveContentSuccess'; export const RECEIVE_CONTENT_ERROR = 'receiveContentError'; export const SET_CONTENT = 'setContent'; +export const SUBMIT_CHANGES = 'submitChanges'; +export const SUBMIT_CHANGES_SUCCESS = 'submitChangesSuccess'; +export const SUBMIT_CHANGES_ERROR = 'submitChangesError'; diff --git a/app/assets/javascripts/static_site_editor/store/mutations.js b/app/assets/javascripts/static_site_editor/store/mutations.js index 8b8bacf35c271eaaa65772e121f5ebede7daed52..f98177bbc18ec6fbc5f158fac62ab50095b3ea0a 100644 --- a/app/assets/javascripts/static_site_editor/store/mutations.js +++ b/app/assets/javascripts/static_site_editor/store/mutations.js @@ -16,4 +16,15 @@ export default { [types.SET_CONTENT](state, content) { state.content = content; }, + [types.SUBMIT_CHANGES](state) { + state.isSavingChanges = true; + }, + [types.SUBMIT_CHANGES_SUCCESS](state, meta) { + state.savedContentMeta = meta; + state.isSavingChanges = false; + state.originalContent = state.content; + }, + [types.SUBMIT_CHANGES_ERROR](state) { + state.isSavingChanges = false; + }, }; diff --git a/app/assets/javascripts/static_site_editor/store/state.js b/app/assets/javascripts/static_site_editor/store/state.js index 1ae11b3343d1cbfc746f388a6d62c0b8cc7fa04b..e457fde591aa4d87a5eafa8ca22aba53b76576c9 100644 --- a/app/assets/javascripts/static_site_editor/store/state.js +++ b/app/assets/javascripts/static_site_editor/store/state.js @@ -1,4 +1,5 @@ const createState = (initialState = {}) => ({ + username: null, projectId: null, sourcePath: null, diff --git a/changelogs/unreleased/update-docker-to-19-03-8-in-auto-devops.yml b/changelogs/unreleased/update-docker-to-19-03-8-in-auto-devops.yml new file mode 100644 index 0000000000000000000000000000000000000000..ec173c5f76d4614f1176ce456aaf3e4cdf77021f --- /dev/null +++ b/changelogs/unreleased/update-docker-to-19-03-8-in-auto-devops.yml @@ -0,0 +1,5 @@ +--- +title: Update Auto DevOps docker version to 19.03.8 +merge_request: 29081 +author: +type: changed diff --git a/doc/README.md b/doc/README.md index bcb3140887dae6a2be7fe624af86190f4a621ff0..6b863436ce2be7a4b4232ddace4050608d4d733a 100644 --- a/doc/README.md +++ b/doc/README.md @@ -238,7 +238,7 @@ The following documentation relates to the DevOps **Verify** stage: | [GitLab CI/CD](ci/README.md) | Explore the features and capabilities of Continuous Integration with GitLab. | | [JUnit test reports](ci/junit_test_reports.md) | Display JUnit test reports on merge requests. | | [Multi-project pipelines](ci/multi_project_pipelines.md) **(PREMIUM)** | Visualize entire pipelines that span multiple projects, including all cross-project inter-dependencies. | -| [Pipeline Graphs](ci/pipelines/index.md#visualizing-pipelines) | Visualize builds. | +| [Pipeline Graphs](ci/pipelines/index.md#visualize-pipelines) | Visualize builds. | | [Review Apps](ci/review_apps/index.md) | Preview changes to your application right from a merge request. |
diff --git a/doc/api/groups.md b/doc/api/groups.md index 33a3c2305d509bc50c1eee8299384b066bd8f095..1809ddfa47fa1447b2efe27ab040f406575822df 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -240,6 +240,10 @@ Example response: ] ``` +NOTE: **Note:** + +To distinguish between a project in the group and a project shared to the group, the `namespace` attribute can be used. When a project has been shared to the group, its `namespace` will be different from the group the request is being made for. + ## Details of a group Get all details of a group. This endpoint can be accessed without authentication @@ -255,7 +259,7 @@ Parameters: | ------------------------ | -------------- | -------- | ----------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user. | | `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only). | -| `with_projects` | boolean | no | Include details from projects that belong to the specified group (defaults to `true`). | +| `with_projects` | boolean | no | Include details from projects that belong to the specified group (defaults to `true`). (Deprecated, [will be removed in 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213797). To get the details of all projects within a group, use the [list a group's projects endpoint](#list-a-groups-projects).) | ```shell curl --header "PRIVATE-TOKEN: " https://gitlab.example.com/api/v4/groups/4 @@ -578,6 +582,10 @@ This endpoint returns: and later. To get the details of all projects within a group, use the [list a group's projects endpoint](#list-a-groups-projects) instead. +NOTE: **Note:** + +The `projects` and `shared_projects` attributes [will be deprecated in GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213797). To get the details of all projects within a group, use the [list a group's projects endpoint](#list-a-groups-projects) instead. + Example response: ```json diff --git a/doc/ci/jenkins/index.md b/doc/ci/jenkins/index.md index 9b72d0bfb5e09e4c03c897c3a05cc3612b5dd7b2..551e32ac816d9a2ba07a82f231e70f9f71ba2ef9 100644 --- a/doc/ci/jenkins/index.md +++ b/doc/ci/jenkins/index.md @@ -50,7 +50,7 @@ There are some high level differences between the products worth mentioning: - on push - on [schedule](../pipelines/schedules.md) - - from the [GitLab UI](../pipelines/index.md#manually-executing-pipelines) + - from the [GitLab UI](../pipelines/index.md#run-a-pipeline-manually) - by [API call](../triggers/README.md) - by [webhook](../triggers/README.md#triggering-a-pipeline-from-a-webhook) - by [ChatOps](../chatops/README.md) diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md index 7983dded81465130b67027f009b1921a730f2835..5a732248ec14e859383a28b9b758267a501cb7f4 100644 --- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md +++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md @@ -116,7 +116,7 @@ unexpected timing. For example, when a source or target branch is advanced. In this case, the pipeline fails because of `fatal: reference is not a tree:` error, which indicates that the checkout-SHA is not found in the merge ref. -This behavior was improved at GitLab 12.4 by introducing [Persistent pipeline refs](../../pipelines/index.md#persistent-pipeline-refs). +This behavior was improved at GitLab 12.4 by introducing [Persistent pipeline refs](../../pipelines/index.md#troubleshooting-fatal-reference-is-not-a-tree). You should be able to create pipelines at any timings without concerning the error. ## Using Merge Trains **(PREMIUM)** diff --git a/doc/ci/multi_project_pipelines.md b/doc/ci/multi_project_pipelines.md index 14277b6b55b9f7736f853c92fd0aa8ab08f0bdb9..2627f83c0430468f09e4f50954146fc52aa29f03 100644 --- a/doc/ci/multi_project_pipelines.md +++ b/doc/ci/multi_project_pipelines.md @@ -38,7 +38,7 @@ With Multi-Project Pipelines you can visualize the entire pipeline, including al > [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/2121) in [GitLab Premium 9.3](https://about.gitlab.com/releases/2017/06/22/gitlab-9-3-released/#multi-project-pipeline-graphs). When you configure GitLab CI/CD for your project, you can visualize the stages of your -[jobs](pipelines/index.md#configuring-pipelines) on a [pipeline graph](pipelines/index.md#visualizing-pipelines). +[jobs](pipelines/index.md#configure-a-pipeline) on a [pipeline graph](pipelines/index.md#visualize-pipelines). ![Multi-project pipeline graph](img/multi_project_pipeline_graph.png) diff --git a/doc/ci/pipelines/img/job_group_v12_10.png b/doc/ci/pipelines/img/job_group_v12_10.png new file mode 100644 index 0000000000000000000000000000000000000000..0ce121ab5729e4fd099efdcd7926df6ec51ba2ca Binary files /dev/null and b/doc/ci/pipelines/img/job_group_v12_10.png differ diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md index 5ce4e1649bccf7ac3a81c9b67071ac52df169629..91908d6c5e41a1c1844294f47c07fd18b21b4436 100644 --- a/doc/ci/pipelines/index.md +++ b/doc/ci/pipelines/index.md @@ -3,183 +3,193 @@ disqus_identifier: 'https://docs.gitlab.com/ee/ci/pipelines.html' type: reference --- -# Creating and using CI/CD pipelines +# CI/CD pipelines > Introduced in GitLab 8.8. NOTE: **Tip:** -Watch our +Watch the ["Mastering continuous software development"](https://about.gitlab.com/webcast/mastering-ci-cd/) -webcast to see a comprehensive demo of GitLab CI/CD pipeline. +webcast to see a comprehensive demo of a GitLab CI/CD pipeline. Pipelines are the top-level component of continuous integration, delivery, and deployment. Pipelines comprise: -- Jobs that define what to run. For example, code compilation or test runs. -- Stages that define when and how to run. For example, that tests run only after code compilation. +- Jobs, which define *what* to do. For example, jobs that compile or test code. +- Stages, which define *when* to run the jobs. For example, stages that run tests after stages that compile the code. -Multiple jobs in the same stage are executed by [Runners](../runners/README.md) in parallel, if there are enough concurrent [Runners](../runners/README.md). +Jobs are executed by [Runners](../runners/README.md). Multiple jobs in the same stage are executed in parallel, +if there are enough concurrent runners. If all the jobs in a stage: - Succeed, the pipeline moves on to the next stage. - Fail, the next stage is not (usually) executed and the pipeline ends early. +In general, pipelines are executed automatically and require no intervention once created. However, there are +also times when you can manually interact with a pipeline. + +A typical pipeline might consist of four stages, executed in the following order: + +- A `build` stage, with a job called `compile`. +- A `test` stage, with two jobs called `test1` and `test2`. +- A `staging` stage, with a job called `deploy-to-stage`. +- A `production` stage, with a job called `deploy-to-prod`. + NOTE: **Note:** If you have a [mirrored repository that GitLab pulls from](../../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository-starter), you may need to enable pipeline triggering in your project's **Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates**. -## Simple pipeline example +## Types of pipelines -As an example, imagine a pipeline consisting of four stages, executed in the following order: +Pipelines can be configured in many different ways: -- `build`, with a job called `compile`. -- `test`, with two jobs called `test` and `test2`. -- `staging`, with a job called `deploy-to-stage`. -- `production`, with a job called `deploy-to-prod`. +- [Multi-project pipelines](../multi_project_pipelines.md) combine pipelines for different projects together. +- [Parent-Child pipelines](../parent_child_pipelines.md) break down complex pipelines + into one parent pipeline that can trigger multiple child sub-pipelines, which all + run in the same project and with the same SHA. +- [Pipelines for Merge Requests](../merge_request_pipelines/index.md) run for merge + requests only (rather than for every commit). +- [Pipelines for Merged Results](../merge_request_pipelines/pipelines_for_merged_results/index.md) + are merge request pipelines that act as though the changes from the source branch have + already been merged into the target branch. +- [Merge Trains](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md) + use pipelines for merged results to queue merges one after the other. -## Visualizing pipelines +## Configure a pipeline -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5742) in GitLab 8.11. +Pipelines and their component jobs and stages are defined in the CI/CD pipeline configuration file for each project. -Pipelines can be complex structures with many sequential and parallel jobs. - -To make it easier to understand the flow of a pipeline, GitLab has pipeline graphs for viewing pipelines -and their statuses. - -Pipeline graphs can be displayed in two different ways, depending on the page you -access the graph from. +- Jobs are the [basic configuration](../yaml/README.md#introduction) component. +- Stages are defined by using the [`stages`](../yaml/README.md#stages) keyword. -NOTE: **Note:** -GitLab capitalizes the stages' names when shown in the pipeline graphs (below). +For a list of configuration options in the CI pipeline file, see the [GitLab CI/CD Pipeline Configuration Reference](../yaml/README.md). -### Regular pipeline graphs +You can also configure specific aspects of your pipelines through the GitLab UI. For example: -Regular pipeline graphs show the names of the jobs of each stage. Regular pipeline graphs can -be found when you are on a [single pipeline page](#accessing-pipelines). For example: +- [Pipeline settings](settings.md) for each project. +- [Pipeline schedules](schedules.md). +- [Custom CI/CD variables](../variables/README.md#creating-a-custom-environment-variable). -![Pipelines example](img/pipelines.png) +### View pipelines -### Pipeline mini graphs +You can find the current and historical pipeline runs under your project's +**CI/CD > Pipelines** page. You can also access pipelines for a merge request by navigating +to its **Pipelines** tab. -Pipeline mini graphs take less space and can tell you at a -quick glance if all jobs passed or something failed. The pipeline mini graph can -be found when you navigate to: +![Pipelines index page](img/pipelines_index.png) -- The pipelines index page. -- A single commit page. -- A merge request page. +Clicking a pipeline will bring you to the **Pipeline Details** page and show +the jobs that were run for that pipeline. From here you can cancel a running pipeline, +retry jobs on a failed pipeline, or [delete a pipeline](#delete-a-pipeline). -Pipeline mini graphs allow you to see all related jobs for a single commit and the net result -of each stage of your pipeline. This allows you to quickly see what failed and -fix it. +[Starting in GitLab 12.3](https://gitlab.com/gitlab-org/gitlab-foss/issues/50499), a link to the +latest pipeline for the last commit of a given branch is available at `/project/pipelines/[branch]/latest`. +Also, `/project/pipelines/latest` will redirect you to the latest pipeline for the last commit +on the project's default branch. -Stages in pipeline mini graphs are collapsible. Hover your mouse over them and click to expand their jobs. +### Run a pipeline manually -| Mini graph | Mini graph expanded | -|:-------------------------------------------------------------|:---------------------------------------------------------------| -| ![Pipelines mini graph](img/pipelines_mini_graph_simple.png) | ![Pipelines mini graph extended](img/pipelines_mini_graph.png) | +Pipelines can be manually executed, with predefined or manually-specified [variables](../variables/README.md). -### Job ordering in pipeline graphs +You might do this if the results of a pipeline (for example, a code build) are required outside the normal +operation of the pipeline. -Job ordering depends on the type of pipeline graph. For [regular pipeline graphs](#regular-pipeline-graphs), jobs are sorted by name. +To execute a pipeline manually: -For [pipeline mini graphs](#pipeline-mini-graphs) ([introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9760) -in GitLab 9.0), jobs are sorted by severity and then by name. +1. Navigate to your project's **CI/CD > Pipelines**. +1. Click on the **Run Pipeline** button. +1. On the **Run Pipeline** page: + 1. Select the branch to run the pipeline for in the **Create for** field. + 1. Enter any [environment variables](../variables/README.md) required for the pipeline run. + 1. Click the **Create pipeline** button. -The order of severity is: +The pipeline will execute the jobs as configured. -- failed -- warning -- pending -- running -- manual -- scheduled -- canceled -- success -- skipped -- created +### Run a pipeline by using a URL query string -For example: +> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/24146) in GitLab 12.5. -![Pipeline mini graph sorting](img/pipelines_mini_graph_sorting.png) +You can use a query string to pre-populate the **Run Pipeline** page. For example, the query string +`.../pipelines/new?ref=my_branch&var[foo]=bar&file_var[file_foo]=file_bar` will pre-populate the +**Run Pipeline** page with: -### Expanding and collapsing job log sections +- **Run for** field: `my_branch`. +- **Variables** section: + - Variable: + - Key: `foo` + - Value: `bar` + - File: + - Key: `file_foo` + - Value: `file_bar` -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/14664) in GitLab 12.0. +The format of the `pipelines/new` URL is: -Job logs are divided into sections that can be collapsed or expanded. Each section will display -the duration. +```plaintext +.../pipelines/new?ref=&var[]=&file_var[]= +``` -In the following example: +The following parameters are supported: -- Two sections are collapsed and can be expanded. -- Three sections are expanded and can be collapsed. +- `ref`: specify the branch to populate the **Run for** field with. +- `var`: specify a `Variable` variable. +- `file_var`: specify a `File` variable. -![Collapsible sections](img/collapsible_log_v12_6.png) +For each `var` or `file_var`, a key and value are required. -#### Custom collapsible sections +### Add manual interaction to your pipeline -You can create collapsible sections in job logs by manually outputting special codes -that GitLab will use to determine what sections to collapse: +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7931) in GitLab 8.15. -- Section start marker: `section_start:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` + `TEXT_OF_SECTION_HEADER` -- Section end marker: `section_end:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` +Manual actions, configured using the [`when:manual`](../yaml/README.md#whenmanual) parameter, +allow you to require manual interaction before moving forward in the pipeline. -You must add these codes to the script section of the CI configuration. For example, -using `echo`: +You can do this straight from the pipeline graph. Just click the play button +to execute that particular job. -```yaml -job1: - script: - - echo -e "section_start:`date +%s`:my_first_section\r\e[0KHeader of the 1st collapsible section" - - echo 'this line should be hidden when collapsed' - - echo -e "section_end:`date +%s`:my_first_section\r\e[0K" -``` +For example, your pipeline might start automatically, but it requires manual action to +[deploy to production](../environments.md#configuring-manual-deployments). In the example below, the `production` +stage has a job with a manual action. -In the example above: +![Pipelines example](img/pipelines.png) -- `date +%s`: The Unix timestamp (for example `1560896352`). -- `my_first_section`: The name given to the section. -- `\r\e[0K`: Prevents the section markers from displaying in the rendered (colored) - job log, but they are displayed in the raw job log. To see them, in the top right - of the job log, click **{doc-text}** (**Show complete raw**). - - `\r`: carriage return. - - `\e[0K`: clear line ANSI escape code. +#### Start multiple manual actions in a stage -Sample raw job log: +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27188) in GitLab 11.11. -```plaintext -section_start:1560896352:my_first_section\r\e[0KHeader of the 1st collapsible section -this line should be hidden when collapsed -section_end:1560896353:my_first_section\r\e[0K -``` +Multiple manual actions in a single stage can be started at the same time using the "Play all manual" button. +Once the user clicks this button, each individual manual action will be triggered and refreshed +to an updated status. -### Pipeline success and duration charts +This functionality is only available: -> - Introduced in GitLab 3.1.1 as Commit Stats, and later renamed to Pipeline Charts. -> - [Renamed](https://gitlab.com/gitlab-org/gitlab/issues/38318) to CI / CD Analytics in GitLab 12.8. +- For users with at least Developer access. +- If the stage contains [manual actions](#add-manual-interaction-to-your-pipeline). -GitLab tracks the history of your pipeline successes and failures, as well as how long each pipeline ran. To view this information, go to **Analytics > CI / CD Analytics**. +### Delete a pipeline -View successful pipelines: +> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/24851) in GitLab 12.7. -![Successful pipelines](img/pipelines_success_chart.png) +Users with [owner permissions](../../user/permissions.md) in a project can delete a pipeline +by clicking on the pipeline in the **CI/CD > Pipelines** to get to the **Pipeline Details** +page, then using the **Delete** button. -View pipeline duration history: +![Pipeline Delete Button](img/pipeline-delete.png) -![Pipeline duration](img/pipelines_duration_chart.png) +CAUTION: **Warning:** +Deleting a pipeline will expire all pipeline caches, and delete all related objects, +such as builds, logs, artifacts, and triggers. **This action cannot be undone.** -## Pipeline quotas +### Pipeline quotas Each user has a personal pipeline quota that tracks the usage of shared runners in all personal projects. Each group has a [usage quota](../../subscriptions/index.md#ci-pipeline-minutes) that tracks the usage of shared runners for all projects created within the group. When a pipeline is triggered, regardless of who triggered it, the pipeline quota for the project owner's [namespace](../../user/group/index.md#namespaces) is used. In this case, the namespace can be the user or group that owns the project. -### How pipeline duration is calculated +#### How pipeline duration is calculated Total running time for a given pipeline excludes retries and pending (queued) time. @@ -216,245 +226,285 @@ The union of A, B, and C is (1, 4) and (6, 7). Therefore, the total running time (4 - 1) + (7 - 6) => 4 ``` -## Configuring pipelines +### Pipeline security on protected branches -Pipelines, and their component jobs and stages, are defined in the [`.gitlab-ci.yml`](../yaml/README.md) file for each project. +A strict security model is enforced when pipelines are executed on +[protected branches](../../user/project/protected_branches.md). -In particular: +The following actions are allowed on protected branches only if the user is +[allowed to merge or push](../../user/project/protected_branches.md#using-the-allowed-to-merge-and-allowed-to-push-settings) +on that specific branch: -- Jobs are the [basic configuration](../yaml/README.md#introduction) component. -- Stages are defined using the [`stages`](../yaml/README.md#stages) keyword. +- Run manual pipelines (using the [Web UI](#run-a-pipeline-manually) or [pipelines API](#pipelines-api)). +- Run scheduled pipelines. +- Run pipelines using triggers. +- Trigger manual actions on existing pipelines. +- Retry or cancel existing jobs (using the Web UI or pipelines API). -For all available configuration options, see the [GitLab CI/CD Pipeline Configuration Reference](../yaml/README.md). +**Variables** marked as **protected** are accessible only to jobs that +run on protected branches, preventing untrusted users getting unintended access to +sensitive information like deployment credentials and tokens. -### Settings and schedules +**Runners** marked as **protected** can run jobs only on protected +branches, preventing untrusted code from executing on the protected runner and +preserving deployment keys and other credentials from being unintentionally +accessed. In order to ensure that jobs intended to be executed on protected +runners will not use regular runners, they must be tagged accordingly. -In addition to configuring jobs through `.gitlab-ci.yml`, additional configuration options are available -through the GitLab UI: +## View jobs in a pipeline -- Pipeline settings for each project. For more information, see [Pipeline settings](settings.md). -- Schedules for pipelines. For more information, see [Pipeline schedules](schedules.md). +When you access a pipeline, you can see the related jobs for that pipeline. -### Grouping jobs +Clicking an individual job will show you its job log, and allow you to: -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6242) in GitLab 8.12. +- Cancel the job. +- Retry the job. +- Erase the job log. -If you have many similar jobs, your [pipeline graph](#visualizing-pipelines) becomes long and hard -to read. +### See why a job failed -For that reason, similar jobs can automatically be grouped together. -If the job names are formatted in certain ways, they will be collapsed into -a single group in regular pipeline graphs (not the mini graphs). +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17782) in GitLab 10.7. -You'll know when a pipeline has grouped jobs if you don't see the retry or -cancel button inside them. Hovering over them will show the number of grouped -jobs. Click to expand them. +When a pipeline fails or is allowed to fail, there are several places where you +can find the reason: -![Grouped pipelines](img/pipelines_grouped.png) +- In the [pipeline graph](#visualize-pipelines), on the pipeline detail view. +- In the pipeline widgets, in the merge requests and commit pages. +- In the job views, in the global and detailed views of a job. -#### Configuring grouping +In each place, if you hover over the failed job you can see the reason it failed. -In the pipeline [configuration file](../yaml/README.md), job names must include two numbers separated with one of -the following (you can even use them interchangeably): +![Pipeline detail](img/job_failure_reason.png) -- A space. -- A slash (`/`). -- A colon (`:`). +In [GitLab 10.8](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17814) and later, +you can also see the reason it failed on the Job detail page. -NOTE: **Note:** -More specifically, it uses [this](https://gitlab.com/gitlab-org/gitlab/blob/2f3dc314f42dbd79813e6251792853bc231e69dd/app/models/commit_status.rb#L99) regular expression: `\d+[\s:\/\\]+\d+\s*`. +### The order of jobs in a pipeline -#### How grouping works +The order of jobs in a pipeline depends on the type of pipeline graph. -The jobs will be ordered by comparing those two numbers from left to right. You -usually want the first to be the index and the second the total. +- For [regular pipeline graphs](#regular-pipeline-graphs), jobs are sorted by name. +- For [pipeline mini graphs](#pipeline-mini-graphs), jobs are sorted by severity and then by name. -For example, the following jobs will be grouped under a job named `test`: +The order of severity is: -- `test 0 3` -- `test 1 3` -- `test 2 3` +- failed +- warning +- pending +- running +- manual +- scheduled +- canceled +- success +- skipped +- created -The following jobs will be grouped under a job named `test ruby`: +For example: -- `test 1:2 ruby` -- `test 2:2 ruby` +![Pipeline mini graph sorting](img/pipelines_mini_graph_sorting.png) -The following jobs will be grouped under a job named `test ruby` as well: +### Group jobs in a pipeline -- `1/3 test ruby` -- `2/3 test ruby` -- `3/3 test ruby` +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6242) in GitLab 8.12. -### Pipelines for merge requests +If you have many similar jobs, your [pipeline graph](#visualize-pipelines) becomes long and hard +to read. -GitLab supports configuring pipelines that run only for merge requests. For more information, see -[Pipelines for merge requests](../merge_request_pipelines/index.md). +You can automatically group similar jobs together. If the job names are formatted in a certain way, +they will be collapsed into a single group in regular pipeline graphs (not the mini graphs). -### Badges +You'll know when a pipeline has grouped jobs if you don't see the retry or +cancel button inside them. Hovering over them will show the number of grouped +jobs. Click to expand them. -Pipeline status and test coverage report badges are available and configurable for each project. +![Grouped pipelines](img/pipelines_grouped.png) -For information on adding pipeline badges to projects, see [Pipeline badges](settings.md#pipeline-badges). +To create a group of jobs, in the [CI/CD pipeline configuration file](../yaml/README.md), +separate each job name with a number and one of the following: -## Multi-project pipelines +- A slash (`/`), for example, `test 1/3`, `test 2/3`, `test 3/3`. +- A colon (`:`), for example, `test 1:3`, `test 2:3`, `test 3:3`. +- A space, for example `test 0 3`, `test 1 3`, `test 2 3`. -Pipelines for different projects can be combined together into [Multi-project pipelines](../multi_project_pipelines.md). +You can use these symbols interchangeably. -[Multi-project pipeline graphs](../multi_project_pipelines.md#multi-project-pipeline-visualization-premium) help -you visualize the entire pipeline, including all cross-project inter-dependencies. **(PREMIUM)** +For example, these three jobs will be in a group named `build ruby`: -## Parent-child pipelines +```yaml +build ruby 1/3: + stage: build + script: + - echo "ruby1" -Complex pipelines can be broken down into one parent pipeline that can trigger -multiple child sub-pipelines, which all run in the same project and with the same SHA. +build ruby 2/3: + stage: build + script: + - echo "ruby2" + +build ruby 3/3: + stage: build + script: + - echo "ruby3" +``` -For more information, see [Parent-Child pipelines](../parent_child_pipelines.md). +In the pipeline, the result is a group named `build ruby` with three jobs: -## Working with pipelines +![Job group](img/job_group_v12_10.png) -In general, pipelines are executed automatically and require no intervention once created. +The jobs will be ordered by comparing the numbers from left to right. You +usually want the first number to be the index and the second number to be the total. -However, there are instances where you'll need to interact with pipelines. These are documented below. +[This regular expression](https://gitlab.com/gitlab-org/gitlab/blob/2f3dc314f42dbd79813e6251792853bc231e69dd/app/models/commit_status.rb#L99) +evaluates the job names: `\d+[\s:\/\\]+\d+\s*`. -### Manually executing pipelines +### Specifying variables when running manual jobs -Pipelines can be manually executed, with predefined or manually-specified [variables](../variables/README.md). +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30485) in GitLab 12.2. -You might do this if the results of a pipeline (for example, a code build) is required outside the normal -operation of the pipeline. +When running manual jobs you can supply additional job specific variables. -To execute a pipeline manually: +You can do this from the job page of the manual job you want to run with +additional variables. -1. Navigate to your project's **CI/CD > Pipelines**. -1. Click on the **Run Pipeline** button. -1. On the **Run Pipeline** page: - 1. Select the branch to run the pipeline for in the **Create for** field. - 1. Enter any [environment variables](../variables/README.md) required for the pipeline run. - 1. Click the **Create pipeline** button. +This is useful when you want to alter the execution of a job by using +environment variables. -The pipeline will execute the jobs as configured. +![Manual job variables](img/manual_job_variables.png) -#### Using a query string +### Delay a job -> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/24146) in GitLab 12.5. +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21767) in GitLab 11.4. -Variables on the **Run Pipeline** page can be pre-populated by passing variable keys and values -in a query string appended to the `pipelines/new` URL. The format is: +When you do not want to run a job immediately, you can use the [`when:delayed`](../yaml/README.md#whendelayed) parameter to +delay a job's execution for a certain period. -```plaintext -.../pipelines/new?ref=&var[]=&file_var[]= -``` +This is especially useful for timed incremental rollout where new code is rolled out gradually. -The following parameters are supported: +For example, if you start rolling out new code and: -- `ref`: specify the branch to populate the **Run for** field with. -- `var`: specify a `Variable` variable. -- `file_var`: specify a `File` variable. +- Users do not experience trouble, GitLab can automatically complete the deployment from 0% to 100%. +- Users experience trouble with the new code, you can stop the timed incremental rollout by canceling the pipeline + and [rolling](../environments.md#retrying-and-rolling-back) back to the last stable version. -For each `var` or `file_var`, a key and value are required. +![Pipelines example](img/pipeline_incremental_rollout.png) -For example, the query string -`.../pipelines/new?ref=my_branch&var[foo]=bar&file_var[file_foo]=file_bar` will pre-populate the -**Run Pipeline** page as follows: +### Expand and collapse job log sections -- **Run for** field: `my_branch`. -- **Variables** section: - - Variable: - - Key: `foo` - - Value: `bar` - - File: - - Key: `file_foo` - - Value: `file_bar` +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/14664) in GitLab 12.0. -### Accessing pipelines +Job logs are divided into sections that can be collapsed or expanded. Each section will display +the duration. -You can find the current and historical pipeline runs under your project's -**CI/CD > Pipelines** page. You can also access pipelines for a merge request by navigating -to its **Pipelines** tab. +In the following example: -![Pipelines index page](img/pipelines_index.png) +- Two sections are collapsed and can be expanded. +- Three sections are expanded and can be collapsed. -Clicking on a pipeline will bring you to the **Pipeline Details** page and show -the jobs that were run for that pipeline. From here you can cancel a running pipeline, -retry jobs on a failed pipeline, or [delete a pipeline](#deleting-a-single-pipeline). +![Collapsible sections](img/collapsible_log_v12_6.png) -### Accessing individual jobs +#### Custom collapsible sections -When you access a pipeline, you can see the related jobs for that pipeline. +You can create collapsible sections in job logs by manually outputting special codes +that GitLab will use to determine what sections to collapse: -Clicking on an individual job will show you its job log, and allow you to: +- Section start marker: `section_start:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` + `TEXT_OF_SECTION_HEADER` +- Section end marker: `section_end:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` -- Cancel the job. -- Retry the job. -- Erase the job log. +You must add these codes to the script section of the CI configuration. For example, +using `echo`: -### Seeing the failure reason for jobs +```yaml +job1: + script: + - echo -e "section_start:`date +%s`:my_first_section\r\e[0KHeader of the 1st collapsible section" + - echo 'this line should be hidden when collapsed' + - echo -e "section_end:`date +%s`:my_first_section\r\e[0K" +``` -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17782) in GitLab 10.7. +In the example above: -When a pipeline fails or is allowed to fail, there are several places where you -can quickly check the reason it failed: +- `date +%s`: The Unix timestamp (for example `1560896352`). +- `my_first_section`: The name given to the section. +- `\r\e[0K`: Prevents the section markers from displaying in the rendered (colored) + job log, but they are displayed in the raw job log. To see them, in the top right + of the job log, click **{doc-text}** (**Show complete raw**). + - `\r`: carriage return. + - `\e[0K`: clear line ANSI escape code. -- In the pipeline graph, on the pipeline detail view. -- In the pipeline widgets, in the merge requests and commit pages. -- In the job views, in the global and detailed views of a job. +Sample raw job log: -In each place, if you hover over the failed job you can see the reason it failed. +```plaintext +section_start:1560896352:my_first_section\r\e[0KHeader of the 1st collapsible section +this line should be hidden when collapsed +section_end:1560896353:my_first_section\r\e[0K +``` -![Pipeline detail](img/job_failure_reason.png) +## Visualize pipelines -From [GitLab 10.8](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17814), -you can also see the reason it failed on the Job detail page. +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5742) in GitLab 8.11. -### Manual actions from pipeline graphs +Pipelines can be complex structures with many sequential and parallel jobs. -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7931) in GitLab 8.15. +To make it easier to understand the flow of a pipeline, GitLab has pipeline graphs for viewing pipelines +and their statuses. -Manual actions, configured using the [`when:manual`](../yaml/README.md#whenmanual) parameter, -allow you to require manual interaction before moving forward in the pipeline. +Pipeline graphs can be displayed in two different ways, depending on the page you +access the graph from. -You can do this straight from the pipeline graph. Just click on the play button -to execute that particular job. +NOTE: **Note:** +GitLab capitalizes the stages' names in the pipeline graphs. -For example, your pipeline start automatically, but require manual action to -[deploy to production](../environments.md#configuring-manual-deployments). In the example below, the `production` -stage has a job with a manual action. +### Regular pipeline graphs + +Regular pipeline graphs show the names of the jobs in each stage. Regular pipeline graphs can +be found when you are on a [single pipeline page](#view-pipelines). For example: ![Pipelines example](img/pipelines.png) -### Specifying variables when running manual jobs +[Multi-project pipeline graphs](../multi_project_pipelines.md#multi-project-pipeline-visualization-premium) help +you visualize the entire pipeline, including all cross-project inter-dependencies. **(PREMIUM)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30485) in GitLab 12.2. +### Pipeline mini graphs -When running manual jobs you can supply additional job specific variables. +Pipeline mini graphs take less space and can tell you at a +quick glance if all jobs passed or something failed. The pipeline mini graph can +be found when you navigate to: -You can do this from the job page of the manual job you want to run with -additional variables. +- The pipelines index page. +- A single commit page. +- A merge request page. -This is useful when you want to alter the execution of a job by using -environment variables. +Pipeline mini graphs allow you to see all related jobs for a single commit and the net result +of each stage of your pipeline. This allows you to quickly see what failed and +fix it. -![Manual job variables](img/manual_job_variables.png) +Stages in pipeline mini graphs are collapsible. Hover your mouse over them and click to expand their jobs. -### Delay a job in a pipeline graph +| Mini graph | Mini graph expanded | +|:-------------------------------------------------------------|:---------------------------------------------------------------| +| ![Pipelines mini graph](img/pipelines_mini_graph_simple.png) | ![Pipelines mini graph extended](img/pipelines_mini_graph.png) | -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21767) in GitLab 11.4. +### Pipeline success and duration charts -When you do not want to run a job immediately, you can use the [`when:delayed`](../yaml/README.md#whendelayed) parameter to -delay a job's execution for a certain period. +> - Introduced in GitLab 3.1.1 as Commit Stats, and later renamed to Pipeline Charts. +> - [Renamed](https://gitlab.com/gitlab-org/gitlab/issues/38318) to CI / CD Analytics in GitLab 12.8. -This is especially useful for timed incremental rollout where new code is rolled out gradually. +GitLab tracks the history of your pipeline successes and failures, as well as how long each pipeline ran. To view this information, go to **Analytics > CI / CD Analytics**. -For example, if you start rolling out new code and: +View successful pipelines: -- Users do not experience trouble, GitLab can automatically complete the deployment from 0% to 100%. -- Users experience trouble with the new code, you can stop the timed incremental rollout by canceling the pipeline - and [rolling](../environments.md#retrying-and-rolling-back) back to the last stable version. +![Successful pipelines](img/pipelines_success_chart.png) -![Pipelines example](img/pipeline_incremental_rollout.png) +View pipeline duration history: + +![Pipeline duration](img/pipelines_duration_chart.png) + +### Pipeline badges + +Pipeline status and test coverage report badges are available and configurable for each project. +For information on adding pipeline badges to projects, see [Pipeline badges](settings.md#pipeline-badges). -### Using the API +## Pipelines API GitLab provides API endpoints to: @@ -464,65 +514,7 @@ GitLab provides API endpoints to: - [Triggering pipelines through the API](../triggers/README.md). - [Pipeline triggers API](../../api/pipeline_triggers.md). -### Start multiple manual actions in a stage - -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27188) in GitLab 11.11. - -Multiple manual actions in a single stage can be started at the same time using the "Play all manual" button. -Once the user clicks this button, each individual manual action will be triggered and refreshed -to an updated status. - -This functionality is only available: - -- For users with at least Developer access. -- If the stage contains [manual actions](#manual-actions-from-pipeline-graphs). - -### Deleting a single pipeline - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/24851) in GitLab 12.7. - -Users with [owner permissions](../../user/permissions.md) in a project can delete a pipeline -by clicking on the pipeline in the **CI/CD > Pipelines** to get to the **Pipeline Details** -page, then using the **Delete** button. - -![Pipeline Delete Button](img/pipeline-delete.png) - -CAUTION: **Warning:** -Deleting a pipeline will expire all pipeline caches, and delete all related objects, -such as builds, logs, artifacts, and triggers. **This action cannot be undone.** - -## Most Recent Pipeline - -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/50499) in GitLab 12.3. - -There's a link to the latest pipeline for the last commit of a given branch at `/project/pipelines/[branch]/latest`. Also, `/project/pipelines/latest` will redirect you to the latest pipeline for the last commit on the project's default branch. - -## Security on protected branches - -A strict security model is enforced when pipelines are executed on -[protected branches](../../user/project/protected_branches.md). - -The following actions are allowed on protected branches only if the user is -[allowed to merge or push](../../user/project/protected_branches.md#using-the-allowed-to-merge-and-allowed-to-push-settings) -on that specific branch: - -- Run manual pipelines (using the [Web UI](#manually-executing-pipelines) or pipelines API). -- Run scheduled pipelines. -- Run pipelines using triggers. -- Trigger manual actions on existing pipelines. -- Retry or cancel existing jobs (using the Web UI or pipelines API). - -**Variables** marked as **protected** are accessible only to jobs that -run on protected branches, preventing untrusted users getting unintended access to -sensitive information like deployment credentials and tokens. - -**Runners** marked as **protected** can run jobs only on protected -branches, avoiding untrusted code to be executed on the protected runner and -preserving deployment keys and other credentials from being unintentionally -accessed. In order to ensure that jobs intended to be executed on protected -runners will not use regular runners, they must be tagged accordingly. - -## Persistent pipeline refs +## Troubleshooting `fatal: reference is not a tree:` > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17043) in GitLab 12.4. diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md index 2f4408aaa6c4621a5be80321dd809536a3ca8695..e619a32b90fcf79fd3f4942a309bb0c241e5f1b5 100644 --- a/doc/ci/variables/README.md +++ b/doc/ci/variables/README.md @@ -465,7 +465,7 @@ limitations with the current Auto DevOps scripting environment. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/44059) in GitLab 10.8. -[Manually triggered pipelines](../pipelines/index.md#manually-executing-pipelines) allow you to override the value of a current variable. +[Manually triggered pipelines](../pipelines/index.md#run-a-pipeline-manually) allow you to override the value of a current variable. For instance, suppose you added a [custom variable `$TEST`](#creating-a-custom-environment-variable) @@ -621,7 +621,7 @@ variables that were set, etc. Before enabling this, you should ensure jobs are visible to [team members only](../../user/permissions.md#project-features). You should -also [erase](../pipelines/index.md#accessing-individual-jobs) all generated job logs +also [erase](../pipelines/index.md#view-jobs-in-a-pipeline) all generated job logs before making them visible again. To enable debug logs (traces), set the `CI_DEBUG_TRACE` variable to `true`: diff --git a/doc/topics/autodevops/customize.md b/doc/topics/autodevops/customize.md index 7efe2c3bdcf473a51c1df6eb02bfc1e6233976dc..28abd73ef97cce0da0d14ce514b75a058024c5e3 100644 --- a/doc/topics/autodevops/customize.md +++ b/doc/topics/autodevops/customize.md @@ -521,7 +521,7 @@ increasing the rollout up to 100%. If `INCREMENTAL_ROLLOUT_MODE` is set to `manual` in your project, then instead of the standard `production` job, 4 different -[manual jobs](../../ci/pipelines/index.md#manual-actions-from-pipeline-graphs) +[manual jobs](../../ci/pipelines/index.md#add-manual-interaction-to-your-pipeline) will be created: 1. `rollout 10%` diff --git a/doc/user/permissions.md b/doc/user/permissions.md index fabe6fd40c93f6be1fbb90b6b60ef95133922649..59867f492b8ce2644c953b71bb46978730505522 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -425,7 +425,7 @@ read through the documentation on the [new CI/CD permissions model](project/new_ The permission to merge or push to protected branches is used to define if a user can run CI/CD pipelines and execute actions on jobs that are related to those branches. -See [Security on protected branches](../ci/pipelines/index.md#security-on-protected-branches) +See [Security on protected branches](../ci/pipelines/index.md#pipeline-security-on-protected-branches) for details about the pipelines security model. ## LDAP users permissions diff --git a/doc/user/project/index.md b/doc/user/project/index.md index 3e1c3007e00fb603f57945458e347b78835649c3..99050f823c56ee3b426fba2a89bc875985a693d8 100644 --- a/doc/user/project/index.md +++ b/doc/user/project/index.md @@ -70,7 +70,7 @@ When you create a project in GitLab, you'll have access to a large number of your GitLab CI/CD pipelines from the UI - [Scheduled Pipelines](../../ci/pipelines/schedules.md): Schedule a pipeline to start at a chosen time - - [Pipeline Graphs](../../ci/pipelines/index.md#visualizing-pipelines): View your + - [Pipeline Graphs](../../ci/pipelines/index.md#visualize-pipelines): View your entire pipeline from the UI - [Job artifacts](../../ci/pipelines/job_artifacts.md): Define, browse, and download job artifacts diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md index 9d288d5da92dd13ef94b5aa6ded14794e3aaf780..2038414dab88c7aebffe8fe173beefaa04dd7d8d 100644 --- a/doc/user/project/merge_requests/index.md +++ b/doc/user/project/merge_requests/index.md @@ -101,7 +101,7 @@ or link to useful information directly in the merge request page: | [Metrics Reports](../../../ci/metrics_reports.md) **(PREMIUM)** | Display the Metrics Report on the merge request so that it's fast and easy to identify changes to important metrics. | | [Multi-Project pipelines](../../../ci/multi_project_pipelines.md) **(PREMIUM)** | When you set up GitLab CI/CD across multiple projects, you can visualize the entire pipeline, including all cross-project interdependencies. | | [Pipelines for merge requests](../../../ci/merge_request_pipelines/index.md) | Customize a specific pipeline structure for merge requests in order to speed the cycle up by running only important jobs. | -| [Pipeline Graphs](../../../ci/pipelines/index.md#visualizing-pipelines) | View the status of pipelines within the merge request, including the deployment process. | +| [Pipeline Graphs](../../../ci/pipelines/index.md#visualize-pipelines) | View the status of pipelines within the merge request, including the deployment process. | | [Test Coverage visualization](test_coverage_visualization.md) | See test coverage results for merge requests, within the file diff. | ### Security Reports **(ULTIMATE)** diff --git a/doc/user/project/protected_branches.md b/doc/user/project/protected_branches.md index 14feb1899640f275611e20e5c735dedd90b568a9..e2ee0dd47fe71c6f62d5427839ccf748841a4900 100644 --- a/doc/user/project/protected_branches.md +++ b/doc/user/project/protected_branches.md @@ -187,7 +187,7 @@ Additionally, direct pushes to the protected branch are denied if a rule is matc The permission to merge or push to protected branches is used to define if a user can run CI/CD pipelines and execute actions on jobs that are related to those branches. -See [Security on protected branches](../../ci/pipelines/index.md#security-on-protected-branches) +See [Security on protected branches](../../ci/pipelines/index.md#pipeline-security-on-protected-branches) for details about the pipelines security model. ## Changelog diff --git a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml index 20063cf6a694a790b6c0cab0846acb48168f9d40..d85078c0a409bbbee808e49c9023f890ba9612c4 100644 --- a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml @@ -1,11 +1,11 @@ performance: stage: performance - image: docker:19.03.5 + image: docker:19.03.8 allow_failure: true variables: DOCKER_TLS_CERTDIR: "" services: - - docker:19.03.5-dind + - docker:19.03.8-dind script: - | if ! docker info &>/dev/null; then diff --git a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml index ceaa8115c3d54846c2c1d1599473685261281730..6b72db951edccfe0edd8af9272499d4eb3bbfa9c 100644 --- a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml @@ -1,10 +1,10 @@ build: stage: build - image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-build-image:v0.2.0" + image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-build-image:v0.2.1" variables: DOCKER_TLS_CERTDIR: "" services: - - docker:19.03.5-dind + - docker:19.03.8-dind script: - | if [[ -z "$CI_COMMIT_TAG" ]]; then diff --git a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml index a6338ff6925add1306ae62205a5e0f5df59a18e9..9c4699f1f445cd48daa6210913b347431b158690 100644 --- a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml @@ -1,9 +1,9 @@ code_quality: stage: test - image: docker:19.03.5 + image: docker:19.03.8 allow_failure: true services: - - docker:19.03.5-dind + - docker:19.03.8-dind variables: DOCKER_DRIVER: overlay2 DOCKER_TLS_CERTDIR: "" diff --git a/locale/gitlab.pot b/locale/gitlab.pot index f4e75cefb67f39b59b3c69b160750c9a0d90bff9..92df6cf31354b711b4aa3a9629f4b6384eb7408b 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -71,6 +71,11 @@ msgstr "" msgid "\"%{path}\" did not exist on \"%{ref}\"" msgstr "" +msgid "%d URL scanned" +msgid_plural "%d URLs scanned" +msgstr[0] "" +msgstr[1] "" + msgid "%d changed file" msgid_plural "%d changed files" msgstr[0] "" @@ -22624,6 +22629,9 @@ msgstr "" msgid "View deployment" msgstr "" +msgid "View details" +msgstr "" + msgid "View details: %{details_url}" msgstr "" diff --git a/spec/frontend/static_site_editor/components/publish_toolbar_spec.js b/spec/frontend/static_site_editor/components/publish_toolbar_spec.js index 55e308256211dc56827da82661905afe3105c340..0edc3f4c9205a34c8eef05e6c867844056394315 100644 --- a/spec/frontend/static_site_editor/components/publish_toolbar_spec.js +++ b/spec/frontend/static_site_editor/components/publish_toolbar_spec.js @@ -1,5 +1,5 @@ import { shallowMount } from '@vue/test-utils'; -import { GlNewButton } from '@gitlab/ui'; +import { GlNewButton, GlLoadingIcon } from '@gitlab/ui'; import PublishToolbar from '~/static_site_editor/components/publish_toolbar.vue'; @@ -16,6 +16,7 @@ describe('Static Site Editor Toolbar', () => { }; const findSaveChangesButton = () => wrapper.find(GlNewButton); + const findLoadingIndicator = () => wrapper.find(GlLoadingIcon); beforeEach(() => { buildWrapper(); @@ -33,6 +34,10 @@ describe('Static Site Editor Toolbar', () => { expect(findSaveChangesButton().attributes('disabled')).toBe('true'); }); + it('does not display saving changes indicator', () => { + expect(findLoadingIndicator().classes()).toContain('invisible'); + }); + describe('when saveable', () => { it('enables Submit Changes button', () => { buildWrapper({ saveable: true }); @@ -40,4 +45,26 @@ describe('Static Site Editor Toolbar', () => { expect(findSaveChangesButton().attributes('disabled')).toBeFalsy(); }); }); + + describe('when saving changes', () => { + beforeEach(() => { + buildWrapper({ saveable: true, savingChanges: true }); + }); + + it('disables Submit Changes button', () => { + expect(findSaveChangesButton().attributes('disabled')).toBe('true'); + }); + + it('displays saving changes indicator', () => { + expect(findLoadingIndicator().classes()).not.toContain('invisible'); + }); + }); + + it('emits submit event when submit button is clicked', () => { + buildWrapper({ saveable: true }); + + findSaveChangesButton().vm.$emit('click'); + + expect(wrapper.emitted('submit')).toHaveLength(1); + }); }); diff --git a/spec/frontend/static_site_editor/components/static_site_editor_spec.js b/spec/frontend/static_site_editor/components/static_site_editor_spec.js index ec984102250489732370e41fdb61efc265c78aed..a40f8edbeb215cf907f0cd0c1398a8a28d454e70 100644 --- a/spec/frontend/static_site_editor/components/static_site_editor_spec.js +++ b/spec/frontend/static_site_editor/components/static_site_editor_spec.js @@ -9,6 +9,8 @@ import StaticSiteEditor from '~/static_site_editor/components/static_site_editor import EditArea from '~/static_site_editor/components/edit_area.vue'; import PublishToolbar from '~/static_site_editor/components/publish_toolbar.vue'; +import { sourceContent } from '../mock_data'; + const localVue = createLocalVue(); localVue.use(Vuex); @@ -18,10 +20,12 @@ describe('StaticSiteEditor', () => { let store; let loadContentActionMock; let setContentActionMock; + let submitChangesActionMock; const buildStore = ({ initialState, getters } = {}) => { loadContentActionMock = jest.fn(); setContentActionMock = jest.fn(); + submitChangesActionMock = jest.fn(); store = new Vuex.Store({ state: createState(initialState), @@ -33,6 +37,7 @@ describe('StaticSiteEditor', () => { actions: { loadContent: loadContentActionMock, setContent: setContentActionMock, + submitChanges: submitChangesActionMock, }, }); }; @@ -119,18 +124,35 @@ describe('StaticSiteEditor', () => { expect(findSkeletonLoader().exists()).toBe(true); }); + it('sets toolbar as saving when saving changes', () => { + buildContentLoadedStore({ + initialState: { + isSavingChanges: true, + }, + }); + buildWrapper(); + + expect(findPublishToolbar().props('savingChanges')).toBe(true); + }); + it('dispatches load content action', () => { expect(loadContentActionMock).toHaveBeenCalled(); }); it('dispatches setContent action when edit area emits input event', () => { - const content = 'new content'; - buildContentLoadedStore(); buildWrapper(); - findEditArea().vm.$emit('input', content); + findEditArea().vm.$emit('input', sourceContent); + + expect(setContentActionMock).toHaveBeenCalledWith(expect.anything(), sourceContent, undefined); + }); + + it('dispatches submitChanges action when toolbar emits submit event', () => { + buildContentLoadedStore(); + buildWrapper(); + findPublishToolbar().vm.$emit('submit'); - expect(setContentActionMock).toHaveBeenCalledWith(expect.anything(), content, undefined); + expect(submitChangesActionMock).toHaveBeenCalled(); }); }); diff --git a/spec/frontend/static_site_editor/mock_data.js b/spec/frontend/static_site_editor/mock_data.js index 0b2a69420d83b261339cc84eee44d316609e20ca..9e1c14515e677b47707b1c7d2260fb43cc870a82 100644 --- a/spec/frontend/static_site_editor/mock_data.js +++ b/spec/frontend/static_site_editor/mock_data.js @@ -14,5 +14,23 @@ twitter_image: '/images/tweets/handbook-gitlab.png' export const sourceContentTitle = 'Handbook'; +export const username = 'gitlabuser'; export const projectId = '123456'; export const sourcePath = 'foobar.md.html'; + +export const savedContentMeta = { + branch: { + label: 'foobar', + url: 'foobar/-/tree/foorbar', + }, + commit: { + label: 'c1461b08 ', + url: 'foobar/-/c1461b08', + }, + mergeRequest: { + label: '123', + url: 'foobar/-/merge_requests/123', + }, +}; + +export const submitChangesError = 'Could not save changes'; diff --git a/spec/frontend/static_site_editor/store/actions_spec.js b/spec/frontend/static_site_editor/store/actions_spec.js index 4ad1e798ccddd6d5703ad2ed614d49b488cb3177..a9c039517b766e558ffb9a2cfed51a80e7b8d8c8 100644 --- a/spec/frontend/static_site_editor/store/actions_spec.js +++ b/spec/frontend/static_site_editor/store/actions_spec.js @@ -3,18 +3,23 @@ import createState from '~/static_site_editor/store/state'; import * as actions from '~/static_site_editor/store/actions'; import * as mutationTypes from '~/static_site_editor/store/mutation_types'; import loadSourceContent from '~/static_site_editor/services/load_source_content'; +import submitContentChanges from '~/static_site_editor/services/submit_content_changes'; import createFlash from '~/flash'; import { + username, projectId, sourcePath, sourceContentTitle as title, sourceContent as content, + savedContentMeta, + submitChangesError, } from '../mock_data'; jest.mock('~/flash'); jest.mock('~/static_site_editor/services/load_source_content', () => jest.fn()); +jest.mock('~/static_site_editor/services/submit_content_changes', () => jest.fn()); describe('Static Site Editor Store actions', () => { let state; @@ -84,4 +89,59 @@ describe('Static Site Editor Store actions', () => { ]); }); }); + + describe('submitChanges', () => { + describe('on success', () => { + beforeEach(() => { + state = createState({ + projectId, + content, + username, + sourcePath, + }); + submitContentChanges.mockResolvedValueOnce(savedContentMeta); + }); + + it('commits submitChangesSuccess mutation', () => { + testAction( + actions.submitChanges, + null, + state, + [ + { type: mutationTypes.SUBMIT_CHANGES }, + { type: mutationTypes.SUBMIT_CHANGES_SUCCESS, payload: savedContentMeta }, + ], + [], + ); + + expect(submitContentChanges).toHaveBeenCalledWith({ + username, + projectId, + content, + sourcePath, + }); + }); + }); + + describe('on error', () => { + const expectedMutations = [ + { type: mutationTypes.SUBMIT_CHANGES }, + { type: mutationTypes.SUBMIT_CHANGES_ERROR }, + ]; + + beforeEach(() => { + submitContentChanges.mockRejectedValueOnce(new Error(submitChangesError)); + }); + + it('dispatches receiveContentError', () => { + testAction(actions.submitChanges, null, state, expectedMutations); + }); + + it('displays flash communicating error', () => { + return testAction(actions.submitChanges, null, state, expectedMutations).then(() => { + expect(createFlash).toHaveBeenCalledWith(submitChangesError); + }); + }); + }); + }); }); diff --git a/spec/frontend/static_site_editor/store/mutations_spec.js b/spec/frontend/static_site_editor/store/mutations_spec.js index db3a1081af5f26cd18df626ebb272adc71f84698..1fd687eed4adee4f24620b2a22616c9d0c657324 100644 --- a/spec/frontend/static_site_editor/store/mutations_spec.js +++ b/spec/frontend/static_site_editor/store/mutations_spec.js @@ -1,61 +1,50 @@ import createState from '~/static_site_editor/store/state'; import mutations from '~/static_site_editor/store/mutations'; import * as types from '~/static_site_editor/store/mutation_types'; -import { sourceContentTitle as title, sourceContent as content } from '../mock_data'; +import { + sourceContentTitle as title, + sourceContent as content, + savedContentMeta, +} from '../mock_data'; describe('Static Site Editor Store mutations', () => { let state; + const contentLoadedPayload = { title, content }; beforeEach(() => { state = createState(); }); - describe('loadContent', () => { - beforeEach(() => { - mutations[types.LOAD_CONTENT](state); - }); - - it('sets isLoadingContent to true', () => { - expect(state.isLoadingContent).toBe(true); - }); - }); - - describe('receiveContentSuccess', () => { - const payload = { title, content }; - - beforeEach(() => { - mutations[types.RECEIVE_CONTENT_SUCCESS](state, payload); - }); - - it('sets current state to LOADING', () => { - expect(state.isLoadingContent).toBe(false); - }); - - it('sets title', () => { - expect(state.title).toBe(payload.title); - }); - - it('sets originalContent and content', () => { - expect(state.content).toBe(payload.content); - expect(state.originalContent).toBe(payload.content); - }); - }); - - describe('receiveContentError', () => { - beforeEach(() => { - mutations[types.RECEIVE_CONTENT_ERROR](state); - }); - - it('sets current state to LOADING_ERROR', () => { - expect(state.isLoadingContent).toBe(false); - }); - }); - - describe('setContent', () => { - it('sets content', () => { - mutations[types.SET_CONTENT](state, content); - - expect(state.content).toBe(content); - }); + it.each` + mutation | stateProperty | payload | expectedValue + ${types.LOAD_CONTENT} | ${'isLoadingContent'} | ${undefined} | ${true} + ${types.RECEIVE_CONTENT_SUCCESS} | ${'isLoadingContent'} | ${contentLoadedPayload} | ${false} + ${types.RECEIVE_CONTENT_SUCCESS} | ${'title'} | ${contentLoadedPayload} | ${title} + ${types.RECEIVE_CONTENT_SUCCESS} | ${'content'} | ${contentLoadedPayload} | ${content} + ${types.RECEIVE_CONTENT_SUCCESS} | ${'originalContent'} | ${contentLoadedPayload} | ${content} + ${types.RECEIVE_CONTENT_ERROR} | ${'isLoadingContent'} | ${undefined} | ${false} + ${types.SET_CONTENT} | ${'content'} | ${content} | ${content} + ${types.SUBMIT_CHANGES} | ${'isSavingChanges'} | ${undefined} | ${true} + ${types.SUBMIT_CHANGES_SUCCESS} | ${'savedContentMeta'} | ${savedContentMeta} | ${savedContentMeta} + ${types.SUBMIT_CHANGES_SUCCESS} | ${'isSavingChanges'} | ${savedContentMeta} | ${false} + ${types.SUBMIT_CHANGES_ERROR} | ${'isSavingChanges'} | ${undefined} | ${false} + `( + '$mutation sets $stateProperty to $expectedValue', + ({ mutation, stateProperty, payload, expectedValue }) => { + mutations[mutation](state, payload); + expect(state[stateProperty]).toBe(expectedValue); + }, + ); + + it(`${types.SUBMIT_CHANGES_SUCCESS} sets originalContent to content current value`, () => { + const editedContent = `${content} plus something else`; + + state = createState({ + originalContent: content, + content: editedContent, + }); + mutations[types.SUBMIT_CHANGES_SUCCESS](state); + + expect(state.originalContent).toBe(state.content); }); });