1---
2stage: none
3group: unassigned
4info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
5---
6
7# Danger bot
8
9The GitLab CI/CD pipeline includes a `danger-review` job that uses [Danger](https://github.com/danger/danger)
10to perform a variety of automated checks on the code under test.
11
12Danger is a gem that runs in the CI environment, like any other analysis tool.
13What sets it apart from (for example, RuboCop) is that it's designed to allow you to
14easily write arbitrary code to test properties of your code or changes. To this
15end, it provides a set of common helpers and access to information about what
16has actually changed in your environment, then simply runs your code!
17
18If Danger is asking you to change something about your merge request, it's best
19just to make the change. If you want to learn how Danger works, or make changes
20to the existing rules, then this is the document for you.
21
22## Danger comments in merge requests
23
24Danger only posts one comment and updates its content on subsequent
25`danger-review` runs. Given this, it's usually one of the first few comments
26in a merge request if not the first. If you didn't see it, try to look
27from the start of the merge request.
28
29### Advantages
30
31- You don't get email notifications each time `danger-review` runs.
32
33### Disadvantages
34
35- It's not obvious Danger updates the old comment, thus you need to
36  pay attention to it if it is updated or not.
37
38## Run Danger locally
39
40A subset of the current checks can be run locally with the following Rake task:
41
42```shell
43bin/rake danger_local
44```
45
46## Operation
47
48On startup, Danger reads a [`Dangerfile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/Dangerfile)
49from the project root. Danger code in GitLab is decomposed into a set of helpers
50and plugins, all within the [`danger/`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/danger/)
51subdirectory, so ours just tells Danger to load it all. Danger then runs
52each plugin against the merge request, collecting the output from each. A plugin
53may output notifications, warnings, or errors, all of which are copied to the
54CI job's log. If an error happens, the CI job (and so the entire pipeline) fails.
55
56On merge requests, Danger also copies the output to a comment on the MR
57itself, increasing visibility.
58
59## Development guidelines
60
61Danger code is Ruby code, so all our [usual backend guidelines](index.md#backend-guides)
62continue to apply. However, there are a few things that deserve special emphasis.
63
64### When to use Danger
65
66Danger is a powerful tool and flexible tool, but not always the most appropriate
67way to solve a given problem or workflow.
68
69First, be aware of the GitLab [commitment to dogfooding](https://about.gitlab.com/handbook/engineering/#dogfooding).
70The code we write for Danger is GitLab-specific, and it **may not** be most
71appropriate place to implement functionality that addresses a need we encounter.
72Our users, customers, and even our own satellite projects, such as [Gitaly](https://gitlab.com/gitlab-org/gitaly),
73often face similar challenges, after all. Think about how you could fulfill the
74same need while ensuring everyone can benefit from the work, and do that instead
75if you can.
76
77If a standard tool (for example, `rubocop`) exists for a task, it's better to
78use it directly, rather than calling it by using Danger. Running and debugging
79the results of those tools locally is easier if Danger isn't involved, and
80unless you're using some Danger-specific functionality, there's no benefit to
81including it in the Danger run.
82
83Danger is well-suited to prototyping and rapidly iterating on solutions, so if
84what we want to build is unclear, a solution in Danger can be thought of as a
85trial run to gather information about a product area. If you're doing this, make
86sure the problem you're trying to solve, and the outcomes of that prototyping,
87are captured in an issue or epic as you go along. This helps us to address
88the need as part of the product in a future version of GitLab!
89
90### Implementation details
91
92Implement each task as an isolated piece of functionality and place it in its
93own directory under `danger` as `danger/<task-name>/Dangerfile`.
94
95Each task should be isolated from the others, and able to function in isolation.
96If there is code that should be shared between multiple tasks, add a plugin to
97`danger/plugins/...` and require it in each task that needs it. You can also
98create plugins that are specific to a single task, which is a natural place for
99complex logic related to that task.
100
101Danger code is just Ruby code. It should adhere to our coding standards, and
102needs tests, like any other piece of Ruby in our codebase. However, we aren't
103able to test a `Dangerfile` directly! So, to maximize test coverage, try to
104minimize the number of lines of code in `danger/`. A non-trivial `Dangerfile`
105should mostly call plugin code with arguments derived from the methods provided
106by Danger. The plugin code itself should have unit tests.
107
108At present, we do this by putting the code in a module in `tooling/danger/...`,
109and including it in the matching `danger/plugins/...` file. Specs can then be
110added in `spec/tooling/danger/...`.
111
112To determine if your `Dangerfile` works, push the branch that contains it to
113GitLab. This can be quite frustrating, as it significantly increases the cycle
114time when developing a new task, or trying to debug something in an existing
115one. If you've followed the guidelines above, most of your code can be exercised
116locally in RSpec, minimizing the number of cycles you need to go through in CI.
117However, you can speed these cycles up somewhat by emptying the
118`.gitlab/ci/rails.gitlab-ci.yml` file in your merge request. Just don't forget
119to revert the change before merging!
120
121#### Adding labels via Danger
122
123NOTE:
124This is currently applicable to the [`gitlab-org/gitlab`](https://gitlab.com/gitlab-org/gitlab)
125project only.
126
127Danger is often used to improve MR hygiene by adding labels. Instead of calling the
128API directly in your `Dangerfile`, add the labels to the `project_helper.labels_to_add` array.
129The main `Dangerfile` will then take care of adding the labels to the MR with a single API call.
130
131#### Shared rules and plugins
132
133If the rule or plugin you implement can be useful for other projects, think about
134upstreaming them to the [`gitlab-dangerfiles`](https://gitlab.com/gitlab-org/ruby/gems/gitlab-dangerfiles) project.
135
136#### Enable Danger on a project
137
138To enable the Dangerfile on another existing GitLab project, run the following
139extra steps:
140
1411. Create a [Project access tokens](../user/project/settings/project_access_tokens.md).
1421. Add the token as a CI/CD project variable named `DANGER_GITLAB_API_TOKEN`.
143
144You should add the ~"Danger bot" label to the merge request before sending it
145for review.
146
147## Current uses
148
149Here is a (non-exhaustive) list of the kinds of things Danger has been used for
150at GitLab so far:
151
152- Coding style
153- Database review
154- Documentation review
155- Merge request metrics
156- Reviewer roulette. Reviewers and maintainers are chosen based on:
157  - Their roles (backend, frontend, database, etc).
158  - Their availability:
159    - No "OOO"/"PTO"/"Parental Leave" in their GitLab or Slack status.
160    - No `:red_circle:`/`:palm_tree:`/`:beach:`/`:beach_umbrella:`/`:beach_with_umbrella:` emojis in GitLab or Slack status.
161  - (Experimental) Their time zone: people for which the local hour is between
162    6 AM and 2 PM are eligible to be picked. This is to ensure they have a good
163    chance to get to perform a review during their current work day. The experimentation is tracked in
164    [this issue](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/563)
165- Single codebase effort
166
167## Limitations
168
169Danger is run but its output is not added to a merge request comment if working
170on a fork. This happens because the secret variable from the canonical project
171is not shared to forks.
172
173### Configuring Danger for forks
174
175Contributors can configure Danger for their forks with the following steps:
176
1771. Add an [environment variable](../ci/variables/index.md) called `DANGER_GITLAB_API_TOKEN` with a
178[personal API token](https://gitlab.com/-/profile/personal_access_tokens?name=GitLab+Dangerbot&scopes=api)
179to your fork that has the `api` scope set.
1801. Making the variable [masked](../ci/variables/index.md#mask-a-cicd-variable) makes sure it
181doesn't show up in the job logs. The variable cannot be
182[protected](../ci/variables/index.md#protect-a-cicd-variable), as it needs
183to be present for all feature branches.
184