.PHONY: build-release check deny docs test test-ignored test-scripts release release-patch release-minor release-major publish tag-current
CURRENT_VERSION := $(shell grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
VERSION_FILES := Cargo.toml .claude-plugin/marketplace.json gemini-extension.json
build-release:
@cargo build --release
check:
@cargo update --quiet
@cargo fmt -- -l | sed 's/^/fmt: formatted /'
@cargo clippy --tests --features mockls --quiet -- -D warnings
@cargo deny --log-level error check
@cargo nextest run --workspace --features mockls --no-fail-fast --status-level fail --final-status-level fail --cargo-quiet --show-progress only
docs:
@cargo doc --document-private-items --no-deps --quiet
deny:
@cargo deny --log-level error check
test-scripts:
@python3 -m pytest scripts/test_constrained_bash.py -v 2>/dev/null || python3 scripts/test_constrained_bash.py
CLEAN_T = $(subst \,,$(subst !,,$(T)))
test-ignored:
@cargo nextest run --workspace --features mockls --run-ignored ignored-only --status-level all --final-status-level all --no-capture $(if $(T),-E 'test($(CLEAN_T))',)
test:
@cargo nextest run --workspace --features mockls --status-level fail --final-status-level slow --cargo-quiet $(if $(N),--stress-count $(N),) $(if $(T),$(if $(findstring !,$(T)),-E 'not test($(CLEAN_T))',-E 'test($(T))'),)
pre-release-check:
@echo "Checking release prerequisites..."
@ @if [ -n "$$(git status --porcelain)" ]; then \
echo "Error: Working tree is not clean. Commit or stash changes first."; \
exit 1; \
fi
@ @if [ "$$(git branch --show-current)" != "main" ]; then \
echo "Error: Not on main branch."; \
exit 1; \
fi
@ @git fetch origin main --quiet
@if [ "$$(git rev-parse HEAD)" != "$$(git rev-parse origin/main)" ]; then \
echo "Error: Local main is not up to date with origin/main."; \
exit 1; \
fi
@echo "Prerequisites OK."
bump-version:
@if [ -z "$(V)" ]; then \
echo "Error: Version not specified. Use V=x.y.z"; \
exit 1; \
fi
@echo "Bumping version: $(CURRENT_VERSION) -> $(V)"
@ @sed -i 's/^version = "$(CURRENT_VERSION)"/version = "$(V)"/' Cargo.toml
@ @sed -i 's/"version": "$(CURRENT_VERSION)"/"version": "$(V)"/' .claude-plugin/marketplace.json
@ @sed -i 's/"version": "$(CURRENT_VERSION)"/"version": "$(V)"/' gemini-extension.json
@ @cargo check --quiet
@echo "Version bumped to $(V)"
next-patch:
$(eval V := $(shell echo $(CURRENT_VERSION) | awk -F. '{print $$1"."$$2"."$$3+1}'))
next-minor:
$(eval V := $(shell echo $(CURRENT_VERSION) | awk -F. '{print $$1"."$$2+1".0"}'))
next-major:
$(eval V := $(shell echo $(CURRENT_VERSION) | awk -F. '{print $$1+1".0.0"}'))
release: pre-release-check
@if [ -z "$(V)" ]; then \
echo "Error: Version not specified. Use 'make release V=x.y.z' or 'make release-patch'"; \
exit 1; \
fi
@cargo update --quiet
@$(MAKE) bump-version V=$(V)
@if ! $(MAKE) check; then \
echo "Checks failed. Rolling back version bump..."; \
git checkout HEAD -- Cargo.toml Cargo.lock .claude-plugin/marketplace.json gemini-extension.json; \
exit 1; \
fi
@git add Cargo.toml Cargo.lock .claude-plugin/marketplace.json gemini-extension.json
@if ! git commit -m "chore: Bump version to $(V)"; then \
echo "Commit failed. Rolling back version bump..."; \
git checkout HEAD -- Cargo.toml Cargo.lock .claude-plugin/marketplace.json gemini-extension.json; \
exit 1; \
fi
@git tag -a "v$(V)" -m "Release v$(V)"
@echo ""
@echo "Release v$(V) prepared locally."
@echo "Run 'make publish' to build, push, and create the release."
release-patch: pre-release-check next-patch
@$(MAKE) release V=$(V)
release-minor: pre-release-check next-minor
@$(MAKE) release V=$(V)
release-major: pre-release-check next-major
@$(MAKE) release V=$(V)
publish:
@echo "Pushing to origin..."
@git push && git push --tags
@echo ""
@echo "Release v$(CURRENT_VERSION) pushed. CD workflow will build and publish."
tag-current:
@if git rev-parse "v$(CURRENT_VERSION)" >/dev/null 2>&1; then \
echo "Tag v$(CURRENT_VERSION) already exists."; \
exit 1; \
fi
@echo "Creating tag v$(CURRENT_VERSION) for current version..."
@git tag -a "v$(CURRENT_VERSION)" -m "Release v$(CURRENT_VERSION)"
@echo "Tag created. Run 'make publish' to build and release."
version:
@echo "Current version: $(CURRENT_VERSION)"
@echo "Latest tag: $$(git describe --tags --abbrev=0 2>/dev/null || echo 'none')"
@echo ""
@echo "Version in files:"
@grep -H 'version' Cargo.toml | head -1
@grep -H 'version' .claude-plugin/marketplace.json | grep -v schema
@grep -H 'version' gemini-extension.json