Last active
August 8, 2018 16:09
-
-
Save stevethomp/62aa48393065bdbd5d6aa92c57f1685d to your computer and use it in GitHub Desktop.
Dangerfile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { danger, warn, fail, markdown, message } from "danger"; | |
import jiraIssue from "danger-plugin-jira-issue"; | |
import { readFileSync } from "fs"; | |
/* | |
Danger will post all these fail/warn/message's as a comment on the PR, from the jenkins user. Over time, as commits are added, the comment is amended. | |
No comment means you're all good and the PR passes these checks. | |
Check out http://danger.systems/js/ for how this all works, and http://danger.systems/js/guides/the_dangerfile.html for creating more rules. | |
*/ | |
// ** Setup ** | |
var updatedFiles = danger.git.created_files.concat(danger.git.modified_files) | |
var swiftFiles = updatedFiles.filter(path => stringContains(path, ".swift")) | |
class LintResult { | |
character: number | |
file: string | |
line: number | |
reason: string | |
rule_id: string | |
severity: string | |
type: string | |
constructor(object: any) { | |
this.character = object["character"] as number | |
this.file = object["file"] as string | |
this.line = object["line"] as number | |
this.reason = object["reason"] as string | |
this.rule_id = object["rule_id"] as string | |
this.severity = object["severity"] as string | |
this.type = object["type"] as string | |
} | |
} | |
// ** Rules ** | |
// No PR is too small to include a description of why you made a change | |
if (danger.github.pr.body.length < 10) { | |
warn('Please include a description of your PR changes.'); | |
} | |
// Check that someone has been assigned to this PR | |
if (danger.github.requested_reviewers.users.length == 0) { | |
warn('Please assign someone to review this PR.'); | |
} | |
// Check that additions are less than 500 (with 50 line buffer) | |
const bigPRThreshold = 550; | |
if (danger.github.pr.additions >= bigPRThreshold) { | |
warn(':exclamation: Big PR'); | |
markdown(`Please try to keep your PR size under ${bigPRThreshold} lines. If your PR contains multiple changes, consider splitting it into multiple PRs to help make reviews faster and easier.`); | |
} | |
// Congratulate PRs that simplify things | |
if (danger.github.pr.deletions > danger.github.pr.additions) { | |
message('๐ Great job! This PR deletes more than it adds. Thanks for keeping us lean!'); | |
} | |
// Checks for a JIRA issue in the title of the PR and links to it, eg: "ABC-101". Opt out by including "No Jira" | |
// yarn add danger-plugin-jira-issue --dev | |
if (!stringContainsAny(danger.github.pr.title.toLocaleLowerCase(), ["no jira", "nojira", "no-jira"])) { | |
jiraIssue({ | |
key: ['ABC', 'abc'], | |
url: 'https://abc.atlassian.net/browse', | |
emoji: ':paperclip:', | |
format(emoji, jiraUrls) { // Optional Formatter | |
return `${emoji} ${jiraUrls.join(", ")} Check it out on JIRA`; | |
} | |
}) | |
} | |
// Runs Swiftlint against added + modified files, and comments the results inline | |
var process = require('child_process'); | |
swiftFiles.forEach(filePath => { | |
var escapedFilePath = filePath.replace(" ", "\\ "); | |
let output = process.execSync("Pods/SwiftLint/swiftlint --config Scripts/.swiftlint.yml --path " + escapedFilePath + " --reporter json") | |
const jsonOutput = JSON.parse(output) | |
jsonOutput.forEach((lint: any) => { | |
const newLintResult = new LintResult(lint) | |
let message = `${newLintResult.type}: ${newLintResult.reason}` | |
let fileComponents = newLintResult.file.split(`jenkins-job-name/`) | |
var file: string = fileComponents[0] | |
if (fileComponents.length >= 2) { | |
file = fileComponents[1] | |
} | |
let line = newLintResult.line | |
if (newLintResult.severity.toLowerCase() === "error") { | |
fail(message, file, line) | |
} else { | |
warn(message, file, line) | |
} | |
}); | |
}) | |
swiftFiles.forEach(filePath => { | |
var fileText = readFileSync(filePath, 'utf8'); | |
if (stringContains(fileText, "UINavigationController(rootViewController:")) { | |
warn(`${fileNameFrom(filePath)} is using a default UINavigationController. Please use ABCNavigationController instead.`); | |
} | |
if (stringContains(filePath, "ViewController.swift") && !stringContains(fileText, "supportedInterfaceOrientations")) { | |
warn(`${fileNameFrom(filePath)} is not defining its supportedInterfaceOrientations. Please do so to ensure orientation is properly handled.`); | |
} | |
}) | |
// ** Helpers ** | |
function fileNameFrom(filePath: string) { | |
return filePath.replace(/^.*(\\|\/|\:)/, ''); | |
} | |
function stringContains(first: string, second: string) { | |
return first.indexOf(second) !== -1 | |
} | |
function stringContainsAny(first: string, any: string[]) { | |
let contains = any.find( tester => | |
stringContains(first, tester) | |
) | |
return contains !== undefined | |
} | |
Hey @mikenikles, thanks! I really like danger's ability to do positive feedback too. I took a look and your dangerfile looks great! I'm inspired by your wording and think I'll try to make ours a bit friendlier.
Good tip on the requested_reviewers
, I took a look! I'm seeing that it's defined as requested_reviewers: GitHubUser[]
so it looks like an array and the length check is working, from https://github.com/danger/danger-js/blob/3c641236595774c1e4202fad43217432fe9c780b/source/dsl/GitHubDSL.ts#L18.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey @stevethomp,
Thanks for sharing your Danger file. I got inspired by
// Congratulate PRs that simplify things
and added a few positive feedback messages to our Danger file at work. (Side note, your tweet earlier today reminded me of Danger and pushed me to integrate Danger into our project. Hopefully my team will appreciate the positive feedback received in their PRs next week ๐)I noticed
if (danger.github.requested_reviewers.length == 0)
(line 20) in your Danger file and wonder if that does what you expect. The reason I bring it up is becauserequested_reviewers
in my case returns an object, not an array. See https://github.com/danger/danger-js/blob/7ae8beeb28d64b471bf089766d39ee89195f8e5f/source/platforms/github/GitHubAPI.ts#L318 where Danger calls the Github API, which returns an object as documented here.