### Setup Danger JS Project Source: https://github.com/danger/danger-js/blob/main/CONTRIBUTING.md Clone the repository, install dependencies using Yarn, and verify the installation by running tests and linters. ```sh git clone https://github.com/danger/danger-js.git cd danger-js # if you don't have yarn installed npm install -g yarn yarn install ``` ```sh yarn test yarn lint ``` -------------------------------- ### Check README for Missing CI Providers Source: https://github.com/danger/danger-js/blob/main/docs/tutorials/node-library.html.md This example checks if all supported CI providers are listed in the README.md file. It reads the README, gets the names of CI providers from the Danger library's internal configuration, and warns if any are missing from the README. ```javascript import { danger, fail, warn } from "danger" import contains from "lodash.contains" // This is a list of all the CI providers import { realProviders } from "./source/ci_source/providers" const readme = fs.readFileSync("README.md", "utf8") const names = realProviders.map(ci => new ci({}).name) const missing = names.filter(name => !contains(readme, name)) if (missing.length) { warn(`These providers are missing from the README: ${sentence(missing.length)}`) } ``` -------------------------------- ### Install Danger JS Dependencies Source: https://github.com/danger/danger-js/blob/main/README.md Clone the repository, navigate to the directory, and install dependencies using Yarn. Ensure Yarn is installed globally. ```sh git clone https://github.com/danger/danger-js.git cd danger-js # if you don't have yarn installed npm install -g yarn yarn install ``` -------------------------------- ### Start Danger Plugin Project with Yeoman Source: https://github.com/danger/danger-js/blob/main/docs/usage/extending-danger.html.md Initiates the Danger plugin creation process using the installed Yeoman generator. Follow the prompts to configure your new plugin. ```sh yo danger-plugin ``` -------------------------------- ### Install Danger and Husky Source: https://github.com/danger/danger-js/blob/main/docs/tutorials/fast-feedback.html.md Add Danger and husky as development dependencies to your project. ```sh yarn add --dev danger husky ``` -------------------------------- ### CI Script Example Source: https://github.com/danger/danger-js/blob/main/docs/tutorials/node-app.html.md Example of CI script commands including Danger CI execution. ```yaml script: - yarn lint - yarn test - yarn danger ci ``` -------------------------------- ### Install Danger JS Source: https://github.com/danger/danger-js/blob/main/docs/usage/danger-process.html.md Instructions for installing Danger JS using Homebrew and npm. This is typically done on a Mac environment. ```bash brew install node npm install -g danger ``` -------------------------------- ### Configure Husky Pre-push Hook Source: https://github.com/danger/danger-js/blob/main/docs/tutorials/fast-feedback.html.md Set up a pre-push hook in your `package.json` to run Danger locally before code is pushed. This example uses a `prepush` script to build the project and then run `danger local`. ```json "scripts": { "prepush": "yarn build; yarn danger:prepush", "danger:prepush": "yarn danger local --dangerfile dangerfile.lite.ts" // [...] } ``` -------------------------------- ### Example Danger Plugin Structure Source: https://github.com/danger/danger-js/blob/main/docs/usage/extending-danger.html.md Illustrates the typical directory structure generated for a Danger plugin project, including source files, tests, and configuration. ```sh $ tree danger-plugin-yarn ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── package.json ├── src │ ├── index.test.ts │ └── index.ts ├── tsconfig.json ├── tslint.json └── yarn.lock ``` -------------------------------- ### Start Dangerfile Evaluation Source: https://github.com/danger/danger-js/blob/main/docs/usage/danger-process.html.md Instantiates and runs a Dangerfile using the Dangerfile.new runtime. This is the primary method for executing Danger code. ```ruby runtime = Dangerfile.new runtime.run ``` -------------------------------- ### Install Yeoman Generator for Danger Plugins Source: https://github.com/danger/danger-js/blob/main/docs/usage/extending-danger.html.md Installs the Yeoman generator and Danger plugin template globally. This is the first step to scaffolding a new Danger plugin. ```sh npm i -g yo generator-danger-plugin ``` -------------------------------- ### Run Danger JS Tests and Linters Source: https://github.com/danger/danger-js/blob/main/README.md Verify your Danger JS installation by running the test suite and linters. Fixers for tslint and prettier are applied on commit. ```sh yarn test yarn lint ``` -------------------------------- ### Match Files with Danger JS Source: https://github.com/danger/danger-js/blob/main/docs/guides/the_dangerfile.html.md Use `danger.git.fileMatch` to create patterns for files you are interested in. This example shows how to check for modified documentation files and app files without corresponding tests. ```js import { danger } from "danger" const docs = danger.git.fileMatch("**/*.md") const app = danger.git.fileMatch("src/**/*.ts") const tests = danger.git.fileMatch("*/__tests__/*") if (docs.edited) { message("Thanks - We :heart: our [documentarians](http://www.writethedocs.org/)") } if (app.modified && !tests.modified) { warn("You have app changes without tests.") } ``` -------------------------------- ### Warn on Missing CHANGELOG for Library Changes Source: https://github.com/danger/danger-js/blob/main/docs/tutorials/node-library.html.md This rule is more specific than the previous one. It warns if there are changes to the library's source code (files starting with 'lib/') but no corresponding CHANGELOG.md entry. This avoids unnecessary warnings for non-code changes. ```javascript import { danger, fail, warn } from "danger" import first from "lodash.first" const changelogChanges = danger.git.fileMatch("CHANGELOG.md") const hasLibraryChanges = first(danger.git.modified_files, path => path.startsWith("lib/")) if (hasLibraryChanges && !changelogChanges.modified) { warn("This pull request may need a CHANGELOG entry.") } ``` -------------------------------- ### Configure Proxy for Debugging with Danger JS Source: https://github.com/danger/danger-js/blob/main/docs/usage/bitbucket_server.html.md Shows how to set environment variables to configure an HTTP or HTTPS proxy for debugging requests, useful for inspecting traffic. ```bash export NODE_TLS_REJECT_UNAUTHORIZED=0 # Avoid certificate error export http_proxy=http://127.0.0.1:8080 or export https_proxy=https://127.0.0.1:8080 ``` -------------------------------- ### Preview Danger DSL as JSON Source: https://github.com/danger/danger-js/blob/main/docs/usage/danger-process.html.md Use the `--js` and `--json` flags with `danger pr` to preview the Danger DSL that will be sent to your custom process. This is useful for understanding the data structure and for generating data fixtures. ```sh danger pr https://github.com/danger/danger-js/pull/395 --js ``` ```sh danger pr https://github.com/danger/danger-js/pull/395 --json > danger-js-395.dsl.json ``` -------------------------------- ### Build List for Unknown Files Source: https://github.com/danger/danger-js/blob/main/source/platforms/gitlab/_tests/fixtures/fileContentsBefore.txt This function formats a list of filenames. If the list exceeds 10 items, it is enclosed in a collapsible details tag for better readability. ```ruby def build_list(items) list = items.map { |filename| "* `#{filename}`" }.join("\n") if items.size > 10 "\n
\n\n#{list}\n\n
" else list end end ``` -------------------------------- ### Danger JS BitBucket Server DSL Overview Source: https://github.com/danger/danger-js/blob/main/docs/usage/bitbucket_server.html.md Illustrates the available properties within the `danger.bitbucket_server` object for interacting with BitBucket Server data. ```typescript danger.bitbucket_server. /** The pull request and repository metadata */ metadata: RepoMetaData /** The related JIRA issues */ issues: JIRAIssue[] /** The PR metadata */ pr: BitBucketServerPRDSL /** The commits associated with the pull request */ commits: BitBucketServerCommit[] /** The comments on the pull request */ comments: BitBucketServerPRActivity[] /** The activities such as OPENING, CLOSING, MERGING or UPDATING a pull request */ activities: BitBucketServerPRActivity[] ``` -------------------------------- ### Simulate CI Environment Locally Source: https://github.com/danger/danger-js/blob/main/docs/guides/the_dangerfile.html.md Use these environment variables to fake a CI environment for local testing. This allows you to run Danger against a specific pull request on your local machine. ```bash export DANGER_FAKE_CI="YEP" export DANGER_TEST_REPO='username/reponame' ``` ```bash git checkout branch-for-pr-1234 DANGER_TEST_PR='1234' yarn danger ci ``` -------------------------------- ### Configure API Authentication Tokens Source: https://github.com/danger/danger-js/blob/main/docs/guides/the_dangerfile.html.md Set these environment variables to authenticate API requests for private repositories or to avoid rate limits. Different variables are available for GitHub, BitBucket Server, and BitBucket Cloud. ```sh export DANGER_GITHUB_API_TOKEN='xxxx' ``` ```sh export DANGER_BITBUCKETSERVER_HOST='xxxx' DANGER_BITBUCKETSERVER_USERNAME='yyyy' DANGER_BITBUCKETSERVER_PASSWORD='zzzz' ``` ```sh export DANGER_BITBUCKETSERVER_HOST='xxxx' DANGER_BITBUCKETSERVER_USERNAME='yyyy' DANGER_BITBUCKETSERVER_TOKEN='zzzz' ``` ```sh export DANGER_BITBUCKETCLOUD_USERNAME='xxxx' export DANGER_BITBUCKETCLOUD_PASSWORD='yyyy' ``` ```sh # You can get OAuth key from Settings > OAuth > Add consumer, put `https://bitbucket.org/site/oauth2/authorize` for `Callback URL`, and enable Read Pull requests, and Read Account Permissions. export DANGER_BITBUCKETCLOUD_OAUTH_KEY='xxxx' export DANGER_BITBUCKETCLOUD_OAUTH_SECRET='yyyy' ``` ```sh # You can get a Repository Access Token from Repo Settings > Security > Acesss Tokens and set Pull requests write scope. export DANGER_BITBUCKETCLOUD_REPO_ACCESSTOKEN='xxxx' ``` -------------------------------- ### Enable Debug Logging for Danger Source: https://github.com/danger/danger-js/blob/main/docs/guides/faq.html.md Prefix Danger commands with DEBUG="*" to enable verbose logging, which is helpful for understanding Danger's internal processes. ```sh DEBUG="*" DANGER_GITHUB_API_TOKEN=[123] yarn danger pr https://github.com/facebook/react/pull/11865 ``` ```sh DEBUG="*" yarn danger ci ``` -------------------------------- ### Troubleshooting STDIN Timeout Source: https://github.com/danger/danger-js/blob/main/docs/usage/danger-process.html.md A workaround for Danger JS STDIN timeout issues. If your process cannot catch the DSL, have it print 'danger://send-dsl' to trigger a re-send. ```text danger://send-dsl ``` -------------------------------- ### Run Danger JS on a PR Source: https://github.com/danger/danger-js/blob/main/README.md Build the project and run your local development copy of Danger JS against a specific GitHub pull request using its URL. ```sh yarn build; node --inspect distribution/commands/danger-pr.js https://github.com/danger/danger-js/pull/817 ``` -------------------------------- ### Release a New Version of Danger JS Source: https://github.com/danger/danger-js/blob/main/README.md Follow the release process by checking out the main branch, ensuring a clean working tree, and publishing a new version using npm. This triggers a CI run to update homebrew. ```sh npm run release -- patch --ci --npm.otp= ``` -------------------------------- ### Local Testing Workflow for Danger Plugins Source: https://github.com/danger/danger-js/blob/main/docs/usage/extending-danger.html.md A sequence of commands for locally testing a Danger plugin against a real pull request. This involves linking the plugin and using `danger pr`. ```sh yarn link yarn add [plugin] -d yarn link [plugin] yarn tsc --watch yarn danger pr -v https://github.com/artsy/emission/pull/597 ``` -------------------------------- ### Run Danger as a Dev-Dependency in CI Source: https://github.com/danger/danger-js/blob/main/docs/usage/github_enterprise.html.md Integrate Danger as a build step after tests when Danger is a dev-dependency. Ensure `DANGER_GHE_ACTIONS_BOT_USER_ID` is set in your environment. ```yml name: Node CI on: [pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@master - name: Use Node.js 10.x uses: actions/setup-node@v1 with: node-version: 10.x - name: install yarn run: npm install -g yarn - name: yarn install, build, and test run: | yarn install --frozen-lockfile yarn build yarn test - name: Danger run: yarn danger ci env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} DANGER_GHE_ACTIONS_BOT_USER_ID: *user_id* ``` -------------------------------- ### Generate Requested Reviewers Fixture Source: https://github.com/danger/danger-js/blob/main/source/platforms/_tests/fixtures/readme.md Use this CURL command to fetch and save the requested reviewers for a pull request as a JSON fixture. ```sh curl \ -H "Authorization: token " \ -H "Accept: application/vnd.github.v3+json" \ --request GET https://api.github.com/repos/artsy/emission/pulls/327/requested_reviewers \ > source/platforms/_tests/fixtures/requested_reviewers.json ``` -------------------------------- ### Bitbucket Cloud DSL Overview Source: https://github.com/danger/danger-js/blob/main/docs/usage/bitbucket_cloud.html.md This outlines the available properties within the `danger.bitbucket_cloud` object for accessing pull request metadata, PR details, commits, comments, and activities. ```typescript danger.bitbucket_cloud. /** The pull request and repository metadata */ metadata: RepoMetaData /** The PR metadata */ pr: BitBucketCloudPRDSL /** The commits associated with the pull request */ commits: BitBucketCloudCommit[] /** The comments on the pull request */ comments: BitBucketCloudPRComment[] /** The activities such as OPENING, COMMENTING, CLOSING, MERGING or UPDATING a pull request */ activities: BitBucketCloudPRActivity[] ``` -------------------------------- ### Check Linter Output for Failures Source: https://github.com/danger/danger-js/blob/main/docs/tutorials/node-app.html.md Reads a linter output file and posts a markdown message to the PR if 'Failed' is found. ```javascript import { danger, markdown } from "danger" import contains from "lodash-contains" import fs from "fs" const testFile = "tests-output.log" const linterOutput = fs.readFileSync(testFile).toString() if (contains(linterOutput, "Failed")) { markdown(`These changes failed to pass the linter: ${linterOutput} `) } ``` -------------------------------- ### Simple Ruby Danger Process Runner Source: https://github.com/danger/danger-js/blob/main/docs/usage/danger-process.html.md A minimal Danger runner implemented in Ruby. It reads the Danger DSL from STDIN, parses it, and checks if the PR body includes 'Hello world'. Results are output as JSON to STDOUT. This runner can be executed with `danger pr --process 'dangerfile.rb` after making it executable. ```ruby #!/usr/bin/env ruby require 'json' dsl_json = STDIN.tty? ? 'Cannot read from STDIN' : $stdin.read danger = JSON.parse(dsl_json).danger results = { warnings: [], messages:[], fails: [], markdowns: [] } if danger.github.pr.body.include? "Hello world" results.messages << { message: "Hey there" } end STDOUT.write(results.to_json) ``` -------------------------------- ### Fail on blacklisted dependency addition Source: https://github.com/danger/danger-js/blob/main/docs/tutorials/dependencies.html.md This snippet checks for the addition of specific blacklisted dependencies in package.json. It uses `JSONDiffForFile` to detect changes and `fail` to stop the build if a blacklisted package is found. ```javascript const blacklist = "spaced-between" schedule(async () => { const packageDiff = await danger.git.JSONDiffForFile("package.json") if (packageDiff.dependencies) { const newDependencies = packageDiff.dependencies.added if (newDependencies.includes(blacklist)) { fail(`Do not add ${blacklist} to our dependencies, see CVE #23") } } }) ``` -------------------------------- ### Enforce Jira Issues and User Approvals with Danger JS Source: https://github.com/danger/danger-js/blob/main/docs/usage/bitbucket_server.html.md Demonstrates how to enforce that a PR has assigned Jira issues and checks for specific user approvals on package.json changes. ```typescript import { danger, warn } from "danger" const bbs = danger.bitbucket_server // Ensure a PR has assigned Jira issues if (bbs.issues.length === 0) { warn("This PR does not have any assigned Jira issues.") } // Make a warning if there are changes to a package.json but that a // user called murphdog hasn't yet weighed in that the changes are fine. const hasPackageChanges = danger.git.modified_files.includes("package.json") const hasMurphDogApproval = bbs.comments.find( c => c.user.slug == "murphdog" && !!c.comment && c.comment.text.includes(":+1:") ) if (hasPackageChanges && !hasMurphDogApproval) { warn("This PR has `package.json` changes, but @murphdog hasn't approved them yet.") } ``` -------------------------------- ### Handle Async Operations with schedule in Peril Source: https://github.com/danger/danger-js/blob/main/docs/guides/peril.html.md Use the `schedule` function within your Dangerfile to manage asynchronous operations. It queues promises or functions with callbacks, ensuring Danger waits for completion before proceeding. This is crucial for handling async code in Peril's inline execution environment. ```javascript import { schedule, danger } from "danger" /// [... a bunch of functions] schedule(async () => { const packageDiff = await danger.git.JSONDiffForFile("package.json") checkForRelease(packageDiff) checkForNewDependencies(packageDiff) checkForLockfileDiff(packageDiff) checkForTypesInDeps(packageDiff) }) ``` -------------------------------- ### Warn on package.json changes without lockfile changes Source: https://github.com/danger/danger-js/blob/main/docs/tutorials/dependencies.html.md Use this to ensure that any modifications to package.json are accompanied by corresponding changes in the lockfile (e.g., yarn.lock). This helps maintain a consistent dependency state. ```javascript import { danger, warn } from "danger" const packageJson = danger.git.fileMatch("package.json") const packageLock = danger.git.fileMatch("yarn.lock") if (packageJson.modified && !packageLock.modified) { warn("There are package.json changes with no corresponding lockfile changes") } ``` -------------------------------- ### Conditionally Run Danger CI Source: https://github.com/danger/danger-js/blob/main/docs/guides/faq.html.md Use this command to ensure Danger only runs when the necessary environment variables are set, preventing external contributors from accessing private tokens. ```sh [ ! -z $DANGER_GITHUB_API_TOKEN ] && yarn danger ci || echo "Skipping Danger for External Contributor" ``` -------------------------------- ### Release a New Version of Danger JS Source: https://github.com/danger/danger-js/blob/main/CONTRIBUTING.md Steps to update the version, commit changes, tag the release, and push to the main branch for deployment to NPM. ```sh git pull # Update package.json with the new version (e.g., 0.21.0) # Modify changelog.md with a new heading (e.g., ### 0.21.0) # Commit both changes git commit -m "Version bump" # Tag this commit git tag 0.21.0 # Push the commit and tag git push origin main --follow-tags ``` -------------------------------- ### Conditional Assignee Check (WIP) Source: https://github.com/danger/danger-js/blob/main/docs/tutorials/node-app.html.md Allows PRs with 'WIP' in the title to skip the assignee check, issuing a warning instead of a failure. ```javascript import { danger, fail, warn } from "danger" if (!danger.github.pr.assignee) { const method = danger.github.pr.title.includes("WIP") ? warn : fail method("This pull request needs an assignee, and optionally include any reviewers.") } ``` -------------------------------- ### Mock Danger Module for Testing Source: https://github.com/danger/danger-js/blob/main/docs/tutorials/transpilation.html.md Mock the 'danger' module using Jest to simulate the Danger environment for testing Dangerfiles. This allows manipulation of objects like danger.github.pr. ```javascript jest.mock("danger", () => jest.fn()) import * as danger from "danger" const dm = danger as any import { rfc5 } from "../org/all-prs" beforeEach(() => { dm.fail = jest.fn() }) it("fails when there's no PR body", () => { dm.danger = { github: { pr: { body: "" } } } return rfc5().then(() => { expect(dm.fail).toHaveBeenCalledWith("Please add a description to your PR.") }) }) it("does nothing when there's a PR body", () => { dm.danger = { github: { pr: { body: "Hello world" } } } return rfc5().then(() => { expect(dm.fail).not.toHaveBeenCalled() }) }) ``` -------------------------------- ### Main Dangerfile Logic for Reviewer Roulette Source: https://github.com/danger/danger-js/blob/main/source/platforms/gitlab/_tests/fixtures/fileContentsBefore.txt This block orchestrates the reviewer roulette process. It fetches changes, determines categories, and conditionally applies the roulette if the MR is not a 'single codebase' or 'CSS cleanup' type. ```ruby changes = helper.changes_by_category # Ignore any files that are known but uncategoried. Prompt for any unknown files changes.delete(:none) categories = changes.keys - [:unknown] # Single codebase MRs are reviewed using a slightly different process, so we # disable the review roulette for such MRs. # CSS Clean up MRs are reviewed using a slightly different process, so we # disable the review roulette for such MRs. if changes.any? && !gitlab.mr_labels.include?('single codebase') && !gitlab.mr_labels.include?('CSS cleanup') team = begin helper.project_team rescue => err warn("Reviewer roulette failed to load team data: #{err.message}") [] end # Exclude the MR author from the team for selection purposes team.delete_if { |teammate| teammate.username == gitlab.mr_author } project = helper.project_name unknown = changes.fetch(:unknown, []) rows = categories.map { |category| spin(team, project, category) } markdown(MESSAGE) markdown(CATEGORY_TABLE_HEADER + rows.join("\n")) unless rows.empty? markdown(UNKNOWN_FILES_MESSAGE + build_list(unknown)) unless unknown.empty? end ``` -------------------------------- ### Use Danger JS as a GitHub Action Source: https://github.com/danger/danger-js/blob/main/docs/usage/github_enterprise.html.md Utilize Danger JS as a standalone action for CI workflows. This method is suitable if you are not running in a JavaScript ecosystem or prefer not to include Danger as a dependency. Set `DANGER_GHE_ACTIONS_BOT_USER_ID` in your environment. ```yml name: "Danger JS" on: [pull_request] jobs: build: name: Danger JS runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Danger uses: danger/danger-js@9.1.6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} DANGER_GHE_ACTIONS_BOT_USER_ID: *user_id* ``` -------------------------------- ### Configure TypeScript Exclusion and Inclusion Source: https://github.com/danger/danger-js/blob/main/docs/tutorials/transpilation.html.md Add your Dangerfile to the 'exclude' section and 'include' section in tsconfig.json to prevent compilation errors and enable inline error checking. ```json { "compilerOptions": {}, "include": ["src/**/*.ts", "src/**/*.tsx", "dangerfile.ts"], "exclude": ["dangerfile.ts", "node_modules"] } ``` -------------------------------- ### Warn on Missing CHANGELOG Entry Source: https://github.com/danger/danger-js/blob/main/docs/tutorials/node-library.html.md Use this rule to warn if a pull request modifies files but does not include a CHANGELOG.md update. This helps ensure documentation is kept up-to-date. ```javascript import { danger, fail, warn } from "danger" const changelogChanges = danger.git.fileMatch("CHANGELOG.md") if (!changelogChanges.modified) { warn("This pull request may need a CHANGELOG entry.") } ``` -------------------------------- ### Minimum PR Description Length Source: https://github.com/danger/danger-js/blob/main/docs/tutorials/node-app.html.md Enforces a minimum length for the pull request body to encourage documentation. ```javascript if (danger.github.pr.body.length < 10) { fail("This pull request needs a description.") } ``` -------------------------------- ### Access GitLab MR Metadata in Dangerfile Source: https://github.com/danger/danger-js/blob/main/docs/usage/gitlab.html.md This shows the available properties within the `danger.gitlab` object for accessing merge request metadata, repository details, and commits. ```typescript danger.gitlab. /** The pull request and repository metadata */ metadata: RepoMetaData /** The Merge Request metadata */ mr: GitLabMR /** The commits associated with the merge request */ commits: GitLabMRCommit[] ``` -------------------------------- ### Check for WIP in PR Title Source: https://github.com/danger/danger-js/blob/main/docs/usage/bitbucket_cloud.html.md Use this snippet to warn if a pull request title indicates it's a Work In Progress. Requires the `danger.bitbucket_cloud.pr.title` property. ```typescript import { danger, warn } from "danger" if (danger.bitbucket_cloud.pr.title.includes("WIP")) { warn("PR is considered WIP") } ``` -------------------------------- ### Advanced Ruby Danger Process Runner Source: https://github.com/danger/danger-js/blob/main/docs/usage/danger-process.html.md A more complex Ruby runner that simulates the Dangerfile evaluation environment. It defines methods for `warn`, `fail`, `markdowns`, and `messages` within a `Dangerfile` class. It reads and evaluates a local Dangerfile, writing results to a temporary file and outputting its path to STDOUT. ```ruby #!/usr/bin/env ruby require 'json' dsl_json = STDIN.tty? ? 'Cannot read from STDIN' : $stdin.read danger = JSON.parse(dsl_json).danger results = { warnings: [], messages:[], fails: [], markdowns: [] } filename = "Dangerfile" class Dangerfile # All these functions are effectively globals inside # the Dangerfile during evaluation def warn(msg) results.warnings << { message: msg } end def fail(msg) results.fails << { message: msg } end def markdowns(msg) results.markdowns << { message: msg } end def messages(msg) results.messages << { message: msg } end def run instance_eval do begin # Eval the cwd's Dangerfile in the context # of this file, making it a custom runtime eval(File.read(filename), nil, filename) # Writes the results to a tmpdir file, then # pass it back to danger-js by putting the # url of the file back via stdout results_path = Dir.tmpdir + "danger-results.json" File.write(results_path, results.to_json) puts "danger-results:/" + results_path rescue Exception => e # Generic error handling message = "Invalid `#{path.basename}` file: #{e.message}" raise Error.new(message, path, e.backtrace, contents) end end end end ``` -------------------------------- ### Spin Function for Reviewer Selection Source: https://github.com/danger/danger-js/blob/main/source/platforms/gitlab/_tests/fixtures/fileContentsAfter.txt Selects a reviewer and maintainer for a given category based on team roles and project. It uses a seeded random number generator for consistent selection based on the branch name and prioritizes traintainers for reviewer roles. ```ruby def spin(team, project, category, branch_name) rng = Random.new(Digest::MD5.hexdigest(branch_name).to_i(16)) reviewers = team.select { |member| member.reviewer?(project, category) } traintainers = team.select { |member| member.traintainer?(project, category) } maintainers = team.select { |member| member.maintainer?(project, category) } # TODO: filter out people who are currently not in the office # https://gitlab.com/gitlab-org/gitlab-ce/issues/57652 # # TODO: take CODEOWNERS into account? # https://gitlab.org/gitlab-ce/issues/57653 # Make traintainers have triple the chance to be picked as a reviewer reviewer = (reviewers + traintainers + traintainers).sample(random: rng) maintainer = maintainers.sample(random: rng) "| #{helper.label_for_category(category)} | #{reviewer&.markdown_name} | #{maintainer&.markdown_name} |" end ``` -------------------------------- ### Basic PR Title Check with Danger JS Source: https://github.com/danger/danger-js/blob/main/docs/usage/bitbucket_server.html.md Checks if the pull request title includes 'WIP' and issues a warning if it does. Requires Danger JS to be set up. ```typescript import { danger, warn } from "danger" if (danger.bitbucket_server.pr.title.includes("WIP")) { warn("PR is considered WIP") } ``` -------------------------------- ### Main Danger JS Logic for GitLab Source: https://github.com/danger/danger-js/blob/main/source/platforms/gitlab/_tests/fixtures/fileContentsAfter.txt Orchestrates the reviewer roulette process for GitLab merge requests. It fetches changes, determines categories, selects reviewers and maintainers, and generates markdown output, excluding certain MRs like 'single codebase' or 'CSS cleanup'. ```ruby changes = helper.changes_by_category # Ignore any files that are known but uncategoried. Prompt for any unknown files changes.delete(:none) categories = changes.keys - [:unknown] # Single codebase MRs are reviewed using a slightly different process, so we # disable the review roulette for such MRs. # CSS Clean up MRs are reviewed using a slightly different process, so we # disable the review roulette for such MRs. if changes.any? && !gitlab.mr_labels.include?('single codebase') && !gitlab.mr_labels.include?('CSS cleanup') # Strip leading and trailing CE/EE markers canonical_branch_name = gitlab .mr_json['source_branch'] .gsub(/^[ce]e-/, '') .gsub(/-[ce]e$/, '') team = begin helper.project_team rescue => err warn("Reviewer roulette failed to load team data: #{err.message}") [] end # Exclude the MR author from the team for selection purposes team.delete_if { |teammate| teammate.username == gitlab.mr_author } project = helper.project_name unknown = changes.fetch(:unknown, []) rows = categories.map { |category| spin(team, project, category, canonical_branch_name) } markdown(MESSAGE) markdown(CATEGORY_TABLE_HEADER + rows.join("\n")) unless rows.empty? markdown(UNKNOWN_FILES_MESSAGE + build_list(unknown)) unless unknown.empty? end ``` -------------------------------- ### Fail on blacklisted dependency in lockfile Source: https://github.com/danger/danger-js/blob/main/docs/tutorials/dependencies.html.md This rule parses the yarn.lock file to detect if a blacklisted dependency has been introduced, even transitively. It uses synchronous file reading for simplicity in a script environment. ```javascript import fs from "fs" const blacklist = "spaced-between" const lockfile = fs.readFileSync("yarn.lock").toString() if (lockfile.includes(blacklist)) { const message = `${blacklist} was added to our dependencies, see CVE #23` const hint = `To find out what introduced it, use 'yarn why ${blacklist}'.` fail(`${message}
${hint}`) } ``` -------------------------------- ### Spin Function for Reviewer Selection Source: https://github.com/danger/danger-js/blob/main/source/platforms/gitlab/_tests/fixtures/fileContentsBefore.txt This function selects a reviewer and maintainer for a given category based on team roles. It prioritizes traintainers for reviewer selection and handles cases where no maintainer is found. ```ruby def spin(team, project, category) reviewers = team.select { |member| member.reviewer?(project, category) } traintainers = team.select { |member| member.traintainer?(project, category) } maintainers = team.select { |member| member.maintainer?(project, category) } # TODO: filter out people who are currently not in the office # TODO: take CODEOWNERS into account? # Make traintainers have triple the chance to be picked as a reviewer reviewer = (reviewers + traintainers + traintainers).sample maintainer = maintainers.sample "| #{helper.label_for_category(category)} | #{reviewer&.markdown_name} | #{maintainer&.markdown_name} |" end ``` -------------------------------- ### Check Merge Request Title in Dangerfile Source: https://github.com/danger/danger-js/blob/main/docs/usage/gitlab.html.md Use this snippet to check if a merge request title contains specific keywords like 'WIP'. Ensure you have imported `danger` and `warn` from 'danger'. ```typescript import { danger, warn } from "danger" if (danger.gitlab.mr.title.includes("WIP")) { warn("PR is considered WIP") } ``` -------------------------------- ### Require Assignee for PRs Source: https://github.com/danger/danger-js/blob/main/docs/tutorials/node-app.html.md Ensures a pull request has an assignee. Fails the build if no assignee is present. ```javascript import { danger, fail, warn } from "danger" if (!danger.github.pr.assignee) { fail("This pull request needs an assignee, and optionally include any reviewers.") } ``` -------------------------------- ### Define Reviewer Roulette Messages Source: https://github.com/danger/danger-js/blob/main/source/platforms/gitlab/_tests/fixtures/fileContentsBefore.txt These constants define the markdown messages used for the reviewer roulette feature, including introductory text and table headers. ```ruby MESSAGE = <