From 0ea79f96662e76116d1f7cc108dee075a03cea1b Mon Sep 17 00:00:00 2001 From: orta Date: Tue, 16 Apr 2024 18:13:16 +0100 Subject: [PATCH 1/3] Improve the init fn --- CHANGELOG.md | 6 +++ source/commands/danger-init.ts | 21 +++++--- source/commands/init/add-to-ci.ts | 59 ++++++++++++++++++++++ source/commands/init/default-dangerfile.ts | 10 ++-- source/commands/init/interfaces.ts | 2 +- source/commands/init/state-setup.ts | 4 +- 6 files changed, 90 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e02b5b98..8c957ca69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,12 @@ + +## 12.1.0 + +It's been 7 years since I looked at `danger init` and err, the world of CI has changed quite a bit since then. So, Danger JS's +`init` command now knows that GitHub Actions exists and will correctly offer some advice on how to set up a Dangerfile for it. - [@orta] + ## 12.0.0 Bumping to 12.x because we've raised the minimum to node version from 14 to 18. This is due to some of our dependencies diff --git a/source/commands/danger-init.ts b/source/commands/danger-init.ts index 95eab8fd7..78747fb10 100644 --- a/source/commands/danger-init.ts +++ b/source/commands/danger-init.ts @@ -6,7 +6,7 @@ import program from "commander" import * as fs from "fs" import { generateDefaultDangerfile } from "./init/default-dangerfile" -import { travis, circle, unsure } from "./init/add-to-ci" +import { travis, circle, unsure, githubActions } from "./init/add-to-ci" import { generateInitialState, createUI } from "./init/state-setup" import { InitUI, InitState, highlight } from "./init/interfaces" @@ -42,9 +42,14 @@ const go = async (app: App) => { state.isAnOSSRepo = isOSS await setupDangerfile(ui, state) - await setupGitHubAccount(ui, state) - await setupGHAccessToken(ui, state) - await addToCI(ui, state) + + if (!state.isAnOSSRepo) { + await setupGitHubAccount(ui, state) + await setupGHAccessToken(ui, state) + await addToCI(ui, state) + } else { + await githubActions(ui, state) + } await wrapItUp(ui, state) await thanks(ui, state) } @@ -65,9 +70,9 @@ const showTodoState = async (ui: InitUI) => { await ui.pause(0.6) ui.say(` - [ ] Create a Dangerfile and add a few simple rules.`) await ui.pause(0.6) - ui.say(` - [ ] Create a GitHub account for Danger to use, for messaging.`) + ui.say(` - [ ] Potentially create a GitHub account for Danger to use, for messaging.`) await ui.pause(0.6) - ui.say(` - [ ] Set up an access token for Danger.`) + ui.say(` - [ ] Set up an access token for Danger to comment with.`) await ui.pause(0.6) ui.say(" - [ ] Set up Danger to run on your CI.\n") @@ -225,7 +230,9 @@ const addToCI = async (ui: InitUI, state: InitState) => { ui.header("Add to CI") await ui.pause(0.6) - if (state.ciType === "travis") { + if (state.ciType === "gh-actions") { + await githubActions(ui, state) + } else if (state.ciType === "travis") { await travis(ui, state) } else if (state.ciType === "circle") { await circle(ui, state) diff --git a/source/commands/init/add-to-ci.ts b/source/commands/init/add-to-ci.ts index 8d9874f58..a499e70d5 100644 --- a/source/commands/init/add-to-ci.ts +++ b/source/commands/init/add-to-ci.ts @@ -1,4 +1,63 @@ import { InitUI, InitState, highlight } from "./interfaces" +import chalk from "chalk" + +export const githubActions = async (ui: InitUI, state: InitState) => { + if (!state.isAnOSSRepo) { + ui.say("For your closed-source project, we can use the default GitHub Auth token for posting.") + ui.pause(0.5) + + ui.say("You will want to add a new step in an existing workflow yaml file.") + ui.pause(0.2) + + ui.say("The step should look like this:") + ui.say("") + ui.say("```yaml") + ui.say(chalk.bold(" - name: Run Danger")) + ui.say(chalk.bold(" run: yarn danger ci")) + ui.say(chalk.bold(" env:")) + ui.say(chalk.bold(" GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}`")) + ui.say("```") + ui.say("") + ui.pause(1) + + ui.say("This will run Danger on every PR, press return when you have added this to one of your workflows.") + ui.waitForReturn() + return + } + + const link = ui.link("issue #918.", "https://github.com/danger/danger-js/issues/918") + ui.say( + `For your OSS project, there are a few options you can find in ${link}. We will continue with using the new GitHub user account here.` + ) + ui.pause(0.5) + + ui.say("For your OSS project, you need to add a new secret to your workflow in a way that is slightly obfuscated.") + ui.say("This is because GitHub Actions doesn't allow you to use the default GITHUB_TOKEN to update its own comments.") + ui.pause(0.5) + ui.say("This would make Danger very spammy on a Pull Request.") + + ui.pause(0.1) + ui.say("To get started, add a new step in an existing workflow file.") + ui.say("The step should look like this:") + ui.say("") + ui.say("```yaml") + ui.say( + chalk.bold(`) + - name: Run Danger + run: | + # Exposing this token is safe because the user of it has no other public repositories + # and has no permission to modify this repository. + TOKEN='ghp_On3bHOkcV2AmVY6' + TOKEN+='56186c3b09b4f86b1c65136769' + DANGER_GITHUB_API_TOKEN=$TOKEN yarn danger ci`) + ) + ui.say("```") + ui.say("") + ui.pause(1) + + ui.say("This will run Danger on every PR, press return when you have added this to one of your workflows.") + ui.waitForReturn() +} export const travis = async (ui: InitUI, state: InitState) => { // https://travis-ci.org/artsy/eigen/settings diff --git a/source/commands/init/default-dangerfile.ts b/source/commands/init/default-dangerfile.ts index f08c7ae41..9ac6dbfa4 100644 --- a/source/commands/init/default-dangerfile.ts +++ b/source/commands/init/default-dangerfile.ts @@ -34,17 +34,21 @@ export const generateDefaultDangerfile = (state: InitState) => { ${rules.join("\n")} ` - return formatDangerfile(dangerfile, dangerfileState) + return formatDangerfile(dangerfile, state, dangerfileState) } -export const formatDangerfile = (dangerfile: string, dangerfileState: any) => { +export const formatDangerfile = ( + dangerfile: string, + initState: InitState, + dangerfileState: ReturnType +) => { if (dangerfileState.hasPrettier) { // eslint-disable-next-line @typescript-eslint/no-require-imports const { format } = require("prettier") // Get package settings const localPrettier = fs.existsSync("package.json") && JSON.parse(fs.readFileSync("package.json", "utf8")).prettier // Always include this - const always = { editorconfig: true } + const always = { editorconfig: true, parser: "typescript", filepath: process.cwd() + " /" + initState.filename } const settings = localPrettier ? { ...always, ...localPrettier } : always return format(dangerfile, settings) diff --git a/source/commands/init/interfaces.ts b/source/commands/init/interfaces.ts index f84250617..c7ccb2b16 100644 --- a/source/commands/init/interfaces.ts +++ b/source/commands/init/interfaces.ts @@ -17,7 +17,7 @@ export interface InitState { hasSetUpAccountToken: boolean repoSlug: string | null - ciType: "travis" | "circle" | "unknown" + ciType: "gh-actions" | "travis" | "circle" | "unknown" isGitHub: boolean } diff --git a/source/commands/init/state-setup.ts b/source/commands/init/state-setup.ts index e4d4e8062..099843122 100644 --- a/source/commands/init/state-setup.ts +++ b/source/commands/init/state-setup.ts @@ -38,7 +38,9 @@ export const generateInitialState = (osProcess: NodeJS.Process): InitState => { const isBabel = checkForBabel() const hasTravis = fs.existsSync(".travis.yml") const hasCircle = fs.existsSync("circle.yml") - const ciType = hasTravis ? "travis" : hasCircle ? "circle" : "unknown" + const hasGitHubActions = fs.existsSync(".github/") && fs.existsSync(".github/workflows") + + const ciType = hasGitHubActions ? "gh-actions" : hasTravis ? "travis" : hasCircle ? "circle" : "unknown" const repoSlug = getRepoSlug() const isGitHub = !!repoSlug From 9dc19b5e5c2460a49fa6cf3b91f726ac1fe12aca Mon Sep 17 00:00:00 2001 From: orta Date: Tue, 16 Apr 2024 18:17:01 +0100 Subject: [PATCH 2/3] Fix logic --- source/commands/danger-init.ts | 3 ++- source/commands/init/add-to-ci.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/source/commands/danger-init.ts b/source/commands/danger-init.ts index 78747fb10..feb0c5a1d 100644 --- a/source/commands/danger-init.ts +++ b/source/commands/danger-init.ts @@ -43,11 +43,12 @@ const go = async (app: App) => { await setupDangerfile(ui, state) - if (!state.isAnOSSRepo) { + if (state.isAnOSSRepo) { await setupGitHubAccount(ui, state) await setupGHAccessToken(ui, state) await addToCI(ui, state) } else { + // We can use the private github workflow for private repos await githubActions(ui, state) } await wrapItUp(ui, state) diff --git a/source/commands/init/add-to-ci.ts b/source/commands/init/add-to-ci.ts index a499e70d5..6e60d5d8c 100644 --- a/source/commands/init/add-to-ci.ts +++ b/source/commands/init/add-to-ci.ts @@ -4,6 +4,7 @@ import chalk from "chalk" export const githubActions = async (ui: InitUI, state: InitState) => { if (!state.isAnOSSRepo) { ui.say("For your closed-source project, we can use the default GitHub Auth token for posting.") + ui.say("So, you don't need to create a bot account.") ui.pause(0.5) ui.say("You will want to add a new step in an existing workflow yaml file.") From 8733b5db5ef52f1941b81fd8c866b6c4e33ecceb Mon Sep 17 00:00:00 2001 From: orta Date: Tue, 16 Apr 2024 18:23:57 +0100 Subject: [PATCH 3/3] Polish pass --- source/commands/danger-init.ts | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/source/commands/danger-init.ts b/source/commands/danger-init.ts index feb0c5a1d..d5147d85a 100644 --- a/source/commands/danger-init.ts +++ b/source/commands/danger-init.ts @@ -208,21 +208,20 @@ const wrapItUp = async (ui: InitUI, _state: InitState) => { await ui.pause(0.6) const link = (name: string, url: string) => ui.say(" * " + ui.link(name, url)) - link("artsy/Emission#dangerfile.ts", "https://github.com/artsy/emission/blob/master/dangerfile.ts") + link("artsy/eigen#dangerfile.ts", "https://github.com/artsy/eigen/blob/master/dangerfile.ts") link( - "facebook/react-native#danger/dangerfile.js", - "https://github.com/facebook/react-native/blob/master/bots/dangerfile.js" + "facebook/react-native#main/packages/react-native-bots/dangerfile.js", + "https://github.com/facebook/react-native/blob/main/packages/react-native-bots/dangerfile.js" ) + link("mui/material-ui#dangerfile.ts", "https://github.com/mui/material-ui/blob/main/dangerfile.ts#L4") link( - "apollographql/apollo-client#dangerfile.ts", - "https://github.com/apollographql/apollo-client/blob/master/config/dangerfile.ts" + "styleguidist/react-styleguidist#dangerfile.ts", + "https://github.com/styleguidist/react-styleguidist/blob/master/dangerfile.ts" ) link( - "styleguidist/react-styleguidist#dangerfile.js", - "https://github.com/styleguidist/react-styleguidist/blob/master/dangerfile.js" + "storybooks/storybook#.ci/danger/dangerfile.ts", + "https://github.com/storybookjs/storybook/blob/master/.ci/danger/dangerfile.ts" ) - link("storybooks/storybook#dangerfle.js", "https://github.com/storybooks/storybook/blob/master/dangerfile.js") - link("ReactiveX/rxjs#dangerfle.js", "https://github.com/ReactiveX/rxjs/blob/master/dangerfile.js") await ui.pause(1) } @@ -250,10 +249,8 @@ const thanks = async (ui: InitUI, _state: InitState) => { ui.say("and every who has sent PRs.\n") ui.say( "If you like Danger, let others know. If you want to know more, follow " + - highlight("@orta") + - " and " + - highlight("@DangerSystems") + - " on Twitter." + highlight("@orta@webtoo.ls") + + " on Mastodon!" ) ui.say("If you don't like something about Danger, help us improve the project - it's all done on volunteer time! xxx") ui.say("Remember: it's nice to be nice.\n")