2020-10-30 14:08:56 -04:00
---
stage: none
group: unassigned
2020-11-26 01:09:20 -05:00
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
2020-10-30 14:08:56 -04:00
---
2019-09-02 20:23:52 -04:00
# Danger bot
2020-03-26 23:07:56 -04:00
The GitLab CI/CD pipeline includes a `danger-review` job that uses [Danger ](https://github.com/danger/danger )
2019-09-02 20:23:52 -04:00
to perform a variety of automated checks on the code under test.
Danger is a gem that runs in the CI environment, like any other analysis tool.
2020-12-07 10:09:49 -05:00
What sets it apart from (for example, RuboCop) is that it's designed to allow you to
2019-09-02 20:23:52 -04:00
easily write arbitrary code to test properties of your code or changes. To this
end, it provides a set of common helpers and access to information about what
has actually changed in your environment, then simply runs your code!
If Danger is asking you to change something about your merge request, it's best
just to make the change. If you want to learn how Danger works, or make changes
to the existing rules, then this is the document for you.
2020-03-05 04:08:31 -05:00
## Danger comments in merge requests
2020-03-06 06:28:26 -05:00
Danger only posts one comment and updates its content on subsequent
`danger-review` runs. Given this, it's usually one of the first few comments
in a merge request if not the first. If you didn't see it, try to look
from the start of the merge request.
2020-03-05 04:08:31 -05:00
### Advantages
2020-03-06 06:28:26 -05:00
- You don't get email notifications each time `danger-review` runs.
2020-03-05 04:08:31 -05:00
### Disadvantages
2020-12-07 10:09:49 -05:00
- It's not obvious Danger updates the old comment, thus you need to
2020-03-06 06:28:26 -05:00
pay attention to it if it is updated or not.
2020-03-05 04:08:31 -05:00
2020-01-28 16:08:56 -05:00
## Run Danger locally
2020-03-31 08:08:09 -04:00
A subset of the current checks can be run locally with the following Rake task:
2020-01-28 16:08:56 -05:00
```shell
2020-02-03 07:09:07 -05:00
bin/rake danger_local
2020-01-28 16:08:56 -05:00
```
2019-09-02 20:23:52 -04:00
## Operation
2021-06-08 14:10:23 -04:00
On startup, Danger reads a [`Dangerfile` ](https://gitlab.com/gitlab-org/gitlab/-/blob/master/Dangerfile )
2020-12-16 19:09:53 -05:00
from the project root. Danger code in GitLab is decomposed into a set of helpers
2019-09-18 10:02:45 -04:00
and plugins, all within the [`danger/` ](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/danger/ )
2020-12-07 10:09:49 -05:00
subdirectory, so ours just tells Danger to load it all. Danger then runs
2019-09-02 20:23:52 -04:00
each plugin against the merge request, collecting the output from each. A plugin
may output notifications, warnings, or errors, all of which are copied to the
2020-12-07 10:09:49 -05:00
CI job's log. If an error happens, the CI job (and so the entire pipeline) fails.
2019-09-02 20:23:52 -04:00
2020-12-07 10:09:49 -05:00
On merge requests, Danger also copies the output to a comment on the MR
2019-09-02 20:23:52 -04:00
itself, increasing visibility.
## Development guidelines
2021-06-28 08:38:12 -04:00
Danger code is Ruby code, so all our [usual backend guidelines ](index.md#backend-guides )
2019-09-02 20:23:52 -04:00
continue to apply. However, there are a few things that deserve special emphasis.
### When to use Danger
Danger is a powerful tool and flexible tool, but not always the most appropriate
way to solve a given problem or workflow.
2020-12-16 19:09:53 -05:00
First, be aware of the GitLab [commitment to dogfooding ](https://about.gitlab.com/handbook/engineering/#dogfooding ).
2019-09-02 20:23:52 -04:00
The code we write for Danger is GitLab-specific, and it **may not** be most
appropriate place to implement functionality that addresses a need we encounter.
Our users, customers, and even our own satellite projects, such as [Gitaly ](https://gitlab.com/gitlab-org/gitaly ),
2020-04-22 14:09:52 -04:00
often face similar challenges, after all. Think about how you could fulfill the
2019-09-02 20:23:52 -04:00
same need while ensuring everyone can benefit from the work, and do that instead
if you can.
2020-12-07 10:09:49 -05:00
If a standard tool (for example, `rubocop` ) exists for a task, it's better to
use it directly, rather than calling it by using Danger. Running and debugging
the results of those tools locally is easier if Danger isn't involved, and
unless you're using some Danger-specific functionality, there's no benefit to
including it in the Danger run.
2019-09-02 20:23:52 -04:00
Danger is well-suited to prototyping and rapidly iterating on solutions, so if
what we want to build is unclear, a solution in Danger can be thought of as a
trial run to gather information about a product area. If you're doing this, make
sure the problem you're trying to solve, and the outcomes of that prototyping,
2020-12-07 10:09:49 -05:00
are captured in an issue or epic as you go along. This helps us to address
2019-09-02 20:23:52 -04:00
the need as part of the product in a future version of GitLab!
### Implementation details
Implement each task as an isolated piece of functionality and place it in its
own directory under `danger` as `danger/<task-name>/Dangerfile` .
Each task should be isolated from the others, and able to function in isolation.
If there is code that should be shared between multiple tasks, add a plugin to
`danger/plugins/...` and require it in each task that needs it. You can also
create plugins that are specific to a single task, which is a natural place for
complex logic related to that task.
Danger code is just Ruby code. It should adhere to our coding standards, and
needs tests, like any other piece of Ruby in our codebase. However, we aren't
2019-09-09 01:02:46 -04:00
able to test a `Dangerfile` directly! So, to maximize test coverage, try to
2019-09-02 20:23:52 -04:00
minimize the number of lines of code in `danger/` . A non-trivial `Dangerfile`
should mostly call plugin code with arguments derived from the methods provided
by Danger. The plugin code itself should have unit tests.
2021-01-20 07:11:06 -05:00
At present, we do this by putting the code in a module in `tooling/danger/...` ,
2019-09-02 20:23:52 -04:00
and including it in the matching `danger/plugins/...` file. Specs can then be
2021-01-20 07:11:06 -05:00
added in `spec/tooling/danger/...` .
2019-09-02 20:23:52 -04:00
2020-12-07 10:09:49 -05:00
To determine if your `Dangerfile` works, push the branch that contains it to
GitLab. This can be quite frustrating, as it significantly increases the cycle
time when developing a new task, or trying to debug something in an existing
one. If you've followed the guidelines above, most of your code can be exercised
locally in RSpec, minimizing the number of cycles you need to go through in CI.
However, you can speed these cycles up somewhat by emptying the
2019-09-02 20:23:52 -04:00
`.gitlab/ci/rails.gitlab-ci.yml` file in your merge request. Just don't forget
to revert the change before merging!
2021-10-27 14:13:16 -04:00
#### Adding labels via Danger
NOTE:
This is currently applicable to the [`gitlab-org/gitlab` ](https://gitlab.com/gitlab-org/gitlab )
project only.
Danger is often used to improve MR hygiene by adding labels. Instead of calling the
API directly in your `Dangerfile` , add the labels to the `project_helper.labels_to_add` array.
The main `Dangerfile` will then take care of adding the labels to the MR with a single API call.
#### Shared rules and plugins
If the rule or plugin you implement can be useful for other projects, think about
upstreaming them to the [`gitlab-org/gitlab-dangerfiles` ](https://gitlab.com/gitlab-org/gitlab-dangerfiles ) project.
#### Enable Danger on a project
2020-12-07 10:09:49 -05:00
To enable the Dangerfile on another existing GitLab project, run the following
2021-07-01 08:08:37 -04:00
extra steps:
2019-12-12 22:07:50 -05:00
2021-07-01 08:08:37 -04:00
1. Create a [Project access tokens ](../user/project/settings/project_access_tokens.md ).
1. Add the token as a CI/CD project variable named `DANGER_GITLAB_API_TOKEN` .
2019-12-12 22:07:50 -05:00
2021-07-01 08:08:37 -04:00
You should add the ~"Danger bot" label to the merge request before sending it
2019-09-02 20:23:52 -04:00
for review.
## Current uses
Here is a (non-exhaustive) list of the kinds of things Danger has been used for
at GitLab so far:
- Coding style
2020-07-07 17:09:13 -04:00
- Database review
- Documentation review
2019-09-02 20:23:52 -04:00
- Merge request metrics
2020-07-07 17:09:13 -04:00
- Reviewer roulette. Reviewers and maintainers are chosen based on:
- Their roles (backend, frontend, database, etc).
- Their availability:
- No "OOO"/"PTO"/"Parental Leave" in their GitLab or Slack status.
- No `:red_circle:` /`:palm_tree:`/`:beach:`/`:beach_umbrella:`/`:beach_with_umbrella:` emojis in GitLab or Slack status.
2021-09-28 11:11:30 -04:00
- (Experimental) Their time zone: people for which the local hour is between
2020-07-07 17:09:13 -04:00
6 AM and 2 PM are eligible to be picked. This is to ensure they have a good
chance to get to perform a review during their current work day. The experimentation is tracked in
[this issue ](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/563 )
2019-09-02 20:23:52 -04:00
- Single codebase effort
## Limitations
2021-03-31 14:09:19 -04:00
Danger is run but its output is not added to a merge request comment if working
on a fork. This happens because the secret variable from the canonical project
2021-08-09 02:10:01 -04:00
is not shared to forks.
2021-08-02 17:09:44 -04:00
### Configuring Danger for forks
Contributors can configure Danger for their forks with the following steps:
1. Add an [environment variable ](../ci/variables/index.md ) called `DANGER_GITLAB_API_TOKEN` with a
2021-07-01 14:07:29 -04:00
[personal API token ](https://gitlab.com/-/profile/personal_access_tokens?name=GitLab+Dangerbot&scopes=api )
2021-08-09 02:10:01 -04:00
to your fork that has the `api` scope set.
2021-08-02 17:09:44 -04:00
1. Making the variable [masked ](../ci/variables/index.md#mask-a-cicd-variable ) makes sure it
2021-03-31 14:09:19 -04:00
doesn't show up in the job logs. The variable cannot be
2021-06-28 11:08:03 -04:00
[protected ](../ci/variables/index.md#protect-a-cicd-variable ), as it needs
2021-03-31 14:09:19 -04:00
to be present for all feature branches.