From 74fed469dcbb68af6d2c510b5eddd187c182f57e Mon Sep 17 00:00:00 2001 From: bherbruck Date: Sat, 10 Oct 2026 21:59:18 -0400 Subject: [PATCH] fix: deploy docs web and Flatpak through one Pages workflow --- .github/workflows/flatpak-pages.yml | 144 ++-------------------------- .github/workflows/pages.yml | 17 ++++ docs/releasing.md | 6 +- packaging/flatpak-site.sh | 68 +++++++++++++ 4 files changed, 100 insertions(+), 135 deletions(-) create mode 100644 packaging/flatpak-site.sh diff --git a/.github/workflows/flatpak-pages.yml b/.github/workflows/flatpak-pages.yml index dfd48416..06e5e6a2 100644 --- a/.github/workflows/flatpak-pages.yml +++ b/.github/workflows/flatpak-pages.yml @@ -12,150 +12,26 @@ on: permissions: contents: read + actions: write concurrency: group: flatpak-pages-${{ github.repository }} cancel-in-progress: false jobs: - build: - name: Build Flatpak repository + publish: + name: Request the combined docs, web, and Flatpak deployment runs-on: ubuntu-24.04 - permissions: - contents: read env: GH_TOKEN: ${{ github.token }} RELEASE_TAG: ${{ github.event.release.tag_name || inputs.release_tag }} - APP_ID: ai.storyteller.solvecraft steps: - - name: Configure Pages - id: pages - uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0 - - - name: Install Flatpak repository tools - run: | - sudo apt-get update - sudo apt-get install -y --no-install-recommends flatpak ostree - - - name: Download and validate release bundles - shell: bash + - name: Deploy through the shared Pages workflow run: | set -euo pipefail - tag="$RELEASE_TAG" - if ! printf '%s' "$tag" | grep -Eq '^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*))?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$'; then - echo "::error::Release tag '$tag' is not strict SemVer prefixed with v" - exit 1 - fi - published_tag="$(gh api "repos/$GITHUB_REPOSITORY/releases/tags/$tag" --jq \ - 'select(.draft == false and .published_at != null) | .tag_name')" - if [[ "$published_tag" != "$tag" ]]; then - echo "::error::$tag is not a published release in $GITHUB_REPOSITORY" - exit 1 - fi - - version="${tag#v}" - mkdir -p bundles - gh release download "$tag" --repo "$GITHUB_REPOSITORY" \ - --pattern SHA256SUMS.txt --dir bundles - for arch in x86_64 aarch64; do - asset="solvecraft-$version-linux-$arch.flatpak" - gh release download "$tag" --repo "$GITHUB_REPOSITORY" \ - --pattern "$asset" --dir bundles - test -s "bundles/$asset" - ( - cd bundles - awk -v file="$asset" '$2 == file || $2 == "*" file { print; found=1 } END { exit !found }' \ - SHA256SUMS.txt | sha256sum --check - - ) - done - test "$(find bundles -maxdepth 1 -type f -name '*.flatpak' | wc -l)" -eq 2 - - for arch in x86_64 aarch64; do - asset="bundles/solvecraft-$version-linux-$arch.flatpak" - validation_repo="$(mktemp -d)" - ostree --repo="$validation_repo" init --mode=archive-z2 - flatpak build-import-bundle "$validation_repo" "$asset" - expected_ref="app/$APP_ID/$arch/stable" - ostree --repo="$validation_repo" refs | grep -Fxq "$expected_ref" || { - echo "::error::$(basename "$asset") does not contain $expected_ref" - exit 1 - } - rm -rf "$validation_repo" - done - - - name: Build repository and site - shell: bash - env: - PAGES_BASE_URL: ${{ steps.pages.outputs.base_url }} - run: | - set -euo pipefail - site="$RUNNER_TEMP/site" - repo_dir="$site/flatpak/repo" - mkdir -p "$repo_dir" - ostree --repo="$repo_dir" init --mode=archive-z2 - - previous_url="${PAGES_BASE_URL%/}/flatpak/repo" - if curl --fail --silent --show-error --location \ - --output /dev/null "$previous_url/summary"; then - ostree --repo="$repo_dir" remote add --no-gpg-verify previous "$previous_url" - ostree --repo="$repo_dir" pull --mirror previous - ostree --repo="$repo_dir" remote delete previous - fi - - version="${RELEASE_TAG#v}" - for arch in x86_64 aarch64; do - flatpak build-import-bundle "$repo_dir" \ - "bundles/solvecraft-$version-linux-$arch.flatpak" - done - flatpak build-update-repo \ - --title="SolveCraft" \ - --comment='Official SolveCraft releases' \ - --description='Official Flatpak repository for SolveCraft' \ - --homepage="https://github.com/$GITHUB_REPOSITORY" \ - --default-branch=stable \ - "$repo_dir" - - for arch in x86_64 aarch64; do - ostree --repo="$repo_dir" rev-parse "app/$APP_ID/$arch/stable" >/dev/null - done - test -s "$repo_dir/summary" - - base_url="${PAGES_BASE_URL%/}" - repo_url="$base_url/flatpak/repo/" - cat >"$site/flatpak/solvecraft.flatpakrepo" <"$site/flatpak/index.html" <SolveCraft Flatpak repository

SolveCraft Flatpak repository

Latest published release: $RELEASE_TAG

Add the SolveCraft repository

flatpak remote-add --if-not-exists solvecraft $base_url/flatpak/solvecraft.flatpakrepo
-          flatpak install solvecraft $APP_ID
- HTML - cat >"$site/index.html" <SolveCraft downloads

SolveCraft downloads

Flatpak repository

Release assets

- HTML - touch "$site/.nojekyll" - - - name: Upload Pages artifact - uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 - with: - path: ${{ runner.temp }}/site - include-hidden-files: true - - deploy: - name: Deploy Pages - needs: build - runs-on: ubuntu-24.04 - permissions: - pages: write - id-token: write - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - steps: - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1 + published="$(gh api "repos/$GITHUB_REPOSITORY/releases/tags/$RELEASE_TAG" \ + --jq 'select(.draft == false and .published_at != null) | .tag_name')" + test "$published" = "$RELEASE_TAG" + gh workflow run pages.yml --repo "$GITHUB_REPOSITORY" --ref main \ + -f release_tag="$RELEASE_TAG" + echo "Requested the combined Pages deployment for $RELEASE_TAG" >>"$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 80a256b6..d36accb6 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -7,6 +7,12 @@ on: push: branches: [main] workflow_dispatch: + inputs: + release_tag: + description: "Published release for Flatpak (empty: latest stable release)" + type: string + required: false + default: "" permissions: contents: read @@ -50,6 +56,17 @@ jobs: cp -r target/book/. site/ cp -r dist/web site/app - uses: actions/configure-pages@v5 + id: pages + - name: Install Flatpak repository tools + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends flatpak ostree + - name: Include the published Flatpak repository + env: + GH_TOKEN: ${{ github.token }} + RELEASE_TAG: ${{ inputs.release_tag || '' }} + PAGES_BASE_URL: ${{ steps.pages.outputs.base_url }} + run: bash packaging/flatpak-site.sh site - uses: actions/upload-pages-artifact@v3 with: path: site diff --git a/docs/releasing.md b/docs/releasing.md index 588162d3..9fabd24c 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -117,7 +117,11 @@ Keep that deployment separate from building the application. A publication made Actions `GITHUB_TOKEN` does not trigger downstream `release: published` workflows; in that case explicitly dispatch the Flatpak workflow with the published tag, or use an appropriately authorized maintainer/App token for publication. Do not assume the repository updated: check -the deployment run. Coordinate its GitHub Pages output with the existing docs website. +the deployment run. The Flatpak workflow requests the shared Pages workflow with that tag; +Pages assembles the documentation, browser app, and Flatpak repository together. Ordinary +docs updates include the latest stable Flatpak release too. Verify the resulting Pages run, +not only the dispatch job, so a release cannot erase the docs or app and docs updates cannot +erase the package repository. ## Repository setup diff --git a/packaging/flatpak-site.sh b/packaging/flatpak-site.sh new file mode 100644 index 00000000..44d55572 --- /dev/null +++ b/packaging/flatpak-site.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +# All Pages deployments include the book, web app, and published Flatpak repository. +# Shared by docs updates and release publication; no other workflow replaces the site. +set -euo pipefail + +site="${1:?site directory required}" +tag="${RELEASE_TAG:-}" +app_id=ai.storyteller.solvecraft +if [ -z "$tag" ]; then + tag="$(gh api "repos/$GITHUB_REPOSITORY/releases?per_page=100" \ + --jq '[.[] | select(.draft == false and .prerelease == false)][0].tag_name // empty')" +fi +# Before the first publication the docs and browser app can still deploy. +if [ -z "$tag" ]; then exit 0; fi +if ! printf '%s' "$tag" | grep -Eq '^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*))?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$'; then + echo "invalid release tag: $tag" >&2 + exit 1 +fi +published="$(gh api "repos/$GITHUB_REPOSITORY/releases/tags/$tag" \ + --jq 'select(.draft == false and .published_at != null) | .tag_name')" +test "$published" = "$tag" +test -s "$site/index.html" +test -s "$site/app/index.html" + +version="${tag#v}" +bundles="$(mktemp -d)" +gh release download "$tag" --repo "$GITHUB_REPOSITORY" --pattern SHA256SUMS.txt --dir "$bundles" +repo_dir="$site/flatpak/repo" +mkdir -p "$repo_dir" +ostree --repo="$repo_dir" init --mode=archive-z2 +base_url="${PAGES_BASE_URL%/}" +previous_url="$base_url/flatpak/repo" +if curl --fail --silent --location --output /dev/null "$previous_url/summary"; then + ostree --repo="$repo_dir" remote add --no-gpg-verify previous "$previous_url" + ostree --repo="$repo_dir" pull --mirror previous + ostree --repo="$repo_dir" remote delete previous +fi +for arch in x86_64 aarch64; do + asset="solvecraft-$version-linux-$arch.flatpak" + gh release download "$tag" --repo "$GITHUB_REPOSITORY" --pattern "$asset" --dir "$bundles" + ( + cd "$bundles" + awk -v file="$asset" '$2 == file || $2 == "*" file { print; found=1 } END { exit !found }' \ + SHA256SUMS.txt | sha256sum --check - + ) + validation_repo="$(mktemp -d)" + ostree --repo="$validation_repo" init --mode=archive-z2 + flatpak build-import-bundle "$validation_repo" "$bundles/$asset" + ostree --repo="$validation_repo" refs | grep -Fxq "app/$app_id/$arch/stable" + flatpak build-import-bundle "$repo_dir" "$bundles/$asset" +done +flatpak build-update-repo --title="SolveCraft" --comment='Official SolveCraft releases' \ + --description='Official Flatpak repository for SolveCraft' \ + --homepage="https://github.com/$GITHUB_REPOSITORY" --default-branch=stable "$repo_dir" +test -s "$repo_dir/summary" +cat >"$site/flatpak/solvecraft.flatpakrepo" <"$site/flatpak/index.html" <SolveCraft Flatpak repository

SolveCraft Flatpak repository

Latest published release: $tag

Add the SolveCraft repository

flatpak remote-add --if-not-exists solvecraft $base_url/flatpak/solvecraft.flatpakrepo
+flatpak install solvecraft $app_id
+HTML +touch "$site/.nojekyll"