mirror of
https://github.com/selfxyz/self.git
synced 2026-04-27 03:01:15 -04:00
Merge pull request #1818 from selfxyz/release/staging-2026-03-06
Release to Staging v2.9.16 - 2026-03-06
This commit is contained in:
19
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
19
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
## Summary
|
||||
|
||||
<!-- Brief description of changes -->
|
||||
|
||||
## Test plan
|
||||
|
||||
<!-- How was this tested? -->
|
||||
|
||||
---
|
||||
|
||||
### Native Consolidation Checklist
|
||||
|
||||
<!-- Check items that apply to this PR. Delete section if not touching native code. -->
|
||||
|
||||
- [ ] CONTRACTS.md reviewed - no unintended contract changes
|
||||
- [ ] Layer 1 bridge contract tests pass (`cd app && yarn jest:run` / `yarn workspace @selfxyz/rn-sdk-test-app test`)
|
||||
- [ ] Layer 3 builds pass (app iOS, RN test app iOS, RN test app Android)
|
||||
- [ ] Layer 4 manual smoke test signed off (if consolidation PR)
|
||||
- [ ] No new native business logic added (logic belongs in TypeScript)
|
||||
25
.github/actions/find-ios-simulator/action.yml
vendored
Normal file
25
.github/actions/find-ios-simulator/action.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: Find iOS Simulator
|
||||
description: Finds an available iPhone simulator on the runner and outputs its UUID.
|
||||
|
||||
outputs:
|
||||
id:
|
||||
description: UUID of the first available iPhone simulator
|
||||
value: ${{ steps.find.outputs.id }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- id: find
|
||||
shell: bash
|
||||
run: |
|
||||
SIM_ID=$(xcrun simctl list devices available -j | python3 -c "
|
||||
import json, sys
|
||||
data = json.load(sys.stdin)
|
||||
for runtime, devices in data['devices'].items():
|
||||
if 'iOS' in runtime:
|
||||
for d in devices:
|
||||
if 'iPhone' in d['name'] and d['isAvailable']:
|
||||
print(d['udid']); sys.exit(0)
|
||||
sys.exit(1)")
|
||||
echo "Found simulator: $SIM_ID"
|
||||
echo "id=$SIM_ID" >> "$GITHUB_OUTPUT"
|
||||
206
.github/workflows/kmp-ci.yml
vendored
206
.github/workflows/kmp-ci.yml
vendored
@@ -5,12 +5,24 @@ permissions:
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths: ["packages/kmp-sdk/**", "packages/kmp-test-app/**"]
|
||||
paths:
|
||||
- "packages/kmp-sdk/**"
|
||||
- "packages/kmp-sdk-test-app/**"
|
||||
- "packages/kmp-minipay-sample/**"
|
||||
- ".github/workflows/kmp-ci.yml"
|
||||
- ".github/actions/**"
|
||||
push:
|
||||
branches: [dev, staging, main]
|
||||
paths: ["packages/kmp-sdk/**", "packages/kmp-test-app/**"]
|
||||
paths:
|
||||
- "packages/kmp-sdk/**"
|
||||
- "packages/kmp-sdk-test-app/**"
|
||||
- "packages/kmp-minipay-sample/**"
|
||||
- ".github/workflows/kmp-ci.yml"
|
||||
- ".github/actions/**"
|
||||
|
||||
jobs:
|
||||
# ── KMP SDK ──────────────────────────────────────────────
|
||||
|
||||
kmp-sdk-tests:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
@@ -34,12 +46,68 @@ jobs:
|
||||
name: kmp-sdk-test-results
|
||||
path: packages/kmp-sdk/shared/build/reports/tests/
|
||||
|
||||
kmp-sdk-android-build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/kmp-sdk
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "17"
|
||||
- uses: ./.github/actions/cache-gradle
|
||||
- uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
cache-disabled: true
|
||||
- run: ./gradlew :shared:assembleDebug
|
||||
|
||||
kmp-sdk-ios-framework:
|
||||
runs-on: namespace-profile-apple-silicon-6cpu
|
||||
timeout-minutes: 60
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/kmp-sdk
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "17"
|
||||
- uses: ./.github/actions/cache-gradle
|
||||
- uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
cache-disabled: true
|
||||
- run: ./gradlew :shared:linkDebugFrameworkIosSimulatorArm64
|
||||
|
||||
kmp-sdk-ios-test:
|
||||
runs-on: namespace-profile-apple-silicon-6cpu
|
||||
timeout-minutes: 60
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/kmp-sdk
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "17"
|
||||
- uses: ./.github/actions/cache-gradle
|
||||
- uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
cache-disabled: true
|
||||
- run: ./gradlew :shared:iosSimulatorArm64Test
|
||||
|
||||
# ── KMP Test App ─────────────────────────────────────────
|
||||
|
||||
kmp-test-app-tests:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/kmp-test-app
|
||||
working-directory: packages/kmp-sdk-test-app
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v4
|
||||
@@ -55,4 +123,134 @@ jobs:
|
||||
if: always()
|
||||
with:
|
||||
name: kmp-test-app-test-results
|
||||
path: packages/kmp-test-app/composeApp/build/reports/tests/
|
||||
path: packages/kmp-sdk-test-app/composeApp/build/reports/tests/
|
||||
|
||||
kmp-test-app-android-build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/kmp-sdk-test-app
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "17"
|
||||
- uses: ./.github/actions/cache-gradle
|
||||
- uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
cache-disabled: true
|
||||
- run: ./gradlew :composeApp:assembleDebug
|
||||
|
||||
kmp-test-app-ios-build:
|
||||
runs-on: namespace-profile-apple-silicon-6cpu
|
||||
timeout-minutes: 60
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/kmp-sdk-test-app
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Generate token for private dependencies
|
||||
uses: ./.github/actions/generate-github-token
|
||||
id: github-token
|
||||
with:
|
||||
app-id: ${{ vars.GH_WORKFLOWS_CROSS_ACCESS_ID }}
|
||||
private-key: ${{ secrets.GH_WORKFLOWS_CROSS_ACCESS_KEY }}
|
||||
configure-netrc: "true"
|
||||
- name: Configure git for HTTPS dependency fetch
|
||||
run: git config --global url."https://github.com/".insteadOf "git@github.com:"
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "17"
|
||||
- uses: ./.github/actions/cache-gradle
|
||||
- uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
cache-disabled: true
|
||||
- name: Build KMP framework for iOS
|
||||
working-directory: packages/kmp-sdk
|
||||
run: ./gradlew :shared:linkDebugFrameworkIosSimulatorArm64
|
||||
- name: Install CocoaPods dependencies
|
||||
working-directory: packages/kmp-sdk-test-app/iosApp
|
||||
run: pod install
|
||||
- name: Find iOS Simulator
|
||||
id: sim
|
||||
uses: ./.github/actions/find-ios-simulator
|
||||
- name: Build iOS app
|
||||
working-directory: packages/kmp-sdk-test-app/iosApp
|
||||
run: |
|
||||
xcodebuild -workspace iosApp.xcworkspace \
|
||||
-scheme iosApp \
|
||||
-sdk iphonesimulator \
|
||||
-destination "id=${{ steps.sim.outputs.id }}" \
|
||||
ONLY_ACTIVE_ARCH=YES \
|
||||
build
|
||||
|
||||
# ── KMP Minipay Sample ──────────────────────────────────
|
||||
|
||||
kmp-minipay-android-build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/kmp-minipay-sample
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "17"
|
||||
- uses: ./.github/actions/cache-gradle
|
||||
- uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
cache-disabled: true
|
||||
- run: ./gradlew :composeApp:assembleDebug
|
||||
|
||||
kmp-minipay-ios-build:
|
||||
runs-on: namespace-profile-apple-silicon-6cpu
|
||||
timeout-minutes: 60
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/kmp-minipay-sample
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Generate token for private dependencies
|
||||
uses: ./.github/actions/generate-github-token
|
||||
id: github-token
|
||||
with:
|
||||
app-id: ${{ vars.GH_WORKFLOWS_CROSS_ACCESS_ID }}
|
||||
private-key: ${{ secrets.GH_WORKFLOWS_CROSS_ACCESS_KEY }}
|
||||
configure-netrc: "true"
|
||||
- name: Configure git for HTTPS dependency fetch
|
||||
run: git config --global url."https://github.com/".insteadOf "git@github.com:"
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "17"
|
||||
- uses: ./.github/actions/cache-gradle
|
||||
- uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
cache-disabled: true
|
||||
- name: Build KMP framework for iOS
|
||||
working-directory: packages/kmp-sdk
|
||||
run: ./gradlew :shared:linkDebugFrameworkIosSimulatorArm64
|
||||
- name: Find iOS Simulator
|
||||
id: sim
|
||||
uses: ./.github/actions/find-ios-simulator
|
||||
- name: Resolve SPM dependencies
|
||||
working-directory: packages/kmp-minipay-sample/iosApp
|
||||
run: |
|
||||
xcodebuild -project iosApp.xcodeproj \
|
||||
-resolvePackageDependencies
|
||||
- name: Build iOS app
|
||||
working-directory: packages/kmp-minipay-sample/iosApp
|
||||
run: |
|
||||
xcodebuild -project iosApp.xcodeproj \
|
||||
-scheme iosApp \
|
||||
-sdk iphonesimulator \
|
||||
-destination "id=${{ steps.sim.outputs.id }}" \
|
||||
ONLY_ACTIVE_ARCH=YES \
|
||||
ARCHS=arm64 \
|
||||
SWIFT_ENABLE_EXPLICIT_MODULES=NO \
|
||||
build
|
||||
|
||||
316
.github/workflows/mobile-ci.yml
vendored
316
.github/workflows/mobile-ci.yml
vendored
@@ -202,319 +202,3 @@ jobs:
|
||||
# Run jest through yarn to avoid the build:deps step since CI already built dependencies
|
||||
yarn test:ci
|
||||
working-directory: ./app
|
||||
build-ios:
|
||||
# This is mostly covered in mobile-e2e.yml so we don't need to run it here frequently
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
# runs-on: macos-latest-large
|
||||
runs-on: namespace-profile-apple-silicon-6cpu
|
||||
needs: build-deps
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
# iOS project configuration - hardcoded for CI stability
|
||||
IOS_PROJECT_NAME: "Self"
|
||||
IOS_PROJECT_SCHEME: "OpenPassport"
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Read and sanitize Node.js version
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ! -f .nvmrc ] || [ -z "$(cat .nvmrc)" ]; then
|
||||
echo "❌ .nvmrc is missing or empty"; exit 1;
|
||||
fi
|
||||
VERSION="$(tr -d '\r\n' < .nvmrc)"
|
||||
VERSION="${VERSION#v}"
|
||||
if ! [[ "$VERSION" =~ ^[0-9]+(\.[0-9]+){0,2}$ ]]; then
|
||||
echo "Invalid .nvmrc content: '$VERSION'"; exit 1;
|
||||
fi
|
||||
echo "NODE_VERSION=$VERSION" >> "$GITHUB_ENV"
|
||||
echo "NODE_VERSION_SANITIZED=${VERSION//\//-}" >> "$GITHUB_ENV"
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
- name: Enable Corepack
|
||||
run: corepack enable
|
||||
- name: Activate Yarn 4.12.0
|
||||
run: corepack prepare yarn@4.12.0 --activate
|
||||
- name: Set up Xcode
|
||||
uses: maxim-lobanov/setup-xcode@v1
|
||||
with:
|
||||
xcode-version: ${{ env.XCODE_VERSION }}
|
||||
- name: Configure Xcode path
|
||||
run: |
|
||||
echo "🔧 Configuring Xcode path to fix iOS SDK issues..."
|
||||
# Fix for macOS 15 runner iOS SDK issues
|
||||
# See: https://github.com/actions/runner-images/issues/12758
|
||||
sudo xcode-select --switch /Applications/Xcode_${{ env.XCODE_VERSION }}.app
|
||||
echo "✅ Xcode path configured"
|
||||
|
||||
# Verify Xcode setup
|
||||
echo "Xcode version:"
|
||||
xcodebuild -version
|
||||
echo "Xcode path:"
|
||||
xcode-select -p
|
||||
|
||||
- name: Check Java installation
|
||||
run: |
|
||||
echo "INSTALL_JAVA=false" >> "$GITHUB_ENV"
|
||||
if command -v java &> /dev/null && java -version &> /dev/null; then
|
||||
echo "Java already installed: $(java -version 2>&1 | head -n 1)"
|
||||
else
|
||||
echo "Java not found or not working, will install..."
|
||||
echo "INSTALL_JAVA=true" >> "$GITHUB_ENV"
|
||||
fi
|
||||
- name: Setup Java environment
|
||||
if: env.INSTALL_JAVA == 'true'
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: "temurin"
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: ${{ env.RUBY_VERSION }}
|
||||
bundler-cache: false
|
||||
- name: Cache Yarn
|
||||
uses: ./.github/actions/cache-yarn
|
||||
with:
|
||||
path: |
|
||||
.yarn/cache
|
||||
node_modules
|
||||
app/node_modules
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}
|
||||
- name: Cache Ruby gems
|
||||
uses: ./.github/actions/cache-bundler
|
||||
with:
|
||||
path: app/vendor/bundle
|
||||
lock-file: app/Gemfile.lock
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-${{ env.GH_GEMS_CACHE_VERSION }}-ruby${{ env.RUBY_VERSION }}
|
||||
- name: Cache Pods
|
||||
uses: ./.github/actions/cache-pods
|
||||
with:
|
||||
path: |
|
||||
app/ios/Pods
|
||||
~/Library/Caches/CocoaPods
|
||||
lockfile: app/ios/Podfile.lock
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}
|
||||
- name: Cache Xcode build
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
app/ios/build
|
||||
~/Library/Developer/Xcode/DerivedData
|
||||
~/Library/Caches/com.apple.dt.Xcode
|
||||
key: ${{ runner.os }}-xcode-${{ env.XCODE_VERSION }}-${{ hashFiles('app/ios/Podfile.lock', 'app/ios/OpenPassport.xcworkspace/contents.xcworkspacedata', 'app/ios/Self.xcworkspace/contents.xcworkspacedata') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-xcode-${{ env.XCODE_VERSION }}-${{ hashFiles('app/ios/Podfile.lock') }}-
|
||||
${{ runner.os }}-xcode-${{ env.XCODE_VERSION }}-
|
||||
- name: Cache Xcode Index
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: app/ios/build/Index.noindex
|
||||
key: ${{ runner.os }}-xcode-index-${{ env.XCODE_VERSION }}-${{ hashFiles('app/ios/Podfile.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-xcode-index-${{ env.XCODE_VERSION }}-
|
||||
- name: Generate token for self repositories
|
||||
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false }}
|
||||
uses: ./.github/actions/generate-github-token
|
||||
id: github-token
|
||||
with:
|
||||
app-id: ${{ vars.GH_WORKFLOWS_CROSS_ACCESS_ID }}
|
||||
private-key: ${{ secrets.GH_WORKFLOWS_CROSS_ACCESS_KEY }}
|
||||
configure-netrc: "true"
|
||||
- name: Install Mobile Dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
- name: Cache Built Dependencies
|
||||
id: built-deps
|
||||
uses: ./.github/actions/cache-built-deps
|
||||
with:
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}
|
||||
- name: Build dependencies (cache miss)
|
||||
# if: steps.built-deps.outputs.cache-hit != 'true'
|
||||
env:
|
||||
SELFXYZ_APP_TOKEN: ${{ steps.github-token.outputs.token || '' }}
|
||||
run: |
|
||||
echo "Cache miss for built dependencies. Building now..."
|
||||
yarn workspace @selfxyz/mobile-app run build:deps
|
||||
- name: Install Ruby Dependencies
|
||||
run: |
|
||||
echo "Installing Ruby dependencies..."
|
||||
bundle config set --local path 'vendor/bundle'
|
||||
bundle install --jobs 4 --retry 3
|
||||
working-directory: ./app
|
||||
- name: Install iOS Dependencies
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 20
|
||||
max_attempts: 3
|
||||
retry_wait_seconds: 10
|
||||
command: |
|
||||
cd app/ios
|
||||
bundle exec bash scripts/pod-install-with-cache-fix.sh
|
||||
env:
|
||||
SELFXYZ_APP_TOKEN: ${{ steps.github-token.outputs.token }}
|
||||
- name: Resolve iOS workspace
|
||||
run: |
|
||||
WORKSPACE_OPEN="ios/OpenPassport.xcworkspace"
|
||||
WORKSPACE_SELF="ios/Self.xcworkspace"
|
||||
|
||||
if xcodebuild -list -workspace "$WORKSPACE_OPEN" 2>/dev/null | grep -q "OpenPassport"; then
|
||||
WORKSPACE_PATH="$WORKSPACE_OPEN"
|
||||
else
|
||||
WORKSPACE_PATH="$WORKSPACE_SELF"
|
||||
fi
|
||||
|
||||
echo "WORKSPACE_PATH=$WORKSPACE_PATH" >> "$GITHUB_ENV"
|
||||
echo "Resolved workspace: $WORKSPACE_PATH"
|
||||
working-directory: ./app
|
||||
- name: Verify iOS Workspace
|
||||
run: |
|
||||
echo "Verifying iOS workspace setup..."
|
||||
|
||||
if [ -z "$WORKSPACE_PATH" ]; then
|
||||
echo "❌ WORKSPACE_PATH is not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$WORKSPACE_PATH" ]; then
|
||||
echo "❌ Workspace not found at: $WORKSPACE_PATH"
|
||||
echo "Available workspaces:"
|
||||
find ios -name "*.xcworkspace" -type d
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "ios/Pods" ]; then
|
||||
echo "❌ Pods directory is missing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify scheme exists by listing available schemes
|
||||
echo "Verifying scheme availability..."
|
||||
AVAILABLE_SCHEMES=$(xcodebuild -list -workspace "$WORKSPACE_PATH" 2>/dev/null | grep -A 200 "Schemes:" | grep -v "Schemes:" | xargs)
|
||||
echo "Available schemes (first 20): $(echo $AVAILABLE_SCHEMES | cut -d' ' -f1-20)..."
|
||||
|
||||
if [[ ! "$AVAILABLE_SCHEMES" =~ ${{ env.IOS_PROJECT_SCHEME }} ]]; then
|
||||
echo "❌ Scheme '${{ env.IOS_PROJECT_SCHEME }}' not found"
|
||||
echo "Full scheme list:"
|
||||
xcodebuild -list -workspace "$WORKSPACE_PATH" 2>/dev/null | grep -A 200 "Schemes:" | grep -v "Schemes:" | head -50
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ iOS workspace is properly configured"
|
||||
echo "✅ Using workspace: $WORKSPACE_PATH"
|
||||
echo "✅ Using scheme: ${{ env.IOS_PROJECT_SCHEME }}"
|
||||
working-directory: ./app
|
||||
- name: Build iOS
|
||||
run: |
|
||||
echo "Building iOS app for simulator (no signing required)..."
|
||||
echo "Project: ${{ env.IOS_PROJECT_NAME }}, Scheme: ${{ env.IOS_PROJECT_SCHEME }}"
|
||||
# Build for iOS Simulator to avoid code signing issues in CI
|
||||
xcodebuild -workspace "$WORKSPACE_PATH" \
|
||||
-scheme ${{ env.IOS_PROJECT_SCHEME }} \
|
||||
-configuration Release \
|
||||
-sdk iphonesimulator \
|
||||
-destination "generic/platform=iOS Simulator" \
|
||||
-derivedDataPath ios/build \
|
||||
-jobs "$(sysctl -n hw.ncpu)" \
|
||||
-parallelizeTargets \
|
||||
-quiet || { echo "❌ iOS build failed"; exit 1; }
|
||||
echo "✅ iOS build succeeded"
|
||||
working-directory: ./app
|
||||
|
||||
build-android:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-deps
|
||||
# This is mostly covered in mobile-e2e.yml so we don't need to run it here frequently
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Read and sanitize Node.js version
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ! -f .nvmrc ] || [ -z "$(cat .nvmrc)" ]; then
|
||||
echo "❌ .nvmrc is missing or empty"; exit 1;
|
||||
fi
|
||||
VERSION="$(tr -d '\r\n' < .nvmrc)"
|
||||
VERSION="${VERSION#v}"
|
||||
if ! [[ "$VERSION" =~ ^[0-9]+(\.[0-9]+){0,2}$ ]]; then
|
||||
echo "Invalid .nvmrc content: '$VERSION'"; exit 1;
|
||||
fi
|
||||
echo "NODE_VERSION=$VERSION" >> "$GITHUB_ENV"
|
||||
echo "NODE_VERSION_SANITIZED=${VERSION//\//-}" >> "$GITHUB_ENV"
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
- name: Enable Corepack
|
||||
run: corepack enable
|
||||
- name: Activate Yarn 4.12.0
|
||||
run: corepack prepare yarn@4.12.0 --activate
|
||||
- name: Cache Yarn
|
||||
uses: ./.github/actions/cache-yarn
|
||||
with:
|
||||
path: |
|
||||
.yarn/cache
|
||||
node_modules
|
||||
app/node_modules
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}
|
||||
- name: Free up disk space
|
||||
uses: ./.github/actions/free-disk-space
|
||||
- name: Cache Gradle
|
||||
uses: ./.github/actions/cache-gradle
|
||||
with:
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}
|
||||
- name: Setup Java environment
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: "temurin"
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
- name: Setup Android SDK
|
||||
uses: android-actions/setup-android@v3
|
||||
with:
|
||||
accept-android-sdk-licenses: true
|
||||
- name: Cache NDK
|
||||
id: ndk-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.ANDROID_HOME }}/ndk/${{ env.ANDROID_NDK_VERSION }}
|
||||
key: ${{ runner.os }}-ndk-${{ env.ANDROID_NDK_VERSION }}
|
||||
- name: Install NDK
|
||||
if: steps.ndk-cache.outputs.cache-hit != 'true'
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 15
|
||||
max_attempts: 3
|
||||
retry_wait_seconds: 10
|
||||
command: sdkmanager "ndk;${{ env.ANDROID_NDK_VERSION }}"
|
||||
- name: Install Mobile Dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
- name: Cache Built Dependencies
|
||||
id: built-deps
|
||||
uses: ./.github/actions/cache-built-deps
|
||||
with:
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}
|
||||
- name: Build dependencies (cache miss)
|
||||
if: steps.built-deps.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Cache miss for built dependencies. Building now..."
|
||||
yarn workspace @selfxyz/mobile-app run build:deps
|
||||
- name: Generate token for self repositories
|
||||
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false }}
|
||||
uses: ./.github/actions/generate-github-token
|
||||
id: github-token
|
||||
with:
|
||||
app-id: ${{ vars.GH_WORKFLOWS_CROSS_ACCESS_ID }}
|
||||
private-key: ${{ secrets.GH_WORKFLOWS_CROSS_ACCESS_KEY }}
|
||||
- name: Setup Android private modules
|
||||
run: |
|
||||
cd ${{ env.APP_PATH }}
|
||||
PLATFORM=android node scripts/setup-private-modules.cjs
|
||||
env:
|
||||
SELFXYZ_APP_TOKEN: ${{ steps.github-token.outputs.token }}
|
||||
CI: true
|
||||
- name: Build Android (with AAPT2 symlink fix)
|
||||
run: yarn android:ci
|
||||
working-directory: ./app
|
||||
- name: Clean up Gradle build artifacts
|
||||
uses: ./.github/actions/cleanup-gradle-artifacts
|
||||
|
||||
5
.github/workflows/mobile-deploy.yml
vendored
5
.github/workflows/mobile-deploy.yml
vendored
@@ -690,6 +690,9 @@ jobs:
|
||||
CI_IOS_BUILD: ${{ needs.bump-version.outputs.ios_build }}
|
||||
CI_ANDROID_BUILD: ${{ needs.bump-version.outputs.android_build }}
|
||||
ENABLE_DEBUG_LOGS: ${{ secrets.ENABLE_DEBUG_LOGS }}
|
||||
GOOGLE_SIGNIN_ANDROID_CLIENT_ID: ${{ secrets.GOOGLE_SIGNIN_ANDROID_CLIENT_ID }}
|
||||
GOOGLE_SIGNIN_IOS_CLIENT_ID: ${{ secrets.GOOGLE_SIGNIN_IOS_CLIENT_ID }}
|
||||
GOOGLE_SIGNIN_WEB_CLIENT_ID: ${{ secrets.GOOGLE_SIGNIN_WEB_CLIENT_ID }}
|
||||
GRAFANA_LOKI_PASSWORD: ${{ secrets.GRAFANA_LOKI_PASSWORD }}
|
||||
GRAFANA_LOKI_URL: ${{ secrets.GRAFANA_LOKI_URL }}
|
||||
GRAFANA_LOKI_USERNAME: ${{ secrets.GRAFANA_LOKI_USERNAME }}
|
||||
@@ -1165,6 +1168,8 @@ jobs:
|
||||
ANDROID_PACKAGE_NAME: ${{ secrets.ANDROID_PACKAGE_NAME }}
|
||||
ENABLE_DEBUG_LOGS: ${{ secrets.ENABLE_DEBUG_LOGS }}
|
||||
GOOGLE_SIGNIN_ANDROID_CLIENT_ID: ${{ secrets.GOOGLE_SIGNIN_ANDROID_CLIENT_ID }}
|
||||
GOOGLE_SIGNIN_IOS_CLIENT_ID: ${{ secrets.GOOGLE_SIGNIN_IOS_CLIENT_ID }}
|
||||
GOOGLE_SIGNIN_WEB_CLIENT_ID: ${{ secrets.GOOGLE_SIGNIN_WEB_CLIENT_ID }}
|
||||
GRAFANA_LOKI_PASSWORD: ${{ secrets.GRAFANA_LOKI_PASSWORD }}
|
||||
GRAFANA_LOKI_URL: ${{ secrets.GRAFANA_LOKI_URL }}
|
||||
GRAFANA_LOKI_USERNAME: ${{ secrets.GRAFANA_LOKI_USERNAME }}
|
||||
|
||||
59
.github/workflows/mobile-sdk-demo-e2e.yml
vendored
59
.github/workflows/mobile-sdk-demo-e2e.yml
vendored
@@ -40,10 +40,8 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
android-e2e:
|
||||
name: Android E2E Tests Demo App
|
||||
# Currently build-only for Android. E2E steps are preserved but skipped (if: false).
|
||||
# To re-enable full E2E: change `if: false` to `if: true` on emulator steps.
|
||||
android-build:
|
||||
name: Android Build Validation Demo App
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-android-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
@@ -108,23 +106,6 @@ jobs:
|
||||
max_attempts: 3
|
||||
retry_wait_seconds: 5
|
||||
command: yarn install --immutable --silent
|
||||
- name: Validate Maestro test file
|
||||
if: false # Skip for build-only test - keep logic for future E2E
|
||||
run: |
|
||||
[ -f packages/mobile-sdk-demo/tests/e2e/launch.android.flow.yaml ] || { echo "❌ Android E2E test file missing"; exit 1; }
|
||||
- name: Cache Maestro
|
||||
if: false # Skip for build-only test - keep logic for future E2E
|
||||
id: cache-maestro
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.maestro
|
||||
key: ${{ runner.os }}-maestro-${{ env.MAESTRO_VERSION }}
|
||||
- name: Install Maestro
|
||||
if: false # Skip for build-only test - keep logic for future E2E
|
||||
run: curl -Ls "https://get.maestro.mobile.dev" | bash
|
||||
- name: Add Maestro to path
|
||||
if: false # Skip for build-only test - keep logic for future E2E
|
||||
run: echo "$HOME/.maestro/bin" >> "$GITHUB_PATH"
|
||||
- name: Free up disk space
|
||||
uses: ./.github/actions/free-disk-space
|
||||
- name: Setup Java environment
|
||||
@@ -145,11 +126,6 @@ jobs:
|
||||
max_attempts: 3
|
||||
retry_wait_seconds: 10
|
||||
command: sdkmanager "ndk;${{ env.ANDROID_NDK_VERSION }}"
|
||||
- name: Enable KVM group perms
|
||||
run: |
|
||||
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
|
||||
sudo udevadm control --reload-rules
|
||||
sudo udevadm trigger --name-match=kvm
|
||||
- name: Build dependencies
|
||||
run: |
|
||||
echo "Building dependencies..."
|
||||
@@ -178,37 +154,6 @@ jobs:
|
||||
echo "📱 APK size: $APK_SIZE bytes"
|
||||
|
||||
echo "🎉 Build verification completed successfully!"
|
||||
echo "ℹ️ Emulator testing is temporarily disabled - build testing only"
|
||||
- name: Run Maestro tests on Android
|
||||
if: false # Skip emulator/E2E for build-only test - keep logic for future E2E
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ env.ANDROID_API_LEVEL }}
|
||||
arch: x86_64
|
||||
target: google_apis
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -camera-front none -memory 8192 -cores 4 -accel on
|
||||
disable-animations: true
|
||||
script: |
|
||||
echo "Installing app on emulator..."
|
||||
APK_PATH="packages/mobile-sdk-demo/android/app/build/outputs/apk/debug/app-debug.apk"
|
||||
[ -f "$APK_PATH" ] || { echo "❌ APK not found at $APK_PATH"; exit 1; }
|
||||
adb install -r "$APK_PATH" || { echo "❌ App installation failed"; exit 1; }
|
||||
echo "✅ App installed successfully"
|
||||
|
||||
echo "⏰ Giving the emulator a moment to settle..."
|
||||
sleep 5
|
||||
|
||||
echo "🎭 Running Maestro tests..."
|
||||
export MAESTRO_DRIVER_STARTUP_TIMEOUT=180000
|
||||
maestro test packages/mobile-sdk-demo/tests/e2e/launch.android.flow.yaml --format junit --output packages/mobile-sdk-demo/maestro-results-android.xml
|
||||
- name: Upload Android test results
|
||||
if: false # Skip for build-only test - keep logic for future E2E
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: maestro-results-android
|
||||
path: packages/mobile-sdk-demo/maestro-results-android.xml
|
||||
if-no-files-found: warn
|
||||
|
||||
ios-e2e:
|
||||
timeout-minutes: 60
|
||||
|
||||
113
.github/workflows/rn-sdk-test-app-ci.yml
vendored
Normal file
113
.github/workflows/rn-sdk-test-app-ci.yml
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
name: RN SDK Test App CI
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "packages/rn-sdk/**"
|
||||
- "packages/rn-sdk-test-app/**"
|
||||
- "packages/kmp-sdk/**"
|
||||
- "packages/self-sdk-swift/**"
|
||||
- ".github/workflows/rn-sdk-test-app-ci.yml"
|
||||
- ".github/actions/**"
|
||||
push:
|
||||
branches: [dev, staging, main]
|
||||
paths:
|
||||
- "packages/rn-sdk/**"
|
||||
- "packages/rn-sdk-test-app/**"
|
||||
- "packages/kmp-sdk/**"
|
||||
- "packages/self-sdk-swift/**"
|
||||
- ".github/workflows/rn-sdk-test-app-ci.yml"
|
||||
- ".github/actions/**"
|
||||
|
||||
jobs:
|
||||
types:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
- name: Check for nested require() in tests
|
||||
run: |
|
||||
if grep -rE "require\(['\"]react(-native)?['\"])" packages/rn-sdk/src/__tests__/ 2>/dev/null; then
|
||||
echo "❌ Found nested require() patterns that cause OOM in CI"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ No nested require() patterns found"
|
||||
- name: Build webview-bridge
|
||||
run: yarn workspace @selfxyz/webview-bridge build
|
||||
- name: Typecheck rn-sdk
|
||||
run: yarn workspace @selfxyz/rn-sdk typecheck
|
||||
- name: Test rn-sdk
|
||||
run: yarn workspace @selfxyz/rn-sdk test
|
||||
- name: Build rn-sdk types
|
||||
run: yarn workspace @selfxyz/rn-sdk tsup
|
||||
- name: Typecheck rn-sdk-test-app
|
||||
run: yarn workspace @selfxyz/rn-sdk-test-app types
|
||||
|
||||
android-build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "17"
|
||||
- name: Generate debug keystore
|
||||
run: |
|
||||
keytool -genkeypair -v -keystore packages/rn-sdk-test-app/android/app/debug.keystore \
|
||||
-alias androiddebugkey -keyalg RSA -keysize 2048 -validity 10000 \
|
||||
-storepass android -keypass android \
|
||||
-dname "CN=Android Debug,O=Android,C=US"
|
||||
- name: Publish KMP SDK to mavenLocal
|
||||
run: |
|
||||
cd packages/kmp-sdk && ./gradlew :shared:publishToMavenLocal --quiet
|
||||
- name: Build Android debug APK
|
||||
run: |
|
||||
chmod +x packages/rn-sdk-test-app/android/gradlew
|
||||
cd packages/rn-sdk-test-app/android && ./gradlew assembleDebug --quiet --parallel --build-cache --no-configuration-cache
|
||||
|
||||
ios-build:
|
||||
runs-on: namespace-profile-apple-silicon-6cpu
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Generate token for private dependencies
|
||||
uses: ./.github/actions/generate-github-token
|
||||
id: github-token
|
||||
with:
|
||||
app-id: ${{ vars.GH_WORKFLOWS_CROSS_ACCESS_ID }}
|
||||
private-key: ${{ secrets.GH_WORKFLOWS_CROSS_ACCESS_KEY }}
|
||||
configure-netrc: "true"
|
||||
- name: Configure git for HTTPS dependency fetch
|
||||
run: git config --global url."https://github.com/".insteadOf "git@github.com:"
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: .nvmrc
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
- name: Build webview-bridge
|
||||
run: yarn workspace @selfxyz/webview-bridge build
|
||||
- name: Install CocoaPods dependencies
|
||||
working-directory: packages/rn-sdk-test-app/ios
|
||||
run: pod install
|
||||
- name: Find iOS Simulator
|
||||
id: sim
|
||||
uses: ./.github/actions/find-ios-simulator
|
||||
- name: Build iOS app
|
||||
working-directory: packages/rn-sdk-test-app/ios
|
||||
run: |
|
||||
xcodebuild -workspace SelfRNTestApp.xcworkspace \
|
||||
-scheme SelfRNTestApp \
|
||||
-sdk iphonesimulator \
|
||||
-destination "id=${{ steps.sim.outputs.id }}" \
|
||||
ONLY_ACTIVE_ARCH=YES \
|
||||
build
|
||||
45
.github/workflows/swift-sdk-ci.yml
vendored
Normal file
45
.github/workflows/swift-sdk-ci.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
name: Swift SDK CI
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "packages/self-sdk-swift/**"
|
||||
- ".github/workflows/swift-sdk-ci.yml"
|
||||
- ".github/actions/**"
|
||||
push:
|
||||
branches: [dev, staging, main]
|
||||
paths:
|
||||
- "packages/self-sdk-swift/**"
|
||||
- ".github/workflows/swift-sdk-ci.yml"
|
||||
- ".github/actions/**"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false }}
|
||||
runs-on: namespace-profile-apple-silicon-6cpu
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Generate token for private dependencies
|
||||
uses: ./.github/actions/generate-github-token
|
||||
id: github-token
|
||||
with:
|
||||
app-id: ${{ vars.GH_WORKFLOWS_CROSS_ACCESS_ID }}
|
||||
private-key: ${{ secrets.GH_WORKFLOWS_CROSS_ACCESS_KEY }}
|
||||
configure-netrc: "true"
|
||||
- name: Configure git for HTTPS dependency fetch
|
||||
run: git config --global url."https://github.com/".insteadOf "git@github.com:"
|
||||
- name: Resolve Swift package dependencies
|
||||
working-directory: packages/self-sdk-swift
|
||||
run: swift package resolve
|
||||
- name: Build Swift package for iOS Simulator
|
||||
working-directory: packages/self-sdk-swift
|
||||
run: |
|
||||
xcodebuild build \
|
||||
-scheme SelfSdkSwift \
|
||||
-sdk iphonesimulator \
|
||||
-destination 'generic/platform=iOS Simulator' \
|
||||
ONLY_ACTIVE_ARCH=NO
|
||||
44
.github/workflows/webview-app-ci.yml
vendored
Normal file
44
.github/workflows/webview-app-ci.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
name: WebView App CI
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "packages/webview-app/**"
|
||||
- "packages/webview-bridge/**"
|
||||
- ".github/workflows/webview-app-ci.yml"
|
||||
- ".github/actions/**"
|
||||
push:
|
||||
branches: [dev, staging, main]
|
||||
paths:
|
||||
- "packages/webview-app/**"
|
||||
- "packages/webview-bridge/**"
|
||||
- ".github/workflows/webview-app-ci.yml"
|
||||
- ".github/actions/**"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
- name: Build webview-bridge
|
||||
run: yarn workspace @selfxyz/webview-bridge build
|
||||
- name: Build webview-app
|
||||
run: yarn workspace @selfxyz/webview-app build
|
||||
|
||||
types:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
- name: Build webview-bridge
|
||||
run: yarn workspace @selfxyz/webview-bridge build
|
||||
- name: Typecheck
|
||||
run: yarn workspace @selfxyz/webview-app typecheck
|
||||
48
.github/workflows/webview-bridge-ci.yml
vendored
Normal file
48
.github/workflows/webview-bridge-ci.yml
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
name: WebView Bridge CI
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "packages/webview-bridge/**"
|
||||
- ".github/workflows/webview-bridge-ci.yml"
|
||||
- ".github/actions/**"
|
||||
push:
|
||||
branches: [dev, staging, main]
|
||||
paths:
|
||||
- "packages/webview-bridge/**"
|
||||
- ".github/workflows/webview-bridge-ci.yml"
|
||||
- ".github/actions/**"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
- name: Build
|
||||
run: yarn workspace @selfxyz/webview-bridge build
|
||||
|
||||
types:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
- name: Typecheck
|
||||
run: yarn workspace @selfxyz/webview-bridge typecheck
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
- name: Test
|
||||
run: yarn workspace @selfxyz/webview-bridge test
|
||||
Reference in New Issue
Block a user