Commit 187ee320 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent a7dc052b
......@@ -53,11 +53,19 @@ export default {
/>
<ci-icon v-else :status="iconStatus" :size="24" />
</div>
<div class="report-block-list-issue-description">
<div class="report-block-list-issue-description-text">{{ summary }}</div>
<popover v-if="popoverOptions" :options="popoverOptions" />
<div class="report-block-list-issue-description-text">
{{ summary
}}<span v-if="popoverOptions" class="text-nowrap"
>&nbsp;<popover v-if="popoverOptions" :options="popoverOptions" class="align-top" />
</span>
</div>
</div>
<div
v-if="$slots.default"
class="text-right flex-fill d-flex justify-content-end flex-column flex-sm-row"
>
<slot></slot>
</div>
</div>
</template>
<script>
import { GlNewButton } from '@gitlab/ui';
import { GlNewButton, GlLoadingIcon } from '@gitlab/ui';
export default {
components: {
GlNewButton,
GlLoadingIcon,
},
props: {
saveable: {
......@@ -11,12 +12,22 @@ export default {
required: false,
default: false,
},
savingChanges: {
type: Boolean,
required: false,
default: false,
},
},
};
</script>
<template>
<div class="d-flex bg-light border-top justify-content-between align-items-center py-3 px-4">
<gl-new-button variant="success" :disabled="!saveable">
<gl-loading-icon :class="{ invisible: !savingChanges }" size="md" />
<gl-new-button
variant="success"
:disabled="!saveable || savingChanges"
@click="$emit('submit')"
>
{{ __('Submit Changes') }}
</gl-new-button>
</div>
......
......@@ -12,14 +12,14 @@ export default {
Toolbar,
},
computed: {
...mapState(['content', 'isLoadingContent']),
...mapState(['content', 'isLoadingContent', 'isSavingChanges']),
...mapGetters(['isContentLoaded', 'contentChanged']),
},
mounted() {
this.loadContent();
},
methods: {
...mapActions(['loadContent', 'setContent']),
...mapActions(['loadContent', 'setContent', 'submitChanges']),
},
};
</script>
......@@ -41,7 +41,11 @@ export default {
:value="content"
@input="setContent"
/>
<toolbar :saveable="contentChanged" />
<toolbar
:saveable="contentChanged"
:saving-changes="isSavingChanges"
@submit="submitChanges"
/>
</div>
</div>
</template>
......@@ -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({
......
// TODO implement
const submitContentChanges = () => new Promise(resolve => setTimeout(resolve, 1000));
export default submitContentChanges;
......@@ -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 () => {};
......@@ -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';
......@@ -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;
},
};
const createState = (initialState = {}) => ({
username: null,
projectId: null,
sourcePath: null,
......
---
title: Update Auto DevOps docker version to 19.03.8
merge_request: 29081
author:
type: changed
......@@ -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. |
<div align="right">
......
......@@ -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: <your_access_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
......
......@@ -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)
......
......@@ -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)**
......
......@@ -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)
......
......@@ -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=<branch>&var[<variable_key>]=<value>&file_var[<file_key>]=<value>
```
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=<branch>&var[<variable_key>]=<value>&file_var[<file_key>]=<value>
```
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.
......
......@@ -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`:
......
......@@ -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%`
......
......@@ -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
......
......@@ -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
......
......@@ -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)**
......
......@@ -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
......
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
......
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
......
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: ""
......
......@@ -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 ""
......
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);
});
});
......@@ -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();
});
});
......@@ -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';
......@@ -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);
});
});
});
});
});
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);
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment