diff --git a/.github/workflows/danger-workflow-tests.yml b/.github/workflows/danger-workflow-tests.yml new file mode 100644 index 0000000..0b27a3a --- /dev/null +++ b/.github/workflows/danger-workflow-tests.yml @@ -0,0 +1,18 @@ +# This isn't a reusable workflow but an actual CI action for this repo itself - to test the workflows. +name: Danger Workflow Tests + +on: + pull_request: + types: [opened, synchronize, reopened, edited, ready_for_review] + +jobs: + danger: + uses: ./.github/workflows/danger.yml + with: + _workflow_version: ${{ github.sha }} + + test-outputs: + runs-on: ubuntu-latest + needs: danger + steps: + - run: "[[ '${{ needs.danger.outputs.outcome }}' == 'success' ]]" diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml new file mode 100644 index 0000000..d2aa447 --- /dev/null +++ b/.github/workflows/danger.yml @@ -0,0 +1,41 @@ +# Runs DangerJS with a pre-configured set of rules on a Pull Request. +on: + workflow_call: + inputs: + _workflow_version: + description: 'Internal: specify github-workflows (this repo) revision to use when checking out scripts.' + type: string + required: false + default: v2 # Note: update when publishing a new version + outputs: + outcome: + description: Whether the Danger run finished successfully. Possible values are success, failure, cancelled, or skipped. + value: ${{ jobs.danger.outputs.outcome }} + +jobs: + danger: + runs-on: ubuntu-latest + outputs: + outcome: ${{ steps.danger.outcome }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Download dangerfile.js + run: wget https://raw.githubusercontent.com/getsentry/github-workflows/${{ inputs._workflow_version }}/danger/dangerfile.js -P ${{ runner.temp }} + + # Using a pre-built docker image in GitHub container registry instaed of NPM to reduce possible attack vectors. + - name: Run DangerJS + id: danger + run: | + docker run \ + --volume ${{ github.workspace }}:/github/workspace \ + --volume ${{ runner.temp }}:${{ runner.temp }} \ + --workdir /github/workspace \ + --user $UID \ + -e "INPUT_ARGS" -e "GITHUB_JOB" -e "GITHUB_REF" -e "GITHUB_SHA" -e "GITHUB_REPOSITORY" -e "GITHUB_REPOSITORY_OWNER" -e "GITHUB_RUN_ID" -e "GITHUB_RUN_NUMBER" -e "GITHUB_RETENTION_DAYS" -e "GITHUB_RUN_ATTEMPT" -e "GITHUB_ACTOR" -e "GITHUB_TRIGGERING_ACTOR" -e "GITHUB_WORKFLOW" -e "GITHUB_HEAD_REF" -e "GITHUB_BASE_REF" -e "GITHUB_EVENT_NAME" -e "GITHUB_SERVER_URL" -e "GITHUB_API_URL" -e "GITHUB_GRAPHQL_URL" -e "GITHUB_REF_NAME" -e "GITHUB_REF_PROTECTED" -e "GITHUB_REF_TYPE" -e "GITHUB_WORKSPACE" -e "GITHUB_ACTION" -e "GITHUB_EVENT_PATH" -e "GITHUB_ACTION_REPOSITORY" -e "GITHUB_ACTION_REF" -e "GITHUB_PATH" -e "GITHUB_ENV" -e "GITHUB_STEP_SUMMARY" -e "RUNNER_OS" -e "RUNNER_ARCH" -e "RUNNER_NAME" -e "RUNNER_TOOL_CACHE" -e "RUNNER_TEMP" -e "RUNNER_WORKSPACE" -e "ACTIONS_RUNTIME_URL" -e "ACTIONS_RUNTIME_TOKEN" -e "ACTIONS_CACHE_URL" -e GITHUB_ACTIONS=true -e CI=true \ + -e GITHUB_TOKEN="${{ github.token }}" \ + -e DANGER_DISABLE_TRANSPILATION="true" \ + ghcr.io/danger/danger-js:11.1.2 \ + --failOnErrors --dangerfile ${{ runner.temp }}/dangerfile.js diff --git a/.github/workflows/updater-scripts-tests.yml b/.github/workflows/updater-scripts-tests.yml index 70d0737..854751a 100644 --- a/.github/workflows/updater-scripts-tests.yml +++ b/.github/workflows/updater-scripts-tests.yml @@ -1,5 +1,5 @@ # This isn't a reusable workflow but an actual CI action for this repo itself - to test scripts. -name: Script Tests +name: Updater Script Tests on: push: diff --git a/.github/workflows/updater-workflow-tests.yml b/.github/workflows/updater-workflow-tests.yml index a416b0f..675a6a1 100644 --- a/.github/workflows/updater-workflow-tests.yml +++ b/.github/workflows/updater-workflow-tests.yml @@ -1,5 +1,5 @@ # This isn't a reusable workflow but an actual CI action for this repo itself - to test the workflows. -name: Workflow Tests +name: Updater Workflow Tests on: push: diff --git a/.github/workflows/versioning.yml b/.github/workflows/versioning.yml index ba8f779..41f86d4 100644 --- a/.github/workflows/versioning.yml +++ b/.github/workflows/versioning.yml @@ -1,4 +1,4 @@ -name: Keep the major version tags up-to-date +name: Sync tags with releases on: release: diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c025b5..82ba5f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased +## 2.1.0 + +### Features + +- New reusable workflow, `danger.yml`, to check Pull Requests with predefined rules ([#34](https://github.com/getsentry/github-workflows/pull/34)) + ## 2.0.0 ### Changes diff --git a/README.md b/README.md index 55e0a17..591a4c5 100644 --- a/README.md +++ b/README.md @@ -77,4 +77,20 @@ jobs: * `api-token`: GH authentication token to create PRs with & push. If you provide the usual `${{ github.token }}`, no followup CI will run on the created PR. - If you want CI to run on the PRs created by the Updater, you need to provide custom user-specific auth token. \ No newline at end of file + If you want CI to run on the PRs created by the Updater, you need to provide custom user-specific auth token. + +## Danger + +Runs DangerJS on Pull Reqeusts in your repository. This uses custom set of rules defined in [this dangerfile](danger/dangerfile.js). + +```yaml +name: Danger + +on: + pull_request: + types: [opened, synchronize, reopened, edited, ready_for_review] + +jobs: + danger: + uses: getsentry/github-workflows/.github/workflows/danger.yml@v2 +``` diff --git a/danger/dangerfile.js b/danger/dangerfile.js new file mode 100644 index 0000000..9e01a69 --- /dev/null +++ b/danger/dangerfile.js @@ -0,0 +1,91 @@ +// e.g. "feat" if PR title is "Feat : add more useful stuff" +// or "ci" if PR branch is "ci/update-danger" +function getPrFlavor() { + if (danger.github && danger.github.pr) { + var separator = undefined; + if (danger.github.pr.title) { + const parts = danger.github.pr.title.split(":"); + if (parts.length > 1) { + return parts[0].toLowerCase().trim(); + } + } + if (danger.github.pr.head && danger.github.pr.head.ref) { + const parts = danger.github.pr.head.ref.split("/"); + if (parts.length > 1) { + return parts[0].toLowerCase(); + } + } + } + return ""; +} + +async function checkDocs() { + if (getPrFlavor().startsWith("feat")) { + message( + 'Do not forget to update Sentry-docs with your feature once the pull request gets approved.' + ); + } +} + +async function checkChangelog() { + const changelogFile = "CHANGELOG.md"; + + // Check if skipped + if (danger.github && danger.github.pr) { + if ( + ["ci", "chore(deps)"].includes(getPrFlavor()) || + (danger.github.pr.body + "").includes("#skip-changelog") + ) { + return; + } + } + + // Check if current PR has an entry in changelog + const changelogContents = await danger.github.utils.fileContents( + changelogFile + ); + + const hasChangelogEntry = RegExp(`#${danger.github.pr.number}\\b`).test( + changelogContents + ); + + if (hasChangelogEntry) { + return; + } + + // Report missing changelog entry + fail( + "Please consider adding a changelog entry for the next release.", + changelogFile + ); + + const prTitleFormatted = danger.github.pr.title + .split(": ") + .slice(-1)[0] + .trim() + .replace(/\.+$/, ""); + + markdown( + ` +### Instructions and example for changelog + +Please add an entry to \`CHANGELOG.md\` to the "Unreleased" section. Make sure the entry includes this PR's number. + +Example: + +\`\`\`markdown +## Unreleased + +- ${prTitleFormatted} ([#${danger.github.pr.number}](${danger.github.pr.html_url})) +\`\`\` + +If none of the above apply, you can opt out of this check by adding \`#skip-changelog\` to the PR description.`.trim() + ); +} + +async function checkAll() { + await checkDocs(); + await checkChangelog(); +} + +schedule(checkAll);