feat(ci): implement semver release channels

- Rename dev-release.yml → alpha-release.yml
- Alpha builds: v0.0.4-alpha.{run_number} (prerelease)
- Add pr-build.yml for draft releases
- PR builds: v0.0.4-pr.{num}.bid.{id} (draft, not published)
- Add attestation permissions for SLSA compliance
- No more deleting/recreating dev tag

Versioning strategy:
- Draft: +pr.{NUM}.bid.{ID} (testable, not published)
- Alpha: -alpha.{N} (canary channel)
- Beta: -beta (quality scored)
- RC: -rc.{N} (release candidate)
- Stable: no suffix

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Snider 2026-02-02 19:17:21 +00:00
parent 4164caa6f7
commit 6e2dbcb6d7
2 changed files with 123 additions and 17 deletions

View file

@ -1,4 +1,4 @@
name: Dev Release
name: Alpha Release
on:
push:
@ -7,9 +7,12 @@ on:
permissions:
contents: write
id-token: write
attestations: write
env:
CORE_VERSION: dev
# Next version - update when releasing
NEXT_VERSION: "0.0.4"
jobs:
build:
@ -55,34 +58,37 @@ jobs:
cp dist/* release/ 2>/dev/null || true
ls -la release/
- name: Delete existing dev release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release delete dev -y || true
- name: Delete existing dev tag
run: git push origin :refs/tags/dev || true
- name: Create dev release
- name: Create alpha release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create dev \
--title "Development Build" \
--notes "Latest development build from the dev branch.
VERSION="v${{ env.NEXT_VERSION }}-alpha.${{ github.run_number }}"
gh release create "$VERSION" \
--title "Alpha: $VERSION" \
--notes "Canary build from dev branch.
**Version:** $VERSION
**Commit:** ${{ github.sha }}
**Built:** $(date -u +'%Y-%m-%d %H:%M:%S UTC')
**Run:** ${{ github.run_id }}
## Channel: Alpha (Canary)
This is an automated pre-release for early testing.
- Systems and early adopters can test breaking changes
- Quality scoring determines promotion to beta
- Use stable releases for production
## Installation
\`\`\`bash
# macOS/Linux
curl -fsSL https://github.com/host-uk/core/releases/download/dev/core-linux-amd64 -o core
curl -fsSL https://github.com/host-uk/core/releases/download/$VERSION/core-linux-amd64 -o core
chmod +x core && sudo mv core /usr/local/bin/
\`\`\`
This is a pre-release for testing. Use tagged releases for production." \
" \
--prerelease \
--target dev \
release/*

100
.github/workflows/pr-build.yml vendored Normal file
View file

@ -0,0 +1,100 @@
name: PR Build
on:
pull_request:
types: [opened, synchronize, reopened]
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to build'
required: true
type: number
permissions:
contents: write
pull-requests: read
env:
# Next version - update when releasing
NEXT_VERSION: "0.0.4"
jobs:
build:
# Only build if PR is from the same repo (not forks) or manually triggered
if: github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch'
strategy:
matrix:
include:
- os: ubuntu-latest
platform: linux/amd64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Build
uses: host-uk/build@dev
with:
build-name: core
build-platform: ${{ matrix.platform }}
build: true
package: true
sign: false
draft-release:
needs: build
runs-on: ubuntu-latest
env:
# Safe: PR number is numeric, not user-controlled string
PR_NUM: ${{ github.event.pull_request.number || inputs.pr_number }}
PR_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
steps:
- uses: actions/checkout@v4
- name: Download artifacts
uses: actions/download-artifact@v4
with:
path: dist
merge-multiple: true
- name: Prepare release files
run: |
mkdir -p release
cp dist/* release/ 2>/dev/null || true
ls -la release/
- name: Create draft release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Build metadata uses + which is valid semver but GitHub tags encode it
VERSION="v${{ env.NEXT_VERSION }}+pr.${PR_NUM}.bid.${{ github.run_id }}"
# GitHub tags can't have + so we use a different format for the tag
TAG="v${{ env.NEXT_VERSION }}-pr.${PR_NUM}.bid.${{ github.run_id }}"
# Delete existing draft for this PR if it exists
gh release delete "$TAG" -y 2>/dev/null || true
git push origin ":refs/tags/$TAG" 2>/dev/null || true
gh release create "$TAG" \
--title "Draft: PR #${PR_NUM}" \
--notes "Draft build for PR #${PR_NUM}.
**Version:** $VERSION
**Tag:** $TAG
**PR:** #${PR_NUM}
**Commit:** ${PR_SHA}
**Built:** $(date -u +'%Y-%m-%d %H:%M:%S UTC')
**Run:** ${{ github.run_id }}
## Channel: Draft
This is a draft build for testing PR changes before merge.
Not intended for production use.
Build artifacts available for download and testing.
" \
--draft \
--prerelease \
release/*