From b7fe0f9fb75749b90c559c7f7d0587f6ce96d75f Mon Sep 17 00:00:00 2001 From: Adam Bovill <a@turo.com> Date: Wed, 13 Sep 2023 22:08:03 +0000 Subject: [PATCH] fix(release-notes-preview): add breaking changes doc check This adds a new check that enforces that a breaking changes document has been created. --- .github/workflows/ci.yaml | 2 +- README.md | 6 +- lint-release-notes/README.md | 57 +++++++++++ lint-release-notes/action.yaml | 165 ++++++++++++++++++++++++++++++ release-notes-preview/README.md | 50 +-------- release-notes-preview/action.yaml | 94 ++++++++++++++++- 6 files changed, 319 insertions(+), 55 deletions(-) create mode 100644 lint-release-notes/README.md create mode 100644 lint-release-notes/action.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7faf124..3aa76cc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: ./release-notes-preview + - uses: ./lint-release-notes with: github-token: ${{ secrets.GITHUB_TOKEN }} lint: diff --git a/README.md b/README.md index 6c45ab1..4143a00 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,13 @@ GitHub Actions for handling releases. ## Actions -### action: [`release-notes-preview`](./release-notes-preview) +### action: [`release-notes-preview`](./lint-release-notes) Automatically generate release notes using semantic-release and post them as a comment in a pull request with the changes that would be included in the next version of the codebase if the pull request is merged. -See usage [here](./release-notes-preview/README.md#usage). +See usage [here](lint-release-notes/README.md#usage). -Documentation is found [here](./release-notes-preview/README.md). +Documentation is found [here](lint-release-notes/README.md). ## Get Help diff --git a/lint-release-notes/README.md b/lint-release-notes/README.md new file mode 100644 index 0000000..8b7175e --- /dev/null +++ b/lint-release-notes/README.md @@ -0,0 +1,57 @@ +# GitHub Action Lint Release Notes + +## Description + +Github action that lints release notes. It generates release notes using semantic-release and posts them as a comment in +a pull request with the changes that would be included in the next version of the codebase if the pull request is +merged. It also will fail if there are breaking changes and no `v<major-version>.md` doc has been created. + +## Configuration + +### Step1: Set any [Semantic Release Configuration](https://github.com/semantic-release/semantic-release/blob/master/docs/usage/configuration.md#configuration) in your repository. + +### Step2: [Add Secrets](https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets) in your repository for the [Semantic Release Authentication](https://github.com/semantic-release/semantic-release/blob/master/docs/usage/ci-configuration.md#authentication) Environment Variables. + +### Step3: Add a [Workflow File](https://help.github.com/en/articles/workflow-syntax-for-github-actions) to your repository to create custom automated processes. + +## Usage + +```yaml +name: Release notes preview + +on: + # It's import that this runs on the push event, as semantic release will not run on pull_request events + push: + branches-ignore: + - main + +jobs: + lint-release-notes: + name: Lint release notes + steps: + - uses: open-turo/actions-release/lint-release-notes@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} +``` + +## Inputs + +| parameter | description | required | default | +| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ----------------------------------------- | +| checkout-repo | Perform checkout as first step of action | `false` | true | +| enforce-breaking-changes-docs | Ensure that an appropriate `v<major-version>.md` doc has been created if there are breaking changes in the PR. Fail if required and missing. | `false` | `true` | +| extra-plugins | Extra plugins for pre-install. You can also specify specifying version range for the extra plugins if you prefer. Defaults to install @open-turo/semantic-release-config. | `false` | @open-turo/semantic-release-config@^1.4.0 | +| github-token | GitHub token that can checkout the repository as well as create tags/releases against it. e.g. 'secrets.GITHUB_TOKEN' | `true` | | +| semantic-version | Specify what version of semantic release to use | `false` | | + +## Outputs + +N/A + +## Runs + +This action is an `composite` action. + +## Notes + +- By default, this action will perform actions/checkout as its first step. diff --git a/lint-release-notes/action.yaml b/lint-release-notes/action.yaml new file mode 100644 index 0000000..467a278 --- /dev/null +++ b/lint-release-notes/action.yaml @@ -0,0 +1,165 @@ +name: GitHub Action Release Notes Preview +description: GitHub Action that publishes a new release. +inputs: + checkout-repo: + required: false + description: Perform checkout as first step of action + default: "true" + github-token: + required: true + description: GitHub token that can checkout the repository as well as create tags/releases against it. e.g. 'secrets.GITHUB_TOKEN' + default: ${{ github.token }} + enforce-breaking-changes-docs: + required: false + description: Ensure that an appropriate `v<major-version>.md` doc has been created if there are breaking changes in the PR. + default: "true" + extra-plugins: + required: false + description: Extra plugins for pre-install. You can also specify specifying version range for the extra plugins if you prefer. Defaults to install @open-turo/semantic-release-config. + default: | + @open-turo/semantic-release-config + semantic-version: + required: false + description: Specify what version of semantic release to use +runs: + using: composite + steps: + - uses: actions/checkout@v3 + if: inputs.checkout-repo + with: + fetch-depth: 0 + - name: Setup tools + uses: open-turo/action-setup-tools@v1 + with: + node: 18.16.1 + - uses: jwalton/gh-find-current-pr@v1 + id: find-pull-request + with: + state: open + - name: Generate release notes + id: release-notes-preview + uses: open-turo/actions-release/semantic-release@v2 + env: + GITHUB_TOKEN: ${{ inputs.github-token }} + with: + branches: ${{ github.ref_name }} + dry-run: true + extra-plugins: ${{ inputs.extra-plugins }} + semantic-version: ${{ inputs.semantic-version }} + + # Add release notes preview to PR + - name: Check for release notes comment + uses: peter-evans/find-comment@v2 + id: fc-release-notes + if: steps.find-pull-request.outputs.number != '' + with: + issue-number: ${{ steps.find-pull-request.outputs.number }} + comment-author: "github-actions[bot]" + body-includes: "<!-- release notes preview comment -->" + - name: Delete previous release note + if: steps.fc-release-notes.outputs.comment-id != '' + uses: jungwinter/comment@v1 + with: + type: delete + comment_id: ${{ steps.fc-release-notes.outputs.comment-id }} + token: ${{ inputs.github-token }} + - name: Comment release notes preview + uses: peter-evans/create-or-update-comment@v1 + if: steps.release-notes-preview.outputs.new-release-notes != '' && steps.find-pull-request.outputs.number != '' + with: + issue-number: ${{ steps.find-pull-request.outputs.number }} + body: | + ## Release notes preview + Below is a preview of the release notes if your PR gets merged. + + --- + <!-- release notes preview comment --> + ${{ steps.release-notes-preview.outputs.new-release-notes }} + - name: Create no release created + uses: peter-evans/create-or-update-comment@v1 + if: steps.release-notes-preview.outputs.new-release-notes == '' && steps.find-pull-request.outputs.number != '' + with: + issue-number: ${{ steps.find-pull-request.outputs.number }} + body: | + <!-- release notes preview comment --> + ## Release notes preview + **_No_ new release will be created.** + + If you are expecting a release, you will need to either fix a bug or add a feature. + Chores, CI, docs, refactoring, style and other changes will not trigger a release. + + # Ensure that a breaking changes doc has been created + - name: Check for breaking changes comment + uses: peter-evans/find-comment@v2 + id: fc-breaking-changes + if: steps.find-pull-request.outputs.number != '' + with: + issue-number: ${{ steps.find-pull-request.outputs.number }} + comment-author: "github-actions[bot]" + body-includes: "<!-- breaking changes comment -->" + - name: Delete previous breaking changes comment + if: steps.fc-breaking-changes.outputs.comment-id != '' + uses: jungwinter/comment@v1 + with: + type: delete + comment_id: ${{ steps.fc-breaking-changes.outputs.comment-id }} + token: ${{ inputs.github-token }} + - name: "Check File Existence" + id: breaking-changes-file + shell: bash + run: | + set -e + breaking_changes_file_missing=false + if [ "${{ steps.release-notes-preview.outputs.new-release-published }}" = "true" ]; then + echo "new release published" + if [ "${{ steps.release-notes-preview.outputs.new-release-type }}" = "major" ]; then + echo "braking change" + file_path="docs/breaking-changes/v${{ steps.release-notes-preview.outputs.new-release-major-version }}.md" + # Check if the file exists + if [ -e "$file_path" ]; then + echo "breaking change doc $file_path exists." + else + echo "breaking change doc $file_path does not exist." + breaking_changes_file_missing=true + fi + fi + fi + echo "required=${breaking_changes_file_missing}" >> $GITHUB_OUTPUT + - name: Comment missing breaking changes doc + uses: peter-evans/create-or-update-comment@v1 + if: steps.breaking-changes-file.outputs.required && inputs.enforce-breaking-changes-docs && steps.find-pull-request.outputs.number != '' + with: + issue-number: ${{ steps.find-pull-request.outputs.number }} + body: | + ## Error: missing breaking changes documentation + This pull request contains breaking changes, but no documentation has been added to `docs/breaking-changes/v${{ steps.release-notes-preview.outputs.new-release-major-version }}.md`. + + <details> + <summary>Instructions for creating breaking changes document:</summary> + + ```shell + mkdir -p docs/breaking-changes + cat <<EOF > docs/breaking-changes/v${{ steps.release-notes-preview.outputs.new-release-major-version }}.md + # Breaking changes in v${{ steps.release-notes-preview.outputs.new-release-major-version }} + + [//]: # "Brief description of current major version release scope" + + ## Description of changes + + [//]: # "Elaborate and add context to help the developer understand the changes." + + ## Upgrade instructions + + [//]: # "Required and suggested prerequisites, example code, etc." + + EOF + ``` + </details> + + --- + <!-- breaking changes comment --> + - name: Fail if we are checking for the breaking changes doc and it is missing + if: steps.breaking-changes-file.outputs.required && inputs.enforce-breaking-changes-docs + shell: bash + run: | + echo "::error::Breaking changes document is missing. Expected: ``docs/breaking-changes/v${{ steps.release-notes-preview.outputs.new-release-major-version }}.md``" && exit 1 diff --git a/release-notes-preview/README.md b/release-notes-preview/README.md index cab9a1a..208f083 100644 --- a/release-notes-preview/README.md +++ b/release-notes-preview/README.md @@ -1,51 +1,5 @@ -# GitHub Action Release Notes Preview +# DEPRECATED!!!! GitHub Action Release Notes Preview ## Description -Github action that generates release notes using semantic-release and posts them as a comment in a pull request with the changes that would be included in the next version of the codebase if the pull request is merged. - -## Configuration - -### Step1: Set any [Semantic Release Configuration](https://github.com/semantic-release/semantic-release/blob/master/docs/usage/configuration.md#configuration) in your repository. - -### Step2: [Add Secrets](https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets) in your repository for the [Semantic Release Authentication](https://github.com/semantic-release/semantic-release/blob/master/docs/usage/ci-configuration.md#authentication) Environment Variables. - -### Step3: Add a [Workflow File](https://help.github.com/en/articles/workflow-syntax-for-github-actions) to your repository to create custom automated processes. - -## Usage - -```yaml -name: Release notes preview - -on: - # It's import that this runs on the push event, as semantic release will not run on pull_request events - push: - -jobs: - release-notes: - name: Release notes preview - steps: - - uses: open-turo/actions-release/release-notes-preview@v1 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} -``` - -## Inputs - -| parameter | description | required | default | -| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ----------------------------------------- | -| extra-plugins | Extra plugins for pre-install. You can also specify specifying version range for the extra plugins if you prefer. Defaults to install @open-turo/semantic-release-config. | `false` | @open-turo/semantic-release-config@^1.4.0 | -| github-token | GitHub token that can checkout the repository as well as create tags/releases against it. e.g. 'secrets.GITHUB_TOKEN' | `true` | | -| semantic-version | Specify what version of semantic release to use | `false` | | - -## Outputs - -N/A - -## Runs - -This action is an `composite` action. - -## Notes - -- By default, this action will perform actions/checkout as its first step. +This has been deprecated and will be removed in the future. Please use `open-turo/actions-release/lint-release-notes@v1`. diff --git a/release-notes-preview/action.yaml b/release-notes-preview/action.yaml index d80b929..73bd2a8 100644 --- a/release-notes-preview/action.yaml +++ b/release-notes-preview/action.yaml @@ -5,6 +5,10 @@ inputs: required: true description: GitHub token that can checkout the repository as well as create tags/releases against it. e.g. 'secrets.GITHUB_TOKEN' default: ${{ github.token }} + enforce-breaking-changes-docs: + required: false + description: Ensure that an appropriate `v<major-version>.md` doc has been created if there are breaking changes in the PR. Fail if required and missing. + default: "true" extra-plugins: required: false description: Extra plugins for pre-install. You can also specify specifying version range for the extra plugins if you prefer. Defaults to install @open-turo/semantic-release-config. @@ -16,6 +20,9 @@ inputs: runs: using: composite steps: + - shell: bash + run: | + echo "::error::DEPRECATION: open-turo/actions-release/release-notes-preview@v1 has been deprecated. Please use open-turo/actions-release/lint-release-notes@v1." - uses: actions/checkout@v3 with: fetch-depth: 0 @@ -37,20 +44,22 @@ runs: dry-run: true extra-plugins: ${{ inputs.extra-plugins }} semantic-version: ${{ inputs.semantic-version }} + + # Add release notes preview to PR - name: Check for release notes comment uses: peter-evans/find-comment@v2 - id: fc + id: fc-release-notes if: steps.find-pull-request.outputs.number != '' with: issue-number: ${{ steps.find-pull-request.outputs.number }} comment-author: "github-actions[bot]" body-includes: "<!-- release notes preview comment -->" - name: Delete previous release note - if: steps.fc.outputs.comment-id != '' + if: steps.fc-release-notes.outputs.comment-id != '' uses: jungwinter/comment@v1 with: type: delete - comment_id: ${{ steps.fc.outputs.comment-id }} + comment_id: ${{ steps.fc-release-notes.outputs.comment-id }} token: ${{ inputs.github-token }} - name: Comment release notes preview uses: peter-evans/create-or-update-comment@v1 @@ -58,6 +67,9 @@ runs: with: issue-number: ${{ steps.find-pull-request.outputs.number }} body: | + # DEPRECATION: + This action has been deprecated. Please update to use `open-turo/actions-release/lint-release-notes@v1`. + ## Release notes preview Below is a preview of the release notes if your PR gets merged. @@ -76,3 +88,79 @@ runs: If you are expecting a release, you will need to either fix a bug or add a feature. Chores, CI, docs, refactoring, style and other changes will not trigger a release. + + # Ensure that a breaking changes doc has been created + - name: Check for breaking changes comment + uses: peter-evans/find-comment@v2 + id: fc-breaking-changes + if: steps.find-pull-request.outputs.number != '' + with: + issue-number: ${{ steps.find-pull-request.outputs.number }} + comment-author: "github-actions[bot]" + body-includes: "<!-- breaking changes comment -->" + - name: Delete previous breaking changes comment + if: steps.fc-breaking-changes.outputs.comment-id != '' + uses: jungwinter/comment@v1 + with: + type: delete + comment_id: ${{ steps.fc-breaking-changes.outputs.comment-id }} + token: ${{ inputs.github-token }} + - name: "Check File Existence" + id: breaking-changes-file + shell: bash + run: | + set -e + breaking_changes_file_missing=false + if [ "${{ steps.release-notes-preview.outputs.new-release-published }}" = "true" ]; then + echo "new release published" + if [ "${{ steps.release-notes-preview.outputs.new-release-type }}" = "major" ]; then + echo "braking change" + file_path="docs/breaking-changes/v${{ steps.release-notes-preview.outputs.new-release-major-version }}.md" + # Check if the file exists + if [ -e "$file_path" ]; then + echo "breaking change doc $file_path exists." + else + echo "breaking change doc $file_path does not exist." + breaking_changes_file_missing=true + fi + fi + fi + echo "required=${breaking_changes_file_missing}" >> $GITHUB_OUTPUT + - name: Comment missing breaking changes doc + uses: peter-evans/create-or-update-comment@v1 + if: steps.breaking-changes-file.outputs.required && inputs.enforce-breaking-changes-docs && steps.find-pull-request.outputs.number != '' + with: + issue-number: ${{ steps.find-pull-request.outputs.number }} + body: | + ## Error: missing breaking changes documentation + This pull request contains breaking changes, but no documentation has been added to `docs/breaking-changes/v${{ steps.release-notes-preview.outputs.new-release-major-version }}.md`. + + <details> + <summary>Instructions for creating breaking changes document:</summary> + + ```shell + mkdir -p docs/breaking-changes + cat <<EOF > docs/breaking-changes/v${{ steps.release-notes-preview.outputs.new-release-major-version }}.md + # Breaking changes in v${{ steps.release-notes-preview.outputs.new-release-major-version }} + + [//]: # "Brief description of current major version release scope" + + ## Description of changes + + [//]: # "Elaborate and add context to help the developer understand the changes." + + ## Upgrade instructions + + [//]: # "Required and suggested prerequisites, example code, etc." + + EOF + ``` + </details> + + --- + <!-- breaking changes comment --> + - name: Fail if we are checking for the breaking changes doc and it is missing + if: steps.breaking-changes-file.outputs.required && inputs.enforce-breaking-changes-docs + shell: bash + run: | + echo "::error::Breaking changes document is missing. Expected: ``docs/breaking-changes/v${{ steps.release-notes-preview.outputs.new-release-major-version }}.md``" && exit 1