So what does danger export? Well:
import { danger, fail, markdown, message, peril, schedule, warn } from 'danger'
Is the entire API for writing a Dangerfile. The interesting one is danger
, so let’s cover everything else first. Y'know - save the best for last. These other exports are mainly the ways in which you can communicate the status of your rules back to Danger.
#Communication
These are functions which you use in rules to provide feedback during code review. Assuming Danger has access to write a comment, then fail
, warn
, message
and markdown
will report directly inline.
// Fails a build, outputting a specific reason for failing into a HTML table.
fail(message: MarkdownString, file?: string, line?: number) => void
// Adds raw markdown into the Danger comment, under the table
markdown(message: MarkdownString, file?: string, line?: number) => void
// Adds a message to the Danger table, the only difference between this
and warn is the emoji which shows in the table.
message(message: MarkdownString, file?: string, line?: number) => void
// Highlights low-priority issues, but does not fail the build. Message
is shown inside a HTML table.
warn(message: MarkdownString, file?: string, line?: number) => void
There's also schedule
which is a bit of a special case. You can find out more from inside the guide On the Dangerfile. It helps you handle async code within your Dangerfile inside Peril.
// A Dangerfile, in Peril, is evaluated as a script, and so async code does not work
out of the box. By using the `schedule` function you can now register a
section of code to evaluate across multiple tick cycles.
// `schedule` currently handles two types of arguments, either a promise or a function with a resolve arg.
schedule(asyncFunction: Scheduleable) => void
#The Danger DSL - Root Objects
OK, great - so now let’s look through the API. This is the data that Danger will provide so that you can build rules for your team culture.
// The BitBucket Cloud metadata. This covers things like PR info,
comments and reviews on the PR, commits, comments, and activities.
// Strictly speaking, `bitbucket_cloud` is a nullable type, if you are not using
BitBucket Cloud then it will be undefined. For the DSL convenience sake though, it
is classed as non-nullable
danger.bitbucket_cloud: BitBucketCloudDSL
// The BitBucket Server metadata. This covers things like PR info,
comments and reviews on the PR, related issues, commits, comments
and activities.
// Strictly speaking, `bitbucket_server` is a nullable type, if you are not using
BitBucket Server then it will be undefined. For the DSL convenience sake though, it
is classed as non-nullable
danger.bitbucket_server: BitBucketServerDSL
// Details specific to the git changes within the code changes.
Currently, this is just the raw file paths that have been
added, removed or modified.
danger.git: GitDSL
// The GitHub metadata. This covers things like PR info,
comments and reviews on the PR, label metadata, commits with
GitHub user identities and some useful utility functions
for displaying links to files.
// Strictly speaking, `github` is a nullable type, if you are not using
GitHub then it will be undefined. For the DSL convenience sake though, it
is classed as non-nullable
// Provides an authenticated API so you can work directly
with the GitHub API. This is an instance of the "@octokit/rest" npm
module.
// Finally, if running through Peril on an event other than a PR
this is the full JSON from the webhook. github-webhook-event-types has the full
typings for those webhooks.
danger.github: GitHubDSL
// The GitLab metadata. This covers things like PR info,
comments and reviews on the MR, commits, comments
and activities.
// Strictly speaking, `gitlab` is a nullable type, if you are not using
GitLab then it will be undefined. For the DSL convenience sake though, it
is classed as non-nullable
danger.gitlab: GitLabDSL
// Functions which are globally useful in most Dangerfiles. Right
now, these functions are around making sentences of arrays, or
for making a like of href links easily.
danger.utils: DangerUtilsDSL
#All Types
This is meant to be the API reference, so I’ll leave the prose at this point. Below is every object inside the Danger DSL. You can jump between the objects by clicking on their types.
I’d recommend first just having a quick browse to have an overview in your head. Then I’d recommend using the editor to actually write some code with auto-complete to get a sense of what the syntax feels like.
- Hide GitHub
- Hide BitBucket
// A BitBucketCloud specific implementation of a git commit.
BitBucketCloudCommit {
// The author of the commit, assumed to be the person who wrote the code.
author: {
// Format: `Foo Bar <foo@bar.com>`
raw: string,
user: BitBucketCloudUser
}
// When the commit was committed to the project, in ISO 8601 format
date: string
// The SHA for the commit
hash: string
// The commit's links
links: BitBucketCloudLinks
// The commit's message
message: string
// The commit's parents
parents: array
}
// A BitBucketServer specific implementation of a git commit.
BitBucketServerCommit {
// The author of the commit, assumed to be the person who wrote the code.
author: {
// The display name of the commit author
displayName: string,
// The email of the commit author
emailAddress: string,
// The id of the commit author
name: string
}
// The UNIX timestamp for when the commit was authored
authorTimestamp: number
// The author of the commit, assumed to be the person who committed/merged the code into a project.
committer: {
// The display name of the commit committer
displayName: string,
// The email of the commit committer
emailAddress: string,
// The id of the commit committer
name: string
}
// When the commit was committed to the project
committerTimestamp: number
// The shortened SHA for the commit
displayId: string
// The SHA for the commit
id: string
// The commit's message
message: string
// The commit's parents
parents: array
}
// The BitBucketServer metadata for your PR
BitBucketServerDSL {
// The activities such as OPENING, CLOSING, MERGING or UPDATING a pull request
activities: array<BitBucketServerPRActivity>
// An authenticated API so you can extend danger's behavior.
api: BitBucketServerAPIDSL
// The comments on the pull request
comments: array<BitBucketServerPRActivity>
// The commits associated with the pull request
commits: array<BitBucketServerCommit>
// The related JIRA issues
issues: array<JIRAIssue>
// The pull request and repository metadata
metadata: RepoMetaData
// The PR metadata
pr: BitBucketServerPRDSL
}
// An exact copy of the PR's reference JSON. This interface has type'd the majority
of it for tooling's sake, but any extra metadata which BitBucket Server send
will still be inside the JS object.
BitBucketServerPRDSL {
// The creator of the PR
author:
// Is the PR closed?
closed: boolean
// Date PR created as number of milliseconds since the unix epoch
createdDate: number
// The text describing the PR
description: string
// The PR submitter's reference
fromRef: BitBucketServerMergeRef
// The PR's ID
id: number
// Misc links for hypermedia conformance
links: any
// Was this PR locked?
locked: boolean
// Is the PR open?
open: boolean
// People who have participated in the PR
participants: array<BitBucketServerPRParticipant>
// People requested as reviewers
reviewers: array<BitBucketServerPRParticipant>
// The pull request's current status.
state: "OPEN" | "MERGED" | "DECLINED" | "SUPERSEDED"
// Title of the pull request.
title: string
// The repo Danger is running on
toRef: BitBucketServerMergeRef
// Date PR updated as number of milliseconds since the unix epoch
updatedDate: number
// The API version
version: number
}
// A BitBucket Server Repo
BitBucketServerRepo {
// Can someone fork this repo?
forkable: boolean
// Links for the projects
links: any
// The repo name
name?: string
// An abstraction for grouping repos
project: {
// The project unique id
id: number,
// The project's human readable project key
key: string,
// Hyperlinks for the project
links: any,
// The name of the project
name: string,
// Is the project publicly available
public: boolean,
// The project's type
type: string
}
// Is the repo public?
public: boolean
// The type of SCM tool, probably "git"
scmId: string
// The slug for the repo
slug: string
}
// A BitBucketServer user account.
BitBucketServerUser {
// Is the account active
active: boolean
// The name to use when referencing the user
displayName: string
// The email for the user
emailAddress: string
// The unique user ID
id: number
// The name of the user
name: string
// The user's slug for URLs
slug: string
// The type of a user, "NORMAL" being a typical user3
type: "NORMAL" | "SERVICE"
}
// The Danger DSL provides the metadata for introspection
in order to create your own rules.
DangerDSLType {
// The BitBucket Cloud metadata. This covers things like PR info,
comments and reviews on the PR, commits, comments, and activities.
// Strictly speaking, `bitbucket_cloud` is a nullable type, if you are not using
BitBucket Cloud then it will be undefined. For the DSL convenience sake though, it
is classed as non-nullable
bitbucket_cloud: BitBucketCloudDSL
// The BitBucket Server metadata. This covers things like PR info,
comments and reviews on the PR, related issues, commits, comments
and activities.
// Strictly speaking, `bitbucket_server` is a nullable type, if you are not using
BitBucket Server then it will be undefined. For the DSL convenience sake though, it
is classed as non-nullable
bitbucket_server: BitBucketServerDSL
// Details specific to the git changes within the code changes.
Currently, this is just the raw file paths that have been
added, removed or modified.
git: GitDSL
// The GitHub metadata. This covers things like PR info,
comments and reviews on the PR, label metadata, commits with
GitHub user identities and some useful utility functions
for displaying links to files.
// Strictly speaking, `github` is a nullable type, if you are not using
GitHub then it will be undefined. For the DSL convenience sake though, it
is classed as non-nullable
// Provides an authenticated API so you can work directly
with the GitHub API. This is an instance of the "@octokit/rest" npm
module.
// Finally, if running through Peril on an event other than a PR
this is the full JSON from the webhook. github-webhook-event-types has the full
typings for those webhooks.
github: GitHubDSL
// The GitLab metadata. This covers things like PR info,
comments and reviews on the MR, commits, comments
and activities.
// Strictly speaking, `gitlab` is a nullable type, if you are not using
GitLab then it will be undefined. For the DSL convenience sake though, it
is classed as non-nullable
gitlab: GitLabDSL
// Functions which are globally useful in most Dangerfiles. Right
now, these functions are around making sentences of arrays, or
for making a like of href links easily.
utils: DangerUtilsDSL
}
// The shape of the JSON passed between Danger and a subprocess. It's built
to be expanded in the future.
DangerJSON {
}
// The representation of what running a Dangerfile generates.
This needs to be passed between processes, so data only please.
DangerResults {
// Failed messages
fails: array<Violation>
// Markdown messages to attach at the bottom of the comment
markdowns: array<Violation>
// A set of messages to show inline
messages: array<Violation>
// Meta information about the runtime evaluation
meta?: reflection
// Messages for info
warnings: array<Violation>
}
// The Danger Utils DSL contains utility functions
that are specific to universal Danger use-cases.
DangerUtilsDSL {
// Creates a link using HTML.
// If `href` and `text` are falsy, null is returned.
If `href` is falsy and `text` is truthy, `text` is returned.
If `href` is truthy and `text` is falsy, an <a> tag is returned with `href` as its href and text value.
Otherwise, if `href` and `text` are truthy, an <a> tag is returned with the `href` and `text` inserted as expected.
href(href: string, text: string) => string | null
// Converts an array of strings into a sentence.
sentence(array: array) => string
}
// A platform agnostic reference to a Git commit
GitCommit {
// Who wrote the commit
author: GitCommitAuthor
// Who deployed the commit
committer: GitCommitAuthor
// The commit message
message: string
// SHAs for the commit's parents
parents?: array
// The SHA for the commit
sha: string
// Potential parent commits, and other assorted metadata
tree: any
// Link to the commit
url: string
}
// An author of a commit
GitCommitAuthor {
// ISO6801 date string
date: string
// The authors email
email: string
// The display name for the author
name: string
}
// The git specific metadata for a PR
GitDSL {
// The git commit Danger is comparing from.
base: string
// The Git commit metadata
commits: array<GitCommit>
// Newly created filepaths relative to the git root
created_files: array
// Removed filepaths relative to the git root
deleted_files: array
// A Chainsmoker object to help match paths as an elegant DSL. It
lets you write a globbed string and then get booleans on whether
there are matches within a certain part of the git DSL.
// Use this to create an object which has booleans set on 4 keys
`modified`, `created`, `edited` (created + modified) and `deleted`.
fileMatch: Chainsmoker
// The git commit Danger is comparing to.
head: string
// Filepaths with changes relative to the git root
modified_files: array
// Provides a simplified JSON diff between the two versions of a JSON file. This will always
be an object whose keys represent what has changed inside a JSON file.
// Any changed values will be represented with the same path, but with a different object instead.
This object will always show a `before` and `after` for the changes. If both values are arrays or
objects the `before` and `after`, then there will also be `added` and `removed` inside the object.
//In the case of two objects, the `added` and `removed` will be an array of keys rather than the values.
//This object is represented as `JSONDiffValue` but I don't know how to make TypeScript force
declare that kind of type structure.
//This should make it really easy to do work when specific keypaths have changed inside a JSON file.
JSONDiffForFile(filename: string) => Promise
// Provides a JSON patch (rfc6902) between the two versions of a JSON file,
returns null if you don't have any changes for the file in the diff.
// Note that if you are looking to just see changes like: before, after, added or removed - you
should use `JSONDiffForFile` instead, as this can be a bit unwieldy for a Dangerfile.
JSONPatchForFile(filename: string) => Promise
// Offers the diff for a specific file
diffForFile(filename: string) => Promise
// Offers the overall lines of code added/removed in the diff
linesOfCode(pattern?: string) => Promise
// Offers the structured diff for a specific file
structuredDiffForFile(filename: string) => Promise
}
// Provides the current PR in an easily used way for params in `github.api` calls
GitHubAPIPR {
// The PR number
number: number
// The repo owner
owner: string
// The repo name
repo: string
}
// A GitHub specific implementation of a git commit, it has GitHub user names instead of an email.
GitHubCommit {
// The GitHub user who wrote the code
author: GitHubUser
// The raw commit metadata
commit: GitCommit
// The GitHub user who shipped the code
committer: GitHubUser
// An array of parent commit shas
parents: array
// The SHA for the commit
sha: string
// the url for the commit on GitHub
url: string
}
// The GitHub metadata for your PR
GitHubDSL {
// An authenticated API so you can extend danger's behavior by using the GitHub v3 API.
// A set up instance of the "github" npm module. You can get the full API here.
api: GitHub
// The github commit metadata for a code review session
commits: array<GitHubCommit>
// The issue metadata for a code review session
issue: GitHubIssue
// The PR metadata for a code review session
pr: GitHubPRDSL
// The people/teams requested to review this PR
requested_reviewers: GitHubReviewers
// The reviews left on this pull request
reviews: array<GitHubReview>
// The PR metadata specifically formatted for using with the GitHub API client
thisPR: GitHubAPIPR
// A scope for useful functions related to GitHub
utils: GitHubUtilsDSL
}
// This is `danger.github.issue` It refers to the issue that makes up the Pull Request.
GitHub treats all pull requests as a special type of issue. This DSL contains only parts of the issue that are
not found in the PR DSL, however it does contain the full JSON structure.
// A GitHub Issue
GitHubIssue {
}
// An exact copy of the PR's reference JSON. This interface has type'd the majority
of it for tooling's sake, but any extra metadata which GitHub send will still be
inside the JS object.
GitHubPRDSL {
// The number of additional lines in the PR
additions: number
// The User who is assigned the PR
assignee: GitHubUser
// The Users who are assigned to the PR
assignees: array<GitHubUser>
// How does the PR author relate to this repo/org?
author_association: "COLLABORATOR" | "CONTRIBUTOR" | "FIRST_TIMER" | "FIRST_TIME_CONTRIBUTOR" | "MEMBER" | "NONE" | "OWNER"
// Merge reference for _this_ repo.
base: GitHubMergeRef
// The markdown body message of the PR
body: string
// The number of changed files in the PR
changed_files: number
// optional ISO6801 Date string for when PR was closed
closed_at: string | null
// The number of comments on the PR
comments: number
// The number of commits in the PR
commits: number
// ISO6801 Date string for when PR was created
created_at: string
// The number of deleted lines in the PR
deletions: number
// Merge reference for the _other_ repo.
head: GitHubMergeRef
// The link back to this PR as user-facing
html_url: string
// Has the PR been locked to contributors only?
locked: boolean
// Has the PR been merged yet?
merged: boolean
// Optional ISO6801 Date string for when PR was merged.
Danger probably shouldn't be running in this state.
merged_at: string | null
// The UUID for the PR
number: number
// The number of review-specific comments on the PR
review_comments: number
// The state for the PR
state: "closed" | "open" | "locked" | "merged"
// The title of the PR
title: string
// ISO6801 Date string for when PR was updated
updated_at: string
// The User who submitted the PR
user: GitHubUser
}
// A GitHub Repo
GitHubRepo {
// Is someone assigned to this PR?
assignee: GitHubUser
// Are there people assigned to this PR?
assignees: array<GitHubUser>
// The textual description of the repo
description: string
// Is the repo a fork?
fork: boolean
// The full name of the owner + repo, e.g. "Danger/Danger-JS"
full_name: string
// The root web URL for the repo, e.g. https://github.com/artsy/emission
html_url: string
// Generic UUID
id: number
// The name of the repo, e.g. "Danger-JS"
name: string
// The owner of the repo
owner: GitHubUser
// Is the repo publicly accessible?
private: boolean
}
// GitHubReview
While a review is pending, it will only have a user. Once a review is complete, the rest of
the review attributes will be present
GitHubReview {
// If there is a review, the body of the review
body?: string
// If there is a review, the commit ID this review was made on
commit_id?: string
// If there is a review, this provides the ID for it
id?: number
// The state of the review
APPROVED, REQUEST_CHANGES, COMMENT or PENDING
state?: "APPROVED" | "REQUEST_CHANGES" | "COMMENT" | "PENDING"
// The user requested to review, or the user who has completed the review
user: GitHubUser
}
// A GitHub user account.
GitHubUser {
// The url for a users's image
avatar_url: string
// The href for a users's page
href: string
// Generic UUID
id: number
// The handle for the user/org
login: string
// Whether the user is an org, or a user
type: "User" | "Organization" | "Bot"
}
// Useful functions for GitHub related work
GitHubUtilsDSL {
// An API for creating, or setting a label to an issue. Usable from Peril
by adding an additional param for settings about a repo.
createOrAddLabel: labelConfig: { color: string, description: string, name: string}, repoConfig?: reflection
createOrUpdatePR: config: { // Base branch for the new branch e.g. what should Danger create the new branch from baseBranch: string, // PR body body: string, // A message for the commit commitMessage: string, // The name of the branch on the repo newBranchName: string, // The danger in danger/danger-js - defaults to the PR base name if undefined owner?: string, // The danger-js in danger/danger-js - defaults to the PR base repo if undefined repo?: string, // PR title title: string}, fileMap: any
// An API for creating, updating and closing an issue. Basically
this is really useful for reporting back via a separate
issue that you may want to keep up to date at all times.
createUpdatedIssueWithID: id: string, content: string, config: { open: boolean, owner: string, repo: string, title: string}
// Downloads a file's contents via the GitHub API. You'll want to use
this instead of `fs.readFile` when aiming to support working with Peril.
fileContents(path: string, repoSlug?: string, ref?: string) => Promise
// Creates HTML for a sentence of clickable links for an array of paths.
This uses the source of the PR as the target, not the destination repo.
You can manually set the target repo and branch however, to make it work how you want.
fileLinks(paths: array, useBasename?: true | false, repoSlug?: string, branch?: string) => string
}
// The Git Related Metadata which is available inside the Danger DSL JSON
GitJSONDSL {
// The Git commit metadata
commits: array<GitCommit>
// Newly created filepaths relative to the git root
created_files: array
// Removed filepaths relative to the git root
deleted_files: array
// Filepaths with changes relative to the git root
modified_files: array
}
// The GitLab metadata for your MR
GitLabDSL {
api: InstanceType
// Merge Request-level MR approvals Configuration
approvals: GitLabApproval
// All of the individual commits in the merge request
commits: array<GitLabMRCommit>
// Info about the repo
metadata: RepoMetaData
// Info about the merge request
mr: GitLabMR
utils: {
fileContents:
}
}
// TODO: These need more comments from someone who uses GitLab, see GitLabDSL.ts in the danger-js repo
GitLabMR {
allow_collaboration: boolean
allow_maintainer_to_push: boolean
approvals_before_merge: null | null
// Who was assigned as the person to review
assignee?: GitLabUser
// Who made it
author: GitLabUser
changes_count: string
closed_at: string | null
closed_by: GitLabUser | null
// When was the MR made
created_at: string
// The body text describing the MR
description: string
diff_refs: {
base_sha: string,
head_sha: string,
start_sha: string
}
discussion_locked: null | null
diverged_commits_count: number
// How many folks have given it an downvote
downvotes: number
first_deployed_to_production_at: string | null
force_remove_source_branch: boolean
// The MR's id
id: number
// The unique ID for this MR
iid: number
labels: array
latest_build_finished_at: string
latest_build_started_at: string
merge_commit_sha: string | null
merge_error: null | null
merge_status:
merge_when_pipeline_succeeds: boolean
merged_at: string
merged_by: GitLabUser
milestone: {
created_at: string,
description: string,
due_date: string,
id: number,
iid: number,
project_id: number,
start_date: string,
state: "closed" | "active",
title: string,
updated_at: string,
web_url: string
}
pipeline: {
id: number,
ref: string,
sha: string,
status: "canceled" | "failed" | "pending" | "running" | "skipped" | "success",
web_url: string
}
// The project ID for this MR
project_id: number
rebase_in_progress: boolean
sha: string
should_remove_source_branch: boolean
// What branch is this MR come from
source_branch: string
source_project_id: number
squash: boolean
// The MR's current availability
state: "closed" | "open" | "locked" | "merged"
subscribed: boolean
// What branch is this MR being merged into
target_branch: string
target_project_id: number
time_stats: {
human_time_estimate: number | null,
human_total_time_spent: number | null,
time_estimate: number,
total_time_spent: number
}
// The given name of the MR
title: string
// When was the MR updated
updated_at: string
// How many folks have given it an upvote
upvotes: number
// Access rights for the user who created the MR
user: {
// Does the author have access to merge?
can_merge: boolean
}
user_notes_count: number
web_url: string
work_in_progress: boolean
}
// This is `danger.bitbucket_server.issues` It refers to the issues that are linked to the Pull Request.
JIRAIssue {
// The unique key for the issue e.g. JRA-11
key: string
// The user-facing URL for that issue
url: string
}
// A map of string keys to JSONDiffValue
JSONDiff {
// A map of string keys to JSONDiffValue
}
// All JSON diff values will be this shape
JSONDiffValue {
// If both before & after are arrays, then you optionally get what is added. Empty if no additional objects.
added?: array
// The value after the PR's applied changes
after: any
// The value before the PR's applied changes
before: any
// If both before & after are arrays, then you optionally get what is removed. Empty if no removed objects.
removed?: array
}
// The results of running a JSON patch
JSONPatch {
// The JSON in a file from the PR submitter
after: any
// The JSON in a file at the PR merge base
before: any
// The set of operations to go from one JSON to another JSON
diff: array<JSONPatchOperation>
}
// An individual operation inside an rfc6902 JSON Patch
JSONPatchOperation {
// An operation type
op: string
// The JSON keypath which the operation applies on
path: string
// The changes for applied
value: string
}
// The available Peril interface, it is possible that this is not
always up to date with true DSL in Peril, but I'll be giving it
a good shot.
PerilDSL {
// When running a task, the data passed in when the task
was originally scheduled, you can also get this as the first
argument in a default function. Deprecated, use a default export
function. I'll remove this sometime.
data?: any
// A set of key:value string based on ENV vars that have
been set to be exposed to your Peril config
env: any
// Allows you to schedule a task declared in your Peril config to run in a certain time-frame,
e.g `runTask("reminder_pr_merge", "in 2 days", { number: 2 })`. For more details on how this
works, see the Peril documentation.
runTask: taskName: string, time: string, data: any
}
// Key details about a repo
RepoMetaData {
// The ID for the pull/merge request "11"
pullRequestID: string
// A path like "artsy/eigen"
repoSlug: string
}
// Git diff sliced into chunks
StructuredDiff {
// Git diff chunks
chunks: array
}
// All Text diff values will be this shape
TextDiff {
// A string containing just the added lines
added: string
// The value after the PR's applied changes
after: string
// The value before the PR's applied changes
before: string
// A string containing the full set of changes
diff: string
// A string containing just the removed lines
removed: string
}
// The result of user doing warn, message or fail, built this way for
expansion later.
Violation {
// Optional path to the file
file?: string
// Optional icon for table (Only valid for messages)
icon?: string
// Optional line in the file
line?: number
// The string representation
message: string
}