mirror of
https://github.com/Sea-Haven-Industries/.github.git
synced 2026-09-30 07:03:11 +00:00
Merge pull request #106 from Sea-Haven-Industries/feat/release-on-reusable-change
feat(release): cut a tag and release when a reusable workflow changes
This commit is contained in:
commit
2fbfb2e7cf
1 changed files with 109 additions and 0 deletions
109
.github/workflows/release-on-merge.yaml
vendored
Normal file
109
.github/workflows/release-on-merge.yaml
vendored
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
name: Release on reusable change
|
||||||
|
|
||||||
|
# Cuts a tag and GitHub Release for THIS repo when a merge to main changes a
|
||||||
|
# reusable workflow.
|
||||||
|
#
|
||||||
|
# Why this exists: every caller in the org pins its `uses:` reference to a
|
||||||
|
# commit SHA of this repo. Dependabot's github-actions updater resolves a newer
|
||||||
|
# SHA for a pinned reference by looking at that repo's tags and releases. This
|
||||||
|
# repo has had neither, so a pinned reference has nothing to be bumped to and
|
||||||
|
# Dependabot correctly reports no update. Tagging each change to a reusable
|
||||||
|
# gives it something to diff against.
|
||||||
|
#
|
||||||
|
# The trigger is deliberately narrow. Only workflows carrying `on:
|
||||||
|
# workflow_call` are consumed by other repos, so only those warrant a release.
|
||||||
|
# Changes to this repo's own CI, its labeler caller, this file, the starter
|
||||||
|
# templates under workflow-templates/ and the docs change nothing for a caller
|
||||||
|
# pinned to a SHA, so they do not cut one. The exclusions below are the
|
||||||
|
# non-reusable workflows; add to this list when adding another workflow that is
|
||||||
|
# not `workflow_call`, or it will cut a release it does not need to.
|
||||||
|
#
|
||||||
|
# Version scheme: patch bump from the highest existing vMAJOR.MINOR.PATCH tag,
|
||||||
|
# starting at 1.0.0 when there are none. Use the manual dispatch with an
|
||||||
|
# explicit version for a minor or major bump, which is the case whenever a
|
||||||
|
# reusable gains a required input, renames one, or otherwise breaks a caller.
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- ".github/workflows/**"
|
||||||
|
- "!.github/workflows/ci.yaml"
|
||||||
|
- "!.github/workflows/labeler.yaml"
|
||||||
|
- "!.github/workflows/release-on-merge.yaml"
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: 'Explicit version, e.g. "1.1.0". Leave empty to patch-bump the highest existing tag.'
|
||||||
|
type: string
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
|
||||||
|
# Runs are serialised, never cancelled. Two merges landing close together would
|
||||||
|
# otherwise both read the same highest tag, compute the same next version, and
|
||||||
|
# the second would find the tag already created and no-op — leaving that change
|
||||||
|
# unreleased. Queuing makes the second run read the tag the first one pushed.
|
||||||
|
concurrency:
|
||||||
|
group: release-on-merge
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
version:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 5
|
||||||
|
outputs:
|
||||||
|
version: ${{ steps.next.outputs.version }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v7
|
||||||
|
with:
|
||||||
|
# Tags are the input to the version calculation, so they must be
|
||||||
|
# fetched; a shallow checkout without them would restart at 1.0.0.
|
||||||
|
fetch-depth: 0
|
||||||
|
fetch-tags: true
|
||||||
|
|
||||||
|
- name: Compute the next version
|
||||||
|
id: next
|
||||||
|
env:
|
||||||
|
OVERRIDE: ${{ inputs.version }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [ -n "${OVERRIDE}" ]; then
|
||||||
|
echo "version=${OVERRIDE#v}" >> "${GITHUB_OUTPUT}"
|
||||||
|
echo "Using the explicitly supplied version ${OVERRIDE}."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Only plain vMAJOR.MINOR.PATCH tags take part. -v:refname sorts by
|
||||||
|
# version rather than lexically, so v1.0.10 ranks above v1.0.9.
|
||||||
|
latest="$(git tag -l 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname | head -n 1)"
|
||||||
|
|
||||||
|
if [ -z "${latest}" ]; then
|
||||||
|
next="1.0.0"
|
||||||
|
echo "No existing version tag. Starting at ${next}."
|
||||||
|
else
|
||||||
|
current="${latest#v}"
|
||||||
|
major="${current%%.*}"
|
||||||
|
rest="${current#*.}"
|
||||||
|
minor="${rest%%.*}"
|
||||||
|
patch="${rest#*.}"
|
||||||
|
|
||||||
|
next="${major}.${minor}.$((patch + 1))"
|
||||||
|
echo "Highest existing tag is ${latest}. Next version is ${next}."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "version=${next}" >> "${GITHUB_OUTPUT}"
|
||||||
|
|
||||||
|
release:
|
||||||
|
needs: version
|
||||||
|
# Referenced by local path, not by SHA. A repo calling its own reusable
|
||||||
|
# cannot pin to a commit of itself without the pin lagging the file it
|
||||||
|
# points at by one merge every time either changes.
|
||||||
|
uses: ./.github/workflows/release.yaml
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.version }}
|
||||||
Loading…
Add table
Reference in a new issue