diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b0e01b17..ea1a832e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,10 +14,14 @@ jobs: verify-tag: name: Verify tag vs Cargo.toml + package.json + CHANGELOG runs-on: ubuntu-latest + permissions: + contents: read outputs: version: ${{ steps.tag.outputs.version }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - name: Extract version from tag id: tag @@ -37,32 +41,14 @@ jobs: exit 1 fi - - name: Verify Cargo.toml version - run: | - CARGO_VERSION=$(grep -m1 '^version' src-tauri/Cargo.toml | cut -d'"' -f2) - if [ "$CARGO_VERSION" != "${{ steps.tag.outputs.version }}" ]; then - echo "::error::Cargo.toml version ($CARGO_VERSION) != tag (${{ steps.tag.outputs.version }})" - exit 1 - fi - - - name: Verify package.json version - run: | - PKG_VERSION=$(node -p "require('./package.json').version") - if [ "$PKG_VERSION" != "${{ steps.tag.outputs.version }}" ]; then - echo "::error::package.json version ($PKG_VERSION) != tag (${{ steps.tag.outputs.version }})" - exit 1 - fi - - - name: Verify CHANGELOG entry - run: | - VERSION='${{ steps.tag.outputs.version }}' - # Use fixed-string match for version prefix to avoid `.` matching any - # char (e.g., `1X2X3` accepted by an unescaped regex). - if ! grep -qF "## [${VERSION}]" CHANGELOG.md \ - && ! grep -qF "## ${VERSION}" CHANGELOG.md; then - echo "::error::CHANGELOG.md has no section for version ${VERSION}" - exit 1 - fi + - name: Verify release version coherence + # Checks package.json, Cargo.toml, tauri.conf.json (app + wix) and + # the CHANGELOG section against the tag. Same script as the local + # pre-tag check documented in RELEASING.md. Version goes through env, + # not inline interpolation, so tag names can't inject into the shell. + env: + VERSION: ${{ steps.tag.outputs.version }} + run: bash scripts/check-release-versions.sh "$VERSION" create-release: name: Create GitHub Release @@ -74,7 +60,9 @@ jobs: release_id: ${{ steps.create_release.outputs.id }} upload_url: ${{ steps.create_release.outputs.upload_url }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - name: Verify updater pubkey is configured run: | @@ -103,7 +91,7 @@ jobs: - name: Create GitHub Release id: create_release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: name: Vortex ${{ github.ref_name }} body: ${{ steps.meta.outputs.body }} @@ -118,7 +106,9 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - name: Install Linux dependencies run: | @@ -130,7 +120,7 @@ jobs: libappindicator3-dev \ librsvg2-dev - - uses: actions/setup-node@v4 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: 22 cache: npm @@ -138,9 +128,9 @@ jobs: - name: Install frontend dependencies run: npm ci - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: workspaces: src-tauri @@ -151,19 +141,19 @@ jobs: run: npx tauri build - name: Upload .deb to release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: src-tauri/target/release/bundle/deb/*.deb - name: Upload .rpm to release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: src-tauri/target/release/bundle/rpm/*.rpm - name: Upload updater bundle to release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: | @@ -193,9 +183,11 @@ jobs: TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - - uses: actions/setup-node@v4 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: 22 cache: npm @@ -203,11 +195,11 @@ jobs: - name: Install frontend dependencies run: npm ci - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable with: targets: aarch64-apple-darwin,x86_64-apple-darwin - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: workspaces: src-tauri @@ -251,13 +243,13 @@ jobs: xcrun stapler staple "$DMG" - name: Upload .dmg to release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: src-tauri/target/universal-apple-darwin/release/bundle/dmg/*.dmg - name: Upload updater bundle to release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: | @@ -271,9 +263,11 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - - uses: actions/setup-node@v4 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: 22 cache: npm @@ -281,9 +275,9 @@ jobs: - name: Install frontend dependencies run: npm ci - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: workspaces: src-tauri @@ -308,13 +302,13 @@ jobs: run: Remove-Item -Path certificate.p12 -ErrorAction SilentlyContinue - name: Upload .msi to release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: src-tauri/target/release/bundle/msi/*.msi - name: Upload updater bundle to release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: | @@ -328,7 +322,9 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - name: Install Flatpak tools run: | @@ -344,7 +340,7 @@ jobs: flatpak build-bundle _repo vortex.flatpak org.vortex.Vortex - name: Upload .flatpak to release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: vortex.flatpak @@ -356,7 +352,9 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - name: Download signature files from release env: @@ -412,7 +410,52 @@ jobs: EOF - name: Upload latest.json to release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: latest.json + + checksums: + name: Publish SHA-256 checksums + provenance + needs: [publish-flatpak, update-updater] + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false + + - name: Download release assets + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG_NAME: ${{ github.ref_name }} + run: | + mkdir -p assets + gh release download "$TAG_NAME" --repo "$GITHUB_REPOSITORY" --dir assets + # On a re-run the previous checksum files are release assets too; + # they must not end up inside the new SHA256SUMS. + rm -f assets/SHA256SUMS assets/PROVENANCE.txt + + - name: Generate SHA256SUMS and PROVENANCE.txt + env: + TAG_NAME: ${{ github.ref_name }} + run: | + # git rev-list resolves annotated tags to the tagged commit; + # GITHUB_SHA is not reliable for that on tag pushes. + COMMIT=$(git rev-list -n1 "$TAG_NAME") + (cd assets && sha256sum *) > SHA256SUMS + { + echo "tag: $TAG_NAME" + echo "commit: $COMMIT" + echo "workflow_run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" + echo "verify: sha256sum --check --ignore-missing SHA256SUMS" + } > PROVENANCE.txt + + - name: Upload SHA256SUMS and PROVENANCE.txt + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + files: | + SHA256SUMS + PROVENANCE.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index b8e18b87..a473ebd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.3.0-beta.1] - 2026-07-19 + +### Highlights + +- CI is now the merge gate: a three-OS matrix (tests, lint, audits, Tauri + packaging), secrets scans, a blocking desktop E2E smoke test, and + reproducible plugin CI with checksummed release artifacts. +- Premium accounts work end to end: real validation, per-service selection, + rotation on quota or cooldown, credentials confined to the OS keyring. +- MediaFire, PixelDrain and Gofile pages are resolved by their hoster plugins + before transfer — HTML pages can no longer be saved as "successful" files. +- Galleries expand into selectable per-image rows in Link Grabber. +- Settings, plugin catalog and docs now match real capabilities: every visible + control either works or is explicitly marked as planned. + +### Known limitations + +- No CAPTCHA solving yet: 1fichier free downloads that require a CAPTCHA are + not supported. +- MEGA downloads are refused with an explicit error until host-side decryption + ships; the plugin only parses and validates links. +- No remote access: the REST API, WebSocket and Web UI do not exist yet; the + Remote Access settings section shows a planned-feature notice. +- Speed limit, disk pre-allocation and DNS-over-HTTPS settings are disabled + ("Coming soon"). +- macOS and Windows binaries ship unsigned; Gatekeeper/SmartScreen warnings + are expected. + +### Upgrade notes (from v0.2.0-beta) + +- SQLite migrations run automatically on first launch (adds the + premium-accounts wiring migration); existing downloads, packages, history + and accounts are preserved. +- `config.toml` keeps the same format; an invalid hand-edited `user_agent` + now falls back to the default instead of aborting startup. +- Installed plugins keep working: every registry entry declares + `min_vortex_version` ≤ 0.2.0, which this release satisfies. Updating + plugins from the Plugins view is still recommended to pick up the fixes + below. + ### Security - **MAT-132 transient premium URLs**: link analysis, IPC, queued downloads, and diff --git a/README.md b/README.md index 1a11f14e..9066469d 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,9 @@ Open-source desktop download manager — successor to JDownloader. Tauri 2 + Rust backend + React 19 frontend, hexagonal architecture, CQRS, WASM plugin system (Extism). -> **Status: v0.2.0-beta** (2026-04-28). Phase 0 of the v2 roadmap shipped — every UI view is wired to a real backend, integrity checking via SHA-256/MD5, dynamic segment splitting, queue reorder, change directory, plugin config UI, history/statistics dashboards. Targeted at testers; REST API, browser extension and headless CLI are deferred to v0.3+. See [CHANGELOG.md](CHANGELOG.md) for the full feature list and [PRD-v2.md](PRD-v2.md) for the v1.0 roadmap. +> **Status: v0.3.0-beta.1** (2026-07-19). Phase 1 of the v2 roadmap shipped — premium accounts (keyring-backed) wired end to end, file hosters (MediaFire, PixelDrain, Gofile), container files (DLC/CCF/RSDF/Metalink), per-image gallery rows in the Link Grabber, and a three-OS CI merge gate with a blocking E2E smoke test. Targeted at testers; CAPTCHA solving, MEGA decryption, REST API and browser extension are deferred to v0.4+. See [CHANGELOG.md](CHANGELOG.md) for the full feature list and [PRD-v2.md](PRD-v2.md) for the v1.0 roadmap. -## Install (v0.2.0-beta) +## Install (v0.3.0-beta.1) > ⚠️ Beta binaries on macOS and Windows ship **unsigned**. First-launch Gatekeeper / SmartScreen warnings are expected — see the per-platform notes below to bypass them. @@ -19,16 +19,16 @@ Open-source desktop download manager — successor to JDownloader. Tauri 2 + Rus | Format | Command | |--------|---------| -| Debian / Ubuntu (`.deb`) | `wget https://github.com/mpiton/vortex/releases/download/v0.2.0-beta/Vortex_0.2.0-beta_amd64.deb && sudo dpkg -i Vortex_0.2.0-beta_amd64.deb` | -| Fedora / RHEL (`.rpm`) | `sudo rpm -i https://github.com/mpiton/vortex/releases/download/v0.2.0-beta/Vortex-0.2.0-beta-1.x86_64.rpm` | -| Portable (`.AppImage`) | `wget https://github.com/mpiton/vortex/releases/download/v0.2.0-beta/Vortex_0.2.0-beta_amd64.AppImage && chmod +x Vortex_*.AppImage && ./Vortex_*.AppImage` | -| Flatpak | `flatpak install --user vortex.flatpak` (download from the [release page](https://github.com/mpiton/vortex/releases/tag/v0.2.0-beta)) | +| Debian / Ubuntu (`.deb`) | `wget https://github.com/mpiton/vortex/releases/download/v0.3.0-beta.1/Vortex_0.3.0-beta.1_amd64.deb && sudo dpkg -i Vortex_0.3.0-beta.1_amd64.deb` | +| Fedora / RHEL (`.rpm`) | `sudo rpm -i https://github.com/mpiton/vortex/releases/download/v0.3.0-beta.1/Vortex-0.3.0-beta.1-1.x86_64.rpm` | +| Portable (`.AppImage`) | `wget https://github.com/mpiton/vortex/releases/download/v0.3.0-beta.1/Vortex_0.3.0-beta.1_amd64.AppImage && chmod +x Vortex_0.3.0-beta.1_amd64.AppImage && ./Vortex_0.3.0-beta.1_amd64.AppImage` | +| Flatpak | `flatpak install --user vortex.flatpak` (download from the [release page](https://github.com/mpiton/vortex/releases/tag/v0.3.0-beta.1)) | ### macOS (universal — Apple Silicon + Intel) ```bash -curl -LO https://github.com/mpiton/vortex/releases/download/v0.2.0-beta/Vortex_0.2.0-beta_universal.dmg -open Vortex_0.2.0-beta_universal.dmg +curl -LO https://github.com/mpiton/vortex/releases/download/v0.3.0-beta.1/Vortex_0.3.0-beta.1_universal.dmg +open Vortex_0.3.0-beta.1_universal.dmg # Drag Vortex.app to /Applications # First launch: right-click Vortex.app → Open → Open (bypasses Gatekeeper) ``` @@ -42,14 +42,17 @@ xattr -dr com.apple.quarantine /Applications/Vortex.app | Format | Notes | |--------|-------| -| MSI installer | [`Vortex_0.2.0-beta_x64_en-US.msi`](https://github.com/mpiton/vortex/releases/download/v0.2.0-beta/Vortex_0.2.0-beta_x64_en-US.msi) — recommended for system-wide install | -| NSIS setup | [`Vortex_0.2.0-beta_x64-setup.exe`](https://github.com/mpiton/vortex/releases/download/v0.2.0-beta/Vortex_0.2.0-beta_x64-setup.exe) — per-user install | +| MSI installer | [`Vortex_0.3.0-beta.1_x64_en-US.msi`](https://github.com/mpiton/vortex/releases/download/v0.3.0-beta.1/Vortex_0.3.0-beta.1_x64_en-US.msi) — recommended for system-wide install | +| NSIS setup | [`Vortex_0.3.0-beta.1_x64-setup.exe`](https://github.com/mpiton/vortex/releases/download/v0.3.0-beta.1/Vortex_0.3.0-beta.1_x64-setup.exe) — per-user install | SmartScreen will warn "Windows protected your PC" → click *More info* → *Run anyway*. -## Features (v0.2.0-beta) +## Features (v0.3.0-beta.1) - **Segmented downloads** — parallel HTTP Range workers with dynamic split (slow-tail rebalancing) and `.vortex-meta` resume across restarts +- **Premium accounts** — add hoster credentials (stored in the OS keyring), validated and injected into plugin requests end to end +- **File hosters** — MediaFire, PixelDrain and Gofile link resolution; MEGA and 1fichier-free links are detected and refused with an explicit reason (no CAPTCHA solver, no host-side decryption yet) +- **Container files** — DLC / CCF / RSDF / Metalink import in the Link Grabber - **Queue manager** — drag-and-drop reorder, Move-to-top / -bottom, priority-aware scheduling, configurable concurrency (1-20) - **Integrity** — SHA-256 / MD5 verification on completion, mismatch surfaces with expected vs. computed hash - **History view** — group-by-day, filter tabs, debounced search, CSV / JSON export, retention purge worker (7 / 30 / 90 / 365 / unlimited days) @@ -131,7 +134,7 @@ A typed SDK crate (`vortex-plugin-sdk`) is on the v1.0 roadmap to make this fast | Version | Target | Theme | |---------|--------|-------| | ✅ **v0.2.0-beta** | 2026-04-28 | Phase 0 — every placeholder view replaced, integrity, queue UX, plugin config UI | -| v0.3 | 2026-07-01 | Phase 1 — Accounts (premium), Packages, file hosters (MEGA, MediaFire, 1fichier…), containers (DLC/CCF/RSDF/Metalink) | +| ✅ **v0.3.0-beta.1** | 2026-07-19 | Phase 1 — Accounts (premium), file hosters (MediaFire, PixelDrain, Gofile), containers (DLC/CCF/RSDF/Metalink), gallery rows, CI merge gate + E2E smoke | | v0.4 | 2026-09-15 | Phase 2 — CAPTCHA pipeline, Real-Debrid / AllDebrid, Scheduler, automation rules, reconnect IP | | v1.0 | 2026-12-15 | Phase 3 — REST API + WebSocket, Web UI, browser extension, Click'n'Load, headless mode, i18n, Flathub | @@ -141,8 +144,8 @@ See [`PRD-v2.md`](PRD-v2.md) for the per-task breakdown. This is a **beta release** — bugs, rough edges and missing flows are expected. Two channels: -- **Bugs** → [open an issue](https://github.com/mpiton/vortex/issues/new?template=bug_report.yml) with the *Vortex version* dropdown set to `v0.2.0-beta` -- **Discussions** → [v0.2.0-beta feedback thread](https://github.com/mpiton/vortex/discussions) for general impressions, missing features, plugin requests +- **Bugs** → [open an issue](https://github.com/mpiton/vortex/issues/new?template=bug_report.yml) with the *Vortex version* dropdown set to `v0.3.0-beta.1` +- **Discussions** → [GitHub Discussions](https://github.com/mpiton/vortex/discussions) for general impressions, missing features, plugin requests ## License diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 00000000..beea85a8 --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,93 @@ +# Releasing Vortex + +Checklist for cutting an app release (example: `v0.3.0-beta.1`). Each item maps to an +acceptance criterion R-01 → R-07 of the release ticket. Nothing here pushes a tag — +publication is the explicit human decision at the very end. + +## 1. Prerequisites + +- [ ] All blocking tickets of the release ticket are Done. +- [ ] `main` is green (CI merge gate: fmt, clippy `-D warnings`, `cargo test --workspace`, + vitest, oxlint, 3-OS build matrix, E2E smoke, plugin CI). **(R-01)** +- [ ] Working tree clean, on a release-prep branch created from up-to-date `main`. + +## 2. Version bump + +Update the version in: + +- `package.json` (+ `package-lock.json` via `npm install --package-lock-only --ignore-scripts`) +- `src-tauri/Cargo.toml` (+ `Cargo.lock` via `cargo update -p vortex --offline`) +- `src-tauri/tauri.conf.json` — `version`, and `bundle.windows.wix.version` + (numeric `x.y.z.w`: keep the semver core, bump the 4th digit per beta iteration, + e.g. `0.3.0-beta.1` → `0.3.0.1`) + +Then verify: + +```bash +scripts/check-release-versions.sh 0.3.0-beta.1 +``` + +The same script runs in CI (`release.yml` → verify-tag), so a mismatch also fails the +tag build. **(R-02)** + +## 3. Changelog and docs + +- [ ] `CHANGELOG.md`: cut a `## [] - YYYY-MM-DD` section from `[Unreleased]`, + with Highlights, Known limitations and Upgrade notes. Use the full version, + prerelease suffix included (e.g. `## [0.3.0-beta.1] - 2026-07-19`) — the + version script greps for that exact heading. +- [ ] Release notes claim **only verified capabilities** — no CAPTCHA solving, no MEGA + decryption, no remote access (REST/WS/Web UI) until they actually ship. **(R-06)** +- [ ] `README.md`: status line, install URLs/filenames, features heading, roadmap row, + feedback links. Asset filenames are predictions until CI builds them — re-check + against the real release assets after the tag build (step 6). + +## 4. Plugins + +- [ ] Every plugin in `registry/registry.toml` passes its own CI (WASM build + `wasm32-wasip1` + ABI smoke). **(R-05)** +- [ ] `cargo test --workspace` includes `registry_coherence` — registry versions, + checksums format and `min_vortex_version` compatibility are asserted there. +- [ ] Registry `checksum_sha256` values come from each plugin's CI release + `SHA256SUMS`, never from a local wasm build (local builds are not + byte-reproducible). + +## 5. Pre-tag audit + +- [ ] `cargo audit` / `npm audit` clean or triaged. **(R-01)** +- [ ] No secrets in the diff, no stale artifacts, no `specs/` files tracked + (`git ls-files | grep -E '^specs/'` must be empty). **(R-07)** +- [ ] Full local suite one last time: + +```bash +cargo clippy --workspace -- -D warnings +cargo test --workspace +npx vitest run +npx oxlint . +scripts/check-release-versions.sh +``` + +## 6. Tag → CI does the rest + +Pushing the tag **is** publishing. It is a deliberate human action, never automated: + +```bash +git tag -a v0.3.0-beta.1 -m "v0.3.0-beta.1" +git push origin v0.3.0-beta.1 +``` + +`release.yml` then: verifies versions (step 2's script), creates the GitHub Release +(prerelease if the tag contains `-`), builds Linux/macOS/Windows bundles, publishes +the flatpak, updates the updater manifest, and uploads `SHA256SUMS` + +`PROVENANCE.txt` (tagged commit + workflow run URL). **(R-03)** + +## 7. Post-build verification + +- [ ] Download one bundle per OS, `sha256sum --check --ignore-missing SHA256SUMS`. **(R-03)** +- [ ] Clean install boots to the Downloads view. **(R-04)** +- [ ] Upgrade over the previous version preserves `config.toml`, `vortex.db` and + in-flight downloads (SQLite migrations run automatically). **(R-04)** +- [ ] README install commands match the actual asset filenames (fix forward if not). + +If a check fails after the tag: fix on a branch, bump to the next iteration +(`-beta.2`), and go back to step 2. Never move or reuse a published tag. diff --git a/package-lock.json b/package-lock.json index a912ac14..c191312c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vortex", - "version": "0.2.0-beta", + "version": "0.3.0-beta.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vortex", - "version": "0.2.0-beta", + "version": "0.3.0-beta.1", "dependencies": { "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", diff --git a/package.json b/package.json index 0000b353..19761667 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vortex", - "version": "0.2.0-beta", + "version": "0.3.0-beta.1", "private": true, "type": "module", "scripts": { diff --git a/scripts/check-release-versions.sh b/scripts/check-release-versions.sh new file mode 100755 index 00000000..0048c7ff --- /dev/null +++ b/scripts/check-release-versions.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# Verify that every version declaration agrees before tagging a release. +# Usage: scripts/check-release-versions.sh [expected-version] +# Without an argument, package.json is the reference. Invoked locally from +# RELEASING.md and in CI by the release.yml verify-tag job. +set -euo pipefail + +cd "$(dirname "$0")/.." + +fail=0 +err() { + echo "::error::$*" >&2 + fail=1 +} + +pkg_version=$(node -p "require('./package.json').version") +cargo_version=$(grep -m1 '^version' src-tauri/Cargo.toml | cut -d'"' -f2) +tauri_version=$(node -p "require('./src-tauri/tauri.conf.json').version") +wix_version=$(node -p "require('./src-tauri/tauri.conf.json').bundle.windows.wix.version") + +expected="${1:-$pkg_version}" + +[ "$pkg_version" = "$expected" ] || err "package.json version ($pkg_version) != expected ($expected)" +[ "$cargo_version" = "$expected" ] || err "src-tauri/Cargo.toml version ($cargo_version) != expected ($expected)" +[ "$tauri_version" = "$expected" ] || err "src-tauri/tauri.conf.json version ($tauri_version) != expected ($expected)" + +# Windows MSI needs a strictly numeric x.y.z.w version whose x.y.z prefix +# matches the semver core of the release (prerelease suffix stripped). +core="${expected%%-*}" +if ! [[ "$wix_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ && "$wix_version" == "$core".* ]]; then + err "tauri.conf.json wix version ($wix_version) must be numeric x.y.z.w starting with $core." +fi + +# Fixed-string match: a `.` in an unescaped regex would match any character. +if ! grep -qF "## [${expected}]" CHANGELOG.md; then + err "CHANGELOG.md has no section for version ${expected}" +fi + +if [ "$fail" -ne 0 ]; then + exit 1 +fi +echo "OK: all release version declarations agree on ${expected} (wix: ${wix_version})" diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 0a1761aa..245ab50c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -7425,7 +7425,7 @@ checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" [[package]] name = "vortex" -version = "0.2.0-beta" +version = "0.3.0-beta.1" dependencies = [ "aes-gcm", "anyhow", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index befecb7b..f6d3553e 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vortex" -version = "0.2.0-beta" +version = "0.3.0-beta.1" description = "A desktop download manager" authors = ["mpiton"] edition = "2024" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 6fe9479a..88004344 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "Vortex", - "version": "0.2.0-beta", + "version": "0.3.0-beta.1", "identifier": "dev.vortex.app", "build": { "frontendDist": "../dist", @@ -36,7 +36,7 @@ ], "windows": { "wix": { - "version": "0.2.0.1" + "version": "0.3.0.1" } } },