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
22 changes: 22 additions & 0 deletions .eas/workflows/development-builds.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Create development builds

on:
pull_request:
branches:
- main
- release/*

jobs:
build_android:
name: Build Android (dev)
type: build
params:
platform: android
profile: development

build_ios_simulator:
name: Build iOS Simulator (dev)
type: build
params:
platform: ios
profile: preview
14 changes: 14 additions & 0 deletions .eas/workflows/preview-update.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Publish preview update

on:
push:
branches:
- '*'
- '!main'

jobs:
publish_preview:
name: Publish preview update
type: update
params:
branch: ${{ github.ref_name || 'preview' }}
67 changes: 67 additions & 0 deletions .eas/workflows/production-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Deploy to production

on:
push:
branches:
- main

jobs:
fingerprint:
name: Fingerprint
type: fingerprint

# NOTE: get-build intentionally uses default behavior (completed builds only).
# If a build is in-progress, we skip and let it complete on its own.
# This prevents duplicate builds and OTA updates that would race with ongoing builds.
# Set wait_for_in_progress: true if you want to wait for in-progress builds instead.
get_android_build:
name: Check existing Android build
needs: [fingerprint]
type: get-build
params:
fingerprint_hash: ${{ needs.fingerprint.outputs.android_fingerprint_hash }}
profile: production

get_ios_build:
name: Check existing iOS build
needs: [fingerprint]
type: get-build
params:
fingerprint_hash: ${{ needs.fingerprint.outputs.ios_fingerprint_hash }}
profile: production

build_android:
name: Build Android
needs: [get_android_build]
if: ${{ !needs.get_android_build.outputs.build_id }}
type: build
params:
platform: android
profile: production

build_ios:
name: Build iOS
needs: [get_ios_build]
if: ${{ !needs.get_ios_build.outputs.build_id }}
type: build
params:
platform: ios
profile: production

publish_android_update:
name: Publish Android OTA update
needs: [get_android_build]
if: ${{ needs.get_android_build.outputs.build_id }}
type: update
params:
branch: production
platform: android

Comment thread
coderabbitai[bot] marked this conversation as resolved.
publish_ios_update:
name: Publish iOS OTA update
needs: [get_ios_build]
if: ${{ needs.get_ios_build.outputs.build_id }}
type: update
params:
branch: production
platform: ios
17 changes: 6 additions & 11 deletions .github/actions/setup-thumbcode/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,10 @@ name: 'Setup ThumbCode Environment'
description: 'Reusable setup action for ThumbCode workflows - installs Node, pnpm, dependencies, and generates tokens'

inputs:
node-version:
description: 'Node.js version to use'
node-version-file:
description: 'File containing Node.js version (defaults to .nvmrc)'
required: false
default: '20'
pnpm-version:
description: 'pnpm version to use'
required: false
default: '10'
default: '.nvmrc'
generate-tokens:
description: 'Whether to generate design tokens'
required: false
Expand All @@ -24,13 +20,12 @@ runs:
steps:
- name: Install pnpm
uses: pnpm/action-setup@c5ba7f7862a0f64c1b1a05fbac13e0b8e86ba08c # v4
with:
version: ${{ inputs.pnpm-version }}
# Reads version from packageManager field in package.json

- name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6
with:
node-version: ${{ inputs.node-version }}
node-version-file: ${{ inputs.node-version-file }}
cache: 'pnpm'

- name: Install dependencies
Expand Down
185 changes: 185 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
name: CD

on:
push:
branches: [main]
paths:
- 'src/**'
- 'app.json'
- 'eas.json'
- 'package.json'
pull_request:
branches: [main]
paths:
- 'src/**'
- 'app.json'
- 'eas.json'
- 'package.json'
workflow_dispatch:
Comment thread
coderabbitai[bot] marked this conversation as resolved.
inputs:
platform:
description: 'Platform to build'
required: true
default: 'all'
type: choice
options:
- all
- android
- ios
- web
profile:
description: 'Build profile'
required: true
default: 'preview'
type: choice
options:
- development
- preview
- production

# Prevent concurrent deployments
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

permissions:
contents: read
pull-requests: write

jobs:
# ============================================
# EAS Update for PRs (OTA Updates)
# ============================================
eas-update:
name: EAS Update (PR Preview)
if: github.event_name == 'pull_request'
Comment thread
coderabbitai[bot] marked this conversation as resolved.
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
pull-requests: write

steps:
- name: Check for EXPO_TOKEN
id: check-token
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
run: |
if [ -z "$EXPO_TOKEN" ]; then
echo "::warning::EXPO_TOKEN secret is not configured. Skipping EAS update."
echo "Learn more: https://docs.expo.dev/eas-update/github-actions"
echo "has_token=false" >> $GITHUB_OUTPUT
else
echo "has_token=true" >> $GITHUB_OUTPUT
fi

- name: Checkout code
if: steps.check-token.outputs.has_token == 'true'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup ThumbCode environment
if: steps.check-token.outputs.has_token == 'true'
uses: ./.github/actions/setup-thumbcode

- name: Setup Expo and EAS
if: steps.check-token.outputs.has_token == 'true'
uses: expo/expo-github-action@c7b66a9c327a43a8fa7c0158e7f30d6040d2481e # v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}

- name: Create preview update
if: steps.check-token.outputs.has_token == 'true'
uses: expo/expo-github-action/preview@c7b66a9c327a43a8fa7c0158e7f30d6040d2481e # v8
with:
command: eas update --auto
env:
# Use production slug to match EAS project configuration
EXPO_PUBLIC_APP_ENV: production

Comment thread
coderabbitai[bot] marked this conversation as resolved.
# ============================================
# EAS Build - Android
# ============================================
build-android:
name: Build Android
if: |
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
(github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'android'))
runs-on: ubuntu-latest
timeout-minutes: 60

steps:
- name: Check for EXPO_TOKEN
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
run: |
if [ -z "$EXPO_TOKEN" ]; then
echo "::error::EXPO_TOKEN secret is required for EAS builds"
exit 1
fi

- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup ThumbCode environment
uses: ./.github/actions/setup-thumbcode

- name: Setup Expo and EAS
uses: expo/expo-github-action@c7b66a9c327a43a8fa7c0158e7f30d6040d2481e # v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}

- name: Build Android
run: |
PROFILE="${{ github.event.inputs.profile || 'preview' }}"
eas build --platform android --profile $PROFILE --non-interactive --no-wait

# ============================================
# EAS Build - iOS
# ============================================
build-ios:
name: Build iOS
if: |
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
(github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'ios'))
runs-on: ubuntu-latest
timeout-minutes: 60

steps:
- name: Check for EXPO_TOKEN
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
run: |
if [ -z "$EXPO_TOKEN" ]; then
echo "::error::EXPO_TOKEN secret is required for EAS builds"
exit 1
fi

- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup ThumbCode environment
uses: ./.github/actions/setup-thumbcode

- name: Setup Expo and EAS
uses: expo/expo-github-action@c7b66a9c327a43a8fa7c0158e7f30d6040d2481e # v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}

- name: Build iOS
run: |
PROFILE="${{ github.event.inputs.profile || 'preview' }}"
eas build --platform ios --profile $PROFILE --non-interactive --no-wait

# ============================================
# NOTE: App Store Submissions
# ============================================
# Production submission jobs are not yet configured.
# See issue #66 for required credentials and setup.
#
# Current release strategy:
# - Web staging: Automatic via Render.com (render.yaml)
# - Mobile builds: Download from expo.dev after EAS build completes
# - Debug APK: Can be downloaded from expo.dev build artifacts
Loading
Loading