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