From c7ef1849da1ab69a76a5ada90f68aeff1e001fc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Borgna?= <121866228+aborgna-q@users.noreply.github.com> Date: Thu, 30 May 2024 11:00:57 +0100 Subject: [PATCH] ci: Update CI workflows to use @hugrbot (#232) - Drops unused Jira issue workflow - Updates the pr-issue action, so @hugrbot posts comments to help you fixing the errors. - Update `python-wheels.yml` so it gets triggered on new releases instead of from someone pushing a `vX.X.X` tag accidentally. It can also be triggered manually as a `workflow_dispatch` on a tag. - Update the release-please action to use @hugrbot's token, so it can now trigger the wheels action. These are all changes imported from `hugr`. --- .github/workflows/issue.yml | 69 -------------------- .github/workflows/pr-title.yml | 95 +++++++++++++++++++++++++++- .github/workflows/python-wheels.yml | 33 ++++++++-- .github/workflows/release-please.yml | 14 ++-- 4 files changed, 128 insertions(+), 83 deletions(-) delete mode 100644 .github/workflows/issue.yml diff --git a/.github/workflows/issue.yml b/.github/workflows/issue.yml deleted file mode 100644 index 002c2fd2..00000000 --- a/.github/workflows/issue.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: New issue - -on: - issues: - types: [opened] - -jobs: - jira_task: - name: Create Jira issue - runs-on: ubuntu-22.04 - steps: - - name: Login - uses: atlassian/gajira-login@v3.0.1 - env: - JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} - JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} - JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} - - name: Parse the priority label into a Jira priority - id: set_priority_var - env: - LABELS: ${{ join(github.event.issue.labels.*.name, ' ') }} - run: | - MY_RESULT="" - for label in $LABELS - do - case $label in - P-low) - MY_RESULT=Low - break;; - P-medium) - MY_RESULT=Medium - break;; - P-high) - MY_RESULT=High - break;; - P-critical) - MY_RESULT=Highest - break;; - esac - done - if [ ! -z $MY_RESULT ] - then - MY_RESULT=", \"priority\": { \"name\": \"$MY_RESULT\" }" - fi - echo "JIRA_PRIORITY_FIELD=$MY_RESULT" >> $GITHUB_OUTPUT - - - name: Create Bug - uses: atlassian/gajira-create@v3.0.1 - if: ${{ contains(github.event.issue.labels.*.name, 'bug') }} - env: - JIRA_PRIORITY_FIELD: ${{ steps.set_priority_var.outputs.JIRA_PRIORITY_FIELD }} - with: - project: TKET - issuetype: Bug - summary: ยซ [guppy] ${{ github.event.issue.title }}ยป - description: ${{ github.event.issue.html_url }} - fields: '{ "labels": ["guppy"] ${{ env.JIRA_PRIORITY_FIELD }} }' - - - name: Create Task - uses: atlassian/gajira-create@v3.0.1 - if: ${{ ! contains(github.event.issue.labels.*.name, 'bug') }} - env: - JIRA_PRIORITY_FIELD: ${{ steps.set_priority_var.outputs.JIRA_PRIORITY_FIELD }} - with: - project: TKET - issuetype: Task - summary: ยซ [guppy] ${{ github.event.issue.title }}ยป - description: ${{ github.event.issue.html_url }} - fields: '{ "labels": ["guppy"] ${{ env.JIRA_PRIORITY_FIELD }} }' diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index 33cb9674..d33312f9 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -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: @@ -70,3 +77,87 @@ jobs: # event triggers in your workflow. ignoreLabels: | 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/python-wheels.yml b/.github/workflows/python-wheels.yml index 678a1517..c1f36c16 100644 --- a/.github/workflows/python-wheels.yml +++ b/.github/workflows/python-wheels.yml @@ -1,12 +1,22 @@ name: Build and publish python wheels +# Builds and publishes the wheels on pypi. +# +# When running on a push-to-main event, or as a workflow dispatch on a branch, +# this workflow will do a dry-run publish to test-pypi. +# +# When running on a release event or as a workflow dispatch for a tag, +# and if the tag matches `hugr-py-v*`, +# this workflow will publish the wheels to pypi. +# If the version is already published, pypi just ignores it. on: workflow_dispatch: push: branches: - main - tags: - - 'v**' + release: + types: + - published jobs: build-publish: @@ -26,7 +36,7 @@ jobs: cache: "poetry" - name: Build sdist and wheels - run: poetry build + run: poetry build -o dist - name: Upload the built packages as artifacts uses: actions/upload-artifact@v4 @@ -37,14 +47,23 @@ jobs: dist/*.whl - name: Publish to test instance of PyPI (dry-run) - if: ${{ github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref_type == 'branch' ) }} + if: | + ${{ github.event_name == 'push' && github.ref_type == 'branch' }} || + ${{ github.event_name == 'workflow_dispatch' && github.ref_type == 'branch'}} run: | + echo "Doing a dry-run publish to test-pypi..." + echo "Based on the following workflow variables, this is not a hugr-py version tag push:" + echo " - event_name: ${{ github.event_name }}" + echo " - ref_type: ${{ github.ref_type }}" + echo " - ref: ${{ github.ref }}" poetry config repositories.test-pypi https://test.pypi.org/legacy/ poetry config pypi-token.test-pypi ${{ secrets.PYPI_TEST_PUBLISH }} - poetry publish -r test-pypi --skip-existing --dry-run + poetry publish -r test-pypi --dist-dir dist --skip-existing --dry-run - name: Publish to PyPI - if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }} + if: | + ${{ (github.event_name == 'release' && github.ref_type == 'tag' && startsWith(github.ref, 'refs/tags/v'))}} || + ${{ (github.event_name == 'workflow_dispatch' && github.ref_type == 'tag' && startsWith(github.ref, 'refs/tags/v'))}} || run: | poetry config pypi-token.pypi ${{ secrets.PYPI_PUBLISH }} - poetry publish --skip-existing + poetry publish --dist-dir dist --skip-existing diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 7d859422..16534f14 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -1,4 +1,8 @@ +# Automatic changelog and version bumping with release-please for python projects +name: Release-please ๐Ÿ + on: + workflow_dispatch: {} push: branches: - main @@ -7,13 +11,13 @@ permissions: contents: write pull-requests: write -name: release-please - jobs: release-please: + name: Create release PR runs-on: ubuntu-latest steps: - - uses: google-github-actions/release-please-action@v4 + - uses: googleapis/release-please-action@v4 with: - token: ${{ secrets.GITHUB_TOKEN }} - config-file: release-please-config.json + # Using a personal access token so releases created by this workflow can trigger the deployment workflow + token: ${{ secrets.HUGRBOT_PAT }} + config-file: release-please-config.json