name: Release on: release: types: [published] permissions: contents: write actions: read jobs: # AUD-159B7-02: publishing a GitHub Release used to BE the gate — this # workflow only built and uploaded, so an asset shipped while both Validate # runs for the very same commit were red. The asset now waits for a green # Validate of the EXACT commit the tag points at, and is withheld otherwise. # # Needs a push with a token that has the `workflow` scope (the ordinary # Personal Access Token used for `git push` refuses workflow file updates). gate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 with: ref: ${{ github.event.release.tag_name }} fetch-depth: 0 - uses: actions/setup-node@v7 with: { node-version: 22 } - name: Require a green Validate for this exact commit env: GH_TOKEN: ${{ github.token }} REPO: ${{ github.repository }} TAG: ${{ github.event.release.tag_name }} run: | set -euo pipefail # HEAD is the peeled commit even when TAG is annotated. Do not trust # target_commitish (it may be a branch name) or an event-context SHA. SHA=$(git rev-parse HEAD) echo "release tag: $TAG; exact commit: $SHA" node scripts/release-gate.mjs "$SHA" - name: Require full performance for a stable release if: ${{ !github.event.release.prerelease }} env: GH_TOKEN: ${{ github.token }} REPO: ${{ github.repository }} run: | set -euo pipefail SHA=$(git rev-parse HEAD) node scripts/release-gate.mjs "$SHA" --workflow=performance.yml --label="Full Performance" build: needs: gate runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 with: ref: ${{ github.event.release.tag_name }} - uses: actions/setup-node@v7 with: { node-version: 22 } - run: npm ci && npm run build - name: Verify compositor frame continuity for a stable release if: ${{ !github.event.release.prerelease }} run: | npx playwright install --with-deps chromium node scripts/bundle-sync.mjs npm run continuity:screencast - name: Upload failed continuity frames if: ${{ failure() && !github.event.release.prerelease }} uses: actions/upload-artifact@v7 with: name: continuity-screencast path: artifacts/continuity-screencast - run: cp dist/houseplan-card.js custom_components/houseplan/frontend/ - name: Attach card to release uses: softprops/action-gh-release@v3 with: files: dist/houseplan-card.js hacs-discovery: # HACS 2.0.x takes the first prerelease in GitHub's response instead of # sorting SemVer. A valid asset can therefore be invisible to beta users # (beta.10 appeared after beta.9). Keep the release asset, but # make that distribution failure impossible to miss in the release run. if: ${{ github.event.release.prerelease }} needs: build runs-on: ubuntu-latest steps: - name: Verify the published tag is the prerelease HACS will discover uses: actions/github-script@v9 with: script: | const releases = await github.paginate(github.rest.repos.listReleases, { owner: context.repo.owner, repo: context.repo.repo, per_page: 100, }); const first = releases.find((r) => r.prerelease && !r.draft); const expected = context.payload.release.tag_name; if (first?.tag_name !== expected) { core.setFailed( `HACS prerelease discovery is stale: GitHub returns ${first?.tag_name ?? 'none'} before ${expected}. ` + `Use an rc/new version line or correct the release ordering before announcing the update.`, ); }