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