Makefile
Rama main · réplica de lectura del repositorio original.
.PHONY: help test verify-all check screenshots build-android build-desktop run run-debug clean \
package-deb package-dmg package-msi package-all \
release release-patch release-minor release-major _release \
generate-keystore setup-secrets lint \
install-hooks version
VERSION ?= $(shell (git describe --tags --abbrev=0 2>/dev/null || echo v1.0.0) | sed 's/^v//')
NEXT_PATCH = $(shell echo $(VERSION) | awk -F. '{printf "%d.%d.%d", $$1, $$2, $$3+1}')
NEXT_MINOR = $(shell echo $(VERSION) | awk -F. '{printf "%d.%d.0", $$1, $$2+1}')
NEXT_MAJOR = $(shell echo $(VERSION) | awk -F. '{printf "%d.0.0", $$1+1}')
SKIP_RELEASE_CHECK ?= 0
help: ## Show this help
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
# ---------------------------------------------------------------------------
# Gradle invocation (verification targets)
# ---------------------------------------------------------------------------
# The macOS Kotlin compiler daemon writes its `*.alive` flag file to the system
# temp dir (java.io.tmpdir), which the Claude Code sandbox denies with
# "Operation not permitted". Route Kotlin's temp to a project-local dir and
# compile in-process so the verify targets run cleanly under the sandbox. The
# trade-off — no persistent compiler daemon, so slightly slower warm builds — is
# why only the verification targets use this; interactive/packaging targets keep
# plain ./gradlew and its daemon. --no-configuration-cache avoids caching a failed
# sandboxed run (org.gradle.configuration-cache=true is on by default).
KOTLIN_TMP := $(CURDIR)/build/tmp-kotlin
GRADLEW_VERIFY = TMPDIR=$(KOTLIN_TMP) ./gradlew --no-configuration-cache \
-Dkotlin.compiler.execution.strategy=in-process -Djava.io.tmpdir=$(KOTLIN_TMP)
# Per-source-set ktlint checks. The top-level `ktlintCheck` also scans generated
# Compose resource collectors and is unreliable — see
# docs/patterns/kotlin-multiplatform/testing.md in the workspace.
KTLINT_CHECK_TASKS = shared:runKtlintCheckOverCommonMainSourceSet \
shared:runKtlintCheckOverAndroidMainSourceSet \
shared:runKtlintCheckOverJvmMainSourceSet \
shared:runKtlintCheckOverCommonTestSourceSet \
shared:runKtlintCheckOverJvmTestSourceSet
$(KOTLIN_TMP):
@mkdir -p $(KOTLIN_TMP)
# ---------------------------------------------------------------------------
# Development
# ---------------------------------------------------------------------------
test: | $(KOTLIN_TMP) ## Run all tests (JVM)
$(GRADLEW_VERIFY) shared:jvmTest --stacktrace
verify-all: | $(KOTLIN_TMP) ## Compile every target (jvm+android+ios) and run JVM tests
$(GRADLEW_VERIFY) \
shared:compileKotlinJvm \
shared:compileAndroidMain \
shared:compileKotlinIosArm64 \
shared:jvmTest --stacktrace
screenshots: ## Regenerate documentation screenshots into screenshots/companionapp
./gradlew shared:jvmTest --tests "com.pulseweaver.heartbeat.ui.DocScreenshotsTest" \
-Dpw.screenshots=true --rerun-tasks
lint: | $(KOTLIN_TMP) ## Run ktlint (per-source-set; top-level ktlintCheck is unreliable)
$(GRADLEW_VERIFY) $(KTLINT_CHECK_TASKS)
run: ## Run desktop app
./gradlew :shared:run
# Debug interval in seconds for `run-debug` (override: make run-debug PW_INTERVAL=10)
PW_INTERVAL ?= 5
run-debug: ## Run desktop app in debug mode (verbose logs + PW_INTERVAL beat, default 5s)
PW_DEBUG=1 PW_INTERVAL=$(PW_INTERVAL) ./gradlew :shared:run
clean: ## Clean build outputs
./gradlew clean
check: lint test ## Lint + tests
# ---------------------------------------------------------------------------
# Build
# ---------------------------------------------------------------------------
build-android: ## Build Android debug APK
./gradlew assembleDebug --stacktrace
build-android-release: ## Build Android release APK (requires keystore env vars)
./gradlew assembleRelease -PappVersion=$(VERSION) --stacktrace
build-desktop: ## Compile desktop JVM target
./gradlew :shared:compileKotlinJvm --stacktrace
# ---------------------------------------------------------------------------
# Package native installers
# ---------------------------------------------------------------------------
package-deb: ## Package Linux .deb
./gradlew :shared:packageDeb -PappVersion=$(VERSION) --stacktrace
package-dmg: ## Package macOS .dmg
./gradlew :shared:packageDmg -PappVersion=$(VERSION) --stacktrace
package-msi: ## Package Windows .msi
./gradlew :shared:packageMsi -PappVersion=$(VERSION) --stacktrace
package-all: package-deb package-dmg package-msi build-android-release ## Build all platform packages
# ---------------------------------------------------------------------------
# Release
# ---------------------------------------------------------------------------
release-patch: ## Changelog → commit → tag → push (patch: x.y.Z+1)
@$(MAKE) _release V=$(NEXT_PATCH)
release-minor: ## Changelog → commit → tag → push (minor: x.Y+1.0)
@$(MAKE) _release V=$(NEXT_MINOR)
release-major: ## Changelog → commit → tag → push (major: X+1.0.0)
@$(MAKE) _release V=$(NEXT_MAJOR)
# Internal: run as $(MAKE) _release V=x.y.z — never call directly
_release:
@git diff --quiet && git diff --staged --quiet || (echo "❌ Dirty working tree — commit or stash changes first" && exit 1)
@echo "Current: v$(VERSION) → Next: v$(V)"
@read -p "Confirm? [y/N] " confirm && [ "$$confirm" = "y" ] || exit 1
@if [ "$(SKIP_RELEASE_CHECK)" != "1" ]; then $(MAKE) check; fi
git-cliff --unreleased --tag "v$(V)" --prepend CHANGELOG.md
@echo "Review and edit CHANGELOG.md before continuing"
@read -p "Continue? [y/N] " confirm && [ "$$confirm" = "y" ] || exit 1
git add CHANGELOG.md
git diff --staged --quiet || git commit -m "chore: release v$(V)"
git tag -a "v$(V)" -m "Release v$(V)"
git push origin main --tags
# ---------------------------------------------------------------------------
# Setup
# ---------------------------------------------------------------------------
version: ## Show current version
@echo "v$(VERSION)"
generate-keystore: ## Generate a new Android release keystore
@if [ -f release.keystore ]; then echo "release.keystore already exists"; exit 1; fi
keytool -genkeypair -v -keystore release.keystore -alias pulseweaver \
-keyalg RSA -keysize 2048 -validity 10000 \
-dname "CN=PulseWeaver, O=PulseWeaver"
@echo ""
@echo "Created release.keystore — keep this file safe and never commit it."
@echo "To set up GitHub Secrets, run: make setup-secrets"
setup-secrets: ## Print instructions for GitHub Actions secrets
@echo ""
@echo "Add these secrets to your GitHub repo (Settings → Secrets → Actions):"
@echo ""
@echo " KEYSTORE_BASE64 base64 < release.keystore | pbcopy (or base64 -w0 on Linux)"
@echo " KEYSTORE_PASSWORD the password you chose during keytool"
@echo " KEY_ALIAS pulseweaver (or whatever alias you used)"
@echo ""
# ---------------------------------------------------------------------------
# Hooks
# ---------------------------------------------------------------------------
install-hooks: ## Install git hooks (run once after cloning)
@ln -sf "$(PWD)/scripts/commit-msg" "$(PWD)/.git/hooks/commit-msg"
@chmod +x "$(PWD)/.git/hooks/commit-msg"
@echo "✅ Git hooks installed."