# This is a **reuseable** workflow that bundles the Desktop App for Intel macOS. # It doesn't get triggered on its own. It gets used in multiple workflows: # - release.yml # - canary.yml # - pr-comment-bundle-desktop.yml on: workflow_call: inputs: version: description: 'Version to set for the build' required: false default: "" type: string signing: description: 'Whether to perform signing and notarization' required: false default: false type: boolean quick_test: description: 'Whether to perform the quick launch test' required: false default: true type: boolean secrets: CERTIFICATE_OSX_APPLICATION: description: 'Certificate for macOS application signing' required: false CERTIFICATE_PASSWORD: description: 'Password for the macOS certificate' required: false APPLE_ID: description: 'Apple ID for notarization' required: false APPLE_ID_PASSWORD: description: 'Password for the Apple ID' required: false APPLE_TEAM_ID: description: 'Apple Team ID' required: false name: Reusable workflow to bundle desktop app for Intel Mac jobs: bundle-desktop-intel: runs-on: macos-latest name: Bundle Desktop App on Intel macOS steps: # Check initial disk space - name: Check initial disk space run: df -h # Validate Signing Secrets if signing is enabled - name: Validate Signing Secrets if: ${{ inputs.signing }} run: | if [[ -z "${{ secrets.CERTIFICATE_OSX_APPLICATION }}" ]]; then echo "Error: CERTIFICATE_OSX_APPLICATION secret is required for signing." exit 1 fi if [[ -z "${{ secrets.CERTIFICATE_PASSWORD }}" ]]; then echo "Error: CERTIFICATE_PASSWORD secret is required for signing." exit 1 fi if [[ -z "${{ secrets.APPLE_ID }}" ]]; then echo "Error: APPLE_ID secret is required for signing." exit 1 fi if [[ -z "${{ secrets.APPLE_ID_PASSWORD }}" ]]; then echo "Error: APPLE_ID_PASSWORD secret is required for signing." exit 1 fi if [[ -z "${{ secrets.APPLE_TEAM_ID }}" ]]; then echo "Error: APPLE_TEAM_ID secret is required for signing." exit 1 fi echo "All required signing secrets are present." - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # Update versions before build - name: Update versions if: ${{ inputs.version != '' }} run: | # Update version in Cargo.toml sed -i.bak 's/^version = ".*"/version = "'${{ inputs.version }}'"/' Cargo.toml rm -f Cargo.toml.bak # Update version in package.json cd ui/desktop npm version ${{ inputs.version }} --no-git-tag-version --allow-same-version - name: Setup Rust uses: dtolnay/rust-toolchain@38b70195107dddab2c7bbd522bcf763bac00963b # pin@stable with: toolchain: stable targets: x86_64-apple-darwin # Pre-build cleanup to ensure enough disk space - name: Pre-build cleanup run: | echo "Performing pre-build cleanup..." # Clean npm cache npm cache clean --force || true # Clean any previous build artifacts rm -rf target || true # Clean Homebrew cache brew cleanup || true # Remove unnecessary large directories rm -rf ~/Library/Caches/* || true # Check disk space after cleanup df -h - name: Cache Cargo registry uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 with: path: ~/.cargo/registry key: ${{ runner.os }}-intel-cargo-registry-${{ hashFiles('**/Cargo.lock') }} restore-keys: | ${{ runner.os }}-intel-cargo-registry- - name: Cache Cargo index uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 with: path: ~/.cargo/index key: ${{ runner.os }}-intel-cargo-index restore-keys: | ${{ runner.os }}-intel-cargo-index - name: Cache Cargo build uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 with: path: target key: ${{ runner.os }}-intel-cargo-build-${{ hashFiles('**/Cargo.lock') }} restore-keys: | ${{ runner.os }}-intel-cargo-build- # Build specifically for Intel architecture - name: Build goosed for Intel run: cargo build --release -p goose-server --target x86_64-apple-darwin # Post-build cleanup to free space - name: Post-build cleanup run: | echo "Performing post-build cleanup..." # Remove debug artifacts rm -rf target/debug || true rm -rf target/x86_64-apple-darwin/debug || true # Keep only what's needed for the next steps rm -rf target/x86_64-apple-darwin/release/deps || true rm -rf target/x86_64-apple-darwin/release/build || true rm -rf target/x86_64-apple-darwin/release/incremental || true # Check disk space after cleanup df -h - name: Copy binary into Electron folder run: cp target/x86_64-apple-darwin/release/goosed ui/desktop/src/bin/goosed - name: Add MacOS certs for signing and notarization if: ${{ inputs.signing }} run: ./scripts/add-macos-cert.sh working-directory: ui/desktop env: CERTIFICATE_OSX_APPLICATION: ${{ secrets.CERTIFICATE_OSX_APPLICATION }} CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }} - name: Set up Node.js uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 # pin@v2 with: node-version: 'lts/*' - name: Install dependencies run: npm ci working-directory: ui/desktop # Configure Electron builder for Intel architecture - name: Configure for Intel build run: | # Set the architecture to x64 for Intel Mac build jq '.build.mac.target[0].arch = "x64"' package.json > package.json.tmp && mv package.json.tmp package.json working-directory: ui/desktop # Check disk space before bundling - name: Check disk space before bundling run: df -h - name: Make Unsigned App if: ${{ !inputs.signing }} run: | attempt=0 max_attempts=2 until [ $attempt -ge $max_attempts ]; do npm run bundle:intel && break attempt=$((attempt + 1)) echo "Attempt $attempt failed. Retrying..." sleep 5 done if [ $attempt -ge $max_attempts ]; then echo "Action failed after $max_attempts attempts." exit 1 fi working-directory: ui/desktop - name: Make Signed App if: ${{ inputs.signing }} run: | attempt=0 max_attempts=2 until [ $attempt -ge $max_attempts ]; do npm run bundle:intel && break attempt=$((attempt + 1)) echo "Attempt $attempt failed. Retrying..." sleep 5 done if [ $attempt -ge $max_attempts ]; then echo "Action failed after $max_attempts attempts." exit 1 fi working-directory: ui/desktop env: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - name: Final cleanup before artifact upload run: | echo "Performing final cleanup..." # Remove build artifacts that are no longer needed rm -rf target || true # Check disk space after cleanup df -h - name: Upload Desktop artifact uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # pin@v4 with: name: Goose-darwin-x64 path: ui/desktop/out/Goose-darwin-x64/Goose_intel_mac.zip - name: Quick launch test (macOS) if: ${{ inputs.quick_test }} run: | # Ensure no quarantine attributes (if needed) xattr -cr "ui/desktop/out/Goose-darwin-x64/Goose.app" echo "Opening Goose.app..." open -g "ui/desktop/out/Goose-darwin-x64/Goose.app" # Give the app a few seconds to start and write logs sleep 5 # Check if it's running if pgrep -f "Goose.app/Contents/MacOS/Goose" > /dev/null; then echo "App appears to be running." else echo "App did not stay open. Possible crash or startup error." exit 1 fi # Kill the app to clean up pkill -f "Goose.app/Contents/MacOS/Goose"