Skip to content

Commit 947b154

Browse files
Merge pull request #1297 from soramitsu/chore/ci-utils-roadmap-hardening
chore(ci): harden CI + roadmap for fearless-utils hygiene
2 parents 84c96ef + 88ade7e commit 947b154

496 files changed

Lines changed: 47812 additions & 68778 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.githooks/prepare-commit-msg

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
MSG_FILE="$1"
4+
# If commit is a merge or has a message already, still ensure signoff trailer exists.
5+
# Append Signed-off-by if missing.
6+
if ! grep -qi '^Signed-off-by:' "$MSG_FILE"; then
7+
NAME_EMAIL="$(git config user.name) <$(git config user.email)>"
8+
printf '\nSigned-off-by: %s\n' "$NAME_EMAIL" >> "$MSG_FILE"
9+
fi

.github/workflows/codecov.yml

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,109 @@ jobs:
1010
runs-on: macOS-latest
1111
steps:
1212
- name: Checkout
13-
uses: actions/checkout@v1
13+
uses: actions/checkout@v4
14+
15+
- name: Configure GitHub auth for private pods (optional)
16+
env:
17+
GH_READ_TOKEN: ${{ secrets.GH_READ_TOKEN }}
18+
run: |
19+
if [ -n "$GH_READ_TOKEN" ]; then
20+
echo "Using GH_READ_TOKEN for authenticated access to soramitsu/*"
21+
git config --global url."https://${GH_READ_TOKEN}:x-oauth-basic@github.com/soramitsu/".insteadOf "https://github.com/soramitsu/"
22+
else
23+
echo "GH_READ_TOKEN not set; proceeding without GitHub auth"
24+
fi
1425
15-
- name: Install Dependencies & Test
26+
- name: Bootstrap Dependencies
27+
run: |
28+
bash scripts/ci/bootstrap.sh
29+
30+
- name: Build & Test (Simulator)
1631
run: |
17-
pod install --repo-update
18-
set -o pipefail && xcodebuild test -workspace fearless.xcworkspace -scheme fearless -destination 'platform=iOS Simulator,name=iPhone 14,OS=16.2' build test | xcpretty --test
32+
set -o pipefail
33+
# Resolve SPM into a stable workspace path and patch after resolve
34+
SP_DIR="$PWD/SourcePackages"
35+
mkdir -p "$SP_DIR"
36+
xcodebuild -resolvePackageDependencies \
37+
-workspace fearless.xcworkspace \
38+
-scheme fearless \
39+
-clonedSourcePackagesDirPath "$SP_DIR"
40+
# Apply patches on the resolved checkout (fail fast if contracts cannot be restored)
41+
SOURCE_PACKAGES_DIR="$SP_DIR" ALLOW_DERIVEDDATA_FALLBACK=0 STRICT_REQUIRED_PATCHES=1 bash scripts/spm-shared-features-fixes.sh "$(pwd)"
42+
# Ensure native crypto checkout/modulemap contract is restored after resolve.
43+
SOURCE_PACKAGES_DIR="$SP_DIR" STRICT_REQUIRED_PATCHES=1 bash scripts/deps/prepare-native-crypto-checkout.sh "$(pwd)" fearless.xcworkspace fearless.tests
44+
echo "Preflight: checking remaining 'enum AddressFactory' in $SP_DIR checkouts (warn-only)"
45+
if command -v rg >/dev/null 2>&1; then
46+
rg -n "\\benum\\s+AddressFactory\\b" "$SP_DIR/checkouts/shared-features-spm/Sources" -S | sed -n '1,120p' || true
47+
else
48+
/usr/bin/grep -RInE "(^|[^A-Za-z0-9_])enum[[:space:]]+AddressFactory(\b|[^.])" "$SP_DIR/checkouts/shared-features-spm/Sources" | sed -n '1,120p' || true
49+
fi
50+
echo "Preflight: checking SSFPolkaswap addressFactory type annotations"
51+
if command -v rg >/dev/null 2>&1; then
52+
if rg -n "addressFactory\s*:\s*([A-Za-z_]+\.)?AddressFactory(\b|[^.])" "$SP_DIR/checkouts/shared-features-spm/Sources/SSFPolkaswap" -S >/dev/null 2>&1; then
53+
echo "WARNING: addressFactory annotations still using AddressFactory (not .Type):" >&2
54+
rg -n "addressFactory\s*:\s*([A-Za-z_]+\.)?AddressFactory(\b|[^.])" "$SP_DIR/checkouts/shared-features-spm/Sources/SSFPolkaswap" -S | sed -n '1,120p' >&2 || true
55+
fi
56+
else
57+
if /usr/bin/grep -RInE "addressFactory\s*:\s*([A-Za-z_]+\.)?AddressFactory(\b|[^.])" "$SP_DIR/checkouts/shared-features-spm/Sources/SSFPolkaswap" >/dev/null 2>&1; then
58+
echo "WARNING: addressFactory annotations still using AddressFactory (not .Type) [grep]:" >&2
59+
/usr/bin/grep -RInE "addressFactory\s*:\s*([A-Za-z_]+\.)?AddressFactory(\b|[^.])" "$SP_DIR/checkouts/shared-features-spm/Sources/SSFPolkaswap" | sed -n '1,120p' >&2 || true
60+
fi
61+
fi
62+
echo "Available simulators (before selection):" && xcrun simctl list devices | sed -n '1,100p'
63+
UDID_RAW="$(LOG_PREFIX='[codecov]' PREFERRED_NAME='iPhone 16' ALLOW_CREATE=1 BOOT_SIMULATOR=0 bash scripts/ci/select-simulator.sh)"
64+
UDID="$(printf '%s\n' "$UDID_RAW" | awk 'match($0, /[A-Fa-f0-9-]{36}/) { print substr($0, RSTART, RLENGTH); exit }')"
65+
if [ -z "$UDID" ]; then
66+
echo "Failed to select simulator UDID. Raw selector output: $UDID_RAW" >&2
67+
exit 1
68+
fi
69+
if ! [[ "$UDID" =~ ^[A-Fa-f0-9-]{36}$ ]]; then
70+
echo "Extracted simulator UDID has invalid format: $UDID" >&2
71+
exit 1
72+
fi
73+
HOST_ARCH="$(uname -m)"
74+
SIM_INFO="$(xcrun simctl list devices available | awk -v udid="$UDID" '
75+
/^-- iOS / { os=$3; next }
76+
{
77+
if (index($0, udid) > 0) {
78+
line = $0
79+
sub(/[[:space:]]*\([A-Fa-f0-9-]{36}\).*/, "", line)
80+
gsub(/^[[:space:]]+|[[:space:]]+$/, "", line)
81+
print line "|" os
82+
exit
83+
}
84+
}
85+
')"
86+
if [ -n "$SIM_INFO" ]; then
87+
SIM_NAME="${SIM_INFO%%|*}"
88+
SIM_OS="${SIM_INFO##*|}"
89+
DESTINATION="platform=iOS Simulator,OS=${SIM_OS},name=${SIM_NAME}"
90+
else
91+
DESTINATION="platform=iOS Simulator,id=$UDID"
92+
fi
93+
case "$HOST_ARCH" in
94+
arm64|x86_64)
95+
DESTINATION="${DESTINATION},arch=${HOST_ARCH}"
96+
;;
97+
esac
98+
echo "Using destination: $DESTINATION"
99+
LOG_FILE="$PWD/build/codecov-xcodebuild.log"
100+
mkdir -p "$PWD/build"
101+
if ! xcodebuild \
102+
-workspace fearless.xcworkspace \
103+
-scheme fearless.tests \
104+
-clonedSourcePackagesDirPath "$SP_DIR" \
105+
-disableAutomaticPackageResolution \
106+
-destination "$DESTINATION" \
107+
build test | tee "$LOG_FILE" | xcpretty --test; then
108+
echo "Build/Test failed. Key errors from $LOG_FILE:" >&2
109+
if command -v rg >/dev/null 2>&1; then
110+
rg -n " error: |\\*\\* (BUILD|TEST) FAILED \\*\\*" "$LOG_FILE" -S | tail -n 100 >&2 || true
111+
else
112+
grep -nE " error: |\\*\\* (BUILD|TEST) FAILED \\*\\*" "$LOG_FILE" | tail -n 100 >&2 || true
113+
fi
114+
exit 1
115+
fi
19116
20117
- name: Upload coverage to Codecov
21118
run: bash <(curl -s https://codecov.io/bash) -J 'fearless'

.gitignore

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ Tests/Mocks/CommonMocks.swift
5656
Tests/Mocks/ModuleMocks.swift
5757
#
5858
# Generamba
59-
Templates/
59+
/Templates/
6060
# Misc
6161
**/.DS_Store
62+
63+
# Swift Package Manager
64+
SourcePackages/
65+
.swiftpm/
66+
.build/
67+
68+
# Ignore project-level SPM resolved file; use workspace-level only
69+
fearless.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
70+
# Private pod/env helper
71+
.env.private

AGENTS.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# Repository Guidelines
2+
3+
<!-- wallet-context:start -->
4+
> About this codebase
5+
> This repository contains the codebase for a cryptocurrency wallet compatible with the Polkadot ecosystem (and related networks).
6+
> It uses dependencies available in the iOS ecosystem (e.g., SoraFoundation, SoraKeystore, FearlessKeys) and has an Android counterpart in soramitsu/fearless-Android.
7+
<!-- wallet-context:end -->
8+
9+
## Project Structure & Modules
10+
- `fearless/`: App sources, split by features/modules.
11+
- `fearlessTests/`, `fearlessIntegrationTests/`: Unit/integration tests.
12+
- `fearless.xcworkspace`, `fearless.xcodeproj`: Xcode workspace/project files.
13+
- `Pods/`, `Podfile`, `Podfile.lock`: CocoaPods dependencies.
14+
- `Jenkinsfile`: CI pipeline configuration.
15+
- Config files: `.swiftlint.yml`, `.swiftformat`, `.periphery.yml`.
16+
17+
## Build, Test, and Dev Commands
18+
- Install dependencies: `pod install`
19+
- Build (Debug, simulator):
20+
- `xcodebuild -workspace fearless.xcworkspace -scheme fearless -configuration Debug -destination 'platform=iOS Simulator,OS=latest,name=iPhone 15' build`
21+
- Run unit tests (on simulator):
22+
- `xcodebuild -workspace fearless.xcworkspace -scheme fearless.tests -destination 'platform=iOS Simulator,OS=latest,name=iPhone 15' test`
23+
- Lint/format:
24+
- `swiftlint` (uses `.swiftlint.yml`)
25+
- `swiftformat .` (uses `.swiftformat`)
26+
- CI matrix: `bash scripts/test-matrix.sh` runs tests for Debug and Release
27+
28+
Example destinations
29+
- iPhone 15: `-destination 'platform=iOS Simulator,OS=latest,name=iPhone 15'`
30+
- iPhone 14 Pro: `-destination 'platform=iOS Simulator,OS=latest,name=iPhone 14 Pro'`
31+
- iPad Pro (11-inch) 4th gen: `-destination 'platform=iOS Simulator,OS=latest,name=iPad Pro (11-inch) (4th generation)'`
32+
33+
Tip: list available destinations with `xcodebuild -showsdks` and `xcrun simctl list devices`.
34+
35+
CI note
36+
- Jenkins is configured to run tests on each build. For deterministic local parity, use `scripts/test-matrix.sh` before opening a PR.
37+
38+
## Coding Style & Naming
39+
- Language: Swift; follow Swift API design guidelines.
40+
- Formatting: SwiftFormat; linting with SwiftLint.
41+
- Files: one main type per file; names in PascalCase; avoid long files.
42+
- Packages/Modules: keep dependencies explicit; prefer dependency injection to singletons.
43+
- Avoid force‑unwraps; handle errors explicitly with clear user messaging.
44+
45+
## Testing Guidelines
46+
- Framework: XCTest; tests live in `fearlessTests/` and `fearlessIntegrationTests/`.
47+
- Naming: mirror the class under test, e.g., `AccountRepositoryTests.swift`; test methods `testX_whenY_thenZ`.
48+
- Coverage: maintain/raise coverage for changed code.
49+
- New code policy: whenever you add a function, add at least one unit test covering it.
50+
51+
## Commit & Pull Requests
52+
- Commits: concise, imperative subjects; reference issues (`#123`). Conventional Commit prefixes (`feat:`, `fix:`, `refactor:`) encouraged.
53+
- Before PR: ensure build + tests pass locally; `swiftlint`/`swiftformat` are clean.
54+
- PR checklist: clear description, linked issue, screenshots/video for UI, steps to test, risk/rollback notes.
55+
- CI must be green (Jenkins or equivalent).
56+
57+
## Security & Configuration
58+
- Never commit secrets or private keys. Use Keychain/secure storage at runtime; use CI secrets for pipelines.
59+
- Do not alter seed handling, signing, or cryptography without maintainer approval.
60+
- Runtime registries and chain/type sources must be aligned with the current Polkadot SDK release; coordinate updates with maintainers.
61+
- Use `*.xcconfig` and environment variables for private values; avoid hardcoding secrets in `Info.plist`.
62+
63+
## Dependencies & Versioning
64+
- Prefer conservative upgrades (patch/minor). Pin major bumps to separate PRs with clear testing notes.
65+
- Summarize upstream changes (link release notes) and provide a rollback plan.
66+
- If aligning to a Polkadot SDK release, ensure iOS utils/runtime dependencies are pinned accordingly (e.g., fearless-utils‑ios or equivalent).
67+
68+
## Preferred Tasks for Agents
69+
- Keep build green: fix warnings, flaky tests, and broken CI when root cause is clear.
70+
- Code hygiene: remove dead code; improve naming; tighten access control.
71+
- Tooling: enforce SwiftLint/SwiftFormat; update configs when safe.
72+
- Tests: add missing unit tests around changed code; stabilize integration tests.
73+
- Docs: keep README/ROADMAP/this guide accurate; small updates are welcome.
74+
75+
## Out of Scope (without prior approval)
76+
- Feature/UI/UX changes.
77+
- Protocol, staking, or on‑chain logic changes.
78+
- Wallet/account management, seeds, encryption, or secure storage changes.
79+
- Adding telemetry/analytics.
80+
81+
## Communication & Escalation
82+
- Use GitHub issues/PRs for decisions and traceability.
83+
- See `CONTRIBUTING.md` for community channels and expectations.
84+
- When in doubt, open an issue and wait for maintainer guidance.
85+
86+
## Sources of Truth
87+
- Roadmap (Aha!): https://soramitsucoltd.aha.io/shared/97bc3006ee3c1baa0598863615cf8d14
88+
- Dev status board: https://soramitsucoltd.aha.io/shared/343e5db57d53398e3f26d0048158c4a2
89+
- Issues: https://github.com/soramitsu/fearless-iOS/issues
90+
- Contributing: ./CONTRIBUTING.md
91+
- Roadmap (repo): ./ROADMAP.md
92+
93+
---
94+
95+
By following these guidelines, agents help keep Fearless Wallet iOS healthy, predictable, and aligned with the published roadmap while minimizing risk to users.
96+
97+
## Build & Archive — End‑to‑End Checklist
98+
99+
The project mixes CocoaPods and Swift Package Manager. Follow these steps in order.
100+
101+
1) Prerequisites (local dev)
102+
- Xcode 15.4+ (Xcode 18 SDK supported; CI pins 15.x when available for SPM/IrohaCrypto stability)
103+
- CocoaPods: `brew install cocoapods` (or `gem install cocoapods`)
104+
- SwiftFormat, SwiftLint (optional for local): `brew install swiftformat swiftlint`
105+
106+
2) Install Pods (always open the workspace)
107+
- From repo root: `pod install`
108+
- Open: `open fearless.xcworkspace`
109+
110+
3) Resolve SPM packages
111+
- CLI: `xcodebuild -resolvePackageDependencies -workspace fearless.xcworkspace -scheme fearless`
112+
- Xcode GUI: File → Packages → Reset Package Caches → Resolve Package Versions (if needed)
113+
114+
4) Build & test on Simulator (no signing)
115+
- Build: `xcodebuild -workspace fearless.xcworkspace -scheme fearless -configuration Debug -destination 'platform=iOS Simulator,OS=latest,name=iPhone 15' build`
116+
- Tests: `bash scripts/test-matrix.sh` (runs Debug + Release simulator tests using `fearless.tests` by default)
117+
118+
5) Archive (two options)
119+
- Development archive (local testing without Distribution certs):
120+
- In Xcode target ‘fearless’ → Signing & Capabilities (Dev config): set Automatic + Apple Development + your team/profile.
121+
- Then: `xcodebuild -workspace fearless.xcworkspace -scheme fearless -configuration Dev -destination 'generic/platform=iOS' -archivePath "$PWD/build/fearless.xcarchive" clean archive`
122+
- Ad‑hoc archive (CI/Release parity):
123+
- Requirements on the machine: Apple Distribution certificate for team `YLWWUD25VZ` + ad‑hoc profile `fearlesswallet-dev-adhoc` installed.
124+
- Project Dev config must be Manual + Apple Distribution + `jp.co.soramitsu.fearlesswallet.dev` + `PROVISIONING_PROFILE_SPECIFIER=fearlesswallet-dev-adhoc`.
125+
126+
6) Private pods (FearlessKeys)
127+
- The pod `FearlessKeys` is private. To allow `pod install` on CI/local without prompting:
128+
- Provide a GitHub Personal Access Token with repo read access (recommended env var: `GH_PAT_READ`).
129+
- Preconfigure git on the agent: `git config --global url."https://${GH_PAT_READ}@github.com/".insteadOf "https://github.com/"` (or run `scripts/secrets/setup-private-pods.sh` which does this for you and writes `.env.private` with `INCLUDE_FEARLESS_KEYS=1`).
130+
- Alternatively, write a `~/.netrc` with GitHub credentials (read-only).
131+
132+
7) IrohaCrypto + SPM stability (Xcode 16/18)
133+
- The SPM package `shared-features-spm` must be pinned to a revision that works with Xcode 16/18 (`3ad0fe9…`). We now enforce this automatically via `scripts/deps/enforce-ssf-pin.sh` in CI (`bootstrap.sh`), local dev (`dev-setup.sh`), and tests (`test-matrix.sh`).
134+
- Dependency-contract validation is centralized in:
135+
- `scripts/deps/check-dependency-contracts.sh`
136+
- Native crypto stability now uses dedicated contract scripts:
137+
- `scripts/deps/prepare-native-crypto-checkout.sh`
138+
- `scripts/deps/apply-native-crypto-package-contract.sh`
139+
- `scripts/deps/apply-native-crypto-modulemap-contract.sh`
140+
- `scripts/deps/verify-native-crypto-package-state.sh`
141+
- Additional required `shared-features-spm` compatibility fixes (BigInt dep, Web3 Data.bytes, AddressFactory type usage, scrypt guard) are applied by `scripts/spm-shared-features-fixes.sh`.
142+
143+
8) Web3 duplication
144+
- The project uses `soramitsu/web3-swift@7.7.7`. Do not add another Web3 source; duplicate packages will cause resolver failure.
145+
146+
## CI Build Requirements (Jenkins)
147+
148+
- CocoaPods available on agents (or handled in a shared pipeline step). If Pods are installed elsewhere, our Jenkinsfile guards will skip `pod install` gracefully.
149+
- Environment variables:
150+
- `GH_PAT_READ` (optional): GitHub PAT for private pods (`FearlessKeys`).
151+
- `DEVELOPER_DIR` (optional): Jenkinsfile auto‑pins to Xcode 15.x if present for SPM stability; otherwise default Xcode is used.
152+
- Private keys in PRs:
153+
- PR builds do NOT require private keys. The Jenkinsfile detects PR context (`CHANGE_ID`) and temporarily comments out the `pod 'FearlessKeys'` line before `pod install`, then restores the file. This prevents private repo access and allows PRs to build without secrets.
154+
- Trusted branches (develop/master/release): Jenkins sets `INCLUDE_FEARLESS_KEYS=1` and, if `GH_PAT_READ` is present, rewrites GitHub URLs to use the token so `pod install` can fetch `FearlessKeys`.
155+
- Steps performed before archive:
156+
- Clean SPM caches; resolve packages if the workspace exists.
157+
- Configure GitHub token (if provided) and run `pod install --repo-update` when `pod` is available.
158+
- Prepare the native crypto checkout against the repo-owned contract when required by the resolved package state.
159+
- Fastlane lane archives Dev as Ad‑hoc with mapping:
160+
- `jp.co.soramitsu.fearlesswallet.dev``fearlesswallet-dev-adhoc`
161+
- Ensure the Apple Distribution cert for `YLWWUD25VZ` is installed on the CI keychain.
162+
163+
## Common Build Failures & Fixes
164+
165+
- “No profile … matching ‘fearlesswallet-dev-adhoc’”: install the ad‑hoc profile (and Distribution certificate) on the machine, or switch PR builds to Development signing.
166+
- “Missing package product ‘MPQRCoreSDK’”: resolve SPM; reset SPM caches; ensure network access for binary targets.
167+
- “umbrella header … IrohaCrypto-umbrella.h not found”: use the pinned `shared-features-spm` revision and run the dedicated native crypto contract scripts / verifier.
168+
- “multiple similar targets ‘Web3’ …”: dedupe to `soramitsu/web3-swift@7.7.7` only.
169+
- “pod install” fails cloning FearlessKeys: supply `GH_PAT_READ` or gate that pod in CI.
170+
- “Ambiguous type ‘MetaAccountModel’ / ‘ChainAccountResponse’ in tests”: tests include `fearlessTests/Helper/TestTypeAliases.swift` to resolve ambiguity to app models. If you add conflicting SDK types, keep this shim or qualify uses (`fearless.MetaAccountModel`).
171+
- “JSONRPCEngine conformance missing in tests”: `fearlessTests/Common/Services/ChainRegistry/MockConnection.swift` provides a test engine conforming to the current `JSONRPCEngine` protocol. If the protocol changes upstream, adjust this file accordingly.
172+
173+
## Troubleshooting Raw Archive Output
174+
175+
- To bypass xcpretty and see the actual error:
176+
- `set -o pipefail; xcodebuild -workspace fearless.xcworkspace -scheme fearless -configuration Dev -destination 'generic/platform=iOS' -archivePath "$PWD/build/fearless.xcarchive" clean archive | tee build/archive.raw.log`
177+
- Then: `tail -n 300 build/archive.raw.log`

0 commit comments

Comments
 (0)