Skip to content

test(ci): run simulator resolver pytest suite #153

test(ci): run simulator resolver pytest suite

test(ci): run simulator resolver pytest suite #153

Workflow file for this run

name: iOS Security Checks
# GitHub Actions hardening notes:
# - Every action is pinned to a full commit SHA. The `v5` tag of
# actions/setup-python is a lightweight tag on commit a26af69b, so the pin
# records that commit rather than a moving major-version tag.
# - This workflow declares read-only token permissions. Repository defaults
# are irrelevant here because an explicit block makes every unlisted scope
# none.
# - Validation jobs must not persist checkout credentials: no step pushes.
# - This is the PR lane. It does not certify a release candidate; producer
# owned payload defects are reported here and enforced by
# release-certification.yml.
permissions:
contents: read
on:
pull_request:
paths:
- '.github/workflows/**'
- '.tool-versions'
- '.swiftlint.yml'
- '.swiftlint-baseline.json'
- '.gitignore'
- 'Makefile'
- 'README.md'
- 'bridge-contract.json'
- 'knip.jsonc'
- 'package.json'
- 'package-lock.json'
- 'vitest.config.ts'
- 'runtime-platform-config.json'
- 'scripts/**'
- 'tools/**'
- 'KeriWallet/**'
- 'KeriWalletTests/**'
- 'KeriWalletUITests/**'
- 'KeriWallet.xcodeproj/**'
- 'generated/**'
- 'Config/**'
- 'ExportOptions.plist.example'
push:
branches:
- main
paths:
- '.github/workflows/**'
- '.tool-versions'
- '.swiftlint.yml'
- '.swiftlint-baseline.json'
- '.gitignore'
- 'Makefile'
- 'README.md'
- 'bridge-contract.json'
- 'knip.jsonc'
- 'package.json'
- 'package-lock.json'
- 'vitest.config.ts'
- 'runtime-platform-config.json'
- 'scripts/**'
- 'tools/**'
- 'KeriWallet/**'
- 'KeriWalletTests/**'
- 'KeriWalletUITests/**'
- 'KeriWallet.xcodeproj/**'
- 'generated/**'
- 'Config/**'
- 'ExportOptions.plist.example'
workflow_dispatch:
jobs:
payload-checks:
runs-on: ubuntu-latest
timeout-minutes: 30
env:
FORTWEB_DIR: ${{ github.workspace }}/.deps/fortweb
FORTWEB_RUNTIME_SOURCE_URL: https://github.com/keri-foundation/fortweb/releases/download/runtime-source-pyodide-314-20260909/runtime-source.tar.gz
FORTWEB_RUNTIME_SOURCE_ARCHIVE_SHA256: e04833249eec88596e0f2f88d32baa6d5fae6b2e964996587061ddac4bd78c72
FORTWEB_RUNTIME_SOURCE_MANIFEST: build/runtime-source/manifest.json
FORTWEB_RUNTIME_SOURCE_MANIFEST_SHA256: 87bcc689d7778840a76284471ff599cef21be41df2b429724f7f4fdc5f022135
FORTWEB_PACKAGE_REF: refs/heads/pyodide-314-runtime
steps:
- name: Check out repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
persist-credentials: false
fetch-depth: 0
- name: Check out FortWeb dependency
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
persist-credentials: false
repository: keri-foundation/fortweb
ref: bdb81afa7593603141e8db306f0636a583d2db02
path: .deps/fortweb
- name: Set up Node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8
with:
node-version: '22.12.0'
cache: npm
- name: Install dependencies
run: npm ci
- name: Set up Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.12'
# Resolver unit tests are hermetic: the simctl subprocess boundary is
# mocked, so they belong on this Linux job rather than the macOS lane.
# Command chain (follow it, do not grep for 'pytest'):
# this step -> make test-resolver -> python3 -m pytest scripts/__tests__/ -q
# pytest is pinned: 9.0.2 declares Requires-Python >=3.10, covering 3.12.
- name: Install pytest
run: python3 -m pip install --disable-pip-version-check pytest==9.0.2
- name: Run simulator resolver tests (pytest)
run: make test-resolver
- name: Build canonical FortWeb runtime
run: |
npm ci --prefix "$FORTWEB_DIR"
(cd "$FORTWEB_DIR" && python3 scripts/acquire_runtime_source.py \
--url "$FORTWEB_RUNTIME_SOURCE_URL" \
--sha256 "$FORTWEB_RUNTIME_SOURCE_ARCHIVE_SHA256" \
--manifest-sha256 "$FORTWEB_RUNTIME_SOURCE_MANIFEST_SHA256" \
--output build/runtime-source)
python3 -m pip install --disable-pip-version-check --no-index --no-deps \
"$FORTWEB_DIR/build/runtime-source/wheelhouse/packaging-26.1-py3-none-any.whl" \
"$FORTWEB_DIR/build/runtime-source/wheelhouse/setuptools-83.0.0-py3-none-any.whl" \
"$FORTWEB_DIR/build/runtime-source/wheelhouse/wheel-0.47.0-py3-none-any.whl"
(cd "$FORTWEB_DIR" && npm run build:runtime && \
FORTWEB_RUNTIME_SOURCE_MANIFEST="$FORTWEB_RUNTIME_SOURCE_MANIFEST" \
FORTWEB_RUNTIME_SOURCE_MANIFEST_SHA256="$FORTWEB_RUNTIME_SOURCE_MANIFEST_SHA256" \
npm run package:runtime -- --runtime-dir dist/runtime --python python3 --output-dir dist/package --ref "$FORTWEB_PACKAGE_REF")
test -f "$FORTWEB_DIR/dist/package/fortweb-runtime-0.0.0.zip"
- name: Verify bridge contract output
run: make bridge-check
- name: Enforce wrapper payload contract
run: make payload-contract
- name: Validate runtime platform configuration
run: npm run validate:runtime-platform-config
- name: Test runtime platform configuration
run: npm run test:runtime-platform-config
- name: Validate runtime requirements compatibility
run: npm run validate:runtime-requirements-compatibility
- name: Test runtime requirements compatibility
run: npm run test:runtime-requirements-compatibility
- name: Run Node tool tests (Vitest)
run: make test-tools
- name: Report unused code and dependencies (Knip)
run: make knip
- name: Verify tracked-tree hygiene
run: make repo-hygiene
swift-tests:
runs-on: macos-26
timeout-minutes: 45
env:
DEVELOPER_DIR: /Applications/Xcode_26.5.app/Contents/Developer
FORTWEB_DIR: ${{ github.workspace }}/.deps/fortweb
FORTWEB_RUNTIME_SOURCE_URL: https://github.com/keri-foundation/fortweb/releases/download/runtime-source-pyodide-314-20260909/runtime-source.tar.gz
FORTWEB_RUNTIME_SOURCE_ARCHIVE_SHA256: e04833249eec88596e0f2f88d32baa6d5fae6b2e964996587061ddac4bd78c72
FORTWEB_RUNTIME_SOURCE_MANIFEST: build/runtime-source/manifest.json
FORTWEB_RUNTIME_SOURCE_MANIFEST_SHA256: 87bcc689d7778840a76284471ff599cef21be41df2b429724f7f4fdc5f022135
FORTWEB_PACKAGE_REF: refs/heads/pyodide-314-runtime
SIMULATOR_NAME: 'iPhone 17 Pro'
SIMULATOR_OS: '26.5'
RESULT_BUNDLE_PATH: build/TestResults.xcresult
steps:
- name: Check out repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
persist-credentials: false
# Lint asks "did THIS pull request add lint debt beyond its reviewed
# baseline?", so it reads the pull-request head. Every step from the
# FortWeb checkout down asks "does this pull request still work when merged
# into main?", so it keeps the merge-result checkout that GitHub creates.
# Those are different questions that need different trees: a frozen
# baseline belongs to the pull-request source, and a moving main must not
# be able to invalidate it. Do not collapse the two back into one checkout.
- name: Check out pull-request head for linting
if: github.event_name == 'pull_request'
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
ref: ${{ github.event.pull_request.head.sha }}
path: .pr-head-lint
persist-credentials: false
fetch-depth: 1
- name: Install SwiftLint
run: brew install swiftlint
- name: Lint pull-request sources
if: github.event_name == 'pull_request'
# Same entrypoint as local validation: SwiftLint over the pull-request
# head with the frozen backlog baseline, failing only on new violations.
# The lint tree is removed afterwards so a nested checkout cannot affect
# repository scanning or Xcode build discovery in the steps below.
run: |
set -euxo pipefail
trap 'rm -rf .pr-head-lint' EXIT
make -C .pr-head-lint lint
- name: Lint checked-out sources
if: github.event_name != 'pull_request'
# Push and manual dispatch have no pull-request head, so lint measures
# the checked-out commit. Baselines are reviewed inputs: CI consumes
# them and never regenerates them.
run: make lint
- name: Check out FortWeb dependency
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
persist-credentials: false
repository: keri-foundation/fortweb
ref: bdb81afa7593603141e8db306f0636a583d2db02
path: .deps/fortweb
- name: Set up Node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8
with:
node-version: '22.12.0'
cache: npm
- name: Install dependencies
run: npm ci
- name: Set up Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.12'
- name: Build canonical FortWeb runtime
run: |
npm ci --prefix "$FORTWEB_DIR"
(cd "$FORTWEB_DIR" && python3 scripts/acquire_runtime_source.py \
--url "$FORTWEB_RUNTIME_SOURCE_URL" \
--sha256 "$FORTWEB_RUNTIME_SOURCE_ARCHIVE_SHA256" \
--manifest-sha256 "$FORTWEB_RUNTIME_SOURCE_MANIFEST_SHA256" \
--output build/runtime-source)
python3 -m pip install --disable-pip-version-check --no-index --no-deps \
"$FORTWEB_DIR/build/runtime-source/wheelhouse/packaging-26.1-py3-none-any.whl" \
"$FORTWEB_DIR/build/runtime-source/wheelhouse/setuptools-83.0.0-py3-none-any.whl" \
"$FORTWEB_DIR/build/runtime-source/wheelhouse/wheel-0.47.0-py3-none-any.whl"
(cd "$FORTWEB_DIR" && npm run build:runtime && \
FORTWEB_RUNTIME_SOURCE_MANIFEST="$FORTWEB_RUNTIME_SOURCE_MANIFEST" \
FORTWEB_RUNTIME_SOURCE_MANIFEST_SHA256="$FORTWEB_RUNTIME_SOURCE_MANIFEST_SHA256" \
npm run package:runtime -- --runtime-dir dist/runtime --python python3 --output-dir dist/package --ref "$FORTWEB_PACKAGE_REF")
test -f "$FORTWEB_DIR/dist/package/fortweb-runtime-0.0.0.zip"
- name: Enforce wrapper payload contract
run: make payload-contract
- name: Validate runtime requirements compatibility
run: npm run validate:runtime-requirements-compatibility
- name: Resolve simulator destination
id: resolve-sim
run: |
SIM_UDID="$(python3 ./scripts/resolve-ios-simulator.py --udid)"
echo "sim_udid=$SIM_UDID" >> "$GITHUB_OUTPUT"
echo "Resolved: $SIM_UDID"
- name: Build and test Swift (native unit + UI)
timeout-minutes: 40
run: |
set -euxo pipefail
FORTWEB_DIR="$FORTWEB_DIR" xcodebuild test \
-project KeriWallet.xcodeproj \
-scheme KeriWallet \
-configuration Debug \
-destination "platform=iOS Simulator,id=${{ steps.resolve-sim.outputs.sim_udid }}" \
-resultBundlePath "$RESULT_BUNDLE_PATH" \
-derivedDataPath build/DerivedData-sim
- name: Collect native bundle failure diagnostics
if: failure()
# Best effort only. The primary failure may have happened before a
# simulator existed (a lint failure, for example), so simulator logs are
# collected only when the destination was already resolved. A diagnostic
# step must never add a second, misleading failure of its own.
env:
# Empty whenever the run failed before the destination was resolved.
RESOLVED_SIM_UDID: ${{ steps.resolve-sim.outputs.sim_udid }}
run: |
set -uxo pipefail
SIM_UDID="$RESOLVED_SIM_UDID"
echo "::group::Simulator logs (last 200 lines)"
if [ -n "$SIM_UDID" ]; then
xcrun simctl spawn "$SIM_UDID" log show --last 2m --predicate 'subsystem CONTAINS "com.apple.dt.XCTest" OR process CONTAINS "KeriWallet"' 2>/dev/null | tail -200 || echo "SIM_LOG_FAILED"
else
echo "NO_SIMULATOR_AVAILABLE_FOR_DIAGNOSTICS"
fi
echo "::endgroup::"
echo "::group::Crash reports"
find ~/Library/Logs/DiagnosticReports -name 'KeriWallet*' -mmin -30 -print -exec cat {} \; 2>/dev/null || echo "NO_CRASH_REPORTS"
echo "::endgroup::"
echo "::group::dyld reports"
find ~/Library/Logs/DiagnosticReports -name '*.dyld_*' -mmin -30 -print -exec cat {} \; 2>/dev/null || echo "NO_DYLD_REPORTS"
echo "::endgroup::"
- name: Upload native bundle failure diagnostics
if: failure()
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
with:
name: native-bundle-diagnostics
path: |
~/Library/Logs/DiagnosticReports/KeriWallet*
~/Library/Logs/DiagnosticReports/*.dyld_*
if-no-files-found: ignore
- name: Upload Swift test results
if: failure() || cancelled()
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
with:
name: swift-test-results
path: ${{ env.RESULT_BUNDLE_PATH }}
if-no-files-found: ignore
archive-proof:
runs-on: macos-26
timeout-minutes: 45
env:
DEVELOPER_DIR: /Applications/Xcode_26.5.app/Contents/Developer
FORTWEB_DIR: ${{ github.workspace }}/.deps/fortweb
FORTWEB_RUNTIME_SOURCE_URL: https://github.com/keri-foundation/fortweb/releases/download/runtime-source-pyodide-314-20260909/runtime-source.tar.gz
FORTWEB_RUNTIME_SOURCE_ARCHIVE_SHA256: e04833249eec88596e0f2f88d32baa6d5fae6b2e964996587061ddac4bd78c72
FORTWEB_RUNTIME_SOURCE_MANIFEST: build/runtime-source/manifest.json
FORTWEB_RUNTIME_SOURCE_MANIFEST_SHA256: 87bcc689d7778840a76284471ff599cef21be41df2b429724f7f4fdc5f022135
FORTWEB_PACKAGE_REF: refs/heads/pyodide-314-runtime
steps:
- name: Check out repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
persist-credentials: false
fetch-depth: 0
- name: Check out FortWeb dependency
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
persist-credentials: false
repository: keri-foundation/fortweb
ref: bdb81afa7593603141e8db306f0636a583d2db02
path: .deps/fortweb
- name: Set up Node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8
with:
node-version: '22.12.0'
cache: npm
- name: Install dependencies
run: npm ci
- name: Set up Python
# ACTION_PIN_UNVERIFIED resolved: v5 is a lightweight tag on
# a26af69be951a213d495a4c3e4e4022e16d87065.
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.12'
- name: Build canonical FortWeb runtime
run: |
npm ci --prefix "$FORTWEB_DIR"
(cd "$FORTWEB_DIR" && python3 scripts/acquire_runtime_source.py \
--url "$FORTWEB_RUNTIME_SOURCE_URL" \
--sha256 "$FORTWEB_RUNTIME_SOURCE_ARCHIVE_SHA256" \
--manifest-sha256 "$FORTWEB_RUNTIME_SOURCE_MANIFEST_SHA256" \
--output build/runtime-source)
python3 -m pip install --disable-pip-version-check --no-index --no-deps \
"$FORTWEB_DIR/build/runtime-source/wheelhouse/packaging-26.1-py3-none-any.whl" \
"$FORTWEB_DIR/build/runtime-source/wheelhouse/setuptools-83.0.0-py3-none-any.whl" \
"$FORTWEB_DIR/build/runtime-source/wheelhouse/wheel-0.47.0-py3-none-any.whl"
(cd "$FORTWEB_DIR" && npm run build:runtime && \
FORTWEB_RUNTIME_SOURCE_MANIFEST="$FORTWEB_RUNTIME_SOURCE_MANIFEST" \
FORTWEB_RUNTIME_SOURCE_MANIFEST_SHA256="$FORTWEB_RUNTIME_SOURCE_MANIFEST_SHA256" \
npm run package:runtime -- --runtime-dir dist/runtime --python python3 --output-dir dist/package --ref "$FORTWEB_PACKAGE_REF")
test -f "$FORTWEB_DIR/dist/package/fortweb-runtime-0.0.0.zip"
- name: Enforce wrapper payload contract (import + validate)
run: make payload-contract
- name: Run release archive verifier unit tests
run: npx vitest run tools/__tests__/release-archive.test.mjs
- name: Build unsigned Release archive
timeout-minutes: 25
run: |
xcodebuild archive \
-project KeriWallet.xcodeproj \
-scheme KeriWallet \
-configuration Release \
-destination 'generic/platform=iOS' \
-archivePath build/KeriWallet.xcarchive \
-derivedDataPath build/DerivedData-device \
CODE_SIGNING_ALLOWED=NO
- name: Verify archived payload integrity (PR lane)
# PR lane: wrapper-owned invariants are enforced. Producer-owned findings
# (for example the FortWeb itms-services payload defect) are reported here
# and enforced by .github/workflows/release-certification.yml instead.
run: node tools/assert-release-archive.mjs --archive build/KeriWallet.xcarchive