-
Notifications
You must be signed in to change notification settings - Fork 77
Expand file tree
/
Copy pathmakefile
More file actions
220 lines (190 loc) Β· 8.76 KB
/
Copy pathmakefile
File metadata and controls
220 lines (190 loc) Β· 8.76 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
.PHONY: all setup clean deps deps-update bootstrap analyze build-runner translations hooks ios-pod-update drift-migrations devcontainer container-tools container-app android release debug beta verify test unit-test integration-test catalogue fvm-check
fvm-check:
@echo "π Checking FVM"
@if ! command -v fvm >/dev/null 2>&1; then \
echo "β FVM is not installed. Please install FVM first:"; \
exit 1; \
fi
@echo "β
FVM is installed"
@fvm install
all: setup
@echo "β¨ All tasks completed!"
setup: fvm-check clean deps build-runner translations hooks
@if [ "$$(uname)" = "Darwin" ]; then $(MAKE) ios-pod-update; fi
@echo "π Setup complete!"
clean:
@echo "π§Ή Clean build artifacts (keeps lockfiles)"
@fvm flutter clean
deps:
@echo "π Fetch dependencies (enforce pubspec.lock)"
@fvm flutter pub get --enforce-lockfile
# Intentionally re-resolve from scratch: deletes the lockfiles and lets pub pick
# fresh versions (and, for branch refs, fresh commits). Use only when you mean to
# update dependencies, then commit the regenerated pubspec.lock.
deps-update:
@echo "π Re-resolving dependencies (deletes pubspec.lock + ios/Podfile.lock)"
@rm -f pubspec.lock ios/Podfile.lock
@fvm flutter pub get
# Melos workspace bootstrap (pub get across the workspace + package linking).
# Wraps `fvm dart run melos` so the pinned SDK (.fvmrc) is used β never bare
# `melos`. Single root package today (useRootAsPackage), so this is ~equivalent
# to `make deps`; it becomes meaningful once packages/ + features/ gain members.
bootstrap:
@echo "π§© Melos bootstrap"
@fvm dart run melos bootstrap
analyze:
@echo "π Analyze whole project (matches CI: --fatal-warnings --fatal-infos)"
@fvm flutter analyze --fatal-warnings --fatal-infos
build-runner:
@echo "ποΈ Build runner for json_serializable and flutter_gen"
@fvm dart run build_runner build --force-jit
build-runner-watch:
@echo "ποΈ Build runner for json_serializable and flutter_gen (watch mode)"
@fvm dart run build_runner watch --delete-conflicting-outputs --force-jit
translations:
@echo "π Generating translations files"
@fvm flutter gen-l10n
hooks:
@CURRENT_HOOKS_PATH=$$(git config --local core.hooksPath); \
if [ "$$CURRENT_HOOKS_PATH" = ".git_hooks/" ]; then \
echo "β
Git hooks already configured"; \
else \
echo "π§ Setting up git pre-commit hooks"; \
git config --local core.hooksPath .git_hooks/; \
fi
drift-migrations:
@echo "π Create schema and sum migrations"
fvm dart run drift_dev make-migrations
ios-pod-update:
@if [ "$$(uname)" != "Darwin" ]; then echo "Skipping pod update (not macOS)"; exit 0; fi
@echo "Fetching iOS dependencies"
@fvm flutter precache --ios
@cd ios && pod install --repo-update && cd -
ios-sqlite-update:
@if [ "$$(uname)" != "Darwin" ]; then echo "Skipping pod update (not macOS)"; exit 0; fi
@echo "Updating SQLite"
@cd ios && pod update sqlite3 && cd -
# Container runtime β default podman, override with CONTAINER=docker for
# environments without podman.
CONTAINER ?= podman
container-tools:
@echo "π§ Building tools image"
@$(CONTAINER) build -f Containerfile.tools -t bull-tools \
--build-arg FLUTTER_VERSION=$$(awk 'BEGIN{RS="";} { gsub(/\r/,""); s=$$0; sub(/.*"flutter"[[:space:]]*:[[:space:]]*"/,"",s); sub(/".*$$/,"",s); print s; exit }' .fvmrc) \
--build-arg JVM_TARGET=$$(grep 'android.jvmTarget' android/gradle.properties | cut -d= -f2) \
--build-arg ANDROID_API_LEVEL=$$(grep 'android.compileSdk' android/gradle.properties | cut -d= -f2) \
--build-arg ANDROID_BUILD_TOOLS=$$(grep 'android.buildToolsVersion' android/gradle.properties | cut -d= -f2) \
--build-arg ANDROID_NDK=$$(grep 'android.ndkVersion' android/gradle.properties | cut -d= -f2) \
$(if $(EXPECTED_RUST_VERSION),--build-arg EXPECTED_RUST_VERSION=$(EXPECTED_RUST_VERSION)) \
.
container-app: container-tools
@echo "π¦ Building app image"
@$(CONTAINER) build -f Containerfile.app -t bull-app \
--build-arg GRADLE_HEAP=$(or $(GRADLE_HEAP),4g) \
.
MODE ?= debug
FORMAT ?= apk
FLAVOR ?= production
# Allow "make android release", "make android debug" or "make android beta".
# release/debug build the production flavor; beta is the tester channel β the
# beta flavor (.beta applicationId, its own signing) in release mode, for direct
# store-less distribution.
ifneq (,$(filter release,$(MAKECMDGOALS)))
MODE := release
endif
ifneq (,$(filter debug,$(MAKECMDGOALS)))
MODE := debug
endif
ifneq (,$(filter beta,$(MAKECMDGOALS)))
MODE := release
FLAVOR := beta
endif
release debug beta:
@:
# Gradle appbundle output dir is camelCase <flavor><BuildType> (e.g. productionRelease).
MODE_CAP := $(if $(filter release,$(MODE)),Release,Debug)
# Host artifact name reflects the build target: BULL-release / BULL-debug for the
# production flavor, and BULL-<flavor> (e.g. BULL-beta) for channel flavors. The
# in-container Flutter output keeps its app-<flavor>-<mode> names below; only the
# extracted host file is branded.
#
# Channel flavors (beta) are signed only when their key is present, mirroring the
# gradle signingConfig guard (android/key-beta.properties). With no key the build
# is unsigned β Flutter still names it app-<flavor>-<mode>.apk, so flag it -unsigned
# on the host so an uninstallable build is obvious. CI requires the key, so this
# only triggers for keyless local beta builds. Production names are left unbranded:
# release is intentionally unsigned in the reproducibility/verify flow and both CI
# upload and verify_build.sh depend on the exact BULL-release name.
ifeq ($(FLAVOR),production)
HOST_NAME := $(MODE)
else ifeq (,$(wildcard android/key-beta.properties))
HOST_NAME := $(FLAVOR)-unsigned
else
HOST_NAME := $(FLAVOR)
endif
# Flutter writes APK and AAB to different, flavor-namespaced paths
ifeq ($(FORMAT),aab)
CONTAINER_OUTPUT := /app/build/app/outputs/bundle/$(FLAVOR)$(MODE_CAP)/app-$(FLAVOR)-$(MODE).aab
HOST_OUTPUT := ./BULL-$(HOST_NAME).aab
FLUTTER_BUILD := fvm flutter build appbundle --$(MODE) --flavor $(FLAVOR)
else
CONTAINER_OUTPUT := /app/build/app/outputs/flutter-apk/app-$(FLAVOR)-$(MODE).apk
HOST_OUTPUT := ./BULL-$(HOST_NAME).apk
FLUTTER_BUILD := fvm flutter build apk --$(MODE) --flavor $(FLAVOR)
endif
android: container-app
@echo "π¨ Building $(FORMAT) ($(FLAVOR) $(MODE)) via $(CONTAINER)"
@$(CONTAINER) rm -f bull-build > /dev/null 2>&1 || true
@$(CONTAINER) run --name bull-build \
--ulimit nofile=65536:65536 \
bull-app bash -c '\
SOURCE_DATE_EPOCH=$$(git -C /app log -1 --format=%ct) && \
CARGO_ENCODED_RUSTFLAGS=$$(printf "%s\037%s\037%s" \
"--remap-path-prefix=$$HOME/.cargo=/cargo" \
"--remap-path-prefix=$$HOME/.rustup=/rustup" \
"--remap-path-prefix=/app=/build") && \
CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 && \
CARGO_NET_GIT_FETCH_WITH_CLI=true && \
export SOURCE_DATE_EPOCH CARGO_ENCODED_RUSTFLAGS CARGO_PROFILE_RELEASE_CODEGEN_UNITS CARGO_NET_GIT_FETCH_WITH_CLI && \
cd /app && \
$(FLUTTER_BUILD)'
@$(CONTAINER) cp bull-build:$(CONTAINER_OUTPUT) $(HOST_OUTPUT)
@$(CONTAINER) rm bull-build > /dev/null
@echo "β
Output extracted: $(HOST_OUTPUT)"
@sha256sum $(HOST_OUTPUT)
verify:
@echo "π Verifying reproducible build"
@./reproducibility/verify_build.sh $(if $(VERSION),--version $(VERSION)) $(if $(APK),--apk $(APK))
devcontainer: container-tools
@echo "ποΈ Building Dev Container"
@devcontainer up --workspace-folder . --config ./.devcontainer/devcontainer.json
test: unit-test integration-test
unit-test:
@echo "πβ running unit tests"
@fvm flutter test test/ --reporter=compact
@for p in packages/*/; do \
if [ -d "$${p}test" ]; then \
echo "πβ running $${p}test"; \
( cd "$$p" && fvm flutter test --reporter=compact ); \
fi; \
done
# integration_test/all_test.dart is a single aggregator entrypoint: it runs
# Bull.init() once, then every test file's main(isInitialized: true). On the
# Linux desktop device the app can only be launched once per `flutter test`
# invocation, so running this one file builds + launches once for the whole
# suite (instead of failing every file but the first, as `flutter test
# integration_test/` does). all_test.dart is a generated, gitignored artifact β
# tool/gen_all_test.dart regenerates it from disk below, so adding a test file
# needs no manual wiring.
integration-test:
@echo "π§ͺ integration tests"
@fvm dart run tool/gen_all_test.dart
@fvm flutter test integration_test/all_test.dart --reporter=expanded
# Build & render the bull_ui design-system catalogue (Widgetbook) locally in the
# browser. Dev-only tooling β never shipped in the app. Regenerates the
# @UseCase directories, then runs the catalogue app on Chrome (hot-reload).
catalogue:
@echo "π Building & rendering the bull_ui catalogue in the browser"
@cd packages/bull_ui_catalogue && \
fvm dart run build_runner build --delete-conflicting-outputs && \
fvm flutter run -d chrome