# Cut a patch release when a PR labelled "security" (Renovate vulnerability # fix) is merged. Called from each repo's own security-release.yml. name: security-release on: workflow_call: inputs: dispatch-workflow: description: Release workflow to start on the new tag (e.g. release.yml); empty to only tag. type: string default: "" initial-version: description: Tag to use when the repo has no vX.Y.Z tag yet. type: string default: v0.1.0 jobs: release: runs-on: ubuntu-latest permissions: contents: write actions: write steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: ${{ github.event.pull_request.merge_commit_sha }} fetch-depth: 0 - name: Work out the next patch tag id: tag env: SHA: ${{ github.event.pull_request.merge_commit_sha }} INITIAL: ${{ inputs.initial-version }} run: | set -euo pipefail if [ -n "$(git tag --points-at "$SHA")" ]; then echo "Merge commit is already tagged: $(git tag --points-at "$SHA")" echo "skip=true" >> "$GITHUB_OUTPUT"; exit 0 fi # Stable vX.Y.Z only: prereleases such as v3.0.0-beta3 are ignored. last=$(git tag --list 'v*' --sort=-v:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1 || true) if [ -z "$last" ]; then next="$INITIAL" else IFS=. read -r major minor patch <<<"${last#v}" next="v${major}.${minor}.$((patch + 1))" fi echo "last=${last:-none} next=$next" echo "next=$next" >> "$GITHUB_OUTPUT" - name: Tag and publish the release if: steps.tag.outputs.skip != 'true' env: GH_TOKEN: ${{ github.token }} TAG: ${{ steps.tag.outputs.next }} SHA: ${{ github.event.pull_request.merge_commit_sha }} PR: ${{ github.event.pull_request.number }} TITLE: ${{ github.event.pull_request.title }} run: | gh release create "$TAG" --repo "$GITHUB_REPOSITORY" --target "$SHA" \ --title "$TAG" --notes "Security release for #${PR}: ${TITLE}" --generate-notes # A tag or release made with the job token does not start other # workflows; workflow_dispatch is GitHub's documented exception. - name: Start the release workflow on the new tag if: steps.tag.outputs.skip != 'true' && inputs.dispatch-workflow != '' env: GH_TOKEN: ${{ github.token }} TAG: ${{ steps.tag.outputs.next }} WF: ${{ inputs.dispatch-workflow }} run: gh workflow run "$WF" --repo "$GITHUB_REPOSITORY" --ref "$TAG"