release #2
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: release | |
| # Cross-platform release builds for the `cairn` binary (R-1). | |
| # | |
| # Trigger: pushing a `v*` tag (e.g. `v0.1.0`) — the maintainer's outward-facing call — or a manual | |
| # `workflow_dispatch`. Each matrix entry builds an optimized `cairn` binary, packages it with its | |
| # SHA-256 checksum, and uploads it as an asset on the GitHub Release for the tag. | |
| # | |
| # Per-platform feature decisions | |
| # ------------------------------ | |
| # `all-backends` pulls the full backend stack: russh (SSH), aws-sdk-s3 (→ aws-lc-rs), google-cloud | |
| # (GCS), azure_storage (Azure Blob), bollard (Docker), kube-rs (Kubernetes). Everything rides the | |
| # rustls stack (no OpenSSL); the one component with native build prerequisites is **aws-lc-rs** (the | |
| # S3 backend's crypto): | |
| # * Linux — needs a C toolchain + CMake (installed below; also covers the musl static build). | |
| # * macOS — non-FIPS builds ship pre-generated bindings, so no extra toolchain is required. | |
| # * Windows — NASM is mandatory for x86_64 aws-lc-rs builds (installed below). | |
| # With those installed, `all-backends` builds on every target, so each target ships the full | |
| # feature set. The `features` matrix field is the documented per-target knob: if a backend ever | |
| # fails to build on a given target, set that entry to a reduced set (e.g. `ssh,cloud` to drop the | |
| # container backends, or `default` for a lean binary) — the release notes step echoes each target's | |
| # feature set so the published notes always say what every binary contains. | |
| # | |
| # This is the release-only counterpart to ci.yml's lean cross-platform / full-Linux split: there the | |
| # heavy stack is Linux-only for fast PR feedback; here we spend the extra build time to ship the full | |
| # binary on all platforms. This workflow does not run without a tag (or a manual dispatch). | |
| on: | |
| push: | |
| tags: ["v*"] | |
| workflow_dispatch: | |
| # Needed for softprops/action-gh-release to create the release and upload assets. | |
| permissions: | |
| contents: write | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| jobs: | |
| build: | |
| name: build ${{ matrix.target }} | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 60 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # Windows x86_64 (MSVC). (Temporary branch: matrix trimmed to Windows-only to produce a | |
| # test binary quickly; the full cross-platform matrix lives on `main`.) | |
| # NOTE: `containers` (Docker/bollard) does not build on Windows — it calls the Unix-only | |
| # `connect_with_unix`. Dropped here so the binary still ships local + SSH + S3/GCS/Azure + | |
| # archive, which is what the Backblaze/copy testing needs. | |
| - os: windows-latest | |
| target: x86_64-pc-windows-msvc | |
| features: ssh,cloud,archive | |
| archive: zip | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.target }} | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| key: ${{ matrix.target }} | |
| # aws-lc-rs (S3 backend) build prerequisites, per target. macOS non-FIPS ships pre-generated | |
| # bindings and needs nothing extra. | |
| - name: Install Linux build deps (CMake + musl tools) | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y cmake musl-tools | |
| - name: Install NASM (Windows, required by aws-lc-rs) | |
| if: runner.os == 'Windows' | |
| uses: ilammy/setup-nasm@v1 | |
| - name: Build | |
| run: cargo build --release -p cairn --features ${{ matrix.features }} --target ${{ matrix.target }} | |
| # Stage the binary + a SHA-256 checksum into a versioned archive named for the target. | |
| - name: Package (Unix) | |
| if: runner.os != 'Windows' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| version="${GITHUB_REF_NAME#v}" | |
| [ "$version" = "$GITHUB_REF_NAME" ] && version="manual-${GITHUB_SHA::8}" | |
| name="cairn-${version}-${{ matrix.target }}" | |
| staging="dist/${name}" | |
| mkdir -p "${staging}" | |
| cp "target/${{ matrix.target }}/release/cairn" "${staging}/" | |
| cp README.md CHANGELOG.md LICENSE-APACHE LICENSE-MIT "${staging}/" 2>/dev/null || true | |
| tar -C dist -czf "${name}.tar.gz" "${name}" | |
| if command -v sha256sum >/dev/null 2>&1; then | |
| sha256sum "${name}.tar.gz" > "${name}.tar.gz.sha256" | |
| else | |
| shasum -a 256 "${name}.tar.gz" > "${name}.tar.gz.sha256" | |
| fi | |
| echo "ASSET=${name}.tar.gz" >> "$GITHUB_ENV" | |
| - name: Package (Windows) | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| $version = "${env:GITHUB_REF_NAME}" -replace '^v','' | |
| if ($version -eq "${env:GITHUB_REF_NAME}") { $version = "manual-" + "${env:GITHUB_SHA}".Substring(0,8) } | |
| $name = "cairn-$version-${{ matrix.target }}" | |
| $staging = "dist/$name" | |
| New-Item -ItemType Directory -Force -Path $staging | Out-Null | |
| Copy-Item "target/${{ matrix.target }}/release/cairn.exe" $staging | |
| foreach ($f in @("README.md","CHANGELOG.md","LICENSE-APACHE","LICENSE-MIT")) { | |
| if (Test-Path $f) { Copy-Item $f $staging } | |
| } | |
| Compress-Archive -Path $staging -DestinationPath "$name.zip" | |
| (Get-FileHash "$name.zip" -Algorithm SHA256).Hash.ToLower() + " $name.zip" | Out-File -Encoding ascii "$name.zip.sha256" | |
| "ASSET=$name.zip" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding ascii | |
| # Make the archive downloadable from the Actions run itself (so a manual `workflow_dispatch`, | |
| # which does not create a release, still yields a fetchable binary via `gh run download`). | |
| - name: Upload build artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.ASSET }} | |
| path: | | |
| ${{ env.ASSET }} | |
| ${{ env.ASSET }}.sha256 | |
| if-no-files-found: error | |
| # Create (or reuse) the release for this tag and attach this target's archive + checksum. | |
| # Each matrix job appends its own assets; the body records each binary's feature set. | |
| - name: Upload to release | |
| if: startsWith(github.ref, 'refs/tags/') | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: Cairn ${{ github.ref_name }} | |
| draft: false | |
| prerelease: false | |
| fail_on_unmatched_files: true | |
| files: | | |
| ${{ env.ASSET }} | |
| ${{ env.ASSET }}.sha256 | |
| # Each matrix job updates the same release; keep the body target-agnostic so it doesn't | |
| # depend on job ordering. All targets are built with the same feature set (all-backends); | |
| # per-asset integrity is the accompanying `.sha256`. See CHANGELOG.md for the full notes. | |
| body: | | |
| Cairn ${{ github.ref_name }} — cross-platform binaries. | |
| Each archive bundles the `cairn` binary built with the full backend stack | |
| (`--features all-backends`: local, SSH/SFTP, S3, GCS, Azure Blob, Docker, Kubernetes) | |
| plus the README, CHANGELOG, and licenses. Targets: Linux x86_64 (gnu + musl static), | |
| macOS (aarch64 + x86_64), Windows x86_64. | |
| Verify each download against its `.sha256` before use. See `CHANGELOG.md` for release notes. |