Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: danger/danger-js
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3.8.4
Choose a base ref
...
head repository: danger/danger-js
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3.8.5
Choose a head ref
  • 7 commits
  • 12 files changed
  • 2 contributors

Commits on Aug 4, 2018

  1. Merged by Peril

    Adds the potential to override the custom module handler in peril
    peril-staging[bot] authored Aug 4, 2018

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    9b63869 View commit details

Commits on Aug 6, 2018

  1. Copy the full SHA
    d04a9fb View commit details

Commits on Aug 11, 2018

  1. More dep updates

    orta committed Aug 11, 2018

    Verified

    This commit was signed with the committer’s verified signature.
    orta Orta Therox
    Copy the full SHA
    702e51d View commit details
  2. Merged by Peril

    Improve the docs, and add something about danger local
    peril-staging[bot] authored Aug 11, 2018

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    acf9b5d View commit details

Commits on Aug 13, 2018

  1. Copy the full SHA
    fbbcc1c View commit details
  2. Merged by Peril

    Adds a create/update label function to the github utils func
    peril-staging[bot] authored Aug 13, 2018

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    a4c420f View commit details
  3. Version bump

    orta committed Aug 13, 2018
    Copy the full SHA
    f4836a1 View commit details
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -13,6 +13,11 @@

## Master

# 3.8.5

- Adds a function to handle creating or adding a label on a PR/Issue. Works with both Danger and Peril:
`danger.github.createOrAddLabel` - [@orta][]

# 3.8.4

- Exposes some internals on module resolution to Peril - [@orta][]
44 changes: 28 additions & 16 deletions VISION.md
Original file line number Diff line number Diff line change
@@ -5,33 +5,45 @@ able to run on a server, and not need direct access to the filesystem to do its

It was started in mid-2016, and has fleshed out into a considerable set of useful tools.

* You can fake running on CI for any PR with `danger pr`.
* You can run Danger rules inside git hooks, or without pull requests metadata via `danger local`.
* You can share code using [danger plugins][plugins].
* You can get started in a fun way via `danger init`.
* Danger can run independently of CI via Peril.
- You can get started in a fun way via `danger init`.
- You can run danger via `danger ci`.
- You can fake running on CI locally for any GitHub PR with `danger pr`.
- You can run Danger rules inside git hooks, or without pull requests metadata via `danger local`.
- You can share code using [danger plugins][plugins].
- Danger can run independently of CI via Peril.

## Future Plans

There are only really two big targets for the future of Danger JS:
There is only really one big target left for the future of Danger JS:

* Inline comments in PRs
* GitLab / BitBucket support
- GitLab

I don't plan on really using either of those features, so I expect both to come from the community instead.
I don't plan on really using this, so I expect both to come from the community instead.

My focus is going to be mainly in the Peril side of Danger. Moving to making it trivial to add Danger to any GitHub
project and really unlocking some complex culture systems. Examples of these can be found on [the Artsy blog][peril].

# Why Danger JS? What about Danger Ruby?

When I started Danger JS, Danger Ruby was two years old, is still doing just fine. See the [original vision file](https://github.com/danger/danger/blob/master/VISION.md). This document assumes you have read it.

The amount of issues we get in comparison to the number of downloads on Rubygems makes me feel pretty confident about Danger Ruby's state of production quality and maturity. I wanted to start thinking about the larger patterns in software, because at Artsy, we are starting to use JavaScript in [for many teams](http://artsy.github.io/blog/2016/08/15/React-Native-at-Artsy/).

I've explored [running JavaScript](https://github.com/danger/danger/pull/423) from the ruby Danger, ([example](https://github.com/artsy/emission/blob/d58b3d57bf41100e3cce3c2c1b1c4d6c19581a68/Dangerfile.js) from production) but this pattern isn't going to work on the larger scale: You cannot use npm modules, nor work with babel/tsc to transpile your `Dangerfile.js` and the requirements on the integrating project to [feel weird](https://github.com/artsy/emission/pull/233). Running JS in Ruby isn't going to work for me.

This realization came at the same time as serious thinking on a hosted version of Danger. With a JavaScript versions we can limit the exposed Danger DSL to only something that can be obtained over the API remotely. By doing this, a hosted Danger does not need to clone and run the associated projects. This is essential for my sanity. I cannot run multiple [servers like CocoaDocs](http://cocoadocs.org). So far, I'm calling this Peril. You can consult the [vision file for Peril](https://github.com/danger/peril/blob/master/VISION.md) if you'd like.
When I started Danger JS, Danger Ruby was two years old, is still doing just fine. See the
[original vision file](https://github.com/danger/danger/blob/master/VISION.md). This document assumes you have read it.

The amount of issues we get in comparison to the number of downloads on Rubygems makes me feel pretty confident about
Danger Ruby's state of production quality and maturity. I wanted to start thinking about the larger patterns in
software, because at Artsy, we are starting to use JavaScript in
[for many teams](http://artsy.github.io/blog/2016/08/15/React-Native-at-Artsy/).

I've explored [running JavaScript](https://github.com/danger/danger/pull/423) from the ruby Danger,
([example](https://github.com/artsy/emission/blob/d58b3d57bf41100e3cce3c2c1b1c4d6c19581a68/Dangerfile.js) from
production) but this pattern isn't going to work on the larger scale: You cannot use npm modules, nor work with
babel/tsc to transpile your `Dangerfile.js` and the requirements on the integrating project
[feel weird](https://github.com/artsy/emission/pull/233). Running JS in Ruby isn't going to work for me.

This realization came at the same time as serious thinking on a hosted version of Danger. With a JavaScript versions we
can limit the exposed Danger DSL to only something that can be obtained over the API remotely. By doing this, a hosted
Danger does not need to clone and run the associated projects. This is essential for my sanity. I cannot run multiple
[servers like CocoaDocs](http://cocoadocs.org). So far, I'm calling this Peril. You can consult the
[vision file for Peril](https://github.com/danger/peril/blob/master/VISION.md) if you'd like.

[plugins]: https://www.npmjs.com/search?q=keywords:danger-plugin&page=1&ranking=optimal
[peril]: http://artsy.github.io/blog/2017/09/04/Introducing-Peril/
51 changes: 34 additions & 17 deletions docs/tutorials/dependencies.html.md
Original file line number Diff line number Diff line change
@@ -8,17 +8,22 @@ blurb: An example of how can you use Danger to keep your dependencies in check.

## Before we get started

This guide continues after "[Getting Started][started]" - so you should have seen Danger comment on your PRs.
This tutorial continues after "[Getting Started][started]" - so you should have seen Danger comment on your PRs.

## Keeping on top of your dependencies

Building pretty-much anything in the node ecosystem involves using using external dependencies. In an ideal situation you want to use as few dependencies as possible, and get the most use out of them. Remember that you are shipping your dependencies too, so you are responsible for them to your end-users.
Building pretty-much anything in the node ecosystem involves using using external dependencies. In an ideal situation
you want to use as few dependencies as possible, and get the most use out of them. Remember that you are shipping your
dependencies too, so you are responsible for them to your end-users.

The numerical scale of dependencies can make it tough to feel like you own your entire stack. So let's try and use Danger to give us more insight into changes related to our dependencies.
The numerical scale of dependencies can make it tough to feel like you own your entire stack. So let's try and use
Danger to give us more insight into changes related to our dependencies.

## Lockfiles

The simplest rule, which we can evolve, is that any time your `package.json` changes you probably want a change to the [`yarn.lock`][lockfile] or [`shrinkwrap.json`][shrinkwrap] file. Yes, not every change to the `package.json` represents a dependency update but we're starting simple. You start off your `Dangerfile` like this:
The simplest rule, which we can evolve, is that any time your `package.json` changes you probably want a change to the
[`yarn.lock`][lockfile] or [`shrinkwrap.json`][shrinkwrap] file. Yes, not every change to the `package.json` represents
a dependency update but we're starting simple. You start off your `Dangerfile` like this:

```js
import { danger, fail, warn } from "danger"
@@ -31,20 +36,24 @@ if (hasPackageChanges && !hasLockfileChanges) {
}
```

This uses `lodash`'s `_.includes()` function to see if `danger.git.modified_files` includes the package, but not the lockfile.
This uses `lodash`'s `_.includes()` function to see if `danger.git.modified_files` includes the package, but not the
lockfile.

### Vetting New Dependencies

This works, and for a while, this is enough. Time passes and you hear about a node module with a [CVE](https://cve.mitre.org) against it, let's call it `"spaced-between"`, you want to ensure it isn't added as a dependency.
This works, and for a while, this is enough. Time passes and you hear about a node module with a
[CVE](https://cve.mitre.org) against it, let's call it `"spaced-between"`, you want to ensure it isn't added as a
dependency.

There are two aspects that you consider:

* Keeping track of changes to `dependencies` (for noted dependencies)
* Reading the lockfile for the dependency (for transitive dependencies)
- Keeping track of changes to `dependencies` (for noted dependencies)
- Reading the lockfile for the dependency (for transitive dependencies)

### Keeping track of changes to dependencies

We can use `danger.git.JSONDiffForFile` to understand the changes to a JSON file during code review. Note: it returns a promise, so we'll need to use `schedule` to make sure it runs async code correctly in Peril.
We can use `danger.git.JSONDiffForFile` to understand the changes to a JSON file during code review. Note: it returns a
promise, so we'll need to use `schedule` to make sure it runs async code correctly in Peril.

```js
const blacklist = "spaced-between"
@@ -91,7 +100,10 @@ Danger can then look inside the added `keys` for your blacklisted module, and fa

### Parsing the lockfile

You can trust that this dependency is going to be added directly to your project without it being highlighted in code review, but you can't be sure that any updates to your dependency tree won't bring it in transitively. A transitive dependency is one that comes in as a dependency of a dependency, one which isn't added to `packages.json` but is in `node_modules`. So you're going to look at a simple rule that parses the text of the file for your blacklisted module.
You can trust that this dependency is going to be added directly to your project without it being highlighted in code
review, but you can't be sure that any updates to your dependency tree won't bring it in transitively. A transitive
dependency is one that comes in as a dependency of a dependency, one which isn't added to `packages.json` but is in
`node_modules`. So you're going to look at a simple rule that parses the text of the file for your blacklisted module.

```js
import fs from "fs"
@@ -107,17 +119,22 @@ if (contains(lockfile, blacklist)) {
}
```
Note the use of `readFileSync`, as Danger is running as a script you'll find it simpler to use the synchronous methods when possible. You could improve the above rule by making danger run `yarn why spaced-between` and outputting the text into the messages. We do this in the [danger repo][danger-why] with `child-process` and `execSync`.
Note the use of `readFileSync`, as Danger is running as a script you'll find it simpler to use the synchronous methods
when possible. You could improve the above rule by making danger run `yarn why spaced-between` and outputting the text
into the messages. We do this in the [danger repo][danger-why] with `child-process` and `execSync`.
### Building from here
This should give you an idea on how to understand changes to your `node_modules`, from here you can create any rules you want using a mix of `JSONDiffForFile`, `fs.readFileSync` and `child_process.execSync`. Here are a few ideas to get you started:
This should give you an idea on how to understand changes to your `node_modules`, from here you can create any rules you
want using a mix of `JSONDiffForFile`, `fs.readFileSync` and `child_process.execSync`. Here are a few ideas to get you
started:
* Convert the check for the package and lockfile to use `JSONDiffForFile` so that it only warns on `dependencies` or `devDependencies`.
* Ensure you never add `@types/[module]` to `dependencies` but only into `devDependencies`.
* When a new dependency is added, use a web-service like [libraries.io][libs] to describe the module inline.
* [Parse][yarn-parse] the `yarn.lock` file, to say how many transitive dependencies are added on every new dependency.
* When a dependency is removed, and no other dependencies are added, do a thumbs up 👍.
- Convert the check for the package and lockfile to use `JSONDiffForFile` so that it only warns on `dependencies` or
`devDependencies`.
- Ensure you never add `@types/[module]` to `dependencies` but only into `devDependencies`.
- When a new dependency is added, use a web-service like [libraries.io][libs] to describe the module inline.
- [Parse][yarn-parse] the `yarn.lock` file, to say how many transitive dependencies are added on every new dependency.
- When a dependency is removed, and no other dependencies are added, do a thumbs up 👍.
[started]: /js/guides/getting_started.html
[lockfile]: https://yarnpkg.com/lang/en/docs/yarn-lock/
57 changes: 57 additions & 0 deletions docs/tutorials/fast-feedback.html.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
title: Fast Feedback via Danger Local
subtitle: Platformless
layout: guide_js
order: 4
blurb: How to use Danger to get per-commit feedback
---

## Before we get started

This tutorial continues after "[Getting Started][started]" - it's not required that you have `danger ci` set up though.

## Locality

With Danger, the typical flow is to help you can check rules on CI and get feedback inside your PR. With Peril you can
move those rules to run on an external server making feedback instant. `danger local` provides a somewhat hybrid
approach.

`danger local` provides a way to run a Dangerfile based on git-hooks. This let's you run rules while you are still in
the same context as your work as opposed to later during the code review. Personally, I find this most useful on
projects when I ship 90% of the code to it.

## How it works

Where `danger ci` uses information from the Pull Request to figure out what has changed, `danger local` naively uses the
local differences in git from master to the current commit to derive the runtime environment. This is naive because if
you don't keep your master branch sync, then it will be checking across potentially many branches.

Inside a Dangerfile `danger.github` and `danger.bitbucket` will be falsy in this context, so you can share a Dangerfile
between `danger local` and `danger ci` as long as you verify that these objects exist before using them.

When I thought about how I wanted to use `danger local` on repos in the Danger org, I opted to make a separate
Dangerfile for `danger local` and import this at the end of the main Dangerfile. This new Dangerfile only contains rules
which can run with just `danger.git`, e.g. CHANGELOG/README checks. I called it `dangerfile.lite.ts`.

## Getting it set up

You need to add both Danger and [husky](https://www.npmjs.com/package/husky) to your project:

```sh
yarn add --dev danger husky
```

When husky is in your dependencies, git-hooks are set up to respond according to matching names in the `"scripts"`
section of your `package.json`. We want to use [a pre-push](https://git-scm.com/docs/githooks#_pre_push) hook to let
`danger local` run before code has been submitted.

```json
"scripts": {
"prepush": "yarn build; yarn danger:prepush",
"danger:prepush": "yarn danger local --dangerfile dangerfile.lite.ts"
// [...]
```

Yes, it's a `pre-push` hook and the script is `prepush`, husky
[removes the dashes](https://github.com/typicode/husky/blob/master/HOOKS.md#hooks). If `master` isn't the branch which
you want as a reference then you can use `--base dev` to change the comparison base.
43 changes: 31 additions & 12 deletions docs/tutorials/node-app.html.md
Original file line number Diff line number Diff line change
@@ -8,15 +8,18 @@ blurb: An example where you work in a team on a node app, and some of the common

## Before we get started

This guide continues after "[Getting Started][started]" - so you should have seen Danger comment on your PRs.
This tutorial continues after "[Getting Started][started]" - so you should have seen Danger comment on your PRs.

## "Node App"

A node app could cover anything from an API, to a website, a native app or a hardware project. The rules on these projects tend to come from your larger dev team culture. In [Artsy][] a lot of our rules for applications come from trying to have a similar culture between all projects.
A node app could cover anything from an API, to a website, a native app or a hardware project. The rules on these
projects tend to come from your larger dev team culture. In [Artsy][] a lot of our rules for applications come from
trying to have a similar culture between all projects.

## Assignees

We use [a slack bot][no-slacking] to let people know when they've been assigned to a PR, and so the first rule added to an app is a check that there are assignees to your PR. This is a really simple check:
We use [a slack bot][no-slacking] to let people know when they've been assigned to a PR, and so the first rule added to
an app is a check that there are assignees to your PR. This is a really simple check:

```js
import { danger, fail, warn } from "danger"
@@ -26,9 +29,11 @@ if (!danger.github.pr.assignee) {
}
```

The `danger.pr` object is the JSON provided by GitHub to [represent a pull request][pr]. So here we're pulling out the `assignee` key and validating that anything is inside it.
The `danger.pr` object is the JSON provided by GitHub to [represent a pull request][pr]. So here we're pulling out the
`assignee` key and validating that anything is inside it.

We can make a small improvement to this rule, by allowing someone to declare that a PR is a work in progress Danger can allow the build to pass, but will provide feedback that there is no assignee.
We can make a small improvement to this rule, by allowing someone to declare that a PR is a "work in progress" Danger
can allow the build to pass, but will provide feedback that there is no assignee.

```js
import { danger, fail, warn } from "danger"
@@ -39,11 +44,13 @@ if (!danger.github.pr.assignee) {
}
```

Using a function as a variable we can determine whether to fail, or warn based on whether the title includes the string `"WIP"`.
Using a function as a variable we can determine whether to fail, or warn based on whether the PR's title includes the
string `"WIP"`.

## PR Messages

In a similar vein, we also want to encourage pull requests as a form of documentation. We can help push people in this direction by not allowing the body of a pull request to be less than a few characters long.
In a similar vein, we also want to encourage pull requests as a form of documentation. We can help push people in this
direction by not allowing the body of a pull request to be less than a few characters long.

```js
if (danger.github.pr.body.length < 10) {
@@ -53,8 +60,9 @@ if (danger.github.pr.body.length < 10) {

This can be expanded to all sorts of checks for example:

* Making sure every PR references an issue, or JIRA ticket.
* Skipping particular rules based on what someone says inside the message. E.g. "This is a trivial PR."
- Making sure every PR references an issue, or JIRA ticket.
- Skipping particular rules based on what someone says inside the message. E.g. "This is a trivial PR." - in Artsy we
allow particular hashtags to suppress feedback from danger.

## Results of CI Processes

@@ -67,7 +75,8 @@ script:
- yarn danger ci
```
If your tool does not have an extra log file output option, you can look at using [`tee`][tee] to copy the text output into a file for later reading ( so you'd change `- yarn lint` to `yarn lint | tee 'linter.log'` )
If your tool does not have an extra log file output option, you can look at using [`tee`][tee] to copy the text output
into a file for later reading ( so you'd change `- yarn lint` to `yarn lint | tee 'linter.log'` )

And here's a really simple check that it contains the word "Failed" and to post the logs into the PR.

@@ -87,13 +96,23 @@ ${linterOutput}
}
```

More mature tools may have a JSON output reporter, so you can parse that file and create your own report for danger to post.
More mature tools may have a JSON output reporter, so you can parse that file and create your own report for danger to
post.

If you build something that is a generic wrapper around a specific linting tool, this is a great place to convert that code [into a plugin][plugin] so that anyone can use it. In this case, Danger effectively is a way of moving these messages into the code review session.
If you build something that is a generic wrapper around a specific linting tool, this is a great place to convert that
code [into a plugin][plugin] so that anyone can use it. In this case, Danger effectively is a way of moving these
messages into the code review session.

For example:

- [danger-plugin-jest][]
- [danger-plugin-tslint][]

[started]: /js/guides/getting_started.html
[artsy]: http://artsy.github.io
[no-slacking]: https://github.com/alloy/no-slacking-on-pull-requests-bot
[pr]: https://developer.github.com/v3/pulls/#get-a-single-pull-request
[tee]: http://linux.101hacks.com/unix/tee-command-examples/
[plugin]: /js/usage/extending-danger.html
[danger-plugin-jest]: https://github.com/macklinu/danger-plugin-jest#danger-plugin-jest
[danger-plugin-tslint]: https://github.com/macklinu/danger-plugin-tslint#readme
27 changes: 19 additions & 8 deletions docs/tutorials/node-library.html.md
Original file line number Diff line number Diff line change
@@ -3,16 +3,20 @@ title: Danger + Node Library
subtitle: Danger + Node Library
layout: guide_js
order: 1
blurb: An example where you work on an OSS node library, so you're trying to improve overall contributions from light contributors.
blurb:
An example where you work on an OSS node library, so you're trying to improve overall contributions from light
contributors.
---

## Before we get started

This guide continues after "[Getting Started][started]" - so you should have seen Danger comment on your PRs.
This tutorial continues after "[Getting Started][started]" - so you should have seen Danger comment on your PRs.

## Keeping on top of your library

End-users want to understand what has changed between versions of your library, and a CHANGELOG is a great way to keep them up to date. However, it can be easy to forget to add a CHANGELOG entry to any changes to a library. So let's add a check that a CHANGELOG entry is added on every PR:
End-users want to understand what has changed between versions of your library, and a CHANGELOG is a great way to keep
them up to date. However, it can be easy to forget to add a CHANGELOG entry to any changes to a library. So let's add a
check that a CHANGELOG entry is added on every PR:

```js
import { danger, fail, warn } from "danger"
@@ -26,7 +30,9 @@ if (!hasCHANGELOGChanges) {

We're using lodash's `_.include` function to check if `CHANGELOG.md` is in the list of modified files.

We went with `warn` here because there are a lot of legitimate reasons to not need a CHANGELOG entry (updating typoes, CI and other infrastructure.) We can improve this though, let's _also_ check that there are changes to the source code for our library.
We went with `warn` here because there are a lot of legitimate reasons to not need a CHANGELOG entry (updating typoes,
CI and other infrastructure.) We can improve this though, let's _also_ check that there are changes to the source code
for our library.

```js
import { danger, fail, warn } from "danger"
@@ -44,11 +50,14 @@ This is a much more specific rule, now changes to the README won't warrant a CHA

### Dependencies

Any dependencies that you use are passed on to all of your library consumers, so you should consider using Danger to keep track of those as they evolve. For more information, see the tutorial on [Dependencies][deps].
Any dependencies that you use are passed on to all of your library consumers, so you should consider using Danger to
keep track of those as they evolve. For more information, see the tutorial on [Dependencies][deps].

### Keep your README up to date

An example from Danger itself, is that we want to ensure the README always shows what CI providers will work by default with Danger. As both the app, and Danger use JavaScript, we can import code from the app and use that to create a new rule.
An example from Danger itself, is that we want to ensure the README always shows what CI providers will work by default
with Danger. As both the app, and Danger use JavaScript, we can import code from the app and use that to create a new
rule.

```js
import { danger, fail, warn } from "danger"
@@ -65,8 +74,10 @@ if (missing.length) {
}
```

Danger also uses a similar check to create our type definition files, if any of the public DSL changes then Danger checks that the type definitions have been updated, and recommends how to do so if not.
Danger also uses a similar check to create our type definition files, if any of the public DSL changes then Danger
checks that the type definitions have been updated, and recommends how to do so if not. These are rare chores which are
really hard to remember to do, and impossible if you're not intimate with the codebase - so providing automated feedback
here is really useful.

[deps]: /js/tutorials/dependencies.html

[started]: /js/guides/getting_started.html
23 changes: 16 additions & 7 deletions docs/tutorials/transpilation.html.md
Original file line number Diff line number Diff line change
@@ -8,17 +8,23 @@ blurb: How Danger's TypeScript/Babel integration works.

### Transpilation

Danger tries to pick up either Babel or TypeScript up at runtime. It does this by `require`ing both dependencies, which will follow the standard [NodeJS require resolution](https://nodejs.org/api/modules.html#modules_all_together). If either don't exist, then the Dangerfile will be treated as not needing transpilation and passed directly to the node runtime.
Danger tries to pick up either Babel or TypeScript up at runtime. It does this by `require`ing both dependencies, which
will follow the standard [NodeJS require resolution](https://nodejs.org/api/modules.html#modules_all_together). If
either don't exist, then the Dangerfile will be treated as not needing transpilation and passed directly to the node
runtime.

A few notes:

* TypeScript is prioritized over Babel
* Babel 7 support for TypeScript is supported
* Whether you use `dangerfile.ts` or `dangerfile.js` is irrelevant, the environment matters more
- TypeScript is prioritized over Babel
- Babel 7 support for TypeScript is supported
- Whether you use `dangerfile.ts` or `dangerfile.js` is irrelevant, the environment matters more

### TypeScript gotchas

You might have a `src` folder where your actual source code is kept, and adding a `dangerfile.ts` at the root which will break compilation. The answer to this is to add the dangerfile to the `"exclude"` section. Then to get inline errors working correct, add it to the `"include"`. It's a neat little trick. You can see it working in [artsy/emission#tsconfig.json][tsconfig]
You might have a `src` folder where your actual source code is kept, and adding a `dangerfile.ts` at the root which will
break compilation. The answer to this is to add the dangerfile to the `"exclude"` section. Then to get inline errors
working correct, add it to the `"include"`. It's a neat little trick. You can see it working in
[artsy/emission#tsconfig.json][tsconfig]

```json
{
@@ -30,9 +36,12 @@ You might have a `src` folder where your actual source code is kept, and adding

### The "danger" module

The `danger` module is removed before evaluation, it's only there to fake your dev env into working correctly. In reality, all of the exports are added to the global environment. If you import `"danger"` in code that isn't evaluated inside Danger itself, it will raise an exception.
The `danger` module is removed before evaluation, it's only there to fake your dev env into working correctly. In
reality, all of the exports are added to the global environment. If you import `"danger"` in code that isn't evaluated
inside Danger itself, it will raise an exception.

You can use something like jest's module mocking system to fake it in tests, sp you can manipulate the object PR to look like whatever you want in tests:
You can use something like jest's module mocking system to fake it in tests, letting you manipulate the object
`danger.github.pr` to look like whatever you want in tests:

```js
jest.mock("danger", () => jest.fn())
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "danger",
"version": "3.8.4",
"version": "3.8.5",
"description": "Unit tests for Team Culture",
"main": "distribution/danger.js",
"typings": "distribution/danger.d.ts",
@@ -116,21 +116,21 @@
"date-fns": "^1.29.0",
"flow-bin": "^0.77.0",
"husky": "^0.14.0",
"jest": "23.4.2",
"jest": "23.5.0",
"jest-json-reporter": "^1.2.2",
"lint-staged": "^7.2.0",
"madge": "^3.2.0",
"prettier": "^1.14.0",
"prettier": "^1.14.2",
"shx": "^0.3.2",
"ts-jest": "^23.1.2",
"ts-jest": "^23.1.3",
"ts-node": "^7.0.0",
"tslint": "^5.11.0",
"tslint-config-prettier": "^1.14.0",
"typedoc": "0.9.0",
"typescript": "^3.0.1"
},
"dependencies": {
"@octokit/rest": "^15.5.0",
"@octokit/rest": "^15.9.5",
"babel-polyfill": "^6.23.0",
"chalk": "^2.3.0",
"commander": "^2.13.0",
13 changes: 13 additions & 0 deletions source/danger.d.ts
Original file line number Diff line number Diff line change
@@ -744,6 +744,19 @@ interface GitHubUtilsDSL {
content: string,
config: { title: string; open: boolean; owner: string; repo: string }
) => Promise<string>

/**
* An API for creating, or setting a label to an issue. Usable from Peril
* by adding an additional param for settings about a repo.
*
* @param {obj} labelConfig The config for the label
* @param {obj | undefined} Optional: the config for the issue
* @returns {Promise<undefined>} No return value.
*/
createOrAddLabel: (
labelConfig: { name: string; color: string; description: string },
repoConfig?: { owner: string; repo: string; id: number }
) => Promise<void>
}

/**
13 changes: 13 additions & 0 deletions source/dsl/GitHubDSL.ts
Original file line number Diff line number Diff line change
@@ -72,6 +72,19 @@ export interface GitHubUtilsDSL {
content: string,
config: { title: string; open: boolean; owner: string; repo: string }
) => Promise<string>

/**
* An API for creating, or setting a label to an issue. Usable from Peril
* by adding an additional param for settings about a repo.
*
* @param {obj} labelConfig The config for the label
* @param {obj | undefined} Optional: the config for the issue
* @returns {Promise<undefined>} No return value.
*/
createOrAddLabel: (
labelConfig: { name: string; color: string; description: string },
repoConfig?: { owner: string; repo: string; id: number }
) => Promise<void>
}

/**
31 changes: 31 additions & 0 deletions source/platforms/github/GitHubUtils.ts
Original file line number Diff line number Diff line change
@@ -30,10 +30,41 @@ const utils = (pr: GitHubPRDSL, api: GitHub): GitHubUtilsDSL => {
return sentence(hrefs)
}

const createOrAddLabel = async (
labelConfig: { name: string; color: string; description: string },
repoConfig?: { owner: string; repo: string; id: number }
) => {
// Create or re-use an existing label
const config = repoConfig || { owner: pr.base.repo.owner.login, repo: pr.base.repo.name, id: pr.number }

const existingLabels = await api.issues.getLabels({ owner: config.owner, repo: config.repo })
const mergeOnGreen = existingLabels.data.find((l: any) => l.name == labelConfig.name)

// Create the label if it doesn't exist yet
if (!mergeOnGreen) {
await api.issues.createLabel({
owner: config.owner,
repo: config.repo,
name: labelConfig.name,
color: labelConfig.color,
description: labelConfig.description,
})
}

// Then add the label
await api.issues.addLabels({
owner: config.owner,
repo: config.owner,
number: config.id,
labels: [labelConfig.name],
})
}

return {
fileLinks,
fileContents: fileContentsGenerator(api, pr.head.repo.full_name, pr.head.ref),
createUpdatedIssueWithID: createUpdatedIssueWithIDGenerator(api),
createOrAddLabel,
}
}

212 changes: 118 additions & 94 deletions yarn.lock

Large diffs are not rendered by default.