mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-03-25 09:25:50 +00:00
239 lines
No EOL
8.4 KiB
YAML
239 lines
No EOL
8.4 KiB
YAML
name: Nightly Release Build
|
|
|
|
on:
|
|
schedule:
|
|
# Run at 2 AM UTC every day (10 PM EST / 7 PM PST)
|
|
- cron: '0 2 * * *'
|
|
workflow_dispatch: # Allow manual triggering
|
|
|
|
permissions:
|
|
contents: read
|
|
pull-requests: write
|
|
issues: write
|
|
|
|
jobs:
|
|
release-build-test:
|
|
name: Build and Test Release Configuration
|
|
runs-on: [self-hosted, macOS, ARM64]
|
|
timeout-minutes: 60
|
|
|
|
steps:
|
|
- name: Clean workspace
|
|
run: |
|
|
# Clean workspace for self-hosted runner
|
|
# Clean workspace but preserve .git directory
|
|
find . -maxdepth 1 -name '.*' -not -name '.git' -not -name '.' -not -name '..' -exec rm -rf {} + || true
|
|
rm -rf * || true
|
|
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Verify Xcode
|
|
run: |
|
|
xcodebuild -version
|
|
swift --version
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '24'
|
|
|
|
- name: Setup pnpm
|
|
uses: pnpm/action-setup@v4
|
|
with:
|
|
version: 9
|
|
dest: ~/pnpm-${{ github.run_id }}
|
|
|
|
- name: Cache Homebrew packages
|
|
uses: actions/cache@v4
|
|
continue-on-error: true
|
|
with:
|
|
path: |
|
|
~/Library/Caches/Homebrew
|
|
/opt/homebrew/Cellar/swiftlint
|
|
/opt/homebrew/Cellar/swiftformat
|
|
/opt/homebrew/Cellar/xcbeautify
|
|
key: ${{ runner.os }}-brew-${{ hashFiles('.github/workflows/mac.yml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-brew-
|
|
|
|
- name: Install tools
|
|
run: |
|
|
# Install or update required tools
|
|
MAX_ATTEMPTS=3
|
|
WAIT_TIME=5
|
|
|
|
for attempt in $(seq 1 $MAX_ATTEMPTS); do
|
|
echo "Tool installation attempt $attempt of $MAX_ATTEMPTS"
|
|
|
|
# Check if another brew process is running
|
|
if pgrep -x "brew" > /dev/null; then
|
|
echo "Another brew process detected, waiting ${WAIT_TIME}s..."
|
|
sleep $WAIT_TIME
|
|
WAIT_TIME=$((WAIT_TIME * 2)) # Exponential backoff
|
|
continue
|
|
fi
|
|
|
|
# Update Homebrew and install all tools in one command
|
|
if brew update && brew install swiftlint swiftformat xcbeautify; then
|
|
echo "Successfully installed/upgraded all tools"
|
|
break
|
|
else
|
|
if [ $attempt -eq $MAX_ATTEMPTS ]; then
|
|
echo "Failed to install tools after $MAX_ATTEMPTS attempts"
|
|
exit 1
|
|
fi
|
|
echo "Command failed, waiting ${WAIT_TIME}s before retry..."
|
|
sleep $WAIT_TIME
|
|
WAIT_TIME=$((WAIT_TIME * 2)) # Exponential backoff
|
|
fi
|
|
done
|
|
|
|
# Show versions
|
|
echo "SwiftLint: $(swiftlint --version || echo 'not found')"
|
|
echo "SwiftFormat: $(swiftformat --version || echo 'not found')"
|
|
echo "xcbeautify: $(xcbeautify --version || echo 'not found')"
|
|
|
|
- name: Cache pnpm store
|
|
uses: actions/cache@v4
|
|
continue-on-error: true
|
|
with:
|
|
path: ~/.local/share/pnpm/store
|
|
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-pnpm-store-
|
|
|
|
- name: Install web dependencies
|
|
run: |
|
|
cd web
|
|
# Clean any stale lock files
|
|
rm -f .pnpm-store.lock .pnpm-debug.log || true
|
|
# Set pnpm to use fewer workers to avoid crashes on self-hosted runners
|
|
export NODE_OPTIONS="--max-old-space-size=4096"
|
|
pnpm config set store-dir ~/.local/share/pnpm/store
|
|
pnpm config set package-import-method hardlink
|
|
# Install with retries
|
|
for i in 1 2 3; do
|
|
echo "Install attempt $i"
|
|
if pnpm install --frozen-lockfile; then
|
|
echo "pnpm install succeeded"
|
|
# Force rebuild of native modules
|
|
echo "Rebuilding native modules..."
|
|
pnpm rebuild || true
|
|
break
|
|
else
|
|
echo "pnpm install failed, cleaning and retrying..."
|
|
rm -rf node_modules .pnpm-store.lock || true
|
|
sleep 5
|
|
fi
|
|
done
|
|
|
|
- name: Build web artifacts
|
|
run: |
|
|
echo "Building web artifacts..."
|
|
cd web
|
|
export CI=true
|
|
pnpm run build
|
|
echo "Web artifacts built successfully"
|
|
|
|
- name: Resolve Dependencies
|
|
run: |
|
|
echo "Resolving Swift package dependencies..."
|
|
xcodebuild -resolvePackageDependencies -workspace VibeTunnel.xcworkspace || echo "Dependency resolution completed"
|
|
|
|
# BUILD RELEASE CONFIGURATION
|
|
- name: Build Release (Universal Binary)
|
|
timeout-minutes: 20
|
|
run: |
|
|
echo "Building Release configuration with universal binary..."
|
|
set -o pipefail && \
|
|
xcodebuild build \
|
|
-workspace VibeTunnel.xcworkspace \
|
|
-scheme VibeTunnel \
|
|
-configuration Release \
|
|
-destination "generic/platform=macOS" \
|
|
-archivePath build/VibeTunnel.xcarchive \
|
|
-showBuildTimingSummary \
|
|
CODE_SIGN_IDENTITY="" \
|
|
CODE_SIGNING_REQUIRED=NO \
|
|
CODE_SIGNING_ALLOWED=NO \
|
|
CODE_SIGN_ENTITLEMENTS="" \
|
|
ENABLE_HARDENED_RUNTIME=NO \
|
|
PROVISIONING_PROFILE_SPECIFIER="" \
|
|
DEVELOPMENT_TEAM="" \
|
|
ONLY_ACTIVE_ARCH=NO \
|
|
ENABLE_TESTABILITY=YES \
|
|
archive | xcbeautify
|
|
|
|
echo "Release build completed successfully"
|
|
|
|
# TEST RELEASE BUILD
|
|
- name: Test Release Configuration
|
|
timeout-minutes: 20
|
|
run: |
|
|
echo "Running tests on Release configuration..."
|
|
set -o pipefail && \
|
|
xcodebuild test \
|
|
-workspace VibeTunnel.xcworkspace \
|
|
-scheme VibeTunnel \
|
|
-configuration Release \
|
|
-destination "platform=macOS" \
|
|
-enableCodeCoverage YES \
|
|
-resultBundlePath TestResults-Release.xcresult \
|
|
CODE_SIGN_IDENTITY="" \
|
|
CODE_SIGNING_REQUIRED=NO \
|
|
CODE_SIGNING_ALLOWED=NO \
|
|
COMPILER_INDEX_STORE_ENABLE=NO \
|
|
ENABLE_TESTABILITY=YES | xcbeautify || {
|
|
echo "::error::Release configuration tests failed"
|
|
# Try to get more detailed error information
|
|
echo "=== Attempting to get test failure details ==="
|
|
xcrun xcresulttool get --path TestResults-Release.xcresult --format json 2>/dev/null | jq '.issues._values[]? | select(.severity == "error")' 2>/dev/null || true
|
|
exit 1
|
|
}
|
|
echo "Release tests completed successfully"
|
|
|
|
# PERFORMANCE VALIDATION
|
|
- name: Validate Release Binary
|
|
run: |
|
|
echo "=== Validating Release Binary ==="
|
|
ARCHIVE_PATH="build/VibeTunnel.xcarchive"
|
|
APP_PATH="$ARCHIVE_PATH/Products/Applications/VibeTunnel.app"
|
|
|
|
if [ -d "$APP_PATH" ]; then
|
|
echo "Found VibeTunnel.app at: $APP_PATH"
|
|
|
|
# Check binary architectures
|
|
echo -e "\n=== Binary Architecture ==="
|
|
lipo -info "$APP_PATH/Contents/MacOS/VibeTunnel" || echo "Binary not found"
|
|
|
|
# Check binary size
|
|
echo -e "\n=== Binary Size ==="
|
|
du -sh "$APP_PATH" || echo "Could not determine app size"
|
|
|
|
# Check if optimizations were applied (Release should be smaller than Debug)
|
|
echo -e "\n=== Optimization Check ==="
|
|
# Look for debug symbols - Release builds should have minimal symbols
|
|
nm "$APP_PATH/Contents/MacOS/VibeTunnel" 2>/dev/null | grep -c "debug" || echo "No debug symbols found (good for Release)"
|
|
|
|
# Verify entitlements
|
|
echo -e "\n=== Entitlements ==="
|
|
codesign -d --entitlements - "$APP_PATH" 2>&1 || echo "No code signing (expected in CI)"
|
|
else
|
|
echo "::warning::Release archive not found at expected location"
|
|
fi
|
|
|
|
# NOTIFY ON FAILURE
|
|
- name: Notify on Failure
|
|
if: failure()
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const issue = await github.rest.issues.create({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
title: `Nightly Release Build Failed - ${new Date().toISOString().split('T')[0]}`,
|
|
body: `The nightly release build failed. Please check the [workflow run](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}) for details.`,
|
|
labels: ['ci', 'nightly-build']
|
|
});
|
|
console.log(`Created issue #${issue.data.number}`); |