Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ jobs:
needs: [auto-version]
if: always() && (needs.auto-version.result == 'success' || needs.auto-version.result == 'skipped')
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.tag.outputs.tag }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand Down Expand Up @@ -117,10 +119,24 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max

# GITHUB_TOKEN tag pushes do not start other workflows, so scheduled
# auto-version tags never fire release.yml on:push. Call it here after
# the image is published. Human/PAT tag pushes still use release.yml
# via on:push (this job is skipped on those events).
create-release:
needs: [build-and-push]
if: always() && needs.build-and-push.result == 'success' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
uses: ./.github/workflows/release.yml
with:
tag: ${{ needs.build-and-push.outputs.tag }}
permissions:
contents: write
packages: read

# Generate and attach tool version manifest to GitHub release
version-manifest:
needs: [build-and-push]
if: always() && needs.build-and-push.result == 'success' && startsWith(github.ref, 'refs/tags/v')
needs: [build-and-push, create-release]
if: always() && needs.build-and-push.result == 'success' && (needs.create-release.result == 'success' || needs.create-release.result == 'skipped')
runs-on: ubuntu-latest
permissions:
contents: write
Expand All @@ -129,8 +145,10 @@ jobs:
- name: Determine version
id: version
run: |
# Strip v prefix: v1.4.2 → 1.4.2 (metadata-action tags images without v)
TAG="${GITHUB_REF_NAME}"
# Prefer the tag computed by build-and-push (schedule/dispatch
# run on refs/heads/main, not the new tag). Strip v prefix:
# v1.4.2 → 1.4.2 (metadata-action tags images without v).
TAG="${{ needs.build-and-push.outputs.tag }}"
VERSION="${TAG#v}"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
Expand Down Expand Up @@ -171,7 +189,7 @@ jobs:

# Notify on failure
notify-failure:
needs: [build-and-push, version-manifest]
needs: [build-and-push, create-release, version-manifest]
if: failure()
runs-on: ubuntu-latest
permissions:
Expand Down
24 changes: 19 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
name: Release

# Tag pushes from a human/PAT fire this via `push`. Scheduled auto-version
# tags are created with GITHUB_TOKEN, which GitHub will not use to start a
# new workflow — build.yml calls this via workflow_call after a successful
# image push instead.
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
workflow_call:
inputs:
tag:
description: Semver git tag to release (e.g. v1.12.16)
required: true
type: string

permissions:
contents: write
Expand All @@ -21,10 +31,14 @@ jobs:
- name: Extract version from tag
id: version
run: |
TAG="${GITHUB_REF_NAME}"
TAG="${{ inputs.tag || github.ref_name }}"
if [[ ! "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Refusing non-semver tag: ${TAG}"
exit 1
fi
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
echo "major=v$(echo "${TAG#v}" | cut -d. -f1)" >> "$GITHUB_OUTPUT"
echo "major=$(echo "${TAG#v}" | cut -d. -f1)" >> "$GITHUB_OUTPUT"

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
Expand All @@ -41,7 +55,7 @@ jobs:
docker pull ghcr.io/devrail-dev/dev-toolchain:${{ steps.version.outputs.version }}

# Major version (floating, always latest v${{ steps.version.outputs.major }}.x.x)
docker pull ghcr.io/devrail-dev/dev-toolchain:${{ steps.version.outputs.major }}
docker pull ghcr.io/devrail-dev/dev-toolchain:v${{ steps.version.outputs.major }}
```

## Verify Image Signature
Expand All @@ -57,8 +71,8 @@ jobs:

- name: Update major version tag
run: |
MAJOR_TAG="${{ steps.version.outputs.major }}"
git tag -f "${MAJOR_TAG}"
MAJOR_TAG="v${{ steps.version.outputs.major }}"
git tag -f "${MAJOR_TAG}" "${{ steps.version.outputs.tag }}"
git push origin "${MAJOR_TAG}" --force
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
of `go install` under QEMU, which failed the 2026-08-31 multi-arch scheduled
build (run 33391871123, issue #60). Checksums are verified against the
upstream release `checksums.txt`.
- Weekly/`workflow_dispatch` auto-version tags now get a GitHub Release and
`tool-versions.json`. `GITHUB_TOKEN` tag pushes cannot start `release.yml`,
so `build.yml` calls it via `workflow_call` after a successful image push.
Release notes no longer render the floating tag as `vv1`.

## [1.12.10] - 2026-07-30

Expand Down
4 changes: 3 additions & 1 deletion DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,11 @@ Once the tag is pushed to origin, GitHub Actions handles everything:
2. **release.yml** -- Creates a GitHub Release with auto-generated release notes and updates the `v1` floating tag
3. **build.yml (version-manifest)** -- Generates `tool-versions.json` from the published container and attaches it to the release

Human/PAT tag pushes (`make release`) trigger `release.yml` via `on: push`. Weekly cron and `workflow_dispatch` create the tag with `GITHUB_TOKEN`, which GitHub will not use to start a new workflow — `build.yml` therefore calls `release.yml` via `workflow_call` after the image push succeeds, then `version-manifest` attaches `tool-versions.json`.

### Routine Rebuilds

Weekly Monday builds require no manual action. The `auto-version` job in `build.yml` finds the latest tag, bumps the patch version, and triggers the full build+release pipeline. This keeps tool versions current without manual intervention.
Weekly Monday builds require no manual action. The `auto-version` job in `build.yml` finds the latest tag, bumps the patch version, publishes the image, creates the GitHub Release, and attaches `tool-versions.json`. This keeps tool versions current without manual intervention.

<!-- devrail:coding-practices -->

Expand Down
Loading