Skip to content

Build & Release

Build & Release #66

Workflow file for this run

name: Build & Release
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
permissions:
contents: write
jobs:
build:
runs-on: macos-14
steps:
- uses: actions/checkout@v6
- name: Install Rust
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
source "$HOME/.cargo/env"
rustup target add aarch64-apple-darwin x86_64-apple-darwin
- name: Cache Rust dependencies
uses: actions/cache@v5
with:
path: |
eagle-core/target
~/.cargo/registry
~/.cargo/git
key: rust-${{ runner.os }}-${{ hashFiles('eagle-core/Cargo.lock') }}
restore-keys: rust-${{ runner.os }}-
- name: Build Rust (arm64)
run: cd eagle-core && cargo build --release --target aarch64-apple-darwin
- name: Build Rust (x86_64)
run: cd eagle-core && cargo build --release --target x86_64-apple-darwin
- name: Create universal Rust library
run: |
lipo -create \
eagle-core/target/aarch64-apple-darwin/release/libeagle_core.a \
eagle-core/target/x86_64-apple-darwin/release/libeagle_core.a \
-output eagle-core/target/release/libeagle_core.a
- name: Compute version
id: version
env:
GH_TOKEN: ${{ github.token }}
run: |
LAST_TAG=$(gh release list --limit 1 --json tagName -q '.[0].tagName' 2>/dev/null || echo "")
if [[ "$LAST_TAG" =~ ^v0\.([0-9]+)\.([0-9]+)$ ]]; then
MAJOR=0
MINOR="${BASH_REMATCH[1]}"
PATCH="${BASH_REMATCH[2]}"
PATCH=$((PATCH + 1))
else
MAJOR=0
MINOR=2
PATCH=0
fi
echo "version=${MAJOR}.${MINOR}.${PATCH}" >> "$GITHUB_OUTPUT"
- name: Build Swift app
run: |
ls -d /Applications/Xcode* | sort -V
XCODE_PATH=$(ls -d /Applications/Xcode* 2>/dev/null | sort -V | tail -1)
sudo xcode-select -s "$XCODE_PATH"
swift --version
mkdir -p build/Eagle.app/Contents/MacOS
mkdir -p build/Eagle.app/Contents/Resources
cp Eagle/Info.plist build/Eagle.app/Contents/Info.plist
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${{ steps.version.outputs.version }}" build/Eagle.app/Contents/Info.plist
cp Eagle/Resources/Eagle.icns build/Eagle.app/Contents/Resources/Eagle.icns
swiftc \
-O \
-import-objc-header Eagle/BridgingHeader.h \
-L eagle-core/target/release \
-leagle_core \
-framework AppKit \
-framework SwiftUI \
-framework UniformTypeIdentifiers \
Eagle/Sources/Eagle/*.swift \
-o build/Eagle.app/Contents/MacOS/Eagle
- name: Import signing certificate
if: github.event_name != 'pull_request'
env:
DEVELOPER_P12: ${{ secrets.DEVELOPER_P12 }}
DEVELOPER_P12_PASSWORD: ${{ secrets.DEVELOPER_P12_PASSWORD }}
run: |
KEYCHAIN_PATH=$RUNNER_TEMP/signing.keychain-db
KEYCHAIN_PASSWORD=$(openssl rand -hex 16)
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
echo "$DEVELOPER_P12" | base64 --decode > $RUNNER_TEMP/developer.p12
security import $RUNNER_TEMP/developer.p12 \
-P "$DEVELOPER_P12_PASSWORD" \
-A \
-t cert \
-f pkcs12 \
-k "$KEYCHAIN_PATH"
security list-keychain -d user -s "$KEYCHAIN_PATH"
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
- name: Code sign app
if: github.event_name != 'pull_request'
run: |
IDENTITY=$(security find-identity -v -p codesigning $RUNNER_TEMP/signing.keychain-db | head -1 | grep -o '"[^"]*"' | tr -d '"')
echo "Signing with identity: $IDENTITY"
codesign --force --options runtime --sign "$IDENTITY" build/Eagle.app/Contents/MacOS/Eagle
codesign --force --options runtime --sign "$IDENTITY" build/Eagle.app
codesign --verify --deep --strict build/Eagle.app
- name: Notarize app
if: github.event_name != 'pull_request'
env:
MACOS_NOTARY_API_KEY: ${{ secrets.MACOS_NOTARY_API_KEY }}
MACOS_NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }}
MACOS_NOTARY_ISSUER_ID: ${{ secrets.MACOS_NOTARY_ISSUER_ID }}
run: |
echo "$MACOS_NOTARY_API_KEY" | base64 --decode > $RUNNER_TEMP/notary_key.p8
ditto -c -k --keepParent build/Eagle.app build/Eagle-notarize.zip
xcrun notarytool submit build/Eagle-notarize.zip \
--key "$RUNNER_TEMP/notary_key.p8" \
--key-id "$MACOS_NOTARY_KEY_ID" \
--issuer "$MACOS_NOTARY_ISSUER_ID" \
--wait
xcrun stapler staple build/Eagle.app
- name: Create DMG
run: |
hdiutil create -volname Eagle \
-srcfolder build/Eagle.app \
-ov -format UDZO \
build/Eagle-${{ steps.version.outputs.version }}.dmg
- name: Sign and notarize DMG
if: github.event_name != 'pull_request'
env:
MACOS_NOTARY_API_KEY: ${{ secrets.MACOS_NOTARY_API_KEY }}
MACOS_NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }}
MACOS_NOTARY_ISSUER_ID: ${{ secrets.MACOS_NOTARY_ISSUER_ID }}
run: |
IDENTITY=$(security find-identity -v -p codesigning $RUNNER_TEMP/signing.keychain-db | head -1 | grep -o '"[^"]*"' | tr -d '"')
codesign --force --sign "$IDENTITY" build/Eagle-${{ steps.version.outputs.version }}.dmg
xcrun notarytool submit build/Eagle-${{ steps.version.outputs.version }}.dmg \
--key "$RUNNER_TEMP/notary_key.p8" \
--key-id "$MACOS_NOTARY_KEY_ID" \
--issuer "$MACOS_NOTARY_ISSUER_ID" \
--wait
xcrun stapler staple build/Eagle-${{ steps.version.outputs.version }}.dmg
- name: Upload artifact
uses: actions/upload-artifact@v7
with:
name: Eagle-${{ steps.version.outputs.version }}.dmg
path: build/Eagle-${{ steps.version.outputs.version }}.dmg
- name: Create release
if: github.event_name != 'pull_request'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="v${{ steps.version.outputs.version }}"
gh release create "$VERSION" \
--title "Eagle $VERSION" \
--notes "Automated build from $(git log -1 --pretty=%s)" \
--draft=false \
build/Eagle-${{ steps.version.outputs.version }}.dmg
- name: Install kpkg
if: github.event_name != 'pull_request'
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release download --repo kandji-inc/kpkg --pattern '*.pkg' --dir /tmp
sudo installer -pkg /tmp/*.pkg -target /
- name: Deploy to Kandji
if: github.event_name != 'pull_request'
env:
KANDJI_TOKEN: ${{ secrets.KANDJI_TOKEN }}
KANDJI_API_URL: ${{ vars.KANDJI_API_URL }}
run: |
mkdir -p ~/Library/KandjiPackages
envsubst < .github/kandji-config.json > ~/Library/KandjiPackages/config.json
kpkg -p build/Eagle-${{ steps.version.outputs.version }}.dmg -n "Eagle"