-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathMakefile
More file actions
378 lines (327 loc) · 18.2 KB
/
Copy pathMakefile
File metadata and controls
378 lines (327 loc) · 18.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
.DEFAULT_GOAL := help
XCODE_PROJECT := KeriWallet.xcodeproj
SCHEME := KeriWallet
APP_BUNDLE_ID := com.kerifoundation.wallet
FORTWEB_DIR ?= ../fortweb
# ── Simulator resolution ─────────────────────────────────────────────────────
# Resolve a single simulator UDID. Precedence:
# SIMULATOR_UDID → use that exact device
# SIMULATOR_NAME ± SIMULATOR_OS → match by name, optionally constrained by OS
# single booted iPhone → auto-select
# newest runtime → preferred model fallback
SIMULATOR_UDID ?=
SIMULATOR_NAME ?=
SIMULATOR_OS ?=
SIM_UDID := $(shell \
export SIMULATOR_UDID="$(SIMULATOR_UDID)" \
SIMULATOR_NAME="$(SIMULATOR_NAME)" \
SIMULATOR_OS="$(SIMULATOR_OS)" && \
python3 scripts/resolve-ios-simulator.py --udid 2>/dev/null || echo "SIM_UNRESOLVED")
SIM_DESTINATION := platform=iOS Simulator,id=$(SIM_UDID)
SIM_DERIVED_DATA := build/DerivedData-sim
DEVICE_DERIVED_DATA := build/DerivedData-device
TEST_RESULTS := build/TestResults.xcresult
ARCHIVE_PATH := build/KeriWallet.xcarchive
EXPORT_DIR := build/export
EXPORT_OPTS := ExportOptions.plist
SIM_APP_PATH := $(SIM_DERIVED_DATA)/Build/Products/Debug-iphonesimulator/KeriWallet.app
DEVICE_APP_PATH := $(DEVICE_DERIVED_DATA)/Build/Products/Debug-iphoneos/KeriWallet.app
DEVICE_REF ?=
# FortWeb-driven Xcode preparation
XCODE_READY_TESTS ?= 1
.PHONY: help setup payload-contract payload-package payload-import bridge-check ios-doctor ios-resolve-sim ios-list-sims ios-list-devices xcode-ready run-sim build test-swift test-swift-build test-swift-run test-tools test-all open lint lint-baseline knip repo-hygiene release-certify release-content-check generated-check clean clean-payload clean-all doctor archive archive-structural archive-verify export upload
help: ## Show available make targets
@grep -E '^[a-zA-Z_-]+:.*##' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*##"}; {printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}'
# ── Shared targets (platform-agnostic — reusable by Fort-android) ─────────────
setup: ## Install Node dependencies (run once after clone)
npm ci
test-tools: ## Run Node tool tests (Vitest — payload/bridge/contract tooling)
npm test
bridge-check: ## Verify BridgeContract.swift and BridgeContract.kt are up to date
npm run bridge:check
# ── iOS-only targets ──────────────────────────────────────────────────────────
# Canonical FortWeb runtime package is produced by FortWeb's OWN tooling
# (package:runtime) from its reviewed runtime source. Fort-ios only imports the
# resulting dist/package/fortweb-runtime-0.0.0.zip. FORTWEB_DIR must be a
# FortWeb checkout (e.g. a #38 ref) with the reviewed runtime source acquired
# (build/runtime-source/manifest.json) and dist/runtime built.
FORTWEB_RUNTIME_SOURCE_MANIFEST ?= build/runtime-source/manifest.json
FORTWEB_RUNTIME_SOURCE_MANIFEST_SHA256 ?= 87bcc689d7778840a76284471ff599cef21be41df2b429724f7f4fdc5f022135
# Producer ref recorded in release metadata. CI checkouts of the pinned FortWeb
# commit are detached, so package:runtime cannot infer a ref via git symbolic-ref.
FORTWEB_PACKAGE_REF ?= refs/heads/pyodide-314-runtime
payload-package: ## Produce canonical FortWeb runtime package (FortWeb package:runtime -> dist/package)
@rm -rf "$(FORTWEB_DIR)/dist/package"
@cd "$(FORTWEB_DIR)" && \
FORTWEB_RUNTIME_SOURCE_MANIFEST="$(FORTWEB_RUNTIME_SOURCE_MANIFEST)" \
FORTWEB_RUNTIME_SOURCE_MANIFEST_SHA256="$(FORTWEB_RUNTIME_SOURCE_MANIFEST_SHA256)" \
npm run package:runtime -- --python python3 --output-dir dist/package --ref "$(FORTWEB_PACKAGE_REF)"
payload-import: payload-package ## Import the canonical FortWeb runtime package into WebPayload
@ZIP="$(FORTWEB_DIR)/dist/package/fortweb-runtime-0.0.0.zip"; \
if [ ! -f "$$ZIP" ]; then \
echo "ERROR: canonical FortWeb runtime ZIP not found at $$ZIP"; \
echo "Ensure FORTWEB_DIR is a FortWeb checkout with reviewed runtime source acquired and dist/runtime built."; \
exit 1; \
fi; \
echo "[payload-import] Importing $$(basename $$ZIP)..."; \
node tools/import-fortweb-runtime-package.mjs "$$ZIP"
payload-contract: payload-import ## Import FortWeb runtime package and run full validation
node tools/assert-no-proof-demo-shell.mjs
node tools/validate-mobile-payload.mjs --payload-dir WebPayload --target ios-webpayload
node tools/assert-payload-integrity.mjs --payload-dir WebPayload
node tools/assert-pyodide-runtime.mjs --payload-dir WebPayload
node tools/assert-payload-containment.mjs
ios-list-sims: ## List available iOS Simulator destinations
xcrun simctl list devices available
ios-list-devices: ## List CoreDevice-visible physical devices
xcrun devicectl list devices
ios-resolve-sim: ## Print resolved simulator information
@SIMULATOR_UDID="$(SIMULATOR_UDID)" SIMULATOR_NAME="$(SIMULATOR_NAME)" SIMULATOR_OS="$(SIMULATOR_OS)" \
python3 scripts/resolve-ios-simulator.py
ios-doctor: ## Verify Xcode, simulator, and payload-source readiness
@command -v xcodebuild >/dev/null || (echo "ERROR: xcodebuild not found" && exit 1)
@command -v xcrun >/dev/null || (echo "ERROR: xcrun not found" && exit 1)
@echo "developer-dir=$${DEVELOPER_DIR:-not set}"
@xcodebuild -version 2>/dev/null | sed 's/^/xcode-/'
@echo "ios-sdk-version=$$(xcrun --sdk iphonesimulator --show-sdk-version 2>/dev/null || echo unknown)"
@echo "deployment-target=$$(xcodebuild -project $(XCODE_PROJECT) -showBuildSettings 2>/dev/null | awk '/IPHONEOS_DEPLOYMENT_TARGET/ {print $$3}' | head -1)"
@echo "swift-version=$$(xcrun swift --version 2>/dev/null | head -1 || echo unknown)"
@echo "fortweb-dir=$(FORTWEB_DIR)"
@echo "payload-present=$$([ -f WebPayload/manifest.json ] && echo yes || echo no)"
@if [ -f WebPayload/manifest.json ]; then \
python3 -c "import json; m=json.load(open('WebPayload/manifest.json')); print('payload-producer='+m.get('producer','unknown')); print('payload-sha='+str(m.get('fortweb_commit_sha','unknown'))[:16])" 2>/dev/null || true; \
fi
@if [ "$$(SIMULATOR_UDID)" != "" ] || [ "$$(SIMULATOR_NAME)" != "" ] || [ "$$(SIMULATOR_OS)" != "" ]; then \
echo "INFO: Using explicit simulator override"; \
SIMULATOR_UDID="$(SIMULATOR_UDID)" SIMULATOR_NAME="$(SIMULATOR_NAME)" SIMULATOR_OS="$(SIMULATOR_OS)" \
python3 scripts/resolve-ios-simulator.py; \
else \
echo "INFO: Auto-resolving simulator (set SIMULATOR_NAME, SIMULATOR_OS, or SIMULATOR_UDID to override)"; \
SIMULATOR_UDID="$(SIMULATOR_UDID)" SIMULATOR_NAME="$(SIMULATOR_NAME)" SIMULATOR_OS="$(SIMULATOR_OS)" \
python3 scripts/resolve-ios-simulator.py; \
fi
@xcrun devicectl list devices >/dev/null 2>&1 || echo "WARNING: no physical device available via CoreDevice"
@if [ ! -f WebPayload/manifest.json ]; then \
echo "ERROR: WebPayload is missing."; \
echo "Run: make xcode-ready FORTWEB_DIR=<FortWeb #38 checkout>"; \
fi
xcode-ready: ## Prepare the repository for opening in Xcode (press Play after)
@command -v xcodebuild >/dev/null || (echo "ERROR: xcodebuild not found. Install Xcode." && exit 1)
@command -v npm >/dev/null || (echo "ERROR: npm not found." && exit 1)
@if [ ! -d node_modules ]; then echo "ERROR: node_modules is missing."; echo "Run: npm ci"; exit 1; fi
@echo "=== Resolving simulator ==="
@SIMULATOR_UDID="$(SIMULATOR_UDID)" SIMULATOR_NAME="$(SIMULATOR_NAME)" SIMULATOR_OS="$(SIMULATOR_OS)" \
python3 scripts/resolve-ios-simulator.py || (echo "ERROR: No compatible iPhone Simulator is installed."; echo "Open Xcode > Settings > Components and install an iOS Simulator runtime."; exit 1)
@echo ""
@echo "=== Syncing payload ==="
@if [ -f WebPayload/manifest.json ]; then \
echo "Payload already staged. Use FORTWEB_DIR to re-sync if needed."; \
else \
$(MAKE) payload-import FORTWEB_DIR=$(FORTWEB_DIR); \
fi
@echo ""
@echo "=== Validating payload ==="
@node tools/validate-mobile-payload.mjs --payload-dir WebPayload --target ios-webpayload
@echo ""
@echo "=== Checking bridge contract ==="
@npm run bridge:check
@if [ "$(XCODE_READY_TESTS)" = "1" ]; then \
echo ""; \
echo "=== Running Node tool tests ==="; \
npm test; \
fi
@echo ""
@echo "=== Ready ==="
@echo "Project: $(XCODE_PROJECT)"
@echo "Open with: make open"
@SIMULATOR_UDID="$(SIMULATOR_UDID)" SIMULATOR_NAME="$(SIMULATOR_NAME)" SIMULATOR_OS="$(SIMULATOR_OS)" \
python3 scripts/resolve-ios-simulator.py 2>/dev/null || true
run-sim: ## Boot, install, and launch on the resolved Simulator
@if [ "$(SIM_UDID)" = "SIM_UNRESOLVED" ]; then \
echo "ERROR: Could not resolve a simulator."; \
echo "Run: make ios-resolve-sim"; \
exit 1; \
fi
open -a Simulator || true
xcrun simctl boot "$(SIM_UDID)" || true
xcrun simctl bootstatus "$(SIM_UDID)" -b
xcrun simctl install "$(SIM_UDID)" "$(SIM_APP_PATH)"
xcrun simctl launch "$(SIM_UDID)" $(APP_BUNDLE_ID)
dev-device: payload-import ## Import canonical payload and build for a generic iOS device output
xcodebuild build \
-project $(XCODE_PROJECT) \
-scheme $(SCHEME) \
-configuration Debug \
-destination 'generic/platform=iOS' \
-derivedDataPath $(DEVICE_DERIVED_DATA)
run-device: ## Install and launch on a physical device (use DEVICE_REF=<udid-or-name>)
@if [ -z "$(DEVICE_REF)" ]; then \
echo "ERROR: DEVICE_REF is required"; \
echo "Run: make ios-list-devices"; \
exit 1; \
fi
xcrun devicectl device install app --device "$(DEVICE_REF)" "$(DEVICE_APP_PATH)"
xcrun devicectl device process launch --device "$(DEVICE_REF)" --terminate-existing $(APP_BUNDLE_ID)
parity-smoke: ## Run the shared payload through simulator then device (requires DEVICE_REF)
@if [ -z "$(DEVICE_REF)" ]; then \
echo "ERROR: DEVICE_REF is required"; \
echo "Run: make ios-list-devices"; \
exit 1; \
fi
@if [ "$(SIM_UDID)" = "SIM_UNRESOLVED" ]; then \
echo "ERROR: Could not resolve a simulator."; \
exit 1; \
fi
$(MAKE) payload-import FORTWEB_DIR=$(FORTWEB_DIR)
$(MAKE) build FORTWEB_DIR=$(FORTWEB_DIR)
$(MAKE) run-sim
$(MAKE) dev-device FORTWEB_DIR=$(FORTWEB_DIR)
$(MAKE) run-device DEVICE_REF="$(DEVICE_REF)"
logs-sim: ## Show recent simulator logs for KeriWallet
@if [ "$(SIM_UDID)" = "SIM_UNRESOLVED" ]; then \
echo "ERROR: Could not resolve a simulator."; \
exit 1; \
fi
xcrun simctl spawn "$(SIM_UDID)" log show --style compact --last 10m --predicate 'subsystem == "com.kerifoundation.wallet" AND (category == "WebBridge" OR category == "WebContainer" OR category == "SchemeHandler" OR category == "WebNav")' | tail -n 200
logs-device: ## Relaunch on device with console attached (use DEVICE_REF=<udid-or-name>)
@if [ -z "$(DEVICE_REF)" ]; then \
echo "ERROR: DEVICE_REF is required"; \
echo "Run: make ios-list-devices"; \
exit 1; \
fi
xcrun devicectl device process launch --device "$(DEVICE_REF)" --terminate-existing --console $(APP_BUNDLE_ID)
build: ## Build KeriWallet for iOS Simulator (Debug)
@if [ "$(SIM_UDID)" = "SIM_UNRESOLVED" ]; then \
echo "ERROR: Could not resolve a simulator."; \
exit 1; \
fi
xcodebuild build \
-project $(XCODE_PROJECT) \
-scheme $(SCHEME) \
-configuration Debug \
-destination '$(SIM_DESTINATION)' \
-derivedDataPath $(SIM_DERIVED_DATA)
test-swift-build: ## Build Swift tests (no simulator boot required)
FORTWEB_DIR="$(FORTWEB_DIR)" xcodebuild build-for-testing \
-project $(XCODE_PROJECT) \
-scheme $(SCHEME) \
-configuration Debug \
-destination '$(SIM_DESTINATION)' \
-derivedDataPath $(SIM_DERIVED_DATA) \
build
test-swift-run: ## Run pre-built Swift tests (simulator must be resolved)
@if [ "$(SIM_UDID)" = "SIM_UNRESOLVED" ]; then \
echo "ERROR: Could not resolve a simulator."; \
exit 1; \
fi
FORTWEB_DIR="$(FORTWEB_DIR)" xcodebuild test-without-building \
-project $(XCODE_PROJECT) \
-scheme $(SCHEME) \
-configuration Debug \
-destination '$(SIM_DESTINATION)' \
-resultBundlePath $(TEST_RESULTS) \
-derivedDataPath $(SIM_DERIVED_DATA) \
-parallel-testing-enabled NO
test-swift: test-swift-build test-swift-run ## Build then run Swift unit + UI tests on iOS Simulator
test-all: test-swift test-tools ## Run Swift + Node tool tests
open: ## Open KeriWallet.xcodeproj in Xcode
open $(XCODE_PROJECT)
lint: ## Run SwiftLint with the frozen backlog baseline (fails on NEW violations)
cd $(CURDIR) && swiftlint lint --config .swiftlint.yml --strict --baseline .swiftlint-baseline.json
lint-baseline: ## Regenerate the SwiftLint violation baseline (only when deliberately removing debt)
cd $(CURDIR) && swiftlint lint --config .swiftlint.yml --write-baseline .swiftlint-baseline.json
release-content-check: ## Scan staged WebPayload (incl. nested archives) for App Store-gated content
cd $(CURDIR) && node tools/scan-release-content.mjs --dir WebPayload
knip: ## Report unused files, exports, dependencies, and unlisted binaries
npm run knip
repo-hygiene: ## Verify the tracked Git tree carries no generated, local-only, or secret material
cd $(CURDIR) && node tools/assert-repo-hygiene.mjs
# Release certification enforces every invariant, including the producer-owned
# ones the PR lane only reports. It is expected to fail while the canonical
# FortWeb runtime still carries unsanitized payload content.
release-certify: ## Certify a candidate archive (enforces producer-owned gates); ARCHIVE_PATH=...
cd $(CURDIR) && node tools/assert-release-archive.mjs \
--archive $(ARCHIVE_PATH) \
--release-certification \
--evidence build/release-evidence.json
generated-check: ## Verify generated bridge contracts are current and deterministic
npm run bridge:check
@test -f KeriWallet/BridgeContract.swift || (echo "ERROR: BridgeContract.swift missing" && exit 1)
@test -f generated/BridgeContract.kt || (echo "ERROR: BridgeContract.kt missing" && exit 1)
# ── Cleanup targets ───────────────────────────────────────────────────────────
clean: ## Remove build artifacts, caches, and temporary output (safe daily cleanup)
rm -rf $(SIM_DERIVED_DATA) $(DEVICE_DERIVED_DATA) $(TEST_RESULTS) $(ARCHIVE_PATH) $(EXPORT_DIR) dist
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
find . -type f -name '*.pyc' -delete 2>/dev/null || true
find . -type f -name '.DS_Store' -delete 2>/dev/null || true
find . -type d -name .pytest_cache -exec rm -rf {} + 2>/dev/null || true
rm -rf test-results
clean-payload: ## Remove staged mobile payload (regenerate with make payload-contract)
@echo "Removing WebPayload/ ..."
rm -rf WebPayload
@echo "Regenerate: make payload-contract FORTWEB_DIR=<FortWeb #38 checkout>"
clean-all: clean clean-payload ## Full developer reset (preserves source, .git, node_modules)
# ── Diagnostics ───────────────────────────────────────────────────────────────
doctor: ## Report environment state without mutation
@echo "=== Xcode ==="
@command -v xcodebuild >/dev/null && xcodebuild -version 2>/dev/null || echo " not found"
@echo "iOS SDK: $$(xcrun --sdk iphonesimulator --show-sdk-version 2>/dev/null || echo unknown)"
@echo "Swift: $$(xcrun swift --version 2>/dev/null | head -1 || echo unknown)"
@echo "Deployment target: $$(xcodebuild -project $(XCODE_PROJECT) -showBuildSettings 2>/dev/null | awk '/IPHONEOS_DEPLOYMENT_TARGET/ {print $$3}' | head -1)"
@echo ""
@echo "=== Simulator ==="
@SIMULATOR_UDID="$(SIMULATOR_UDID)" SIMULATOR_NAME="$(SIMULATOR_NAME)" SIMULATOR_OS="$(SIMULATOR_OS)" \
python3 scripts/resolve-ios-simulator.py 2>/dev/null || echo " No compatible simulator found"
@echo ""
@echo "=== FortWeb ==="
@echo "FORTWEB_DIR: $(FORTWEB_DIR)"
@echo "Payload present: $$([ -f WebPayload/manifest.json ] && echo yes || echo no)"
@echo "Payload valid: $$(node tools/validate-mobile-payload.mjs --payload-dir WebPayload --target ios-webpayload 2>/dev/null | grep result || echo unknown)"
@echo ""
@echo "=== Node tooling ==="
@echo "Node: $$(node --version 2>/dev/null || echo unknown)"
@echo "npm: $$(npm --version 2>/dev/null || echo unknown)"
@echo "Bridge: $$(node tools/gen-bridge-contract.mjs --check 2>/dev/null | tail -1 || echo unknown)"
@echo ""
@echo "=== SwiftLint ==="
@command -v swiftlint >/dev/null && swiftlint version 2>/dev/null || echo " not installed"
@echo ""
@echo "=== Git ==="
@echo "Branch: $$(git branch --show-current 2>/dev/null)"
@echo "Dirty: $$(git status --short 2>/dev/null | grep -v '^??' | head -5 || echo clean)"
# ── TestFlight targets ────────────────────────────────────────────────────────
archive: payload-import ## Archive KeriWallet for App Store (Release)
xcodebuild archive \
-project $(XCODE_PROJECT) \
-scheme $(SCHEME) \
-configuration Release \
-archivePath $(ARCHIVE_PATH) \
-destination 'generic/platform=iOS' \
-allowProvisioningUpdates
archive-structural: ## Build unsigned Release .xcarchive for structural/payload proof
xcodebuild archive \
-project $(XCODE_PROJECT) \
-scheme $(SCHEME) \
-configuration Release \
-destination 'generic/platform=iOS' \
-archivePath $(ARCHIVE_PATH) \
-derivedDataPath $(DEVICE_DERIVED_DATA) \
CODE_SIGNING_ALLOWED=NO
archive-verify: ## Verify the Release archive contains the validated production payload
node tools/assert-release-archive.mjs --archive $(ARCHIVE_PATH)
export: archive ## Export .ipa from archive using ExportOptions.plist
@if [ ! -f $(EXPORT_OPTS) ]; then \
echo "ERROR: $(EXPORT_OPTS) not found — copy ExportOptions.plist.example and fill in your Team ID"; \
exit 1; \
fi
xcodebuild -exportArchive \
-archivePath $(ARCHIVE_PATH) \
-exportOptionsPlist $(EXPORT_OPTS) \
-exportPath $(EXPORT_DIR) \
-allowProvisioningUpdates
upload: export ## Upload .ipa to App Store Connect / TestFlight
@IPA=$$(find $(EXPORT_DIR) -name '*.ipa' -print -quit); \
if [ -z "$$IPA" ]; then echo "ERROR: no .ipa found in $(EXPORT_DIR)"; exit 1; fi; \
echo "Uploading $$IPA to App Store Connect..."; \
xcrun altool --upload-app -f "$$IPA" -t ios --apiKey "$$APP_STORE_API_KEY" --apiIssuer "$$APP_STORE_API_ISSUER"