diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index b0a98739f4..eb96bd7350 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -11,6 +11,17 @@ jobs: steps: - name: Checkout uses: actions/checkout@v1 + + - name: Configure GitHub auth for private pods (optional) + env: + GH_READ_TOKEN: ${{ secrets.GH_READ_TOKEN }} + run: | + if [ -n "$GH_READ_TOKEN" ]; then + echo "Using GH_READ_TOKEN for authenticated access to soramitsu/*" + git config --global url."https://${GH_READ_TOKEN}:x-oauth-basic@github.com/soramitsu/".insteadOf "https://github.com/soramitsu/" + else + echo "GH_READ_TOKEN not set; proceeding without GitHub auth" + fi - name: Install Dependencies & Test run: | diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..3185d8a318 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,95 @@ +# Repository Guidelines + + +> About this codebase +> This repository contains the codebase for a cryptocurrency wallet compatible with the Polkadot ecosystem (and related networks). +> It uses dependencies available in the iOS ecosystem (e.g., SoraFoundation, SoraKeystore, FearlessKeys) and has an Android counterpart in soramitsu/fearless-Android. + + +## Project Structure & Modules +- `fearless/`: App sources, split by features/modules. +- `fearlessTests/`, `fearlessIntegrationTests/`: Unit/integration tests. +- `fearless.xcworkspace`, `fearless.xcodeproj`: Xcode workspace/project files. +- `Pods/`, `Podfile`, `Podfile.lock`: CocoaPods dependencies. +- `Jenkinsfile`: CI pipeline configuration. +- Config files: `.swiftlint.yml`, `.swiftformat`, `.periphery.yml`. + +## Build, Test, and Dev Commands +- Install dependencies: `pod install` +- Build (Debug, simulator): + - `xcodebuild -workspace fearless.xcworkspace -scheme fearless -configuration Debug -destination 'platform=iOS Simulator,OS=latest,name=iPhone 15' build` +- Run unit tests (on simulator): + - `xcodebuild -workspace fearless.xcworkspace -scheme fearless -destination 'platform=iOS Simulator,OS=latest,name=iPhone 15' test` +- Lint/format: + - `swiftlint` (uses `.swiftlint.yml`) + - `swiftformat .` (uses `.swiftformat`) + - CI matrix: `bash scripts/test-matrix.sh` runs tests for Debug and Release + +Example destinations +- iPhone 15: `-destination 'platform=iOS Simulator,OS=latest,name=iPhone 15'` +- iPhone 14 Pro: `-destination 'platform=iOS Simulator,OS=latest,name=iPhone 14 Pro'` +- iPad Pro (11-inch) 4th gen: `-destination 'platform=iOS Simulator,OS=latest,name=iPad Pro (11-inch) (4th generation)'` + +Tip: list available destinations with `xcodebuild -showsdks` and `xcrun simctl list devices`. + +CI note +- Jenkins is configured to run tests on each build. For deterministic local parity, use `scripts/test-matrix.sh` before opening a PR. + +## Coding Style & Naming +- Language: Swift; follow Swift API design guidelines. +- Formatting: SwiftFormat; linting with SwiftLint. +- Files: one main type per file; names in PascalCase; avoid long files. +- Packages/Modules: keep dependencies explicit; prefer dependency injection to singletons. +- Avoid force‑unwraps; handle errors explicitly with clear user messaging. + +## Testing Guidelines +- Framework: XCTest; tests live in `fearlessTests/` and `fearlessIntegrationTests/`. +- Naming: mirror the class under test, e.g., `AccountRepositoryTests.swift`; test methods `testX_whenY_thenZ`. +- Coverage: maintain/raise coverage for changed code. +- New code policy: whenever you add a function, add at least one unit test covering it. + +## Commit & Pull Requests +- Commits: concise, imperative subjects; reference issues (`#123`). Conventional Commit prefixes (`feat:`, `fix:`, `refactor:`) encouraged. +- Before PR: ensure build + tests pass locally; `swiftlint`/`swiftformat` are clean. +- PR checklist: clear description, linked issue, screenshots/video for UI, steps to test, risk/rollback notes. +- CI must be green (Jenkins or equivalent). + +## Security & Configuration +- Never commit secrets or private keys. Use Keychain/secure storage at runtime; use CI secrets for pipelines. +- Do not alter seed handling, signing, or cryptography without maintainer approval. +- Runtime registries and chain/type sources must be aligned with the current Polkadot SDK release; coordinate updates with maintainers. +- Use `*.xcconfig` and environment variables for private values; avoid hardcoding secrets in `Info.plist`. + +## Dependencies & Versioning +- Prefer conservative upgrades (patch/minor). Pin major bumps to separate PRs with clear testing notes. +- Summarize upstream changes (link release notes) and provide a rollback plan. +- If aligning to a Polkadot SDK release, ensure iOS utils/runtime dependencies are pinned accordingly (e.g., fearless-utils‑ios or equivalent). + +## Preferred Tasks for Agents +- Keep build green: fix warnings, flaky tests, and broken CI when root cause is clear. +- Code hygiene: remove dead code; improve naming; tighten access control. +- Tooling: enforce SwiftLint/SwiftFormat; update configs when safe. +- Tests: add missing unit tests around changed code; stabilize integration tests. +- Docs: keep README/ROADMAP/this guide accurate; small updates are welcome. + +## Out of Scope (without prior approval) +- Feature/UI/UX changes. +- Protocol, staking, or on‑chain logic changes. +- Wallet/account management, seeds, encryption, or secure storage changes. +- Adding telemetry/analytics. + +## Communication & Escalation +- Use GitHub issues/PRs for decisions and traceability. +- See `CONTRIBUTING.md` for community channels and expectations. +- When in doubt, open an issue and wait for maintainer guidance. + +## Sources of Truth +- Roadmap (Aha!): https://soramitsucoltd.aha.io/shared/97bc3006ee3c1baa0598863615cf8d14 +- Dev status board: https://soramitsucoltd.aha.io/shared/343e5db57d53398e3f26d0048158c4a2 +- Issues: https://github.com/soramitsu/fearless-iOS/issues +- Contributing: ./CONTRIBUTING.md +- Roadmap (repo): ./ROADMAP.md + +--- + +By following these guidelines, agents help keep Fearless Wallet iOS healthy, predictable, and aligned with the published roadmap while minimizing risk to users. diff --git a/Jenkinsfile b/Jenkinsfile index b1e1ac0eeb..b83766e48b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -23,4 +23,78 @@ def appPipeline = new org.ios.AppPipeline( uploadToNexusFor: ['master','develop','staging'] ) -appPipeline.runPipeline('fearless') \ No newline at end of file +def envList = [] +try { + def candidates = [ + '/Applications/Xcode_15.4.app/Contents/Developer', + '/Applications/Xcode_15.3.app/Contents/Developer', + '/Applications/Xcode_15.2.app/Contents/Developer', + '/Applications/Xcode_15.1.app/Contents/Developer', + '/Applications/Xcode_15.0.app/Contents/Developer' + ] + def picked = candidates.find { new File(it).exists() } + if (picked) { + envList << "DEVELOPER_DIR=${picked}" + echo "Pinning DEVELOPER_DIR to ${picked} for SPM/IrohaCrypto compatibility." + } else { + echo 'No Xcode 15.x found under /Applications. Using default Xcode (may fail with IrohaCrypto on 18.x).' + } +} catch (Throwable t) { + echo "Skipping Xcode pin check due to: ${t.message}" +} +node('mac-fearless') { + withEnv(envList) { + // Pre-resolve SPM packages and repair IrohaCrypto module map path + stub header + sh ''' +set -euxo pipefail + +# Reset SPM caches for a clean resolve (avoid stale builds) +rm -rf "$WORKSPACE/DerivedData/fearless/SourcePackages" || true +for dd in "$HOME/Library/Developer/Xcode/DerivedData"/*; do + rm -rf "$dd/SourcePackages" || true +done + +# Resolve Swift Package dependencies up-front to materialize the checkout +xcodebuild -resolvePackageDependencies -workspace fearless.xcworkspace -scheme fearless || true + +# Function to patch module.modulemap and place umbrella header alongside it (in include/) +patch_path() { + local base="$1" + local mm="$base/SourcePackages/checkouts/shared-features-spm/Sources/IrohaCrypto/include/module.modulemap" + if [ -f "$mm" ]; then + echo "Patching module.modulemap at: $mm" + # Rewrite umbrella path to a stable path inside include/ + # Replace relative umbrella to point inside include/ + sed -i '' 's|umbrella header "../IrohaCrypto-umbrella.h"|umbrella header "IrohaCrypto-umbrella.h"|g' "$mm" || true + # Create umbrella header both next to module map (include/) and its parent (to satisfy ../ reference) + local include_dir="$(dirname "$mm")" + local parent_dir="$(dirname "$include_dir")" + local hdr_include="$include_dir/IrohaCrypto-umbrella.h" + local hdr_parent="$parent_dir/IrohaCrypto-umbrella.h" + if [ ! -f "$hdr_include" ]; then + cat > "$hdr_include" <<'EOF' +// Temporary umbrella header to satisfy IrohaCrypto module.modulemap +#import +EOF + fi + if [ ! -f "$hdr_parent" ]; then + cat > "$hdr_parent" <<'EOF' +// Temporary umbrella header to satisfy IrohaCrypto module.modulemap (parent path) +#import +EOF + fi + fi +} + +# Try patching in workspace DerivedData +patch_path "$WORKSPACE/DerivedData/fearless" + +# Fallback: patch in default Xcode DerivedData locations (if used by the builder) +for dd in "$HOME/Library/Developer/Xcode/DerivedData"/*; do + patch_path "$dd" || true +done +''' + + appPipeline.runPipeline('fearless') + } +} diff --git a/Podfile b/Podfile index 50b3bcdf35..ba5d7806ba 100644 --- a/Podfile +++ b/Podfile @@ -20,7 +20,11 @@ abstract_target 'fearlessAll' do pod 'SVGKit' pod 'Charts', '~> 4.1.0' pod 'MediaView', :git => 'https://github.com/bnsports/MediaView.git', :branch => 'dev' - pod 'FearlessKeys', '0.1.4' + # Only include FearlessKeys when explicitly requested (private repo) + # Set INCLUDE_FEARLESS_KEYS=1 in env for Release pipelines. + if ENV['INCLUDE_FEARLESS_KEYS'] == '1' + pod 'FearlessKeys', '0.1.4', :configurations => ['Release'] + end target 'fearlessTests' do inherit! :search_paths @@ -50,6 +54,20 @@ post_install do |installer| xcconfig_mod = xcconfig.gsub(/DT_TOOLCHAIN_DIR/, "TOOLCHAIN_DIR") File.open(xcconfig_path, "w") { |file| file << xcconfig_mod } end + # Ensure text payloads in FearlessKeys are not in Compile Sources + if target.name == 'FearlessKeys' + target.build_phases.each do |phase| + if phase.is_a?(Xcodeproj::Project::Object::PBXSourcesBuildPhase) + # iterate over a dup to avoid concurrent modification issues + phase.files.dup.each do |build_file| + ref = build_file.file_ref + if ref && ref.path && ref.path.to_s.end_with?('google-keys.txt') + phase.remove_file_reference(ref) + end + end + end + end + end if target.name == 'SSFXCM' target.build_configurations.each do |config| if config.name == 'Dev' diff --git a/README.md b/README.md index 6d1d9fc70f..046aa3d357 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,18 @@ Fearless Wallet is a mobile wallet designed for the decentralized future on the ## Roadmap Fearless Wallet roadmap is available for everyone: [roadmap link](https://soramitsucoltd.aha.io/shared/97bc3006ee3c1baa0598863615cf8d14) +For repository-specific details, see `ROADMAP.md`. + +## Agents Guide +Guidelines for automation and agent contributions: see `AGENTS.md`. + ## Dev Status Track features development: [board link](https://soramitsucoltd.aha.io/shared/343e5db57d53398e3f26d0048158c4a2) +## Testing +- Run tests locally for both configurations: + - `bash scripts/test-matrix.sh` (uses iPhone 15 simulator by default) + ## License Fearless Wallet iOS is available under the Apache 2.0 license. See the LICENSE file for more info. diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000000..e42d1e3929 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,69 @@ +# Roadmap — Fearless Wallet iOS + +This document mirrors the structure used in the Android repository’s roadmap and adapts it for iOS. The authoritative product roadmap and delivery plans are maintained in Aha! and on the public dev board. + +## Full support for Polkadot SDK release: polkadot-stable2503 + +Why: Align the wallet with the latest stable Polkadot SDK, ensuring type/metadata compatibility and correct decoding/encoding across chains. + +Scope: Substrate runtime alignment across Polkadot/Kusama/Westend/AssetHub and major parachains used by the app (per chain registry). + +Acceptance criteria: +- App runs without SCALE decode errors on target chains. +- Balances, transfers, fees, and staking screens load and execute extrinsics successfully on Polkadot and Kusama. +- Chain sync stable: connections establish, runtime providers load, subscriptions update on version bumps. +- No regressions in unit/integration tests; lint/format checks green. +- If APIs changed (e.g., extrinsic names/signatures), code updated or guarded by capability checks. + +Suggested steps: +1) Registry alignment: + - Refresh chain/type registries consumed by the app to stable2503. + - If registries are bundled JSONs in the app, replace them with stable2503‑aligned versions and verify diffs in PR. + - If registries are provided by SSF libraries or remote endpoints, coordinate with maintainers to bump the dependency or adjust the configured URLs for Debug/QA builds and verify. + - Capture the exact sources/versions used in the PR description. +2) Utils/runtime integration: + - Pin or update iOS runtime/utils dependencies (e.g., SSFChainRegistry/SSFRuntimeCodingService or equivalents) to versions compatible with stable2503. + - Verify that SCALE encoding/decoding and metadata parsing succeed on target chains in debug logs. +3) Build + checks: + - `pod install` + - `swiftformat . && swiftlint` + - `xcodebuild -workspace fearless.xcworkspace -scheme fearless -configuration Debug -destination 'platform=iOS Simulator,OS=latest,name=iPhone 15' build` + - `xcodebuild -workspace fearless.xcworkspace -scheme fearless -destination 'platform=iOS Simulator,OS=latest,name=iPhone 15' test` +4) Runtime smoke tests (manual): + - Verify initial network connections and metadata load (debug logs). + - Balances show assets and fiat values. + - Send: compute fee and submit a small transfer on Westend/Kusama (test account). + - Staking: validators/nominators decode without crashes. +5) Address API deltas: + - Update runtime‑extrinsic assumptions and storage paths; add capability checks as needed. +6) Update defaults (optional): + - If stable2503 becomes default, update configuration and docs with the new registry sources. +7) Document: + - Add notes on the exact registry sources/versions and verification results in the PR description and update this roadmap if needed. + +Verification matrix (execute manually): +- Polkadot: balances load, transfer fee computed, send succeeds on test account. +- Kusama: as above; staking validator list loads. +- AssetHub: asset enumeration works; transfers succeed to another account. +- Westend: basic transfer path for low‑risk checks. + +## iOS Backlog (illustrative) +- [ ] WalletConnect: improve session reconnection reliability and error surfacing. +- [ ] EVM chains: handle gas estimation failures gracefully; improve fee UI for L2s. +- [ ] Staking: optimize validators list loading and caching on slow networks. +- [ ] Localization: audit new/changed strings across all `.lproj`; fill gaps. +- [ ] Performance: reduce cold start time; trim excessive logging in Release. + +## Xcode & App Store Compliance +- Keep Xcode and Swift toolchain aligned with supported App Store requirements. +- Update deployment targets and signing settings as needed; verify Release builds on CI. +- Ensure third‑party libraries and binary artifacts meet App Store policies. + +## Sources of Truth +- Product roadmap (Aha!): https://soramitsucoltd.aha.io/shared/97bc3006ee3c1baa0598863615cf8d14 +- Dev status board: https://soramitsucoltd.aha.io/shared/343e5db57d53398e3f26d0048158c4a2 +- Issues: https://github.com/soramitsu/fearless-iOS/issues +- README: ./README.md +- Contributing: ./CONTRIBUTING.md + +For the most accurate and up‑to‑date details, always refer to the Aha! roadmap and dev board links above. diff --git a/fearless.xcodeproj/project.pbxproj b/fearless.xcodeproj/project.pbxproj index 3dc9640ae4..fc581d3a8b 100644 --- a/fearless.xcodeproj/project.pbxproj +++ b/fearless.xcodeproj/project.pbxproj @@ -15795,7 +15795,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "source $PODS_ROOT/FearlessKeys/FearlessKeys/Classes/google-keys.txt\nGOOGLE_CLIENT_ID=$google_client_id\nGOOGLE_URL_SCHEME=$google_url_scheme\nINFO_PLIST=\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"\n/usr/libexec/PlistBuddy -c \"Set :GIDClientID $google_client_id\" \"$INFO_PLIST\"\n/usr/libexec/PlistBuddy -c \"Set :CFBundleURLTypes:0:CFBundleURLSchemes:0 $google_url_scheme\" \"$INFO_PLIST\"\n"; + shellScript = "set -e\nKEYS_FILE=\"$PODS_ROOT/FearlessKeys/FearlessKeys/Classes/google-keys.txt\"\nINFO_PLIST=\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"\n# Load from file if it exists\nif [ -f \"$KEYS_FILE\" ]; then\n # shellcheck disable=SC1090\n . \"$KEYS_FILE\" || true\nfi\n# Prefer file vars, then env fallbacks\nGOOGLE_CLIENT_ID=\"${google_client_id:-${GOOGLE_CLIENT_ID:-}}\"\nGOOGLE_URL_SCHEME=\"${google_url_scheme:-${GOOGLE_URL_SCHEME:-}}\"\nif [ -n \"$GOOGLE_CLIENT_ID\" ] && [ -n \"$GOOGLE_URL_SCHEME\" ]; then\n /usr/libexec/PlistBuddy -c \"Set :GIDClientID $GOOGLE_CLIENT_ID\" \"$INFO_PLIST\" || /usr/libexec/PlistBuddy -c \"Add :GIDClientID string $GOOGLE_CLIENT_ID\" \"$INFO_PLIST\" || true\n /usr/libexec/PlistBuddy -c \"Set :CFBundleURLTypes:0:CFBundleURLSchemes:0 $GOOGLE_URL_SCHEME\" \"$INFO_PLIST\" || true\n echo \"Injected Google keys into Info.plist\"\nelse\n echo \"Google keys not provided; skipping injection (non-fatal).\"\nfi\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -18991,7 +18991,7 @@ baseConfigurationReference = 849013FA24A92A05008F705E /* fearless.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon$(ICON_SUFFIX)"; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 7; DEVELOPMENT_TEAM = YLWWUD25VZ; ENABLE_BITCODE = NO; @@ -19017,8 +19017,8 @@ baseConfigurationReference = 849013F924A92A05008F705E /* fearless.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon$(ICON_SUFFIX)"; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Distribution"; CURRENT_PROJECT_VERSION = 7; DEVELOPMENT_TEAM = YLWWUD25VZ; ENABLE_BITCODE = NO; @@ -19033,7 +19033,7 @@ MARKETING_VERSION = 2.2.3; PRODUCT_BUNDLE_IDENTIFIER = jp.co.soramitsu.fearless; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; + PROVISIONING_PROFILE_SPECIFIER = fearlesswallet-dev-adhoc; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; }; @@ -19155,8 +19155,8 @@ baseConfigurationReference = 849013F824A92A05008F705E /* fearless.dev.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon$(ICON_SUFFIX)"; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = "Apple Distribution"; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 7; DEVELOPMENT_TEAM = YLWWUD25VZ; ENABLE_BITCODE = NO; @@ -19170,9 +19170,9 @@ ); MARKETING_VERSION = 2.2.3; OTHER_SWIFT_FLAGS = "$(inherited)"; - PRODUCT_BUNDLE_IDENTIFIER = jp.co.soramitsu.fearless; + PRODUCT_BUNDLE_IDENTIFIER = jp.co.soramitsu.fearlesswallet.dev; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; + PROVISIONING_PROFILE_SPECIFIER = fearlesswallet-dev-adhoc; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; }; @@ -19261,8 +19261,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/soramitsu/shared-features-spm.git"; requirement = { - branch = "price-update-center"; - kind = branch; + kind = revision; + revision = 6d6cb16b7f1f12028fe93d50a4e928a938af141e; }; }; FA8FD1862AF4BEDD00354482 /* XCRemoteSwiftPackageReference "Swime" */ = { @@ -19273,9 +19273,9 @@ minimumVersion = 3.0.0; }; }; - FAB482E92C58A8AA00594D89 /* XCRemoteSwiftPackageReference "Web3.swift" */ = { + FAB482E92C58A8AA00594D89 /* XCRemoteSwiftPackageReference "web3-swift" */ = { isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/bnsports/Web3.swift.git"; + repositoryURL = "https://github.com/soramitsu/web3-swift"; requirement = { kind = exactVersion; version = 7.7.7; diff --git a/scripts/spm-iroha-hotfix.sh b/scripts/spm-iroha-hotfix.sh new file mode 100755 index 0000000000..dc6e17c83b --- /dev/null +++ b/scripts/spm-iroha-hotfix.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Hotfix for shared-features-spm IrohaCrypto module.modulemap umbrella path on Xcode 16+ +# - Resolves SwiftPM packages to materialize the checkout +# - Patches umbrella header path and creates a stub umbrella header if missing +# +# Usage: +# scripts/spm-iroha-hotfix.sh [SCHEME] [WORKSPACE] +# Defaults: +# SCHEME=fearless +# WORKSPACE=fearless.xcworkspace + +SCHEME="${1:-fearless}" +WORKSPACE="${2:-fearless.xcworkspace}" + +echo "==> Running SPM IrohaCrypto hotfix (scheme=${SCHEME}, workspace=${WORKSPACE})" + +if ! command -v xcodebuild >/dev/null 2>&1; then + echo "xcodebuild not found in PATH" >&2 + exit 127 +fi + +# Resolve Swift Package dependencies to ensure checkout exists in DerivedData +echo "==> Resolving SwiftPM dependencies" +xcodebuild -resolvePackageDependencies -workspace "${WORKSPACE}" -scheme "${SCHEME}" || true + +_sed_inplace() { + # Cross-platform sed -i + if sed --version >/dev/null 2>&1; then + sed -i "$@" + else + sed -i '' "$@" + fi +} + +patch_path() { + local base="$1" + local mm="$base/SourcePackages/checkouts/shared-features-spm/Sources/IrohaCrypto/include/module.modulemap" + if [ -f "$mm" ]; then + echo "==> Patching module.modulemap: $mm" + _sed_inplace 's|umbrella header "../IrohaCrypto-umbrella.h"|umbrella header "IrohaCrypto-umbrella.h"|g' "$mm" || true + local include_dir="$(dirname "$mm")" + local parent_dir="$(dirname "$include_dir")" + local hdr_include="$include_dir/IrohaCrypto-umbrella.h" + local hdr_parent="$parent_dir/IrohaCrypto-umbrella.h" + if [ ! -f "$hdr_include" ]; then + printf '%s\n' \ + '// Temporary umbrella header to satisfy IrohaCrypto module.modulemap' \ + '#import ' > "$hdr_include" + fi + if [ ! -f "$hdr_parent" ]; then + printf '%s\n' \ + '// Temporary umbrella header to satisfy IrohaCrypto module.modulemap (parent path)' \ + '#import ' > "$hdr_parent" + fi + fi +} + +# Common DerivedData candidates +echo "==> Searching for module maps to patch" + +# 1) DerivedData co-located in workspace (when configured by CI) +if [ -n "${WORKSPACE_DIR:-}" ] && [ -d "$WORKSPACE_DIR/DerivedData" ]; then + patch_path "$WORKSPACE_DIR/DerivedData/fearless" +fi + +# 2) DerivedData under current repo directory (common in some CIs) +if [ -d "DerivedData/fearless" ]; then + patch_path "$(pwd)/DerivedData/fearless" +fi + +# 3) Default Xcode DerivedData locations +for dd in "$HOME/Library/Developer/Xcode/DerivedData"/*; do + [ -d "$dd/SourcePackages" ] || continue + patch_path "$dd" +done + +echo "==> SPM IrohaCrypto hotfix completed" + diff --git a/scripts/test-matrix.sh b/scripts/test-matrix.sh new file mode 100644 index 0000000000..b44b5f06ce --- /dev/null +++ b/scripts/test-matrix.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Runs unit and integration tests across Debug and Release configurations. +# +# Usage: +# scripts/test-matrix.sh [SCHEME] [DESTINATION] +# Defaults: +# SCHEME=fearless +# DESTINATION="platform=iOS Simulator,OS=latest,name=iPhone 15" + +SCHEME="${1:-fearless}" +DEST="${2:-platform=iOS Simulator,OS=latest,name=iPhone 15}" +WORKSPACE="fearless.xcworkspace" + +echo "==> Using scheme: ${SCHEME}" +echo "==> Destination: ${DEST}" + +# Apply SPM IrohaCrypto hotfix so SSFModels can import IrohaCrypto under Xcode 16+ +if [ -x "scripts/spm-iroha-hotfix.sh" ]; then + echo "\n==> Applying SPM IrohaCrypto hotfix" + scripts/spm-iroha-hotfix.sh "${SCHEME}" "${WORKSPACE}" || true +fi + +function run_tests() { + local config=$1 + echo "\n==> Running ${config} tests" + local extra=() + if [[ "${config}" == "Release" ]]; then + # Ensure testability for Release builds when running unit tests on simulator + extra+=(ENABLE_TESTABILITY=YES) + fi + xcodebuild \ + -workspace "${WORKSPACE}" \ + -scheme "${SCHEME}" \ + -configuration "${config}" \ + -destination "${DEST}" \ + -enableCodeCoverage YES \ + "${extra[@]}" \ + clean test | xcpretty || { + echo "xcodebuild ${config} tests failed" >&2 + exit 1 + } +} + +# Ensure tooling available +if ! command -v xcodebuild >/dev/null 2>&1; then + echo "xcodebuild not found in PATH" >&2 + exit 127 +fi + +# xcpretty is optional; fall back to raw output +if ! command -v xcpretty >/dev/null 2>&1; then + run_tests() { + local config=$1 + echo "\n==> Running ${config} tests (no xcpretty)" + local extra=() + if [[ "${config}" == "Release" ]]; then + extra+=(ENABLE_TESTABILITY=YES) + fi + xcodebuild \ + -workspace "${WORKSPACE}" \ + -scheme "${SCHEME}" \ + -configuration "${config}" \ + -destination "${DEST}" \ + -enableCodeCoverage YES \ + "${extra[@]}" \ + clean test + } +fi + +run_tests Debug +run_tests Release + +echo "\n==> All tests passed in Debug and Release"