Add channel-aware release tooling and updater recovery
This commit is contained in:
164
.gitea/workflows/release.yml
Normal file
164
.gitea/workflows/release.yml
Normal file
@@ -0,0 +1,164 @@
|
||||
name: Publish launcher release
|
||||
|
||||
# Manual-release mode is active. Restore the v* tag-push trigger when automatic
|
||||
# Gitea publication is wanted again.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: launcher-release-publication
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Build, verify, and publish tagged release
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Check out the exact tag
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- name: Validate and derive release metadata
|
||||
id: release
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TAG="${GITHUB_REF_NAME:?GITHUB_REF_NAME is required}"
|
||||
if [[ "$(git cat-file -t "$TAG")" != "tag" ]]
|
||||
then
|
||||
printf 'Release tag must be annotated: %s\n' "$TAG" >&2
|
||||
exit 1
|
||||
fi
|
||||
python3 -m ptlinux.update_resolver inspect-tag "$TAG" > release-metadata.json
|
||||
VERSION="$(jq -er '.version' release-metadata.json)"
|
||||
CHANNEL="$(jq -er '.channel' release-metadata.json)"
|
||||
PRERELEASE="$(jq -er '.prerelease' release-metadata.json)"
|
||||
COMMIT="$(git rev-parse "${TAG}^{commit}")"
|
||||
if [[ "$COMMIT" != "$(git rev-parse HEAD)" ]]
|
||||
then
|
||||
printf 'Checkout does not match tagged commit %s.\n' "$COMMIT" >&2
|
||||
exit 1
|
||||
fi
|
||||
mapfile -t OTHER_RELEASE_TAGS < <(
|
||||
git tag --list | while IFS= read -r candidate
|
||||
do
|
||||
[[ "$candidate" == "$TAG" ]] || printf '%s\n' "$candidate"
|
||||
done
|
||||
)
|
||||
python3 -m ptlinux.update_resolver validate-next \
|
||||
"$CHANNEL" "$VERSION" "${OTHER_RELEASE_TAGS[@]}"
|
||||
{
|
||||
printf 'tag=%s\n' "$TAG"
|
||||
printf 'version=%s\n' "$VERSION"
|
||||
printf 'channel=%s\n' "$CHANNEL"
|
||||
printf 'prerelease=%s\n' "$PRERELEASE"
|
||||
printf 'commit=%s\n' "$COMMIT"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Recover the previewed release notes
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
NOTES_FILE="${RUNNER_TEMP}/release-notes.md"
|
||||
git for-each-ref --format='%(contents)' \
|
||||
"refs/tags/${{ steps.release.outputs.tag }}" > "$NOTES_FILE"
|
||||
if [[ ! -s "$NOTES_FILE" ]]
|
||||
then
|
||||
printf '%s\n' 'Annotated release tag has no release notes.' >&2
|
||||
exit 1
|
||||
fi
|
||||
printf 'RELEASE_NOTES_FILE=%s\n' "$NOTES_FILE" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Run release preflight checks
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for command in git bash curl jq python3 tar gzip sha256sum rsync openssl base64 realpath stat
|
||||
do
|
||||
command -v "$command" >/dev/null || {
|
||||
printf 'Required release command is unavailable: %s\n' "$command" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
python3 -c 'import sys; raise SystemExit(0 if sys.version_info >= (3, 11) else 1)'
|
||||
python3 -m compileall -q ptlinux ptdiag scripts
|
||||
python3 -m unittest discover -s release_tests -p 'test_*.py'
|
||||
python3 -m unittest discover -s tests -p 'test_*.py'
|
||||
bash -n scripts/release.sh scripts/build-release.sh \
|
||||
scripts/verify-release.sh scripts/publish-gitea-release.sh \
|
||||
scripts/publish-release-history.sh
|
||||
|
||||
- name: Materialize the protected manifest signing key
|
||||
shell: bash
|
||||
env:
|
||||
MANIFEST_SIGNING_KEY: ${{ secrets.MANIFEST_SIGNING_KEY }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -z "${MANIFEST_SIGNING_KEY:-}" ]]
|
||||
then
|
||||
printf '%s\n' 'MANIFEST_SIGNING_KEY is required for release publication.' >&2
|
||||
exit 1
|
||||
fi
|
||||
umask 077
|
||||
SIGNING_KEY_FILE="${RUNNER_TEMP}/launcher-manifest-signing-key.pem"
|
||||
printf '%s\n' "$MANIFEST_SIGNING_KEY" > "$SIGNING_KEY_FILE"
|
||||
chmod 0600 "$SIGNING_KEY_FILE"
|
||||
printf 'PTLINUX_SIGNING_KEY=%s\n' "$SIGNING_KEY_FILE" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Build deterministic release artifacts
|
||||
shell: bash
|
||||
env:
|
||||
RELEASE_COMMIT: ${{ steps.release.outputs.commit }}
|
||||
RELEASE_TAG: ${{ steps.release.outputs.tag }}
|
||||
REPOSITORY_URL: ${{ github.server_url }}/${{ github.repository }}
|
||||
REQUIRE_RELEASE_SIGNATURE: "1"
|
||||
run: |
|
||||
set -euo pipefail
|
||||
export SOURCE_DATE_EPOCH
|
||||
SOURCE_DATE_EPOCH="$(git show -s --format=%ct '${{ steps.release.outputs.commit }}')"
|
||||
./scripts/build-release.sh \
|
||||
'${{ steps.release.outputs.version }}' \
|
||||
'${{ steps.release.outputs.channel }}' \
|
||||
./dist
|
||||
|
||||
- name: Verify complete release artifacts
|
||||
shell: bash
|
||||
env:
|
||||
REQUIRE_RELEASE_SIGNATURE: "1"
|
||||
run: |
|
||||
set -euo pipefail
|
||||
./scripts/verify-release.sh \
|
||||
'${{ steps.release.outputs.version }}' \
|
||||
'${{ steps.release.outputs.channel }}' \
|
||||
./dist
|
||||
|
||||
- name: Create Gitea release, upload assets, and update channel metadata
|
||||
shell: bash
|
||||
env:
|
||||
RELEASE_BRANCH: main
|
||||
RELEASE_COMMIT: ${{ steps.release.outputs.commit }}
|
||||
RELEASE_PRERELEASE: ${{ steps.release.outputs.prerelease }}
|
||||
RELEASE_TAG: ${{ steps.release.outputs.tag }}
|
||||
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
./scripts/publish-gitea-release.sh \
|
||||
'${{ steps.release.outputs.version }}' \
|
||||
'${{ steps.release.outputs.channel }}' \
|
||||
./dist \
|
||||
"$RELEASE_NOTES_FILE"
|
||||
|
||||
- name: Remove signing key
|
||||
if: always()
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ -n "${PTLINUX_SIGNING_KEY:-}" ]]
|
||||
then
|
||||
rm -f -- "$PTLINUX_SIGNING_KEY"
|
||||
fi
|
||||
Reference in New Issue
Block a user