Update RustCFML #3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Update RustCFML | |
| # Follows the engine's current STABLE release and rebuilds the site on it. | |
| # | |
| # Adapted from the worker host's workflow of the same name, which learned two | |
| # things the hard way: | |
| # | |
| # * Do not follow upstream TAGS. Every RustCFML version tag is published as a | |
| # prerelease and a human promotes one to stable, so following tags meant a | |
| # bump per patch release — a dozen in two days. `gh release view` resolves | |
| # the promoted one. | |
| # * Do not open a pull request. One superseded PR per release, none merged, is | |
| # how a dependency ends up six versions behind. The build gate is what makes | |
| # a PR unnecessary: wasm32 must compile against the new engine before | |
| # anything is committed, and a failure leaves main untouched. | |
| # | |
| # What it bumps, and why both: Cargo.toml pins the engine the Worker runs, and | |
| # Application.cfc's `this.version` drives the footer and every download link. | |
| # Before this existed those two drifted 30 releases apart, because the | |
| # tools/set-version.py the README points at is not in the repository. | |
| # | |
| # Mechanism: scheduled poll, so nothing is needed in the RustCFML repo. | |
| on: | |
| schedule: | |
| - cron: "0 * * * *" | |
| workflow_dispatch: {} | |
| permissions: | |
| contents: write | |
| env: | |
| UPSTREAM_REPO: RustCFML/RustCFML | |
| jobs: | |
| update: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| changed: ${{ steps.versions.outputs.changed }} | |
| latest: ${{ steps.versions.outputs.latest }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }} | |
| - name: Determine current and latest versions | |
| id: versions | |
| env: | |
| GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| current="$(grep -oP 'cfml-worker\s*=.*tag\s*=\s*"\K[^"]+' Cargo.toml)" | |
| site="$(grep -oP 'this\.version\s*=\s*"\K[^"]+' Application.cfc)" | |
| echo "Worker pins: $current" | |
| echo "Site quotes: $site" | |
| # GitHub's "latest release" excludes prereleases, which is exactly the | |
| # promoted-to-stable one. | |
| latest="$(gh release view --repo "${UPSTREAM_REPO}" --json tagName --jq .tagName)" | |
| echo "Latest stable: $latest" | |
| [ -n "$latest" ] || { echo "::error::no stable release found"; exit 1; } | |
| { | |
| echo "current=$current" | |
| echo "latest=$latest" | |
| } >> "$GITHUB_OUTPUT" | |
| # Rebuild when either file is behind: the site version can lag even | |
| # when the worker pin does not. | |
| if [ "$current" = "$latest" ] && [ "$site" = "$latest" ]; then | |
| echo "Already on $latest. Nothing to do." | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| elif [ "$(printf '%s\n%s\n' "$current" "$latest" | sort -V | tail -n1)" != "$latest" ]; then | |
| echo "Pinned $current is newer than the latest stable $latest. Leaving it alone." | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Set up Rust (wasm32) | |
| if: steps.versions.outputs.changed == 'true' | |
| run: | | |
| set -euo pipefail | |
| rustup toolchain install stable --profile minimal | |
| rustup target add wasm32-unknown-unknown | |
| - name: Cache cargo | |
| if: steps.versions.outputs.changed == 'true' | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: cargo-${{ runner.os }}-${{ hashFiles('Cargo.lock') }} | |
| restore-keys: | | |
| cargo-${{ runner.os }}- | |
| - name: Bump both files and verify the build | |
| if: steps.versions.outputs.changed == 'true' | |
| env: | |
| CURRENT: ${{ steps.versions.outputs.current }} | |
| LATEST: ${{ steps.versions.outputs.latest }} | |
| run: | | |
| set -euo pipefail | |
| sed -i "s|tag = \"${CURRENT}\"|tag = \"${LATEST}\"|" Cargo.toml | |
| sed -i "s|this\.version = \"[^\"]*\"|this.version = \"${LATEST}\"|" Application.cfc | |
| # Prove both edits landed: a sed pattern that matches nothing still | |
| # exits 0, and the run would commit a bump that never happened. | |
| grep -q "tag = \"${LATEST}\"" Cargo.toml \ | |
| || { echo "::error::Cargo.toml does not pin ${LATEST}"; exit 1; } | |
| grep -q "this.version = \"${LATEST}\"" Application.cfc \ | |
| || { echo "::error::Application.cfc does not quote ${LATEST}"; exit 1; } | |
| cargo update -p cfml-worker --precise "${LATEST}" | |
| # The gate that makes committing without review safe. | |
| cargo build --release --target wasm32-unknown-unknown | |
| - name: Commit to main | |
| if: steps.versions.outputs.changed == 'true' | |
| env: | |
| CURRENT: ${{ steps.versions.outputs.current }} | |
| LATEST: ${{ steps.versions.outputs.latest }} | |
| run: | | |
| set -euo pipefail | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git add Cargo.toml Cargo.lock Application.cfc | |
| git commit -m "Rebuild on RustCFML ${LATEST} (was ${CURRENT}) | |
| ${LATEST} was promoted to stable upstream. The Worker's engine pin and | |
| the version the site quotes are bumped together, and wasm32 compiled | |
| against the new engine in CI before this was committed." | |
| git push origin "HEAD:${{ github.ref_name }}" | |
| # Called directly rather than left to the push above: a push authenticated | |
| # with GITHUB_TOKEN does not trigger `on: push` workflows. | |
| deploy: | |
| needs: update | |
| if: needs.update.outputs.changed == 'true' | |
| uses: ./.github/workflows/deploy.yml | |
| secrets: inherit |