From de38e636a4131600e04efb5c3252c9f8f2096e21 Mon Sep 17 00:00:00 2001 From: Mathieu Piton <27002047+mpiton@users.noreply.github.com> Date: Sun, 19 Jul 2026 09:05:10 +0200 Subject: [PATCH 1/2] chore(release): prepare v0.3.0-beta.1 (MAT-137) Bump every version declaration to 0.3.0-beta.1 (package.json, Cargo.toml, tauri.conf.json app + wix, lockfiles) and add scripts/check-release-versions.sh so local pre-tag checks and the CI verify-tag job run the same coherence check, now covering tauri.conf.json and the wix version which CI never verified before. release.yml: pin all actions by commit SHA, replace the three inline version checks with the shared script (version passed via env, not inline interpolation), and add a checksums job that publishes SHA256SUMS and PROVENANCE.txt (tagged commit + workflow run URL) on every release. Cut the CHANGELOG 0.3.0-beta.1 section with honest known limitations (no CAPTCHA, MEGA refused, no remote access) and upgrade notes, update README to the new version, and document the whole flow in RELEASING.md. Pushing the tag stays a manual decision, per the ticket. --- .github/workflows/release.yml | 129 ++++++++++++++++++------------ CHANGELOG.md | 40 +++++++++ README.md | 31 +++---- RELEASING.md | 91 +++++++++++++++++++++ package-lock.json | 4 +- package.json | 2 +- scripts/check-release-versions.sh | 43 ++++++++++ src-tauri/Cargo.lock | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 4 +- 10 files changed, 275 insertions(+), 73 deletions(-) create mode 100644 RELEASING.md create mode 100755 scripts/check-release-versions.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b0e01b17..891cf054 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,7 +17,7 @@ jobs: outputs: version: ${{ steps.tag.outputs.version }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Extract version from tag id: tag @@ -37,32 +37,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 +56,7 @@ 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 - name: Verify updater pubkey is configured run: | @@ -103,7 +85,7 @@ jobs: - name: Create GitHub Release id: create_release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 with: name: Vortex ${{ github.ref_name }} body: ${{ steps.meta.outputs.body }} @@ -118,7 +100,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Install Linux dependencies run: | @@ -130,7 +112,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 +120,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 +133,19 @@ jobs: run: npx tauri build - name: Upload .deb to release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.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@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.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@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: | @@ -193,9 +175,9 @@ 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 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: 22 cache: npm @@ -203,11 +185,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 +233,13 @@ jobs: xcrun stapler staple "$DMG" - name: Upload .dmg to release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.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@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: | @@ -271,9 +253,9 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: 22 cache: npm @@ -281,9 +263,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 +290,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@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.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@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: | @@ -328,7 +310,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Install Flatpak tools run: | @@ -344,7 +326,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@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: vortex.flatpak @@ -356,7 +338,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Download signature files from release env: @@ -412,7 +394,50 @@ jobs: EOF - name: Upload latest.json to release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.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 + + - 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@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.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..2a7278fc 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_*.AppImage && ./Vortex_*.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** → [v0.3.0-beta.1 feedback thread](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..e966577a --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,91 @@ +# 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 `## [X.Y.Z] - YYYY-MM-DD` section from `[Unreleased]`, + with Highlights, Known limitations and Upgrade notes. +- [ ] 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..1ef3274d --- /dev/null +++ b/scripts/check-release-versions.sh @@ -0,0 +1,43 @@ +#!/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 numeric x.y.z.w version: its x.y.z prefix must match +# the semver core of the release (prerelease suffix stripped). +core="${expected%%-*}" +case "$wix_version" in + "$core".*) ;; + *) err "tauri.conf.json wix version ($wix_version) does not start with $core." ;; +esac + +# 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" } } }, From d87537e944490f809e1cafe9802c733b8eb202fb Mon Sep 17 00:00:00 2001 From: Mathieu Piton <27002047+mpiton@users.noreply.github.com> Date: Sun, 19 Jul 2026 09:22:13 +0200 Subject: [PATCH 2/2] chore(release): harden release.yml and version script per review verify-tag gets contents: read, every checkout stops persisting the workflow token (nothing in the pipeline pushes via git), and the action-gh-release pins move from v2.6.2 to v3.0.2. The wix version check now requires strictly numeric x.y.z.w instead of a prefix match, README launches the AppImage by exact filename and links Discussions without promising a thread that doesn't exist yet, and RELEASING.md spells out that the changelog heading keeps the prerelease suffix. --- .github/workflows/release.yml | 40 ++++++++++++++++++++++--------- README.md | 4 ++-- RELEASING.md | 6 +++-- scripts/check-release-versions.sh | 11 ++++----- 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 891cf054..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@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - name: Extract version from tag id: tag @@ -57,6 +61,8 @@ jobs: upload_url: ${{ steps.create_release.outputs.upload_url }} steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - name: Verify updater pubkey is configured run: | @@ -85,7 +91,7 @@ jobs: - name: Create GitHub Release id: create_release - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: name: Vortex ${{ github.ref_name }} body: ${{ steps.meta.outputs.body }} @@ -101,6 +107,8 @@ jobs: contents: write steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - name: Install Linux dependencies run: | @@ -133,19 +141,19 @@ jobs: run: npx tauri build - name: Upload .deb to release - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 + 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@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 + 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@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: | @@ -176,6 +184,8 @@ jobs: TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: @@ -233,13 +243,13 @@ jobs: xcrun stapler staple "$DMG" - name: Upload .dmg to release - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 + 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@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: | @@ -254,6 +264,8 @@ jobs: contents: write steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: @@ -290,13 +302,13 @@ jobs: run: Remove-Item -Path certificate.p12 -ErrorAction SilentlyContinue - name: Upload .msi to release - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 + 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@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: | @@ -311,6 +323,8 @@ jobs: contents: write steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - name: Install Flatpak tools run: | @@ -326,7 +340,7 @@ jobs: flatpak build-bundle _repo vortex.flatpak org.vortex.Vortex - name: Upload .flatpak to release - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: vortex.flatpak @@ -339,6 +353,8 @@ jobs: contents: write steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - name: Download signature files from release env: @@ -394,7 +410,7 @@ jobs: EOF - name: Upload latest.json to release - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: latest.json @@ -407,6 +423,8 @@ jobs: contents: write steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - name: Download release assets env: @@ -435,7 +453,7 @@ jobs: } > PROVENANCE.txt - name: Upload SHA256SUMS and PROVENANCE.txt - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2 with: token: ${{ secrets.GITHUB_TOKEN }} files: | diff --git a/README.md b/README.md index 2a7278fc..9066469d 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Open-source desktop download manager — successor to JDownloader. Tauri 2 + Rus |--------|---------| | 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_*.AppImage && ./Vortex_*.AppImage` | +| 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) @@ -145,7 +145,7 @@ 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.3.0-beta.1` -- **Discussions** → [v0.3.0-beta.1 feedback thread](https://github.com/mpiton/vortex/discussions) for general impressions, missing features, plugin requests +- **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 index e966577a..beea85a8 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -32,8 +32,10 @@ tag build. **(R-02)** ## 3. Changelog and docs -- [ ] `CHANGELOG.md`: cut a `## [X.Y.Z] - YYYY-MM-DD` section from `[Unreleased]`, - with Highlights, Known limitations and Upgrade notes. +- [ ] `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, diff --git a/scripts/check-release-versions.sh b/scripts/check-release-versions.sh index 1ef3274d..0048c7ff 100755 --- a/scripts/check-release-versions.sh +++ b/scripts/check-release-versions.sh @@ -24,13 +24,12 @@ expected="${1:-$pkg_version}" [ "$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 numeric x.y.z.w version: its x.y.z prefix must match -# the semver core of the release (prerelease suffix stripped). +# 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%%-*}" -case "$wix_version" in - "$core".*) ;; - *) err "tauri.conf.json wix version ($wix_version) does not start with $core." ;; -esac +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