diff --git a/.github/workflows/audit-tests.yml b/.github/workflows/audit-tests.yml index 4d0d8b7..1d72a0a 100644 --- a/.github/workflows/audit-tests.yml +++ b/.github/workflows/audit-tests.yml @@ -4,7 +4,13 @@ name: Audit tests # audit or its exemption list is checked before it lands. Needs no token. on: + # `ready_for_review` is not one of pull_request's default types (opened, + # synchronize, reopened), and the job below skips a draft. Without it a pull + # request opened as a draft never gets this check at all: marking it ready + # re-triggers nothing, so the skipped run stands and the PR merges unchecked. + # Measured on #23, which was opened as a draft deliberately. pull_request: + types: [opened, synchronize, reopened, ready_for_review] workflow_dispatch: permissions: diff --git a/.github/workflows/hygiene.yml b/.github/workflows/hygiene.yml index ea0d306..f988a45 100644 --- a/.github/workflows/hygiene.yml +++ b/.github/workflows/hygiene.yml @@ -12,6 +12,14 @@ name: Hygiene (reusable) # package tests -- they need `gh` and a token, both of which every runner # already has. Requiring an install here would add a dependency, a bootstrap # problem for package-tools checking itself, and minutes to 37 repositories. +# +# `release-publish` is the odd one out: most repositories pass it by finding +# NOTHING, because they create and update their release with +# `softprops/action-gh-release`, which publishes an existing draft on its own. +# Only a hand-rolled `gh release edit` can leave one as a draft. A check whose +# clean answer is an empty result can lie by simply stopping matching, so that +# script drives its own matcher against built-in controls on every invocation +# and refuses to report anything when one of them misbehaves. on: workflow_call: @@ -32,6 +40,10 @@ on: description: Verify every path composer.json references survives the archive. type: boolean default: true + run-release-publish: + description: Verify no workflow can leave a GitHub release sitting as a draft. + type: boolean + default: true php-version: description: PHP version for the dist-integrity check. type: string @@ -70,6 +82,34 @@ jobs: env: GH_TOKEN: ${{ github.token }} + release-publish: + name: Release publishing + if: inputs.run-release-publish + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - name: Check out the calling repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: repo + persist-credentials: false + + - name: Check out the shared checks + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: laranail/package-tools + ref: ${{ inputs.checks-ref }} + path: checks + persist-credentials: false + + # The path argument, for the same reason as action-pins above: without it the + # script resolves its target from its own __file__ and would check + # package-tools' own workflows rather than the caller's -- silently passing. + # No token either, unlike the other two jobs: this one is a text scan. + - name: No workflow can leave a release as a draft + run: python3 checks/scripts/verify-release-publish.py "${GITHUB_WORKSPACE}/repo" + tag-currency: name: Release currency # Never on a pull request: a PR that adds commits always makes a release due,