Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .github/workflows/release-intel-compat.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Desktop Intel Compatibility

on:
workflow_dispatch:
inputs:
version:
description: "Version to stamp into the Intel compatibility build"
required: true
type: string

permissions:
contents: read

jobs:
macos_intel_compat:
name: macOS x64 compatibility build
runs-on: macos-13
env:
OKCODE_COMMIT_HASH: ${{ github.sha }}
OKCODE_BUILD_TIMESTAMP: ${{ github.event.inputs.version }}
OKCODE_RELEASE_CHANNEL: prerelease
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version-file: package.json

- name: Setup Node
uses: actions/setup-node@v6
with:
node-version-file: package.json

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Align package versions to release version
run: node scripts/update-release-package-versions.ts "${{ github.event.inputs.version }}"

- name: Build Intel desktop artifact
env:
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
run: >
bun run dist:desktop:artifact --
--platform mac
--target dmg
--arch x64
--build-version "${{ github.event.inputs.version }}"
--signed
--require-signed
--verbose

- name: Upload Intel compatibility artifact
uses: actions/upload-artifact@v7
with:
name: desktop-mac-x64-compat
path: |
release/*.dmg
release/*.zip
release/latest-mac*.yml
if-no-files-found: error
219 changes: 6 additions & 213 deletions .github/workflows/release-ios.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
name: Release iOS
name: iOS Release Dry Run

on:
push:
tags:
- "v*.*.*"
workflow_dispatch:
inputs:
version:
Expand All @@ -15,215 +12,11 @@ permissions:
contents: read

jobs:
preflight:
name: Preflight
guidance:
name: Coordinated train guidance
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.release_meta.outputs.version }}
tag: ${{ steps.release_meta.outputs.tag }}
is_prerelease: ${{ steps.release_meta.outputs.is_prerelease }}
ref: ${{ github.sha }}
steps:
- name: Checkout
uses: actions/checkout@v6

- id: release_meta
name: Resolve release version
shell: bash
run: |
if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
raw="${{ github.event.inputs.version }}"
else
raw="${GITHUB_REF_NAME}"
fi

version="${raw#v}"
if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]]; then
echo "Invalid release version: $raw" >&2
exit 1
fi

echo "version=$version" >> "$GITHUB_OUTPUT"
echo "tag=v$version" >> "$GITHUB_OUTPUT"
if [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "is_prerelease=false" >> "$GITHUB_OUTPUT"
else
echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
fi

build-ios:
name: Build & Upload to TestFlight
needs: [preflight]
runs-on: macos-14
env:
RELEASE_VERSION: ${{ needs.preflight.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: ${{ needs.preflight.outputs.ref }}
fetch-depth: 0

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version-file: package.json

- name: Setup Node
uses: actions/setup-node@v6
with:
node-version-file: package.json

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Align package versions to release version
run: node scripts/update-release-package-versions.ts "$RELEASE_VERSION"

- name: Update iOS version in Xcode project
run: node scripts/update-ios-version.ts "$RELEASE_VERSION" --build-number "$GITHUB_RUN_NUMBER"

- name: Build mobile web bundle
run: bun run --cwd apps/mobile build

- name: Sync Capacitor iOS
run: bunx cap sync ios --deployment
working-directory: apps/mobile

- name: Install Apple certificate and provisioning profile
env:
IOS_CERTIFICATE_P12: ${{ secrets.IOS_CERTIFICATE_P12 }}
IOS_CERTIFICATE_PASSWORD: ${{ secrets.IOS_CERTIFICATE_PASSWORD }}
IOS_PROVISIONING_PROFILE: ${{ secrets.IOS_PROVISIONING_PROFILE }}
run: |
set -euo pipefail

# Validate required secrets
for secret_name in IOS_CERTIFICATE_P12 IOS_CERTIFICATE_PASSWORD IOS_PROVISIONING_PROFILE; do
if [[ -z "${!secret_name}" ]]; then
echo "Missing required secret: $secret_name" >&2
exit 1
fi
done

# Create temporary keychain
KEYCHAIN_PATH="$RUNNER_TEMP/app-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"

# Import distribution certificate
CERT_PATH="$RUNNER_TEMP/certificate.p12"
echo "$IOS_CERTIFICATE_P12" | base64 --decode > "$CERT_PATH"
security import "$CERT_PATH" \
-P "$IOS_CERTIFICATE_PASSWORD" \
-A -t cert -f pkcs12 \
-k "$KEYCHAIN_PATH"
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security list-keychain -d user -s "$KEYCHAIN_PATH"

# Install provisioning profile
PROFILE_PATH="$RUNNER_TEMP/profile.mobileprovision"
echo "$IOS_PROVISIONING_PROFILE" | base64 --decode > "$PROFILE_PATH"
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp "$PROFILE_PATH" ~/Library/MobileDevice/Provisioning\ Profiles/

- name: Build iOS archive
env:
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
set -euo pipefail

xcodebuild archive \
-project apps/mobile/ios/App/App.xcodeproj \
-scheme App \
-configuration Release \
-destination 'generic/platform=iOS' \
-archivePath "$RUNNER_TEMP/App.xcarchive" \
CODE_SIGN_STYLE=Manual \
DEVELOPMENT_TEAM="$APPLE_TEAM_ID" \
CODE_SIGN_IDENTITY="iPhone Distribution" \
PROVISIONING_PROFILE_SPECIFIER="${{ secrets.IOS_PROVISIONING_PROFILE_NAME }}" \
-allowProvisioningUpdates \
COMPILER_INDEX_STORE_ENABLE=NO

- name: Generate ExportOptions.plist
env:
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
cat > "$RUNNER_TEMP/ExportOptions.plist" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>app-store-connect</string>
<key>destination</key>
<string>upload</string>
<key>teamID</key>
<string>${APPLE_TEAM_ID}</string>
<key>uploadSymbols</key>
<true/>
<key>signingStyle</key>
<string>manual</string>
<key>provisioningProfiles</key>
<dict>
<key>com.openknots.okcode.mobile</key>
<string>${{ secrets.IOS_PROVISIONING_PROFILE_NAME }}</string>
</dict>
</dict>
</plist>
PLIST

- name: Export IPA
run: |
set -euo pipefail

xcodebuild -exportArchive \
-archivePath "$RUNNER_TEMP/App.xcarchive" \
-exportPath "$RUNNER_TEMP/export" \
-exportOptionsPlist "$RUNNER_TEMP/ExportOptions.plist"

- name: Write App Store Connect API key
env:
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
run: |
set -euo pipefail
KEY_DIR="$HOME/private_keys"
mkdir -p "$KEY_DIR"
printf '%s' "$APPLE_API_KEY" > "$KEY_DIR/AuthKey_${APPLE_API_KEY_ID}.p8"

- name: Upload to TestFlight
env:
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
run: |
set -euo pipefail

IPA_FILE=$(find "$RUNNER_TEMP/export" -name "*.ipa" -print -quit)
if [[ -z "$IPA_FILE" ]]; then
echo "No IPA file found in export directory" >&2
ls -la "$RUNNER_TEMP/export/"
exit 1
fi

echo "Uploading $IPA_FILE to TestFlight..."

xcrun altool --upload-app \
-f "$IPA_FILE" \
-t ios \
--apiKey "$APPLE_API_KEY_ID" \
--apiIssuer "$APPLE_API_ISSUER"

echo "Upload to TestFlight complete!"

- name: Cleanup keychain
if: always()
- name: Explain release entrypoint
run: |
KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db"
if [[ -f "$KEYCHAIN_PATH" ]]; then
security delete-keychain "$KEYCHAIN_PATH" || true
fi
rm -f "$HOME/private_keys/AuthKey_${{ secrets.APPLE_API_KEY_ID }}.p8" || true
echo "Use .github/workflows/release.yml for official tags and coordinated RC/stable releases."
echo "This workflow is reserved for manual iOS dry runs while stabilizing the TestFlight lane."
Loading
Loading