Want to Automate Code Reviews? Set Up Danger JS for Unsupported CIs
Want to Automate Code Reviews? Set Up Danger JS for Unsupported CIs
With Google CloudBuild as an example.
What is Danger JS?
You can skip this section if you are already familiar withDanger JS.
Danger JS is an open-source build tool that allows software developers to automate common code review chores. Using Danger JS, we can automatically run a set of rules against your Pull Request (PR) and leave a code review comment.
It automates repetitive and trivial code review comments like:
This PR is large, please consider breaking it down so we can effectively review it.
or
Please update the changelog file.
It helps developers to focus on reviewing the problem that the PR is trying to solve, rather than getting distracted by code review chores.
Automatically handle code review chores.
An example code
To better understand how it works, let’s take a common use case as an example:What if we want to leave a comment if a pull request is too big?
You can write a JS function using Danger JS to accomplish this use case:
If the number of lines changed in a pull request is more than the arbitrarybigPRThreshold
value, then leave a “warning” comment in the pull request.
Setting up Danger JS
Below, I summarize the steps involved in setting up Danger JS in your CI.
- Install Danger by running
yarn add danger —dev
ornpm install --save-dev danger
. - Create adangerfileand include it in your repository’s root folder. It can be
dangerfile.ts
ordangerfile.js
. - Set up a GitHub bot and/or generate a GitHub token with sufficient access to comment, approve or reject a Pull Request.
- Refer to thislist of setup instructionsthat you’ll need to follow depending on the CI that you use.
What if my CI is unsupported?
For example, if you want to use Danger JS within your company’s internal CI or Google Cloud Build. Google Cloud Build isnot a supported CI at the time of writing.
We have two options for that:
- Contributeback to Danger.
- Use Danger’s “manual mode”,which is whatwe will cover in the next sections.
1. Write your Dangerfile
Start by installing danger. We will use npm for our example.
npm install --save-dev danger
Import what we need from our Danger package.
import {danger, warn, markdown} from 'danger';
Create ourdangerfile.ts
. We will implement the following functions:
reviewLargePR()
Same as our previous code exampleensurePRHasAssignee()
Fail the PR if there is no assignee.
Ourdangerfile.ts
:
2. Test locally using danger-pr
We can test ourdangerfile
locally by usingdanger-pr.js
. This will not leave a comment on the pull request. It will print out the expected PR comments in the terminal. This option allows us to debugdangerfile
locally without spamming comments on a real PR.
Run the following command in your repository’s root folder, in the same folder as thedangerfile.ts
:
# Your GitHub API token
export DANGER_GITHUB_API_TOKEN=<yourtoken>
node_modules/danger/distribution/commands/danger-pr.js https://github.com/danger/danger-js/pull/1192
In our example above, we are using apublic PR to Danger JS’s GitHub repository. At the time of writing, this PR has around 7,000~ lines changed. This number is “large” according to our Dangerfile’s rules.
Our output will show that the PR is large:
3. Run with danger-ci using “Manual Mode”
Danger can support CIs that are not on their current supported list by using their “manual mode”.
Running Danger’s CI command
Now that our dangerfile works as expected, let’s run usingdanger-ci
locally. This command will leave a comment on the PR that we specify.
ℹ️ Make sure that youhave configured the required GitHub accesswhen running the CI command.
Set the environment variables
We can enable manual mode by setting the required environment variables.
Set your CI’s name:
# Replace with your unsupported CI's name, e.g. CloudBuild
export DANGER_MANUAL_CI=<UNSUPPORTED_CI_NAME>
Specify your GitHub repository:
# Replace with your GitHub repository
export DANGER_MANUAL_GH_REPO=<githuborg/githubrepo>
Set your GitHub API access token in case you haven’t yet:
# Replace with your GitHub API token
export DANGER_GITHUB_API_TOKEN=<yourtoken>
Run the Danger CI command
Now that we have set the required environment variables👆, run thedanger-ci
command:
DANGER_MANUAL_PR_NUM=<PR Number> node_modules/danger/distribution/commands/danger-ci.js
The environment variableDANGER_MANUAL_PR_NUM
is the PR number of the PR that we want Danger to review. For example, if your PR is:https://github.com/danger/danger-js/pull/1192
, the environment variable will beDANGER_MANUAL_PR_NUM=1192
.
An example
ℹ️ Note that we have the option to write a shell script that runs all the commands in this example, instead of running the commands one at a time.
Let’s take a public GitHub Pull Request that I’ve set up as an example.
- The repository isardydedase/danger-example.
- Theexample PRishttps://github.com/ardydedase/danger-example/pull/1. Note our PR number
1
. - We will use the same
dangerfile
that checks if the PR is too big and if it has an assignee.See ourdangerfile.tsin our example repository.
Let’s set up our environment variables:
# Replace with your unsupported CI's name, e.g. CloudBuild
export DANGER_MANUAL_CI=MyCI
# Replace with your GitHub repository
export DANGER_MANUAL_GH_REPO=ardydedase/danger-example
# Replace with your GitHub API token
export DANGER_GITHUB_API_TOKEN=<yourtoken>
Then run thedanger-ci
command with the PR number, which is1
in this example:
DANGER_MANUAL_PR_NUM=1 node_modules/danger/distribution/commands/danger-ci.js
In our example, the PR fails because there is no assigned user to the PR.
The PR comment on GitHub will be:
☝️ I’m using my personal GitHub token for this demo, so it’s my username that appears on the PR. Ideally, we should set up a GitHub bot.
We will perform the same steps in our unsupported CI: set the environment variables and run thedanger-ci
command. We will cover this in the next section. 👇
4. Run Danger locally with an Unsupported CI (Google CloudBuild)
After testing our dangerfile in Step 3, we are now ready to configure Danger with our unsupported CI.
We will use Google CloudBuild as our CI in our example because:
- At the time of writing, Google CloudBuild is not yet a supported CI in Danger JS.
- It has a Local Cloud Builder CLI tool we can use to test our build configuration YAML locally.
Google Cloud Prerequisites
We will need our CloudBuild CLI tool installed to test our Danger build with Google Cloud locally. Please refer to the docs linked below:
- Prerequisite: Ensure that you have installed the Google Cloud CLI.Refer to this doc.
- Install the Local Cloud Builder CLI. We will need this to run
cloud-build-local
.
CloudBuild configuration file
Let’s create our config file:
ℹ️ Replace theGITHUB_API_TOKEN
with your token.
When we runcloud-build-local
,dryrun
is enabled by default unless we specify otherwise. This gives us the option to check our build’s syntax, saving us time to test. Let’s start by running thecloud-build-local
command below to make sure that our config file has no syntax error:
cloud-build-local --config=./cloudbuild-local.yaml .
If the above command is successful, the output will be:
Let’s now set thedryrun
flag to false to run the danger build locally:
cloud-build-local --config=./cloudbuild-local.yaml --dryrun=false .
👆 The above command will a few minutes to complete. Downloading the node docker image will take the most time.
A successful build will show a similar output below:
And it should leave a PR comment as well:
5. Google Cloud setup
Now that our local configuration works as expected, we can use the same configuration in our production Cloud Build setup.
Configuration for Production environment
Our production setup is almost the same, except that we are retrieving the PR number from CloudBuild. Instead of hard-coding, we will assign$_PR_NUMBER
toDANGER_MANUAL_PR_NUM
.
Our Danger CI command will be:
DANGER_MANUAL_PR_NUM=$_PR_NUMBER node_modules/danger/distribution/commands/danger-ci.js
We should also store our GitHub API token in Google Cloud’s Secrets Manager or any “secrets” manager that you are using.
If we are using Google Secrets manager, we will need to update our build configuration to use it: