Release #46
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 | |
| # Tag a version (e.g. `git tag v0.0.5 && git push --tags`) to build the | |
| # Duckle binary for every OS and attach it directly to a draft GitHub | |
| # release. We do NOT ship installers (no NSIS / MSI / DMG / DEB / RPM / | |
| # AppImage). The asset on the release is the raw executable that the | |
| # user can run. | |
| on: | |
| push: | |
| tags: ['v*'] | |
| workflow_dispatch: | |
| inputs: | |
| release_tag: | |
| description: 'Existing release tag to (re)upload binaries to. Builds from the branch this run is dispatched on; the tag itself is never moved. Leave empty on a normal tag push.' | |
| required: false | |
| default: '' | |
| jobs: | |
| # Single point that creates the draft release so the per-OS build | |
| # jobs don't race on `gh release create`. | |
| prepare-release: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Create draft release if missing | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GH_REPO: ${{ github.repository }} | |
| REL_TAG: ${{ github.event.inputs.release_tag || github.ref_name }} | |
| run: | | |
| set -e | |
| tag="$REL_TAG" | |
| if gh release view "$tag" >/dev/null 2>&1; then | |
| echo "release $tag already exists" | |
| else | |
| gh release create "$tag" --draft --title "Duckle $tag" | |
| fi | |
| build: | |
| needs: prepare-release | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # Linux | |
| - os: ubuntu-24.04 | |
| binary: duckle | |
| asset: Duckle-linux-x64 | |
| - os: ubuntu-24.04-arm | |
| binary: duckle | |
| asset: Duckle-linux-arm64 | |
| # macOS - both built on the macos-14 (Apple Silicon) runner. | |
| # The Intel binary is cross-compiled to x86_64-apple-darwin | |
| # rather than run on a macos-13 runner: GitHub's Intel-mac | |
| # runners are scarce / being deprecated and routinely leave | |
| # the job queued for hours, stalling the whole release. | |
| - os: macos-14 | |
| binary: duckle | |
| asset: Duckle-macos-x64 | |
| target: x86_64-apple-darwin | |
| - os: macos-14 | |
| binary: duckle | |
| asset: Duckle-macos-arm64 | |
| # Windows | |
| - os: windows-latest | |
| binary: duckle.exe | |
| asset: Duckle-windows-x64.exe | |
| - os: windows-11-arm | |
| binary: duckle.exe | |
| asset: Duckle-windows-arm64.exe | |
| runs-on: ${{ matrix.os }} | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # Reclaim ~20 GB on Linux runners so the full workspace + embedded | |
| # binaries build does not hit "No space left on device". | |
| - name: Free disk space (Linux) | |
| if: runner.os == 'Linux' | |
| shell: bash | |
| run: | | |
| sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc \ | |
| /opt/hostedtoolcache/CodeQL /usr/local/.ghcup /usr/local/share/boost \ | |
| /usr/local/share/powershell /usr/share/swift || true | |
| sudo docker image prune --all --force || true | |
| df -h / | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Install frontend deps | |
| run: npm --prefix frontend ci | |
| - name: Build frontend (embedded into the Rust binary) | |
| run: npm --prefix frontend run build | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.target || '' }} | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Install Linux WebView deps (Tauri) | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| libwebkit2gtk-4.1-dev libgtk-3-dev \ | |
| libayatana-appindicator3-dev librsvg2-dev libsoup-3.0-dev | |
| - name: Build duckle-runner + duckle-mcp (bundled into the app) | |
| shell: bash | |
| run: | | |
| set -e | |
| if [ -n "${{ matrix.target }}" ]; then | |
| cargo build --profile release-runner --target "${{ matrix.target }}" -p duckle-runner -p duckle-mcp | |
| base="target/${{ matrix.target }}/release-runner" | |
| else | |
| cargo build --profile release-runner -p duckle-runner -p duckle-mcp | |
| base="target/release-runner" | |
| fi | |
| mkdir -p apps/desktop/bin | |
| if [ "${{ runner.os }}" = "Windows" ]; then | |
| cp "$base/duckle-runner.exe" apps/desktop/bin/duckle-runner.exe | |
| cp "$base/duckle-mcp.exe" apps/desktop/bin/duckle-mcp.exe | |
| else | |
| cp "$base/duckle-runner" apps/desktop/bin/duckle-runner | |
| cp "$base/duckle-mcp" apps/desktop/bin/duckle-mcp | |
| fi | |
| - name: Build raw Duckle binary | |
| shell: bash | |
| run: | | |
| set -e | |
| if [ -n "${{ matrix.target }}" ]; then | |
| cargo build --release --target "${{ matrix.target }}" \ | |
| --manifest-path apps/desktop/Cargo.toml --features custom-protocol | |
| else | |
| cargo build --release \ | |
| --manifest-path apps/desktop/Cargo.toml --features custom-protocol | |
| fi | |
| - name: Stage release assets | |
| shell: bash | |
| run: | | |
| set -e | |
| mkdir -p _release | |
| if [ -n "${{ matrix.target }}" ]; then | |
| src="target/${{ matrix.target }}/release/${{ matrix.binary }}" | |
| else | |
| src="target/release/${{ matrix.binary }}" | |
| fi | |
| # The standalone desktop binary, named exactly as before so the | |
| # in-app update check (apps/desktop/src/update_check.rs) and the | |
| # README download table keep matching it. Single file, double-click. | |
| # The duckle-runner is embedded into this binary at compile time | |
| # (no separate with-runner asset needed). | |
| cp "$src" "_release/${{ matrix.asset }}" | |
| - name: Upload to release | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GH_REPO: ${{ github.repository }} | |
| REL_TAG: ${{ github.event.inputs.release_tag || github.ref_name }} | |
| run: | | |
| set -e | |
| asset="${{ matrix.asset }}" | |
| gh release upload "$REL_TAG" "_release/$asset" --clobber |