From a4397d48de7f7b8b75d7c0d22744a1c6a230a529 Mon Sep 17 00:00:00 2001 From: lucaronin Date: Sun, 12 Apr 2026 22:14:53 +0200 Subject: [PATCH] fix: split alpha and stable release channels --- ...{release-canary.yml => release-stable.yml} | 74 +-- .github/workflows/release.yml | 79 ++-- docs/ABSTRACTIONS.md | 21 +- docs/ARCHITECTURE.md | 58 ++- docs/GETTING-STARTED.md | 7 + ...table-release-channels-and-beta-cohorts.md | 44 ++ docs/adr/README.md | 3 +- src-tauri/src/app_updater.rs | 179 +++++++ src-tauri/src/commands/system.rs | 48 ++ src-tauri/src/lib.rs | 3 + src-tauri/src/settings.rs | 77 +++- src-tauri/tauri.conf.json | 2 +- src/App.tsx | 2 +- src/components/SettingsPanel.test.tsx | 76 +-- src/components/SettingsPanel.tsx | 435 ++++++++++++------ src/hooks/useSettings.test.ts | 5 +- src/hooks/useSettings.ts | 17 +- src/hooks/useUpdater.test.ts | 342 +++++++------- src/hooks/useUpdater.ts | 90 ++-- src/lib/appUpdater.ts | 37 ++ src/lib/releaseChannel.test.ts | 38 ++ src/lib/releaseChannel.ts | 13 + .../canary-release-feature-flags.spec.ts | 50 -- tests/smoke/release-channel-settings.spec.ts | 52 +++ 24 files changed, 1227 insertions(+), 525 deletions(-) rename .github/workflows/{release-canary.yml => release-stable.yml} (83%) create mode 100644 docs/adr/0057-alpha-stable-release-channels-and-beta-cohorts.md create mode 100644 src-tauri/src/app_updater.rs create mode 100644 src/lib/appUpdater.ts create mode 100644 src/lib/releaseChannel.test.ts create mode 100644 src/lib/releaseChannel.ts delete mode 100644 tests/smoke/canary-release-feature-flags.spec.ts create mode 100644 tests/smoke/release-channel-settings.spec.ts diff --git a/.github/workflows/release-canary.yml b/.github/workflows/release-stable.yml similarity index 83% rename from .github/workflows/release-canary.yml rename to .github/workflows/release-stable.yml index a27b4153..77e83e7a 100644 --- a/.github/workflows/release-canary.yml +++ b/.github/workflows/release-stable.yml @@ -1,31 +1,32 @@ -name: Release (Canary) +name: Release (Stable) on: push: - branches: - - canary + tags: + - 'stable-v*' concurrency: - group: release-canary-${{ github.ref }} + group: release-stable-${{ github.ref }} cancel-in-progress: true jobs: # ───────────────────────────────────────────────────────────── - # Phase 1: Compute the canary version string + # Phase 1: Compute the stable version string once # ───────────────────────────────────────────────────────────── version: - name: Compute version + name: Compute stable version runs-on: ubuntu-latest outputs: version: ${{ steps.ver.outputs.version }} tag: ${{ steps.ver.outputs.tag }} steps: - id: ver + shell: bash run: | - VERSION="0.$(date -u +%Y%m%d).${GITHUB_RUN_NUMBER}-canary" + VERSION="${GITHUB_REF_NAME#stable-v}" echo "version=$VERSION" >> "$GITHUB_OUTPUT" - echo "tag=v$VERSION" >> "$GITHUB_OUTPUT" - echo "### Canary version: \`$VERSION\`" >> "$GITHUB_STEP_SUMMARY" + echo "tag=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT" + echo "### Stable version: \`$VERSION\`" >> "$GITHUB_STEP_SUMMARY" # ───────────────────────────────────────────────────────────── # Phase 2: Build each architecture in parallel @@ -131,10 +132,10 @@ jobs: retention-days: 1 # ───────────────────────────────────────────────────────────── - # Phase 3: Publish GitHub Release (prerelease) + # Phase 3: Publish GitHub Release # ───────────────────────────────────────────────────────────── release: - name: GitHub Release (canary) + name: GitHub Release (stable) needs: [version, build] runs-on: ubuntu-latest permissions: @@ -149,26 +150,26 @@ jobs: - name: Generate release notes run: | - PREV_TAG=$(git tag --sort=-version:refname | grep canary | head -n 1 || echo "") + PREV_TAG=$(git tag --list 'stable-v*' --sort=-version:refname | grep -vx "${{ needs.version.outputs.tag }}" | head -n 1 || echo "") if [ -z "$PREV_TAG" ]; then NOTES=$(git log --oneline --no-merges -20) else - NOTES=$(git log --oneline --no-merges "${PREV_TAG}..HEAD") + NOTES=$(git log --oneline --no-merges "${PREV_TAG}..${{ needs.version.outputs.tag }}") fi { - echo "## What's Changed (Canary)" + echo "## What's Changed" echo "" echo "$NOTES" | while IFS= read -r line; do echo "- $line"; done echo "" echo "---" - echo "**Canary build — pre-release, may be unstable**" + echo "**Stable release — manually promoted from \`main\`**" echo "" echo "**Requires Apple Silicon (M1/M2/M3)**" echo "" - echo "*Built from \`$(git rev-parse --short HEAD)\` on $(date -u +%Y-%m-%d)*" + echo "*Built from \`$(git rev-parse --short ${{ needs.version.outputs.tag }})\` on $(date -u +%Y-%m-%d)*" } > release_notes.md - - name: Build latest-canary.json + - name: Build stable-latest.json run: | VERSION="${{ needs.version.outputs.version }}" TAG="${{ needs.version.outputs.tag }}" @@ -179,10 +180,10 @@ jobs: ARM_SIG=$(cat updater-aarch64/*.app.tar.gz.sig) ARM_TARBALL=$(ls updater-aarch64/*.app.tar.gz | xargs basename) - cat > latest-canary.json << EOF + cat > stable-latest.json << EOF { "version": "${VERSION}", - "notes": "Canary build. See ${PAGES_URL} for release notes.", + "notes": "Stable release. See ${PAGES_URL} for full release notes.", "pub_date": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", "platforms": { "darwin-aarch64": { @@ -192,24 +193,24 @@ jobs: } } EOF - echo "latest-canary.json:"; cat latest-canary.json + echo "stable-latest.json:"; cat stable-latest.json - - name: Publish GitHub Release (prerelease) + - name: Publish GitHub Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ needs.version.outputs.tag }} - name: Tolaria ${{ needs.version.outputs.version }} (Canary) + name: Tolaria ${{ needs.version.outputs.version }} body_path: release_notes.md draft: false - prerelease: true + prerelease: false files: | dmg-aarch64/*.dmg updater-aarch64/*.app.tar.gz updater-aarch64/*.app.tar.gz.sig - latest-canary.json + stable-latest.json # ───────────────────────────────────────────────────────────── - # Phase 4: Update GitHub Pages (preserve stable latest.json) + # Phase 4: Update GitHub Pages # ───────────────────────────────────────────────────────────── pages: name: Update release history page @@ -227,13 +228,16 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - mkdir -p _site + mkdir -p _site/alpha _site/stable gh api repos/${{ github.repository }}/releases --paginate > _site/releases.json PAGES_URL="https://refactoringhq.github.io/${GITHUB_REPOSITORY#*/}" - # Download stable latest.json from existing GH Pages (preserve it) - curl -fsSL "${PAGES_URL}/latest.json" -o _site/latest.json || echo '{}' > _site/latest.json - # Copy canary latest.json from this release - gh release download --repo ${{ github.repository }} "${{ needs.version.outputs.tag }}" --pattern "latest-canary.json" --output _site/latest-canary.json || true + + curl -fsSL "${PAGES_URL}/alpha/latest.json" -o _site/alpha/latest.json || echo '{}' > _site/alpha/latest.json + gh release download --repo ${{ github.repository }} "${{ needs.version.outputs.tag }}" --pattern "stable-latest.json" --output _site/stable/latest.json || echo '{}' > _site/stable/latest.json + + cp _site/alpha/latest.json _site/latest.json + cp _site/alpha/latest.json _site/latest-canary.json + cat > _site/index.html << 'HTMLEOF' @@ -253,13 +257,13 @@ jobs: .release .downloads { margin-top: 0.75rem; display: flex; gap: 0.5rem; flex-wrap: wrap; } .release .downloads a { display: inline-block; padding: 0.375rem 0.75rem; background: #155DFF; color: #fff; border-radius: 6px; text-decoration: none; font-size: 0.8125rem; font-weight: 500; } .release .downloads a:hover { background: #1248CC; } - .canary { border-left: 3px solid #f59e0b; } + .alpha { border-left: 3px solid #f59e0b; } .empty { color: #787774; text-align: center; padding: 3rem; }

Tolaria Release History

-

Auto-updated on every release

+

Alpha builds update on every push to main. Stable builds appear when a stable-vX.Y.Z tag is promoted.