# Release Packaging and Local Deployment This document covers the current local release workflow for `aria2-rust-pro`. The scripts under `scripts/release/` cover three concrete needs: - host-runnable `--version` smoke validation; - deterministic local artifact naming plus SHA-256 generation; - packaging of the current workspace's Windows or Linux release binary into a ready-to-share archive. - exporting a locally built Docker image tag into a portable tar archive under `dist\docker\`. As of the Phase 3 Cargo-native workflow push, the primary entrypoints now live in `xtask/`. The PowerShell files under `scripts/release/` remain as thin compatibility shims so existing local habits still work, but the canonical project automation surface is now: ```powershell rtk cargo run --manifest-path .\xtask\Cargo.toml -- release smoke-version rtk cargo run --manifest-path .\xtask\Cargo.toml -- release package-local rtk cargo run --manifest-path .\xtask\Cargo.toml -- docker smoke-local rtk cargo run --manifest-path .\xtask\Cargo.toml -- docker smoke ``` These commands do not update `progress.md` or the compatibility ledger, and they do not claim cross-host release certification by themselves. They are local release helpers for the current workspace state. ## Files - `xtask/`: canonical Cargo-native workflow entrypoints for release smoke and local packaging. - `scripts/release/smoke-version.ps1`: thin shim around `xtask release smoke-version`. - `scripts/release/package-local.ps1`: thin shim around `xtask release package-local`. - `scripts/docker/smoke-local.ps1`: thin shim around `xtask docker smoke-local`. - `scripts/docker/smoke.ps1`: thin shim around `xtask docker smoke`. - `scripts/docker/export-local.ps1`: thin shim around `xtask docker export-local`. - `docs/release/RELEASE-NOTES-TEMPLATE.md`: reusable release-page and handoff template for public-facing releases. ## Artifact naming The package script emits archives named like: - `aria2-rust-pro-v1.0.0-x86_64-pc-windows-msvc.zip` - `aria2-rust-pro-v1.0.0-x86_64-unknown-linux-gnu.tar.gz` The target triple always stays in the file name so mixed-host staging stays unambiguous. Output defaults to the workspace-level dist area: ```powershell dist\release\v\ ``` Generated files per package run: - the archive itself (`.zip` on Windows targets, `.tar.gz` otherwise); - `.sha256`; - `SHA256SUMS.txt`; - `.manifest.json`. ## Version smoke From the repo root: ```powershell rtk cargo run --manifest-path .\xtask\Cargo.toml -- release smoke-version pwsh ./scripts/release/smoke-version.ps1 ``` Build first, then smoke: ```powershell rtk cargo run --manifest-path .\xtask\Cargo.toml -- release smoke-version --build pwsh ./scripts/release/smoke-version.ps1 -Build ``` Smoke a specific binary: ```powershell rtk cargo run --manifest-path .\xtask\Cargo.toml -- release smoke-version --binary-path .\target\release\aria2-rust-pro.exe pwsh ./scripts/release/smoke-version.ps1 -BinaryPath .\target\release\aria2-rust-pro.exe ``` The command succeeds only when the rendered banner keeps the upstream-compatible first line `aria2 version 1.37.0` and also contains `Rust rewrite package: aria2-rust-pro `. ## Versioning and changelog The workspace version in the root `Cargo.toml` is the source of truth. Release tags must use `vMAJOR.MINOR.PATCH` and match that version. Preview the next user-facing changelog entry with: ```powershell rtk git-cliff --config .\cliff.toml --unreleased ``` For a release tag, a checked-in `docs/release/vX.Y.Z.md` remains authoritative. When it is absent, the release workflow generates the Gitea release body from `cliff.toml` and the Conventional Commit history. On an actual release tag, the release workflow compares each public workspace crate against the preceding SemVer tag with `cargo-semver-checks`. The first release tag has no predecessor and therefore skips that comparison. ## Packaging the current host build Build and package the host release binary: ```powershell rtk cargo run --manifest-path .\xtask\Cargo.toml -- release package-local --build pwsh ./scripts/release/package-local.ps1 -Build ``` Package an already-built host binary without rebuilding: ```powershell rtk cargo run --manifest-path .\xtask\Cargo.toml -- release package-local pwsh ./scripts/release/package-local.ps1 ``` Write artifacts to a custom directory: ```powershell rtk cargo run --manifest-path .\xtask\Cargo.toml -- release package-local --build --output-root .\dist\release pwsh ./scripts/release/package-local.ps1 -Build -OutputRoot .\dist\release ``` ## Packaging Windows and Linux artifacts from the current workspace ### Windows host, Windows artifact On the current Windows workspace, the default path uses: - `target\release\aria2-rust-pro.exe` - optional `target\release\aria2_rust_pro.pdb` The archive is a `.zip` containing the binary, optional PDB, root `README.md`, and the release packaging guide under `docs/release/README.md`. Version-specific release notes such as `docs/release/v1.0.0.md` are used as Gitea release body text, not bundled into every archive by default. ### Linux host, Linux artifact On Linux with PowerShell 7 and Cargo available, the same script works: ```bash pwsh ./scripts/release/package-local.ps1 -Build ``` The Linux archive format is `.tar.gz`, and the default packaged binary path is `target/release/aria2-rust-pro`. ### Cross-target handling from one workspace When the binary already exists under a target-specific Cargo directory, pass the target triple: ```powershell rtk cargo run --manifest-path .\xtask\Cargo.toml -- release package-local --build --target-triple x86_64-pc-windows-msvc rtk cargo run --manifest-path .\xtask\Cargo.toml -- release package-local --build --target-triple x86_64-unknown-linux-gnu pwsh ./scripts/release/package-local.ps1 -Build -TargetTriple x86_64-pc-windows-msvc pwsh ./scripts/release/package-local.ps1 -Build -TargetTriple x86_64-unknown-linux-gnu ``` If the workspace cannot execute the packaged binary on the current host, package the prebuilt file directly and skip the runtime smoke: ```powershell rtk cargo run --manifest-path .\xtask\Cargo.toml -- release package-local --target-triple x86_64-unknown-linux-gnu --source-binary .\target\x86_64-unknown-linux-gnu\release\aria2-rust-pro --skip-version-smoke pwsh ./scripts/release/package-local.ps1 ` -TargetTriple x86_64-unknown-linux-gnu ` -SourceBinary .\target\x86_64-unknown-linux-gnu\release\aria2-rust-pro ` -SkipVersionSmoke ``` That flow supports current-workspace staging for non-host artifacts, but the runtime smoke must still be re-run on a compatible machine before calling the artifact release-ready. ## Local deployment checklist 1. Unpack the archive to a clean directory. 2. Run the binary with `--version` and confirm the expected workspace version. 3. Compare the archive checksum with either `.sha256` or `SHA256SUMS.txt`. 4. For container deployment, keep using the documented `docker/` workflow plus `xtask docker smoke`, `xtask docker smoke-local`, or `xtask docker export-local`. The matching `scripts/docker/*.ps1` files are compatibility wrappers for those Cargo-native commands. 5. For direct CLI deployment, provide the same config/session/runtime paths you already use for local compatibility testing. ## Exporting a local Docker image tar When the Docker daemon is available and a local image exists or can be built: ```powershell rtk cargo run --manifest-path .\xtask\Cargo.toml -- docker export-local --build pwsh ./scripts/docker/export-local.ps1 -Build ``` That command writes a tar archive, checksum files, and a manifest under: ```powershell dist\docker\v\ ``` The default tag is `aria2-rust-pro:local`. To export another tag: ```powershell rtk cargo run --manifest-path .\xtask\Cargo.toml -- docker export-local --tag aria2-rust-pro:smoke pwsh ./scripts/docker/export-local.ps1 -Tag aria2-rust-pro:smoke ``` ## Docker smoke checks After packaging or deployment changes, run the Cargo-native Docker smokes from the repo root: ```powershell rtk cargo run --manifest-path .\xtask\Cargo.toml -- docker smoke-local rtk cargo run --manifest-path .\xtask\Cargo.toml -- docker smoke --tag aria2-rust-pro:smoke ``` `xtask docker smoke-local` proves the entrypoint/config-generation path without a Docker daemon. `xtask docker smoke` builds the image, starts a container, checks generated config, and probes live JSON-RPC inside the running container. The PowerShell scripts are compatibility wrappers around the same commands: ```powershell pwsh ./scripts/docker/smoke-local.ps1 pwsh ./scripts/docker/smoke.ps1 -Tag aria2-rust-pro:smoke ``` The daemon-backed wrapper also forwards `-Build`, `-HostRpcPort`, `-RpcSecret`, and `-SpecialMode` to the matching `xtask docker smoke` options. ## Self-hosted Gitea release verification The self-hosted Gitea release workflow should be validated before cleaning up old runner records in the Gitea UI. Keep runner cleanup as an infrastructure follow-up, not part of the first release recovery step. Use this order after CI has gone green on `main`: 1. Trigger the release workflow with `workflow_dispatch` and leave `validation_only=true`, or run the equivalent release commands on the runner host. Validation mode runs the release gates from the current ref and skips Gitea publishing, so it can test the runner without mutating an existing release. 2. Confirm the strict gate reaches the daemon-backed Docker smoke and that `xtask docker smoke` completes its JSON-RPC probe. 3. Confirm `xtask docker export-local --build --tag aria2-rust-pro:release` stages the Docker tar, manifest, and `SHA256SUMS.txt`. 4. For an actual tag-publish run, set `validation_only=false` or push a release tag, then confirm `scripts/ci/publish-gitea-release.sh` can create or update the Gitea release with all staged assets. 5. Only after the release workflow has passed, remove stale offline runner UI records that no longer correspond to the active runner. Do not delete the active runner registration while release validation is still in progress. The current production runner identity should be confirmed from the latest passing Gitea Actions run before any old offline entry is removed. Do not move an already published tag just to validate the workflow; use the default no-publish validation mode instead. Recovered runner evidence: - release validation run 107 passed on commit `6d4956b` with `validation_only=true`; - push CI run 108 passed on the same commit; - the release validation spent roughly 720 seconds in fast gates and 784 seconds in strict gates, while checkout, tool bootstrap, release package, and Docker export were short; - no stale `GITEA-ACTIONS` containers or persisted temporary Gitea tokens should remain after runner-side validation. Treat those timings as a baseline when optimizing the self-hosted runner. Prefer persistent Cargo registry/git cache or further runner-image prebaking before target-directory caching, because target caches can be polluted by toolchain, feature, and commit differences. ## Scope and remaining release limits These scripts are the active local release helpers: - they stage host artifacts and Docker image tar exports from the current workspace; - they do not, by themselves, certify that the current tree has reclosed every reopened modernization phase; - archived release records are preserved only as historical evidence under `docs/archive/`; - Docker image publication/signing still remains an external release-management concern, while `export-local.ps1` and `xtask docker export-local` stage a portable tar from the local daemon state under `dist\docker\v\`.