From cedd2f08354f93a4d888bde064b33513557ad334 Mon Sep 17 00:00:00 2001 From: ys Date: Mon, 5 Oct 2026 14:55:08 +0100 Subject: [PATCH] ci: validate PRs and prepare 3.0.0 releases Preserve the existing decryption code and version 3.0.0. Run full builds and tests on PRs, publish only matching version tags on main, and include commits in release notes. --- .github/workflows/build-release.yml | 109 +++++++++++++++++++++++----- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 23 ++++++ src/queue.rs | 2 +- 5 files changed, 118 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 1ab7d44..8f4c0a5 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -2,10 +2,9 @@ name: Build and Release PS3Dec on: push: - branches: [main, dev] tags: ['v*'] pull_request: - branches: [main, dev] + branches: [main] workflow_dispatch: permissions: @@ -16,8 +15,64 @@ concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + checks: + name: Rust and Python checks + runs-on: ubuntu-24.04 + timeout-minutes: 15 + env: + CARGO_TERM_COLOR: always + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Verify release tag and versions + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + run: | + if ! git merge-base --is-ancestor "$GITHUB_SHA" origin/main; then + echo "Release tags must point to a commit on main." >&2 + exit 1 + fi + python3 - <<'PY' + import os + import tomllib + from pathlib import Path + + package = tomllib.loads(Path("Cargo.toml").read_text())["package"] + version = package["version"] + tag = os.environ["GITHUB_REF_NAME"] + if tag != f"v{version}": + raise SystemExit(f"Tag {tag} does not match Cargo.toml; expected v{version}.") + lock = tomllib.loads(Path("Cargo.lock").read_text()) + locked = next((p for p in lock["package"] if p["name"] == package["name"] and "source" not in p), None) + if locked is None or locked["version"] != version: + raise SystemExit("Cargo.lock version does not match Cargo.toml; run cargo check and commit both files.") + print(f"Release version verified: {tag}") + PY + + - name: Load the repository's pinned Rust toolchain + run: rustup show active-toolchain + + - name: Cache Rust dependencies + uses: swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 + with: + key: checks + save-if: ${{ github.event_name != 'pull_request' }} + + - name: Check Rust formatting + run: cargo fmt --all -- --check + + - name: Check Python syntax + run: python3 -m compileall -q tests + + - name: Check Rust code with Clippy + run: cargo clippy --locked --all-targets -- -D warnings + build: name: Build ${{ matrix.target }} + needs: checks runs-on: ${{ matrix.os }} timeout-minutes: 45 strategy: @@ -98,7 +153,8 @@ jobs: - name: End-to-end decryption checks if: runner.os == 'Linux' run: | - cargo build --locked --bin ps3dec + mkdir -p target/debug + cp "target/$TARGET/release/$BINARY" "target/debug/$BINARY" python3 -B tests/e2e.py - name: Prepare package @@ -132,8 +188,7 @@ jobs: name: Publish release needs: build if: >- - github.event_name == 'push' && - (github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/v')) + github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-24.04 timeout-minutes: 15 permissions: @@ -142,15 +197,38 @@ jobs: run: shell: bash steps: - - name: Checkout full history for branch validation - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Checkout release history + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: fetch-depth: 0 persist-credentials: false - - name: Verify stable release comes from main - if: startsWith(github.ref, 'refs/tags/') - run: git merge-base --is-ancestor "$GITHUB_SHA" origin/main + - name: Include commits in release notes + run: | + python3 - <<'PY' + import os + import subprocess + from pathlib import Path + + sha = os.environ["GITHUB_SHA"] + previous = subprocess.run( + ["git", "--no-pager", "describe", "--tags", "--match", "v[0-9]*", "--match", "[0-9]*", "--abbrev=0", f"{sha}^"], + capture_output=True, text=True, + ) + commit_range = f"{previous.stdout.strip()}..{sha}" if previous.returncode == 0 else sha + commits = subprocess.run( + ["git", "--no-pager", "log", "--no-merges", "--format=- %s (%h)", commit_range], + capture_output=True, text=True, check=True, + ).stdout + repo_url = f"{os.environ['GITHUB_SERVER_URL']}/{os.environ['GITHUB_REPOSITORY']}" + run_url = f"{repo_url}/actions/runs/{os.environ['GITHUB_RUN_ID']}" + Path("RELEASE_NOTES.md").write_text( + f"Built from commit [{sha}]({repo_url}/commit/{sha}).\n\n" + f"[Build run]({run_url}).\n\n" + "Verify downloads with SHA256SUMS.\n\n" + "## Commits\n\n" + commits, + ) + PY - name: Download all platform archives uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 @@ -166,15 +244,12 @@ jobs: - name: Publish release with generated notes uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1 with: - tag: ${{ github.ref == 'refs/heads/dev' && format('dev-{0}', github.run_number) || github.ref_name }} + tag: ${{ github.ref_name }} commit: ${{ github.sha }} - prerelease: ${{ github.ref == 'refs/heads/dev' }} - makeLatest: ${{ github.ref != 'refs/heads/dev' }} + prerelease: false + makeLatest: true generateReleaseNotes: true - body: | - Built from commit [${{ github.sha }}](${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}). - [Build run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}). - Verify downloads with SHA256SUMS. + bodyFile: RELEASE_NOTES.md artifacts: artifacts/*.tar.gz,artifacts/*.zip,artifacts/SHA256SUMS artifactErrorsFailBuild: true immutableCreate: true diff --git a/Cargo.lock b/Cargo.lock index 16810e8..f4ebb6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -982,7 +982,7 @@ dependencies = [ [[package]] name = "ps3decrs" -version = "2.0.1" +version = "3.0.0" dependencies = [ "aes", "atomicwrites", diff --git a/Cargo.toml b/Cargo.toml index 3a97609..b60ab7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ps3decrs" -version = "2.0.1" +version = "3.0.0" edition = "2024" description = "PS3 ISO decryption tool." repository = "https://github.com/Redrrx/ps3dec" diff --git a/README.md b/README.md index f60f7d9..767d980 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,29 @@ If you visit the releases page you might find two types * Stable == ready to use, reliable enough. * Preview == trying out requests, and toying around before stable. +### creating a release + +You choose the version; nothing bumps it for you. + +| Event | What happens | +|-------|--------------| +| Push to `dev` or merge into `main` | No extra build | +| Open or update a PR into `main` | Rust formatting, Clippy, Python syntax, all six platform builds, and Linux decryption tests | +| Push a `v*` tag | Check the version, build and test, then publish if everything passes | +| Manual run | Full checks and builds, without publishing | + +1. Set your version in `Cargo.toml`, then run `cargo check` to update `Cargo.lock`. +2. Commit both files, open a PR into `main`, and wait for the checks to pass. Require **Rust and Python checks** and all six **Build** checks before merging. +3. Merge the PR, then tag your chosen version from the updated `main`: + +```sh +git switch main +git pull --ff-only origin main +git tag v3.0.0 +git push origin v3.0.0 +``` + +`3.0.0` is an example; use your chosen version and an unused tag. The tag must match `Cargo.toml` and `Cargo.lock`, and point to a commit on `main`. Release notes include commits since the previous version tag and GitHub's generated notes. Linux tests use the release executable already built, so there's no second debug build. ## Acknowledgements diff --git a/src/queue.rs b/src/queue.rs index 3ea43b8..1873ba9 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -349,7 +349,7 @@ pub fn run( return run_tui(args, &pool, logs); } let interactive = io::stderr().is_terminal() && logs.is_none(); - let style = progress_style(); + let style = progress_style(); let _header = interactive.then(|| { let header = ProgressBar::hidden(); header.set_prefix(" # ISO");