Skip to content

Add Vertex regions; bump ZAi defaults; stream fix #250

Add Vertex regions; bump ZAi defaults; stream fix

Add Vertex regions; bump ZAi defaults; stream fix #250

Workflow file for this run

name: Build macOS
on:
push:
branches: [ main, develop ]
tags: [ 'v*' ]
pull_request:
branches: [ main, develop ]
workflow_dispatch: # Manual trigger
concurrency:
group: build-macos-${{ github.ref }}
cancel-in-progress: false
env:
VSCODE_QUALITY: stable
jobs:
build-macos-arm64:
name: Build macOS (ARM64)
runs-on: macos-latest
timeout-minutes: 120
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: '.nvmrc'
cache: 'npm'
- name: Setup Python 3
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Install tsx (TypeScript runner)
run: npm install -g tsx
- name: Run preinstall script manually
run: tsx build/npm/preinstall.ts
- name: Install dependencies (skip scripts)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npm install --ignore-scripts
- name: Run postinstall script manually
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: tsx build/npm/postinstall.ts
- name: Rebuild native modules
run: npm rebuild
- name: Generate DOM whitelist from MDN
run: node build/scripts/generateDOMWhitelist.mjs
- name: Install roopik-zoo extension dependencies
working-directory: extensions/roopik-zoo
run: |
if ! npm install; then
echo "Normal install failed, trying with --legacy-peer-deps..."
npm install --legacy-peer-deps
node ../../.github/scripts/install-all-peer-deps.js || true
fi
- name: Install @roo-code/types dependencies
working-directory: extensions/roopik-zoo/packages/types
run: npm install
- name: Build @roo-code/types package
working-directory: extensions/roopik-zoo/packages/types
run: npm run build
- name: Install @roo-code/build dependencies
working-directory: extensions/roopik-zoo/packages/build
run: npm install
- name: Build @roo-code/build package
working-directory: extensions/roopik-zoo/packages/build
run: npm run build
- name: Create .env file for roopik-zoo
working-directory: extensions/roopik-zoo
env:
ROO_CODE_API_URL: ${{ secrets.ROO_CODE_API_URL || 'https://app.roocode.com' }}
ROO_CODE_PROVIDER_URL: ${{ secrets.ROO_CODE_PROVIDER_URL || 'https://app.roocode.com/proxy/v1' }}
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY || '' }}
run: |
cat > .env << EOF
ROO_CODE_API_URL=${ROO_CODE_API_URL}
ROO_CODE_PROVIDER_URL=${ROO_CODE_PROVIDER_URL}
POSTHOG_API_KEY=${POSTHOG_API_KEY}
EOF
- name: Build roopik-zoo extension
working-directory: extensions/roopik-zoo
run: npm run build
- name: Install roopik extension dependencies (skip postinstall)
working-directory: extensions/roopik
run: npm install --ignore-scripts
- name: Install roopik webview dependencies
working-directory: extensions/roopik/webview
run: npm install
- name: Build roopik extension
working-directory: extensions/roopik
run: npm run build
- name: Build MCP STDIO binary (macOS ARM64)
working-directory: tools/roopik/mcp-stdio-server
run: |
npm ci
mkdir -p ../../../resources/mcp-binaries
npm run build:binary:mac-arm64
- name: Build macOS application (arm64)
env:
BUILD_SOURCEVERSION: ${{ github.sha }}
run: npm run gulp vscode-darwin-arm64
- name: Import Apple signing certificate
env:
AGENT_TEMPDIRECTORY: ${{ runner.temp }}
MAC_CERT_P12: ${{ secrets.MAC_CERT_P12 }}
MAC_CERT_PASSWORD: ${{ secrets.MAC_CERT_PASSWORD }}
run: |
KEYCHAIN_PATH="$AGENT_TEMPDIRECTORY/buildagent.keychain"
CERT_PATH="$AGENT_TEMPDIRECTORY/mac_cert.p12"
echo "$MAC_CERT_P12" | base64 --decode > "$CERT_PATH"
security create-keychain -p "" "$KEYCHAIN_PATH"
security import "$CERT_PATH" -k "$KEYCHAIN_PATH" -P "$MAC_CERT_PASSWORD" -T /usr/bin/codesign -T /usr/bin/security
security list-keychains -s "$KEYCHAIN_PATH"
security unlock-keychain -p "" "$KEYCHAIN_PATH"
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "" "$KEYCHAIN_PATH"
- name: Debug signing identities
env:
AGENT_TEMPDIRECTORY: ${{ runner.temp }}
run: security find-identity -v -p codesigning "$AGENT_TEMPDIRECTORY/buildagent.keychain"
- name: Codesign app
env:
AGENT_TEMPDIRECTORY: ${{ runner.temp }}
VSCODE_ARCH: arm64
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
APP_PATH="$(find ../VSCode-darwin-arm64 -maxdepth 2 -name "*.app" -print -quit)"
if [ -z "$APP_PATH" ]; then
echo "No .app found under ../VSCode-darwin-arm64"
exit 1
fi
SIGN_IDENTITY="$(security find-identity -v -p codesigning "$AGENT_TEMPDIRECTORY/buildagent.keychain" \
| awk -v team="$APPLE_TEAM_ID" '/Developer ID Application/ && $0 ~ team {print $2; exit}')"
if [ -z "$SIGN_IDENTITY" ]; then
echo "No Developer ID Application identity found in build.keychain"
exit 1
fi
echo "Using signing identity SHA: $SIGN_IDENTITY"
BUILD_DIR="$(dirname "$GITHUB_WORKSPACE")"
DEBUG=electron-osx-sign* CODESIGN_IDENTITY="$SIGN_IDENTITY" tsx build/darwin/sign.ts "$BUILD_DIR"
# Verify
codesign --verify --deep --strict --verbose=2 "$APP_PATH"
- name: Prepare signed artifact
run: |
APP_PATH="$(find ../VSCode-darwin-arm64 -maxdepth 2 -name "*.app" -print -quit)"
if [ -z "$APP_PATH" ]; then
echo "No .app found under ../VSCode-darwin-arm64"
exit 1
fi
mkdir -p .artifacts
SIGNED_ZIP=".artifacts/Roopik-macos-signed.zip"
ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "$SIGNED_ZIP"
- name: Upload macOS artifacts (arm64)
uses: actions/upload-artifact@v6
with:
name: roopik-macos-arm64
path: |
.artifacts/Roopik-macos-signed.zip
retention-days: 10
notarize-macos-arm64:
name: Notarize macOS (ARM64)
runs-on: macos-latest
timeout-minutes: 60
needs: build-macos-arm64
steps:
- name: Download signed artifact
uses: actions/download-artifact@v6
with:
name: roopik-macos-arm64
- name: Notarize and staple
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
run: |
SIGNED_ZIP="$(find . -name 'Roopik-macos-signed.zip' -print -quit)"
if [ -z "$SIGNED_ZIP" ]; then
echo "Signed zip not found in downloaded artifacts."
find . -maxdepth 3 -type f -name "*.zip" -print
exit 1
fi
rm -rf .notarize
mkdir -p .notarize
ditto -x -k "$SIGNED_ZIP" .notarize
APP_PATH="$(find .notarize -maxdepth 3 -name "*.app" -print -quit)"
if [ -z "$APP_PATH" ]; then
echo "No .app found in notarize payload"
exit 1
fi
DMG_ROOT=".dmgroot"
DMG_NAME="Roopik-macos.dmg"
rm -rf "$DMG_ROOT"
mkdir -p "$DMG_ROOT"
cp -R "$APP_PATH" "$DMG_ROOT/"
ln -s /Applications "$DMG_ROOT/Applications"
rm -f "$DMG_NAME"
hdiutil detach "/Volumes/Roopik" -force || true
hdiutil create -volname "Roopik" -srcfolder "$DMG_ROOT" -ov -format UDZO "$DMG_NAME"
SUBMIT_JSON="$(xcrun notarytool submit "$DMG_NAME" \
--apple-id "$APPLE_ID" \
--team-id "$APPLE_TEAM_ID" \
--password "$APPLE_APP_PASSWORD" \
--output-format json)"
echo "$SUBMIT_JSON"
REQUEST_ID="$(echo "$SUBMIT_JSON" | /usr/bin/python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")"
echo "Notarization request id: $REQUEST_ID"
MAX_ATTEMPTS=60
SLEEP_SECONDS=60
ATTEMPT=1
while [ "$ATTEMPT" -le "$MAX_ATTEMPTS" ]; do
LOG_JSON="$(xcrun notarytool log "$REQUEST_ID" \
--apple-id "$APPLE_ID" \
--team-id "$APPLE_TEAM_ID" \
--password "$APPLE_APP_PASSWORD" \
--output-format json 2>/dev/null || true)"
STATUS="Pending"
if [ -n "$LOG_JSON" ] && [[ "$LOG_JSON" == \{* || "$LOG_JSON" == \[* ]]; then
STATUS="$(/usr/bin/python3 -c 'import json,sys; print(json.load(sys.stdin).get("status","Pending"))' <<<"$LOG_JSON")"
fi
echo "Notarization status ($ATTEMPT/$MAX_ATTEMPTS): $STATUS"
if [ "$STATUS" = "Accepted" ]; then
break
fi
if [ "$STATUS" = "Invalid" ]; then
echo "$LOG_JSON"
exit 1
fi
sleep "$SLEEP_SECONDS"
ATTEMPT=$((ATTEMPT + 1))
done
if [ "$STATUS" != "Accepted" ]; then
echo "Notarization did not finish in time. Request id: $REQUEST_ID"
exit 1
fi
xcrun stapler staple "$APP_PATH"
xcrun stapler staple "$DMG_NAME"
NOTARIZED_ZIP="./Roopik-macos-notarized.zip"
ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "$NOTARIZED_ZIP"
NOTARIZED_DMG="./Roopik-macos-notarized.dmg"
mv "$DMG_NAME" "$NOTARIZED_DMG"
mkdir -p .artifacts/public
cp "$NOTARIZED_ZIP" .artifacts/public/roopik-macos-latest.zip
cp "$NOTARIZED_DMG" .artifacts/public/roopik-macos-latest.dmg
- name: Upload macOS release artifact (arm64)
uses: actions/upload-artifact@v6
with:
name: roopik-macos-release
path: .artifacts/public/
retention-days: 10
- name: Install AWS CLI
continue-on-error: true
run: brew install awscli
- name: Upload macOS installers to R2
continue-on-error: true
env:
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
R2_BUCKET: ${{ secrets.R2_BUCKET }}
R2_PUBLIC_BASE_URL: ${{ secrets.R2_PUBLIC_BASE_URL }}
run: |
export PATH="$HOME/Library/Python/3.11/bin:$PATH"
endpoint="https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com"
prefix="macos/"
export AWS_ACCESS_KEY_ID="$R2_ACCESS_KEY_ID"
export AWS_SECRET_ACCESS_KEY="$R2_SECRET_ACCESS_KEY"
export AWS_EC2_METADATA_DISABLED=true
aws s3 cp "Roopik-macos-notarized.dmg" "s3://${R2_BUCKET}/${prefix}roopik-macos-latest.dmg" --endpoint-url "$endpoint" --no-progress
aws s3 cp "Roopik-macos-notarized.zip" "s3://${R2_BUCKET}/${prefix}roopik-macos-latest.zip" --endpoint-url "$endpoint" --no-progress
if [ -z "${R2_PUBLIC_BASE_URL:-}" ]; then
echo "R2_PUBLIC_BASE_URL not set, skipping update manifest upload."
exit 0
fi
# Re-find APP_PATH since environment variables don't persist between steps
# Look in .notarize folder where we zipped it from earlier
APP_PATH="$(find .notarize -maxdepth 3 -name "*.app" -print -quit)"
if [ -z "$APP_PATH" ]; then
echo "Could not find .app to read version from!"
# Fallback to package.json version if APP_PATH fails
version="$(node -p "require('./package.json').version")"
else
version="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$APP_PATH/Contents/Info.plist" 2>/dev/null || true)"
if [ -z "$version" ]; then
version="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "$APP_PATH/Contents/Info.plist" 2>/dev/null || true)"
fi
fi
if [ -z "$version" ]; then
version="0.0.0"
fi
commit="${{ github.sha }}"
hash="$(shasum -a 256 "Roopik-macos-notarized.zip" | awk '{print tolower($1)}')"
pub_date="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
base="${R2_PUBLIC_BASE_URL%/}"
url="${base}/macos/roopik-macos-latest.zip"
json="$(printf '{"version":"%s","productVersion":"%s","url":"%s","sha256hash":"%s","pub_date":"%s"}' "$commit" "$version" "$url" "$hash" "$pub_date")"
printf '%s' "$json" > latest.json
aws s3 cp latest.json "s3://${R2_BUCKET}/macos/stable/latest.json" --endpoint-url "$endpoint" --no-progress