Skip to content
Snippets Groups Projects
Commit 6b8d671d authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 163a7046
No related branches found
No related tags found
No related merge requests found
Showing
with 787 additions and 65 deletions
---
type: reference
---
# Pipeline Architecture
Pipelines are the fundamental building blocks for CI/CD in GitLab. This page documents
some of the important concepts related to them.
There are three main ways to structure your pipelines, each with their
own advantages. These methods can be mixed and matched if needed:
- [Basic](#basic-pipelines): Good for straightforward projects where all the configuration is in one easy to find place.
- [Directed Acylic Graph](#directed-acyclic-graph-pipelines): Good for large, complex projects that need efficient execution.
- [Child/Parent Pipelines](#child--parent-pipelines): Good for monorepos and projects with lots of independently defined components.
For more details about
any of the keywords used below, check out our [CI YAML reference](../yaml/) for details.
## Basic Pipelines
This is the simplest pipeline in GitLab. It will run everything in the build stage concurrently,
and once all of those finish, it will run everything in the test stage the same way, and so on.
It's not the most efficient, and if you have lots of steps it can grow quite complex, but it's
easier to maintain:
```mermaid
graph LR
subgraph deploy stage
deploy --> deploy_a
deploy --> deploy_b
end
subgraph test stage
test --> test_a
test --> test_b
end
subgraph build stage
build --> build_a
build --> build_b
end
build_a -.-> test
build_b -.-> test
test_a -.-> deploy
test_b -.-> deploy
```
Example basic `/.gitlab-ci.yml` pipeline configuration matching the diagram:
```yaml
stages:
- build
- test
- deploy
image: alpine
build_a:
stage: build
script:
- echo "This job builds something."
build_b:
stage: build
script:
- echo "This job builds something else."
test_a:
stage: test
script:
- echo "This job tests something. It will only run when all jobs in the"
- echo "build stage are complete."
test_b:
stage: test
script:
- echo "This job tests something else. It will only run when all jobs in the"
- echo "build stage are complete too. It will start at about the same time as test_a."
deploy_a:
stage: deploy
script:
- echo "This job deploys something. It will only run when all jobs in the"
- echo "test stage complete."
deploy_b:
stage: deploy
script:
- echo "This job deploys something else. It will only run when all jobs in the"
- echo "test stage complete. It will start at about the same time as deploy_a."
```
## Directed Acyclic Graph Pipelines
If efficiency is important to you and you want everything to run as quickly as possible,
you can use [Directed Acylic Graphs (DAG)](../directed_acyclic_graph/index.md). Use the
[`needs` keyword](../yaml/README.md#needs) to define dependency relationships between
your jobs. When GitLab knows the relationships between your jobs, it can run everything
as fast as possible, and even skips into subsequent stages when possible.
In the example below, if `build_a` and `test_a` are much faster than `build_b` and
`test_b`, GitLab will start `deploy_a` even if `build_b` is still running.
```mermaid
graph LR
subgraph Pipeline using DAG
build_a --> test_a --> deploy_a
build_b --> test_b --> deploy_b
end
```
Example DAG `/.gitlab-ci.yml` configuration matching the diagram:
```yaml
stages:
- build
- test
- deploy
image: alpine
build_a:
stage: build
script:
- echo "This job builds something quickly."
build_b:
stage: build
script:
- echo "This job builds something else slowly."
test_a:
stage: test
needs: build_a
script:
- echo "This test job will start as soon as build_a finishes."
- echo "It will not wait for build_b, or other jobs in the build stage, to finish."
test_b:
stage: test
needs: build_b
script:
- echo "This test job will start as soon as build_b finishes."
- echo "It will not wait for other jobs in the build stage to finish."
deploy_a:
stage: deploy
needs: test_a
script:
- echo "Since build_a and test_a run quickly, this deploy job can run much earlier."
- echo "It does not need to wait for build_b or test_b."
deploy_b:
stage: deploy
needs: test_b
script:
- echo "Since build_b and test_b run slowly, this deploy job will run much later."
```
## Child / Parent Pipelines
In the examples above, it's clear we've got two types of things that could be built independently.
This is an ideal case for using [Child / Parent Pipelines](../parent_child_pipelines.md)) via
the [`trigger` keyword](../yaml/README.md#trigger). It will separate out the configuration
into multiple files, keeping things very simple. You can also combine this with:
- The [`rules` keyword](../yaml/README.md#rules): For example, have the child pipelines triggered only
when there are changes to that area.
- The [`include` keyword](../yaml/README.md#include): Bring in common behaviors, ensuring
you are not repeating yourself.
- [DAG pipelines](#directed-acyclic-graph-pipelines) inside of child pipelines, achieving the benefits of both.
```mermaid
graph LR
subgraph Parent pipeline
trigger_a -.-> build_a
trigger_b -.-> build_b
subgraph child pipeline B
build_b --> test_b --> deploy_b
end
subgraph child pipeline A
build_a --> test_a --> deploy_a
end
end
```
Example `/.gitlab-ci.yml` configuration for the parent pipeline matching the diagram:
```yaml
stages:
- triggers
trigger_a:
stage: triggers
trigger:
include: a/.gitlab-ci.yml
rules:
- changes:
- a/*
trigger_b:
stage: triggers
trigger:
include: b/.gitlab-ci.yml
rules:
- changes:
- b/*
```
Example child `a` pipeline configuration, located in `/a/.gitlab-ci.yml`, making
use of the DAG `needs:` keyword:
```yaml
stages:
- build
- test
- deploy
image: alpine
build_a:
stage: build
script:
- echo "This job builds something."
test_a:
stage: test
needs: build_a
script:
- echo "This job tests something."
deploy_a:
stage: deploy
needs: test_a
script:
- echo "This job deploys something."
```
Example child `b` pipeline configuration, located in `/b/.gitlab-ci.yml`, making
use of the DAG `needs:` keyword:
```yaml
stages:
- build
- test
- deploy
image: alpine
build_b:
stage: build
script:
- echo "This job builds something else."
test_b:
stage: test
needs: build_b
script:
- echo "This job tests something else."
deploy_b:
stage: deploy
needs: test_b
script:
- echo "This job deploys something else."
```
It's also possible to set jobs to run before or after triggering child pipelines,
for example if you have common setup steps or a unified deployment at the end.
Loading
Loading
@@ -17,6 +17,11 @@ NOTE: **Note:**
Coming over to GitLab from Jenkins? Check out our [reference](../jenkins/index.md)
for converting your pre-existing pipelines over to our format.
 
NOTE: **Note:**
There are a few different [basic pipeline architectures](../pipelines/pipeline_architectures.md)
that you can consider for use in your project. You may want to familiarize
yourself with these prior to getting started.
GitLab offers a [continuous integration](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/) service. For each commit or push to trigger your CI
[pipeline](../pipelines.md), you must:
 
Loading
Loading
Loading
Loading
@@ -17,12 +17,12 @@ First, in your `.gitlab-ci.yml` add:
 
```yaml
services:
- postgres:latest
- postgres:12.2-alpine
 
variables:
POSTGRES_DB: nice_marmot
POSTGRES_USER: runner
POSTGRES_PASSWORD: ""
POSTGRES_PASSWORD: "runner-password"
```
 
NOTE: **Note:**
Loading
Loading
@@ -37,7 +37,7 @@ And then configure your application to use the database, for example:
```yaml
Host: postgres
User: runner
Password:
Password: runner-password
Database: nice_marmot
```
 
Loading
Loading
Loading
Loading
@@ -7,7 +7,7 @@ check if a comment is still relevant and what needs to be done to address it.
 
Examples:
 
```rb
```ruby
# Deprecated scope until code_owner column has been migrated to rule_type.
# To be removed with https://gitlab.com/gitlab-org/gitlab/issues/11834.
scope :code_owner, -> { where(code_owner: true).or(where(rule_type: :code_owner)) }
Loading
Loading
Loading
Loading
@@ -8,7 +8,7 @@ To use this type, add `limit: 2` to the migration that creates the column.
 
Example:
 
```rb
```ruby
def change
add_column :ci_job_artifacts, :file_format, :integer, limit: 2
end
Loading
Loading
Loading
Loading
@@ -783,33 +783,64 @@ nicely on different mobile devices.
- When providing a shell command and its output, prefix the shell command with `$` and
leave a blank line between the command and the output.
- When providing a command without output, don't prefix the shell command with `$`.
- If you need to include triple backticks inside a code block, use four backticks
for the codeblock fences instead of three.
- For regular code blocks, always use a highlighting class corresponding to the
language for better readability. Examples:
 
~~~md
````markdown
```ruby
Ruby code
```
 
```js
```javascript
JavaScript code
```
 
```md
```markdown
[Markdown code example](example.md)
```
 
```text
```plaintext
Code or text for which no specific highlighting class is available.
```
~~~
- To display raw Markdown instead of rendered Markdown, you can use triple backticks
with `md`, like the `Markdown code` example above, unless you want to include triple
backticks in the code block as well. In that case, use triple tildes (`~~~`) instead.
- [Syntax highlighting for code blocks](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers)
is available for many languages. Use `shell` instead of `bash` or `sh` for shell output.
- For a complete reference on code blocks, check the [Kramdown guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/#code-blocks).
````
Syntax highlighting is required for code blocks added to the GitLab documentation.
Refer to the table below for the most common language classes, or check the
[complete list](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers)
of language classes available.
| Preferred language tags | Language aliases and notes |
|-------------------------|------------------------------------------------------------------------------|
| `asciidoc` | |
| `dockerfile` | Alias: `docker`. |
| `elixir` | |
| `erb` | |
| `golang` | Alias: `go`. |
| `graphql` | |
| `haml` | |
| `html` | |
| `ini` | For some simple config files that are not in TOML format. |
| `javascript` | Alias `js`. |
| `json` | |
| `markdown` | Alias: `md`. |
| `mermaid` | |
| `nginx` | |
| `perl` | |
| `php` | |
| `plaintext` | Examples with no defined language, such as output from shell commands or API calls. If a codeblock has no language, it defaults to `plaintext`. Alias: `text`. |
| `prometheus` | Prometheus configuration examples. |
| `python` | |
| `ruby` | Alias: `rb`. |
| `shell` | Aliases: `bash` or `sh`. |
| `sql` | |
| `toml` | Runner configuration examples, and other toml formatted configuration files. |
| `typescript` | Alias: `ts`. |
| `xml` | |
| `yaml` | Alias: `yml`. |
For a complete reference on code blocks, check the [Kramdown guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/#code-blocks).
 
## GitLab SVG icons
 
Loading
Loading
Loading
Loading
@@ -240,13 +240,13 @@ Here are the steps to gate a new feature in Gitaly behind a feature flag.
 
1. Create a package scoped flag name:
 
```go
```golang
var findAllTagsFeatureFlag = "go-find-all-tags"
```
 
1. Create a switch in the code using the `featureflag` package:
 
```go
```golang
if featureflag.IsEnabled(ctx, findAllTagsFeatureFlag) {
// go implementation
} else {
Loading
Loading
@@ -256,7 +256,7 @@ Here are the steps to gate a new feature in Gitaly behind a feature flag.
 
1. Create Prometheus metrics:
 
```go
```golang
var findAllTagsRequests = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "gitaly_find_all_tags_requests_total",
Loading
Loading
@@ -280,7 +280,7 @@ Here are the steps to gate a new feature in Gitaly behind a feature flag.
 
1. Set headers in tests:
 
```go
```golang
import (
"google.golang.org/grpc/metadata"
 
Loading
Loading
Loading
Loading
@@ -195,7 +195,7 @@ When comparing expected and actual values in tests, use
and others to improve readability when comparing structs, errors,
large portions of text, or JSON documents:
 
```go
```golang
type TestData struct {
// ...
}
Loading
Loading
Loading
Loading
@@ -918,12 +918,12 @@ instead of the default `ruby:latest`:
1. Set `AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` to `--build-arg=RUBY_VERSION=alpine`.
1. Add the following to a custom `Dockerfile`:
 
```docker
ARG RUBY_VERSION=latest
FROM ruby:$RUBY_VERSION
```dockerfile
ARG RUBY_VERSION=latest
FROM ruby:$RUBY_VERSION
 
# ... put your stuff here
```
# ... put your stuff here
```
 
NOTE: **Note:**
Passing in complex values (newlines and spaces, for example) will likely
Loading
Loading
@@ -955,14 +955,14 @@ In projects:
1. Activate the experimental `Dockerfile` syntax by adding the following
to the top of the file:
 
```docker
```dockerfile
# syntax = docker/dockerfile:experimental
```
 
1. To make secrets available in any `RUN $COMMAND` in the `Dockerfile`, mount
the secret file and source it prior to running `$COMMAND`:
 
```docker
```dockerfile
RUN --mount=type=secret,id=auto-devops-build-secrets . /run/secrets/auto-devops-build-secrets && $COMMAND
```
 
Loading
Loading
Loading
Loading
@@ -80,11 +80,11 @@ under which this application will be deployed.
![Google auth](../autodevops/img/guide_google_auth_v12_3.png)
 
1. The last step is to provide the cluster details.
1. Give it a name, leave the environment scope as is, and choose the GCP project under which the cluster
will be created (per the instructions to [configure your Google account](#configuring-your-google-account), a project should have already been created for you).
1. Choose the [region/zone](https://cloud.google.com/compute/docs/regions-zones/) under which the cluster will be created.
1. Enter the number of nodes you want it to have.
1. Choose the [machine type](https://cloud.google.com/compute/docs/machine-types).
1. Give it a name, leave the environment scope as is, and choose the GCP project under which the cluster
will be created (per the instructions to [configure your Google account](#configuring-your-google-account), a project should have already been created for you).
1. Choose the [region/zone](https://cloud.google.com/compute/docs/regions-zones/) under which the cluster will be created.
1. Enter the number of nodes you want it to have.
1. Choose the [machine type](https://cloud.google.com/compute/docs/machine-types).
 
![GitLab GKE cluster details](../autodevops/img/guide_gitlab_gke_details_v12_3.png)
 
Loading
Loading
@@ -180,40 +180,40 @@ your cluster either using [Cloud Shell](https://cloud.google.com/shell/) or the
 
1. After connecting to your cluster, check if the Ingress-NGINX controller is running and ModSecurity is enabled.
 
This is done by running the following commands:
This is done by running the following commands:
 
```bash
$ kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller'
ingress-nginx-ingress-controller-55f9cf6584-dxljn 2/2 Running
```shell
$ kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller'
ingress-nginx-ingress-controller-55f9cf6584-dxljn 2/2 Running
 
$ kubectl -n gitlab-managed-apps exec -it $(kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' | awk '{print $1}') -- cat /etc/nginx/nginx.conf | grep 'modsecurity on;'
modsecurity on;
```
$ kubectl -n gitlab-managed-apps exec -it $(kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' | awk '{print $1}') -- cat /etc/nginx/nginx.conf | grep 'modsecurity on;'
modsecurity on;
```
 
1. Verify the Rails application has been installed properly.
 
```bash
$ kubectl get ns
auto-devv-2-16730183-production Active
```shell
$ kubectl get ns
auto-devv-2-16730183-production Active
 
$ kubectl get pods -n auto-devv-2-16730183-production
NAME READY STATUS RESTARTS
production-5778cfcfcd-nqjcm 1/1 Running 0
production-postgres-6449f8cc98-r7xgg 1/1 Running 0
```
$ kubectl get pods -n auto-devv-2-16730183-production
NAME READY STATUS RESTARTS
production-5778cfcfcd-nqjcm 1/1 Running 0
production-postgres-6449f8cc98-r7xgg 1/1 Running 0
```
 
1. To make sure the Rails application is responding, send a request to it by running:
 
```bash
$ kubectl get ing -n auto-devv-2-16730183-production
NAME HOSTS PORTS
production-auto-deploy fjdiaz-auto-devv-2.34.68.60.207.nip.io,le-16730183.34.68.60.207.nip.io 80, 443
```shell
$ kubectl get ing -n auto-devv-2-16730183-production
NAME HOSTS PORTS
production-auto-deploy fjdiaz-auto-devv-2.34.68.60.207.nip.io,le-16730183.34.68.60.207.nip.io 80, 443
 
$ curl --location --insecure fjdiaz-auto-devv-2.34.68.60.207.nip.io | grep 'Rails!' --after 2 --before 2
<body>
<p>You're on Rails!</p>
</body>
```
$ curl --location --insecure fjdiaz-auto-devv-2.34.68.60.207.nip.io | grep 'Rails!' --after 2 --before 2
<body>
<p>You're on Rails!</p>
</body>
```
 
Now that we have confirmed our system is properly setup, we can go ahead and test
the WAF with OWASP CRS!
Loading
Loading
@@ -223,7 +223,7 @@ the WAF with OWASP CRS!
Now let's send a potentially malicious request, as if we were a scanner,
checking for vulnerabilities within our application and examine the modsecurity logs:
 
```bash
```shell
$ curl --location --insecure fjdiaz-auto-devv-2.34.68.60.207.nip.io --header "User-Agent: absinthe" | grep 'Rails!' --after 2 --before 2
<body>
<p>You're on Rails!</p>
Loading
Loading
doc/user/project/integrations/img/prometheus_dashboard_environments_v12_8.png

7.25 KiB

doc/user/project/integrations/img/prometheus_monitoring_dashboard_v12_8.png

29 KiB

Loading
Loading
@@ -55,6 +55,17 @@ will help you to quickly create a deployment:
1. Navigate to your project's **CI/CD > Pipelines** page, and run a pipeline on any branch.
1. When the pipeline has run successfully, graphs will be available on the **Operations > Metrics** page.
 
![Monitoring Dashboard](img/prometheus_monitoring_dashboard_v12_8.png)
#### Using the Metrics Dashboard
##### Select an environment
The **Environment** dropdown box above the dashboard displays the list of all [environments](#monitoring-cicd-environments).
It enables you to search as you type through all environments and select the one you're looking for.
![Monitoring Dashboard Environments](img/prometheus_dashboard_environments_v12_8.png)
#### About managed Prometheus deployments
 
Prometheus is deployed into the `gitlab-managed-apps` namespace, using the [official Helm chart](https://github.com/helm/charts/tree/master/stable/prometheus). Prometheus is only accessible within the cluster, with GitLab communicating through the [Kubernetes API](https://kubernetes.io/docs/concepts/overview/kubernetes-api/).
Loading
Loading
@@ -428,6 +439,29 @@ Note the following properties:
 
![single stat panel type](img/prometheus_dashboard_single_stat_panel_type.png)
 
###### Percentile based results
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/201946) in GitLab 12.8.
Query results sometimes need to be represented as a percentage value out of 100. You can use the `max_value` property at the root of the panel definition:
```yaml
dashboard: 'Dashboard Title'
panel_groups:
- group: 'Group Title'
panels:
- title: "Single Stat"
type: "single-stat"
max_value: 100
metrics:
- id: 10
query: 'max(go_memstats_alloc_bytes{job="prometheus"})'
unit: '%'
label: "Total"
```
For example, if you have a query value of `53.6`, adding `%` as the unit results in a single stat value of `53.6%`, but if the maximum expected value of the query is `120`, the value would be `44.6%`. Adding the `max_value` causes the correct percentage value to display.
##### Heatmaps
 
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/30581) in GitLab 12.5.
Loading
Loading
performance:
stage: performance
# pin to a version matching the dind service, just to be safe
image: docker:19.03.5
allow_failure: true
variables:
DOCKER_TLS_CERTDIR: ""
services:
# pin to a known working version until https://gitlab.com/gitlab-org/gitlab-runner/issues/6697 is fixed
- docker:19.03.5-dind
script:
- |
Loading
Loading
Loading
Loading
@@ -4,7 +4,6 @@ build:
variables:
DOCKER_TLS_CERTDIR: ""
services:
# pin to a known working version until https://gitlab.com/gitlab-org/gitlab-runner/issues/6697 is fixed
- docker:19.03.5-dind
script:
- |
Loading
Loading
code_quality:
stage: test
# pin to a version matching the dind service, just to be safe
image: docker:19.03.5
allow_failure: true
services:
# pin to a known working version until https://gitlab.com/gitlab-org/gitlab-runner/issues/6697 is fixed
- docker:19.03.5-dind
variables:
DOCKER_DRIVER: overlay2
Loading
Loading
Loading
Loading
@@ -48,7 +48,8 @@ module Quality
resource_names = raw_resource_names
command = [
'delete',
%(--namespace "#{namespace}")
%(--namespace "#{namespace}"),
'--ignore-not-found'
]
 
Array(release_name).each do |release|
Loading
Loading
Loading
Loading
@@ -534,6 +534,9 @@ msgstr ""
msgid "(removed)"
msgstr ""
 
msgid "*"
msgstr ""
msgid "+ %{amount} more"
msgstr ""
 
Loading
Loading
@@ -1544,6 +1547,9 @@ msgstr ""
msgid "All email addresses will be used to identify your commits."
msgstr ""
 
msgid "All environments"
msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
 
Loading
Loading
@@ -8385,6 +8391,9 @@ msgstr ""
msgid "Fetching licenses failed. You are not permitted to perform this action."
msgstr ""
 
msgid "File"
msgstr ""
msgid "File Hooks"
msgstr ""
 
Loading
Loading
@@ -19425,6 +19434,12 @@ msgstr ""
msgid "There was an error fetching the Designs"
msgstr ""
 
msgid "There was an error fetching the environments information."
msgstr ""
msgid "There was an error fetching the variables."
msgstr ""
msgid "There was an error fetching value stream analytics stages."
msgstr ""
 
Loading
Loading
@@ -21367,6 +21382,9 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
 
msgid "Variable"
msgstr ""
msgid "Variables"
msgstr ""
 
Loading
Loading
export default {
mockVariables: [
{
environment_scope: 'All environments',
id: 113,
key: 'test_var',
masked: false,
protected: false,
value: 'test_val',
variable_type: 'Variable',
},
{
environment_scope: 'All environments',
id: 114,
key: 'test_var_2',
masked: false,
protected: false,
value: 'test_val_2',
variable_type: 'Variable',
},
{
environment_scope: 'All environments',
id: 115,
key: 'test_var_3',
masked: false,
protected: false,
value: 'test_val_3',
variable_type: 'Variable',
},
],
mockVariablesApi: [
{
environment_scope: '*',
id: 113,
key: 'test_var',
masked: false,
protected: false,
value: 'test_val',
variable_type: 'env_var',
},
{
environment_scope: '*',
id: 114,
key: 'test_var_2',
masked: false,
protected: false,
value: 'test_val_2',
variable_type: 'file',
},
],
mockVariablesDisplay: [
{
environment_scope: 'All environments',
id: 113,
key: 'test_var',
masked: false,
protected: false,
value: 'test_val',
variable_type: 'Variable',
},
{
environment_scope: 'All environments',
id: 114,
key: 'test_var_2',
masked: false,
protected: false,
value: 'test_val_2',
variable_type: 'File',
},
],
mockEnvironments: [
{
id: 28,
name: 'staging',
slug: 'staging',
external_url: 'https://staging.example.com',
state: 'available',
},
{
id: 29,
name: 'production',
slug: 'production',
external_url: 'https://production.example.com',
state: 'available',
},
],
};
import Api from '~/api';
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import getInitialState from '~/ci_variable_list/store/state';
import * as actions from '~/ci_variable_list/store/actions';
import * as types from '~/ci_variable_list/store/mutation_types';
import mockData from '../services/mock_data';
import { prepareDataForDisplay, prepareEnvironments } from '~/ci_variable_list/store/utils';
jest.mock('~/api.js');
jest.mock('~/flash.js');
describe('CI variable list store actions', () => {
let mock;
let state;
const mockVariable = {
environment_scope: '*',
id: 63,
key: 'test_var',
masked: false,
protected: false,
value: 'test_val',
variable_type: 'env_var',
_destory: true,
};
const payloadError = new Error('Request failed with status code 500');
beforeEach(() => {
mock = new MockAdapter(axios);
state = getInitialState();
state.endpoint = '/variables';
});
afterEach(() => {
mock.restore();
});
describe('toggleValues', () => {
const valuesHidden = false;
it('commits TOGGLE_VALUES mutation', () => {
testAction(actions.toggleValues, valuesHidden, {}, [
{
type: types.TOGGLE_VALUES,
payload: valuesHidden,
},
]);
});
});
describe('clearModal', () => {
it('commits CLEAR_MODAL mutation', () => {
testAction(actions.clearModal, {}, {}, [
{
type: types.CLEAR_MODAL,
},
]);
});
});
describe('resetEditing', () => {
it('commits RESET_EDITING mutation', () => {
testAction(
actions.resetEditing,
{},
{},
[
{
type: types.RESET_EDITING,
},
],
[{ type: 'fetchVariables' }],
);
});
});
describe('deleteVariable', () => {
it('dispatch correct actions on successful deleted variable', done => {
mock.onPatch(state.endpoint).reply(200);
testAction(
actions.deleteVariable,
mockVariable,
state,
[],
[
{ type: 'requestDeleteVariable' },
{ type: 'receiveDeleteVariableSuccess' },
{ type: 'fetchVariables' },
],
() => {
done();
},
);
});
it('should show flash error and set error in state on delete failure', done => {
mock.onPatch(state.endpoint).reply(500, '');
testAction(
actions.deleteVariable,
mockVariable,
state,
[],
[
{ type: 'requestDeleteVariable' },
{
type: 'receiveDeleteVariableError',
payload: payloadError,
},
],
() => {
expect(createFlash).toHaveBeenCalled();
done();
},
);
});
});
describe('updateVariable', () => {
it('dispatch correct actions on successful updated variable', done => {
mock.onPatch(state.endpoint).reply(200);
testAction(
actions.updateVariable,
mockVariable,
state,
[],
[
{ type: 'requestUpdateVariable' },
{ type: 'receiveUpdateVariableSuccess' },
{ type: 'fetchVariables' },
],
() => {
done();
},
);
});
it('should show flash error and set error in state on update failure', done => {
mock.onPatch(state.endpoint).reply(500, '');
testAction(
actions.updateVariable,
mockVariable,
state,
[],
[
{ type: 'requestUpdateVariable' },
{
type: 'receiveUpdateVariableError',
payload: payloadError,
},
],
() => {
expect(createFlash).toHaveBeenCalled();
done();
},
);
});
});
describe('addVariable', () => {
it('dispatch correct actions on successful added variable', done => {
mock.onPatch(state.endpoint).reply(200);
testAction(
actions.addVariable,
{},
state,
[],
[
{ type: 'requestAddVariable' },
{ type: 'receiveAddVariableSuccess' },
{ type: 'fetchVariables' },
],
() => {
done();
},
);
});
it('should show flash error and set error in state on add failure', done => {
mock.onPatch(state.endpoint).reply(500, '');
testAction(
actions.addVariable,
{},
state,
[],
[
{ type: 'requestAddVariable' },
{
type: 'receiveAddVariableError',
payload: payloadError,
},
],
() => {
expect(createFlash).toHaveBeenCalled();
done();
},
);
});
});
describe('fetchVariables', () => {
it('dispatch correct actions on fetchVariables', done => {
mock.onGet(state.endpoint).reply(200, { variables: mockData.mockVariables });
testAction(
actions.fetchVariables,
{},
state,
[],
[
{ type: 'requestVariables' },
{
type: 'receiveVariablesSuccess',
payload: prepareDataForDisplay(mockData.mockVariables),
},
],
() => {
done();
},
);
});
it('should show flash error and set error in state on fetch variables failure', done => {
mock.onGet(state.endpoint).reply(500);
testAction(actions.fetchVariables, {}, state, [], [{ type: 'requestVariables' }], () => {
expect(createFlash).toHaveBeenCalledWith('There was an error fetching the variables.');
done();
});
});
});
describe('fetchEnvironments', () => {
it('dispatch correct actions on fetchEnvironments', done => {
Api.environments = jest.fn().mockResolvedValue({ data: mockData.mockEnvironments });
testAction(
actions.fetchEnvironments,
{},
state,
[],
[
{ type: 'requestEnvironments' },
{
type: 'receiveEnvironmentsSuccess',
payload: prepareEnvironments(mockData.mockEnvironments),
},
],
() => {
done();
},
);
});
it('should show flash error and set error in state on fetch environments failure', done => {
Api.environments = jest.fn().mockRejectedValue();
testAction(
actions.fetchEnvironments,
{},
state,
[],
[{ type: 'requestEnvironments' }],
() => {
expect(createFlash).toHaveBeenCalledWith(
'There was an error fetching the environments information.',
);
done();
},
);
});
});
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment