From 99a2bfc85b98698a2b014e69d044bb79ac9edc65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Borgna?= <121866228+aborgna-q@users.noreply.github.com> Date: Fri, 31 May 2024 14:21:47 +0100 Subject: [PATCH] ci: Update CI workflows (#131) Brings in some updated workflows from [CQCL/hugr](http://github.com/CQCL/hugr). - Adds new issues to the hugrverse project. - Checks the conventional commit format in the PR titles, and lets @hugrbot post help messages. - Automate publishing to crates.io with release-plz - Simplifies the changelog format configuration (using the one from CQCL/tket2). --- .github/workflows/issue-to-project.yml | 17 +++++ .github/workflows/pr-title.yml | 99 ++++++++++++++++++++++++-- .github/workflows/release-plz.yml | 8 +-- cliff.toml | 73 ------------------- release-plz.toml | 18 ++++- 5 files changed, 133 insertions(+), 82 deletions(-) create mode 100644 .github/workflows/issue-to-project.yml delete mode 100644 cliff.toml diff --git a/.github/workflows/issue-to-project.yml b/.github/workflows/issue-to-project.yml new file mode 100644 index 0000000..b43919b --- /dev/null +++ b/.github/workflows/issue-to-project.yml @@ -0,0 +1,17 @@ +name: Add issues to project + +on: + issues: + types: + - opened + +jobs: + add-to-project: + name: Add issue to project + runs-on: ubuntu-latest + steps: + - uses: actions/add-to-project@v1.0.1 + with: + project-url: https://github.com/orgs/CQCL-DEV/projects/10 + github-token: ${{ secrets.HUGRBOT_PAT }} + id: add-project diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index 0a74226..d33312f 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -3,7 +3,7 @@ name: Check Conventional Commits format on: pull_request_target: branches: - - main + - main types: - opened - edited @@ -14,7 +14,7 @@ on: types: [checks_requested] permissions: - pull-requests: read + pull-requests: write jobs: main: @@ -23,8 +23,15 @@ jobs: # The action does not support running on merge_group events, # but if the check succeeds in the PR there is no need to check it again. if: github.event_name == 'pull_request_target' + outputs: + # Whether the PR title indicates a breaking change. + breaking: ${{ steps.breaking.outputs.breaking }} + # Whether the PR body contains a "BREAKING CHANGE:" footer describing the breaking change. + has_breaking_footer: ${{ steps.breaking.outputs.has_breaking_footer }} steps: - - uses: amannn/action-semantic-pull-request@v5 + - name: Validate the PR title format + uses: amannn/action-semantic-pull-request@v5 + id: lint_pr_title env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -69,4 +76,88 @@ jobs: # labels change, you might want to use the `labeled` and `unlabeled` # event triggers in your workflow. ignoreLabels: | - ignore-semantic-pull-request \ No newline at end of file + ignore-semantic-pull-request + + # `action-semantic-pull-request` does not parse the title, so it cannot + # detect if it is marked as a breaking change. + # + # Since at this point we know the PR title is a valid conventional commit, + # we can use a simple regex that looks for a '!:' sequence. It could be + # more complex, but we don't care about false positives. + - name: Check for breaking change flag + id: breaking + run: | + if [[ "${PR_TITLE}" =~ ^.*\!:.*$ ]]; then + echo "breaking=true" >> $GITHUB_OUTPUT + else + echo "breaking=false" >> $GITHUB_OUTPUT + fi + + # Check if the PR comment has a "BREAKING CHANGE:" footer describing + # the breaking change. + if [[ "${PR_BODY}" != *"BREAKING CHANGE:"* ]]; then + echo "has_breaking_footer=false" >> $GITHUB_OUTPUT + else + echo "has_breaking_footer=true" >> $GITHUB_OUTPUT + fi + env: + PR_TITLE: ${{ github.event.pull_request.title }} + PR_BODY: ${{ github.event.pull_request.body }} + + # Post a help comment if the PR title indicates a breaking change but does + # not contain a "BREAKING CHANGE:" footer. + - name: Require "BREAKING CHANGE:" footer for breaking changes + id: breaking-comment + if: ${{ steps.breaking.outputs.breaking == 'true' && steps.breaking.outputs.has_breaking_footer == 'false' }} + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: pr-title-lint-error + message: | + Hey there and thank you for opening this pull request! 👋🏼 + + It looks like your proposed title indicates a breaking change. If that's the case, + please make sure to include a "BREAKING CHANGE:" footer in the body of the pull request + describing the breaking change and any migration instructions. + GITHUB_TOKEN: ${{ secrets.HUGRBOT_PAT }} + - name: Fail if the footer is required but missing + if: ${{ steps.breaking.outputs.breaking == 'true' && steps.breaking.outputs.has_breaking_footer == 'false' }} + run: exit 1 + + - name: Post a comment if the PR badly formatted + uses: marocchino/sticky-pull-request-comment@v2 + # When the previous steps fails, the workflow would stop. By adding this + # condition you can continue the execution with the populated error message. + if: always() && (steps.lint_pr_title.outputs.error_message != null) + with: + header: pr-title-lint-error + message: | + Hey there and thank you for opening this pull request! 👋🏼 + + We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) + and it looks like your proposed title needs to be adjusted. + + Your title should look like this. The scope field is optional. + ``` + (): + ``` + + If the PR includes a breaking change, mark it with an exclamation mark: + ``` + !: + ``` + and include a "BREAKING CHANGE:" footer in the body of the pull request. + + Details: + ``` + ${{ steps.lint_pr_title.outputs.error_message }} + ``` + GITHUB_TOKEN: ${{ secrets.HUGRBOT_PAT }} + + # Delete previous comments when the issues have been resolved + # This step doesn't run if any of the previous checks fails. + - name: Delete previous comments + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: pr-title-lint-error + delete: true + GITHUB_TOKEN: ${{ secrets.HUGRBOT_PAT }} diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml index 65ea1f9..0552da8 100644 --- a/.github/workflows/release-plz.yml +++ b/.github/workflows/release-plz.yml @@ -1,4 +1,5 @@ -name: Release-plz +# Automatic changelog, version bumping, and semver-checks with release-plz for rust projects +name: Release-plz 🦀 permissions: pull-requests: write @@ -22,7 +23,6 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: Run release-plz uses: MarcoIeni/release-plz-action@v0.5 - with: - command: release-pr env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.HUGRBOT_PAT }} + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/cliff.toml b/cliff.toml deleted file mode 100644 index 8c3dba1..0000000 --- a/cliff.toml +++ /dev/null @@ -1,73 +0,0 @@ -# git-cliff ~ default configuration file -# https://git-cliff.org/docs/configuration -# -# Lines starting with "#" are comments. -# Configuration options are organized into tables and keys. -# See documentation for more information on available options. - -[changelog] -# changelog header -header = """ -# Changelog\n -""" -# template for the changelog body -# https://tera.netlify.app/docs -body = """ -{% if version %}\ - ## {{ version }} ({{ timestamp | date(format="%Y-%m-%d") }}) -{% else %}\ - ## Unreleased (XXXX-XX-XX) -{% endif %}\ -{% for group, commits in commits | group_by(attribute="group") %} - ### {{ group | upper_first }} - {% for commit in commits %} - - {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }}\ - {% endfor %} -{% endfor %}\n -""" -# remove the leading and trailing whitespace from the template -trim = true -# changelog footer -footer = "" - -[git] -# parse the commits based on https://www.conventionalcommits.org -conventional_commits = true -# filter out the commits that are not conventional -filter_unconventional = true -# process each line of a commit as an individual commit -split_commits = false -# regex for preprocessing the commit messages -commit_preprocessors = [ - { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/CQCL/portgraph/issues/${2}))"}, # replace issue numbers -] -# regex for parsing and grouping commits -commit_parsers = [ - { message = "^feat", group = "Features" }, - { message = "^fix", group = "Bug Fixes" }, - { message = "^docs", group = "Documentation" }, - { message = "^style", group = "Styling" }, - { message = "^refactor", group = "Refactor" }, - { message = "^perf", group = "Performance" }, - { message = "^test", group = "Testing" }, - { message = "^chore\\(release\\): prepare for", skip = true }, - { message = "^chore", group = "Miscellaneous Tasks", skip = true }, - { message = "^revert", group = "Reverted changes", skip = true }, - { message = "^ci", group = "CI", skip = true }, -] -# protect breaking changes from being skipped due to matching a skipping commit_parser -protect_breaking_commits = true -# filter out the commits that are not matched by commit parsers -filter_commits = false -# glob pattern for matching git tags -tag_pattern = "v[0-9.]*" -# regex for skipping tags -skip_tags = "v0.1.0-beta.1" -# regex for ignoring tags -ignore_tags = "" -# sort the tags topologically -topo_order = false -# sort the commits inside sections by oldest-first/newest-first -sort_commits = "oldest" -# limit the number of commits included in the changelog. -# limit_commits = 42 diff --git a/release-plz.toml b/release-plz.toml index 0d7dd7e..d9b9e1c 100644 --- a/release-plz.toml +++ b/release-plz.toml @@ -1,2 +1,18 @@ [workspace] -changelog_config = "cliff.toml" # use a custom git-cliff configuration +pr_draft = true + +[changelog] +sort_commits = "oldest" + +commit_parsers = [ + { message = "^feat", group = "New Features" }, + { message = "^fix", group = "Bug Fixes" }, + { message = "^docs", group = "Documentation" }, + { message = "^style", group = "Styling" }, + { message = "^refactor", group = "Refactor" }, + { message = "^perf", group = "Performance" }, + { message = "^test", group = "Testing" }, + { message = "^chore", group = "Miscellaneous Tasks", skip = true }, + { message = "^revert", group = "Reverted changes", skip = true }, + { message = "^ci", group = "CI", skip = true }, +]