-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathMakefile
More file actions
274 lines (229 loc) · 10.7 KB
/
Copy pathMakefile
File metadata and controls
274 lines (229 loc) · 10.7 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
CLI_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
$(eval $(sort $(subst :,\:,$(CLI_ARGS))):;@:)
ifeq ($(MAKECMDGOALS),)
PRIMARY_GOAL := help
else
PRIMARY_GOAL := $(firstword $(MAKECMDGOALS))
endif
include docker/.env
# Current user ID and group ID except MacOS where it conflicts with Docker abilities
ifeq ($(shell uname), Darwin)
export UID=1000
export GID=1000
else
export UID=$(shell id -u)
export GID=$(shell id -g)
endif
export COMPOSE_PROJECT_NAME=${STACK_NAME}
DOCKER_COMPOSE_DEV := docker compose -f docker/compose.yml -f docker/dev/compose.yml
DOCKER_COMPOSE_TEST := docker compose -f docker/compose.yml -f docker/test/compose.yml
PACKAGE_PLATFORM ?= linux/amd64
PACKAGE_LINUX_DIST ?= dist/linux-amd64
PACKAGE_MACOS_ARCH ?= $(shell uname -m | sed -e 's/x86_64/amd64/' -e 's/aarch64/arm64/')
PACKAGE_MACOS_DIST ?= dist/macos-$(PACKAGE_MACOS_ARCH)
PACKAGE_WINDOWS_DIST ?= dist/windows-amd64
PACKAGE_PHAR_DIST ?= dist/phar
PACKAGE_IMAGE ?= ${IMAGE}-static
MACOS_PACKAGE_ARGS ?=
WINDOWS_PACKAGE_ARGS ?=
.PHONY: build up open down stop clear shell yii composer rector cs-fix test test-coverage test-coverage-clover psalm composer-dependency-analyser bench-generate bench-generate-realistic bench bench-baseline bench-compare bench-profile profile-build php build-docs package package-phar package-linux package-macos package-windows package-distroless package-distroless-push prod-build prod-push prod-deploy help
#
# Development
#
ifeq ($(PRIMARY_GOAL),build)
build: ## Build docker images
$(DOCKER_COMPOSE_DEV) build $(CLI_ARGS)
endif
ifeq ($(PRIMARY_GOAL),up)
up: ## Up the dev environment
@set -eu; \
if $(DOCKER_COMPOSE_DEV) up -d --wait --wait-timeout 60 --remove-orphans; then \
port="$$( $(DOCKER_COMPOSE_DEV) port app 19777 )"; \
host_port="$${port##*:}"; \
url="http://localhost$$( [ "$$host_port" = '80' ] || printf ':%s' "$$host_port" )"; \
printf '🚀 Started server at %s\n' "$$url"; \
else \
echo '❌ Failed to start server.' >&2; \
container_id="$$( $(DOCKER_COMPOSE_DEV) ps -a -q app 2>/dev/null || true )"; \
if [ -n "$$container_id" ]; then \
state="$$(docker inspect -f '{{.State.Status}}' "$$container_id" 2>/dev/null || true)"; \
health="$$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{end}}' "$$container_id" 2>/dev/null || true)"; \
exit_code="$$(docker inspect -f '{{.State.ExitCode}}' "$$container_id" 2>/dev/null || true)"; \
error="$$(docker inspect -f '{{.State.Error}}' "$$container_id" 2>/dev/null || true)"; \
[ -n "$$health" ] && echo "Container health: $$health" >&2; \
[ -n "$$state" ] && echo "Container state: $$state" >&2; \
[ -n "$$exit_code" ] && echo "Container exit code: $$exit_code" >&2; \
[ -n "$$error" ] && echo "Container error: $$error" >&2; \
echo 'Recent logs:' >&2; \
$(DOCKER_COMPOSE_DEV) logs --tail=50 app >&2 || true; \
fi; \
exit 1; \
fi
endif
ifeq ($(PRIMARY_GOAL),open)
open: ## Open the running app in the default browser
@set -eu; \
if ! port="$$( $(DOCKER_COMPOSE_DEV) port app 19777 2>/dev/null )" || [ -z "$$port" ]; then \
echo 'Start server with `make up` first.' >&2; \
exit 0; \
fi; \
host_port="$${port##*:}"; \
url="http://localhost$$( [ "$$host_port" = '80' ] || printf ':%s' "$$host_port" )"; \
opener="$$(command -v xdg-open || command -v open || command -v wslview || true)"; \
if [ -z "$$opener" ]; then \
echo "Could not open $$url." >&2; \
exit 0; \
fi; \
"$$opener" "$$url" >/dev/null 2>&1 &
endif
ifeq ($(PRIMARY_GOAL),down)
down: ## Down the dev environment
$(DOCKER_COMPOSE_DEV) down --remove-orphans
endif
ifeq ($(PRIMARY_GOAL),stop)
stop: ## Stop the dev environment
$(DOCKER_COMPOSE_DEV) stop
endif
ifeq ($(PRIMARY_GOAL),clear)
clear: ## Remove development docker containers and volumes
$(DOCKER_COMPOSE_DEV) down --volumes --remove-orphans
endif
ifeq ($(PRIMARY_GOAL),shell)
shell: ## Get into container shell
$(DOCKER_COMPOSE_DEV) exec app /bin/bash
endif
ifeq ($(PRIMARY_GOAL),yii)
yii: ## Execute Yii command
$(DOCKER_COMPOSE_DEV) run --rm -e XDEBUG_MODE=off app ./yii $(CLI_ARGS)
.PHONY: yii
endif
ifeq ($(PRIMARY_GOAL),composer)
composer: ## Run Composer
$(DOCKER_COMPOSE_DEV) run --rm app composer $(CLI_ARGS)
endif
ifeq ($(PRIMARY_GOAL),rector)
rector: ## Run Rector
$(DOCKER_COMPOSE_DEV) run --rm app ./vendor/bin/rector $(CLI_ARGS)
endif
ifeq ($(PRIMARY_GOAL),cs-fix)
cs-fix: ## Run PHP CS Fixer
$(DOCKER_COMPOSE_DEV) run --rm app ./vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --diff
endif
#
# Tests and analysis
#
ifeq ($(PRIMARY_GOAL),test)
test: ## Run tests
$(DOCKER_COMPOSE_TEST) run --rm app ./vendor/bin/phpunit $(CLI_ARGS)
endif
ifeq ($(PRIMARY_GOAL),test-coverage)
test-coverage: ## Run tests with coverage
$(DOCKER_COMPOSE_TEST) run --rm app ./vendor/bin/phpunit --coverage-html runtime/coverage $(CLI_ARGS)
endif
ifeq ($(PRIMARY_GOAL),test-coverage-clover)
test-coverage-clover: ## Run tests with Clover coverage
$(DOCKER_COMPOSE_TEST) run --rm app bash -lc 'mkdir -p runtime/coverage && ./vendor/bin/phpunit --coverage-clover runtime/coverage/clover.xml $(CLI_ARGS)'
endif
ifeq ($(PRIMARY_GOAL),psalm)
psalm: ## Run Psalm
$(DOCKER_COMPOSE_DEV) run --rm app ./vendor/bin/psalm $(CLI_ARGS)
endif
ifeq ($(PRIMARY_GOAL),composer-dependency-analyser)
composer-dependency-analyser: ## Run Composer Dependency Analyser
$(DOCKER_COMPOSE_DEV) run --rm app ./vendor/bin/composer-dependency-analyser --config=composer-dependency-analyser.php $(CLI_ARGS)
endif
ifeq ($(PRIMARY_GOAL),bench-generate)
bench-generate: ## Generate benchmark data (10k entries)
$(DOCKER_COMPOSE_DEV) run --rm app php benchmarks/generate_content.php $(CLI_ARGS)
endif
ifeq ($(PRIMARY_GOAL),bench-generate-realistic)
bench-generate-realistic: ## Generate realistic benchmark data (1k large entries)
$(DOCKER_COMPOSE_DEV) run --rm app php benchmarks/generate_realistic_content.php $(CLI_ARGS)
endif
ifeq ($(PRIMARY_GOAL),bench)
bench: ## Run benchmarks (xdebug off). Use BENCH_FILTER=ClassName to filter.
$(DOCKER_COMPOSE_DEV) run --rm -e XDEBUG_MODE=off app ./vendor/bin/phpbench run $(if $(BENCH_FILTER),--filter=$(BENCH_FILTER)) $(CLI_ARGS)
endif
ifeq ($(PRIMARY_GOAL),bench-baseline)
bench-baseline: ## Run benchmarks (xdebug off) and write a baseline. Use BENCH_FILTER=ClassName to filter.
$(DOCKER_COMPOSE_DEV) run --rm -e XDEBUG_MODE=off app ./vendor/bin/phpbench run --tag=original --retry-threshold=2 $(if $(BENCH_FILTER),--filter=$(BENCH_FILTER)) $(CLI_ARGS)
endif
ifeq ($(PRIMARY_GOAL),bench-compare)
bench-compare: ## Run benchmarks (xdebug off) and compare with baseline. Use BENCH_FILTER=ClassName to filter.
$(DOCKER_COMPOSE_DEV) run --rm -e XDEBUG_MODE=off app ./vendor/bin/phpbench run --report=aggregate --ref=original --retry-threshold=2 $(if $(BENCH_FILTER),--filter=$(BENCH_FILTER)) $(CLI_ARGS)
endif
ifeq ($(PRIMARY_GOAL),bench-profile)
bench-profile: ## Run benchmarks with XDebug profiling. Use BENCH_FILTER=ClassName to filter.
@mkdir -p runtime/xdebug
$(DOCKER_COMPOSE_DEV) run --rm -e XDEBUG_MODE=profile -e XDEBUG_OUTPUT_DIR=/app/runtime/xdebug app ./vendor/bin/phpbench run --iterations=1 --revs=1 --warmup=1 --php-config='{"xdebug.output_dir":"/app/runtime/xdebug"}' $(if $(BENCH_FILTER),--filter=$(BENCH_FILTER)) $(CLI_ARGS)
endif
ifeq ($(PRIMARY_GOAL),profile-build)
profile-build: ## Run yii build with XDebug profiling. Pass build args after target.
@mkdir -p runtime/xdebug
$(DOCKER_COMPOSE_DEV) run --rm -e XDEBUG_MODE=profile app php -d xdebug.start_with_request=yes -d xdebug.output_dir=/app/runtime/xdebug yii $(CLI_ARGS)
endif
ifeq ($(PRIMARY_GOAL),php)
php: ## Run a PHP script
$(DOCKER_COMPOSE_DEV) run --rm app php $(CLI_ARGS)
endif
ifeq ($(PRIMARY_GOAL),build-docs)
build-docs: ## Build documentation site from docs/ directory
$(DOCKER_COMPOSE_DEV) run --rm app ./yii build --content-dir=docs --output-dir=docs-output --no-cache
endif
ifeq ($(PRIMARY_GOAL),package)
package: ## Build Linux static binary into dist/linux-amd64/
@mkdir -p $(PACKAGE_LINUX_DIST)
@rm -f $(PACKAGE_LINUX_DIST)/yiipress.phar
docker buildx build --file docker/Dockerfile --target package-linux-artifacts --platform $(PACKAGE_PLATFORM) --output type=local,dest=$(PACKAGE_LINUX_DIST) .
endif
ifeq ($(PRIMARY_GOAL),package-phar)
package-phar: ## Build YiiPress PHAR into dist/phar/
docker buildx build --file docker/Dockerfile --target package-phar-artifacts --platform $(PACKAGE_PLATFORM) --output type=local,dest=$(PACKAGE_PHAR_DIST) .
endif
ifeq ($(PRIMARY_GOAL),package-linux)
package-linux: ## Build Linux static binary into dist/linux-amd64/
@mkdir -p $(PACKAGE_LINUX_DIST)
@rm -f $(PACKAGE_LINUX_DIST)/yiipress.phar
docker buildx build --file docker/Dockerfile --target package-linux-artifacts --platform $(PACKAGE_PLATFORM) --output type=local,dest=$(PACKAGE_LINUX_DIST) .
endif
ifeq ($(PRIMARY_GOAL),package-macos)
package-macos: ## Build macOS static executable into dist/macos-<arch>/
@command -v bash >/dev/null 2>&1 || { echo 'Bash is required for package-macos.' >&2; exit 127; }
build/package-macos.sh --dist-dir $(PACKAGE_MACOS_DIST) --arch $(PACKAGE_MACOS_ARCH) $(MACOS_PACKAGE_ARGS)
endif
ifeq ($(PRIMARY_GOAL),package-windows)
package-windows: ## Build Windows static executable into dist/windows-amd64/
@command -v pwsh >/dev/null 2>&1 || { echo 'PowerShell 7 (pwsh) is required for package-windows.' >&2; exit 127; }
pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -File build/package-windows.ps1 -DistDir $(PACKAGE_WINDOWS_DIST) $(WINDOWS_PACKAGE_ARGS)
endif
ifeq ($(PRIMARY_GOAL),package-distroless)
package-distroless: ## Build local distroless image containing only the static Linux binary
docker buildx build --file docker/Dockerfile --target distroless --platform $(PACKAGE_PLATFORM) --load -t $(PACKAGE_IMAGE):$(IMAGE_TAG) .
endif
ifeq ($(PRIMARY_GOAL),package-distroless-push)
package-distroless-push: ## Build and push distroless image containing only the static Linux binary
docker buildx build --file docker/Dockerfile --target distroless --platform $(PACKAGE_PLATFORM) --push -t $(PACKAGE_IMAGE):$(IMAGE_TAG) .
endif
#
# Production
#
ifeq ($(PRIMARY_GOAL),prod-build)
prod-build: ## PROD | Build an image
docker build --file docker/Dockerfile --target prod --pull -t ${IMAGE}:${IMAGE_TAG} .
endif
ifeq ($(PRIMARY_GOAL),prod-push)
prod-push: ## PROD | Push image to repository
docker push ${IMAGE}:${IMAGE_TAG}
endif
ifeq ($(PRIMARY_GOAL),prod-deploy)
prod-deploy: ## PROD | Deploy to production
docker -H ${PROD_SSH} stack deploy --prune --detach=false --with-registry-auth -c docker/compose.yml -c docker/prod/compose.yml ${STACK_NAME}
endif
#
# Other
#
ifeq ($(PRIMARY_GOAL),help)
# Output the help for each task, see https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
help: ## This help.
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
endif