release #14
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 | |
| # Build release artifacts and attach them to a GitHub Release: | |
| # - Linux tarballs, Debian packages, and AppImages (x86_64 + aarch64) via | |
| # scripts/package-linux.sh | |
| # - macOS dmg (Apple silicon) via scripts/package-macos.sh | |
| # The Release is the only distribution channel — Linux builds are available as | |
| # tarballs, Debian packages, and AppImages. | |
| # | |
| # Trigger: tag-release.yml tags `v<version>` when a Cargo.toml version bump | |
| # lands on main and dispatches this workflow on that tag. Pushing such a tag | |
| # by hand works too. A workflow_dispatch on a branch ref only builds and | |
| # uploads artifacts (no Release published). | |
| on: | |
| push: | |
| tags: ["v*"] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| linux: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - runner: ubuntu-24.04 # x86_64 | |
| - runner: ubuntu-24.04-arm # aarch64 | |
| runs-on: ${{ matrix.runner }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: gpui system deps | |
| run: | | |
| sudo apt-get update -qq | |
| sudo apt-get install -y -qq \ | |
| libxkbcommon-dev libxkbcommon-x11-dev libwayland-dev \ | |
| libx11-dev libxcb1-dev libx11-xcb-dev \ | |
| libfontconfig1-dev libfreetype-dev libasound2-dev \ | |
| libvulkan-dev pkg-config cmake | |
| - name: rust toolchain (rust-toolchain.toml) | |
| run: rustup show active-toolchain || rustup toolchain install | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: package | |
| run: scripts/package-linux.sh | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: linux-${{ runner.arch }} | |
| path: | | |
| target/package/*.tar.gz | |
| target/package/*.deb | |
| target/package/*.AppImage | |
| if-no-files-found: error | |
| # Heads-up: the macOS cfg paths (Keychain in agent_accounts.rs) have never | |
| # been type-checked against the Apple SDK — this job may surface errors on | |
| # its first runs. continue-on-error keeps the Linux release shippable. | |
| # | |
| # Signing/notarization (both optional — absent secrets fall back to an | |
| # ad-hoc-signed build): | |
| # MACOS_CERT_P12 / MACOS_CERT_PASSWORD — base64 "Developer ID Application" | |
| # certificate + private key (.p12) and its export password. | |
| # APPLE_ID / APPLE_APP_PASSWORD / APPLE_TEAM_ID — Apple ID, app-specific | |
| # password from account.apple.com, and 10-char team id for notarytool. | |
| # All three present → the package script notarizes and staples the app + | |
| # dmg (no Gatekeeper warning). | |
| macos: | |
| runs-on: macos-latest # Apple silicon | |
| continue-on-error: true | |
| env: | |
| MACOS_CERT_P12: ${{ secrets.MACOS_CERT_P12 }} | |
| MACOS_CERT_PASSWORD: ${{ secrets.MACOS_CERT_PASSWORD }} | |
| APPLE_ID: ${{ secrets.APPLE_ID }} | |
| APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }} | |
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: rust toolchain (rust-toolchain.toml) | |
| run: rustup show active-toolchain || rustup toolchain install | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: import Developer ID certificate | |
| if: env.MACOS_CERT_P12 != '' | |
| run: | | |
| keychain="$RUNNER_TEMP/release.keychain-db" | |
| pass="$(openssl rand -hex 16)" | |
| security create-keychain -p "$pass" "$keychain" | |
| security set-keychain-settings -lut 3600 "$keychain" | |
| security unlock-keychain -p "$pass" "$keychain" | |
| # A leaf without its issuer in a searchable keychain is not a valid | |
| # codesigning identity, so seed both Developer ID intermediates. | |
| for ca in DeveloperIDCA DeveloperIDG2CA; do | |
| curl -fsSL -o "$RUNNER_TEMP/$ca.cer" \ | |
| "https://www.apple.com/certificateauthority/$ca.cer" | |
| security import "$RUNNER_TEMP/$ca.cer" -k "$keychain" \ | |
| -T /usr/bin/codesign | |
| done | |
| printf '%s' "$MACOS_CERT_P12" | base64 -d >"$RUNNER_TEMP/cert.p12" | |
| security import "$RUNNER_TEMP/cert.p12" -k "$keychain" \ | |
| -P "$MACOS_CERT_PASSWORD" -T /usr/bin/codesign | |
| rm -f "$RUNNER_TEMP/cert.p12" | |
| # Allow codesign to use the imported key without a UI prompt. | |
| security set-key-partition-list -S apple-tool:,apple: \ | |
| -s -k "$pass" "$keychain" >/dev/null | |
| security list-keychains -d user -s "$keychain" login.keychain-db | |
| identity="$(security find-identity -v -p codesigning "$keychain" \ | |
| | sed -n 's/.*"\(Developer ID Application: [^"]*\)".*/\1/p' | head -1)" | |
| [ -n "$identity" ] || { echo "p12 contains no Developer ID Application identity"; exit 1; } | |
| echo "CODESIGN_IDENTITY=$identity" >>"$GITHUB_ENV" | |
| - name: notary credentials | |
| if: env.APPLE_ID != '' | |
| run: | | |
| # Secrets keep whatever whitespace was pasted into them, and | |
| # notarytool answers a trailing newline in the team id with the same | |
| # opaque 403 as a genuinely wrong one. | |
| apple_id="$(printf '%s' "$APPLE_ID" | tr -d '[:space:]')" | |
| password="$(printf '%s' "$APPLE_APP_PASSWORD" | tr -d '[:space:]')" | |
| team_id="$(printf '%s' "$APPLE_TEAM_ID" | tr -d '[:space:]')" | |
| # The signing certificate's subject ends in "(<team id>)", so a | |
| # mismatch is detectable here instead of as a notary rejection. | |
| cert_team="$(printf '%s' "$CODESIGN_IDENTITY" \ | |
| | sed -n 's/.*(\([A-Z0-9]\{10\}\))$/\1/p')" | |
| if [ -n "$cert_team" ] && [ "$cert_team" != "$team_id" ]; then | |
| echo "APPLE_TEAM_ID does not match the signing certificate's team ($cert_team)" | |
| exit 1 | |
| fi | |
| { | |
| echo "NOTARY_APPLE_ID=$apple_id" | |
| echo "NOTARY_PASSWORD=$password" | |
| echo "NOTARY_TEAM_ID=$team_id" | |
| } >>"$GITHUB_ENV" | |
| - name: package dmg | |
| run: scripts/package-macos.sh | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: macos-${{ runner.arch }} | |
| path: | | |
| target/package/*.dmg | |
| if-no-files-found: error | |
| publish: | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| needs: [linux, macos] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| path: dist | |
| merge-multiple: true | |
| - name: version guard (tag == artifact version) | |
| run: | | |
| ver="${GITHUB_REF_NAME#v}" | |
| ls dist/ | |
| ls dist/ | grep -q "keiki-$ver-" \ | |
| || { echo "tag v$ver does not match built artifact versions — bump Cargo.toml [workspace.package] version"; exit 1; } | |
| - uses: softprops/action-gh-release@v2 | |
| with: | |
| files: dist/* | |
| generate_release_notes: true | |
| - name: macOS dmg present | |
| run: | | |
| # The macOS job is continue-on-error, so a signing or notarization | |
| # failure otherwise publishes a Linux-only Release under a green run. | |
| # Release first, then fail loudly. | |
| ls dist/ | grep -q '\.dmg$' \ | |
| || { echo "no dmg in the Release — the macOS job failed; see its log"; exit 1; } |