Replace the image-only tag pipeline with a full release workflow that also
publishes a Gitea Release whose body is the annotated tag's message,
generated from Conventional Commits by git-cliff. No hand-written release
notes are required.
- cliff.toml: group commits (Features, Bug Fixes, Refactor, Documentation,
Tests, Miscellaneous Tasks) with scopes and short-SHA links; emit only the
current tag's section rather than the full history.
- .gitea/workflows/release.yml: tag-driven. Reads the release body from the
annotated tag (git tag -l --format), so the tag message and release body are
a single source of truth. Idempotent create/PATCH; prints the Gitea API
error body on failure so a 403 names the missing token scope instead of
failing silently. Adds a workflow_dispatch tag input so manual re-runs
target the right tag instead of the default branch.
- Makefile: release VERSION=vX.Y.Z generates notes via git cliff --latest
against a throwaway tag, then creates an annotated tag with
--cleanup=verbatim so the markdown group headers are preserved (git's
default cleanup strips lines starting with "#").
- release: project-attached wrapper accepting a positional version arg
(./release 0.3.0 or ./release v0.3.0) and auto-prefixing v, for ergonomic
one-command releases.
Restructure the container setup to support registry-based deployment:
the default docker-compose.yml now pulls a prebuilt app image from the
Gitea container registry instead of building locally, while a new
docker-compose.dev.yml override preserves the local build + integration
test workflow for development.
Why:
- Production and self-hosting should consume a published image, not
rebuild from source on the host. The default `docker compose up` now
pulls the app image (git.linuxhg.com/bookhoard/bookhoard) alongside the
public postgres image, with no build step required.
- Development still needs to build from source and run integration
tests, so those concerns move to an override file the Makefile applies.
Shared config (env, volumes, ports, healthchecks) lives in one place to
avoid drift between environments.
Changes:
- docker-compose.yml (prod base): the app service now references
`image: git.linuxhg.com/bookhoard/bookhoard:${IMAGE_TAG:-latest}` instead
of a build context. The tests service is removed (moved to the
override). IMAGE_TAG lets deployers pin or roll back a specific version.
- docker-compose.dev.yml (new override): adds the local `build:` context
for the app and defines the integration `tests` service (profile-gated).
Everything else is inherited from the base file via compose merging.
- Makefile: introduce a COMPOSE variable that merges the base and
override (`-f docker-compose.yml -f docker-compose.dev.yml`); all dev
targets now use it. Plain `docker compose` against the base file only
remains the production path.
- README: quickstart updated to pull and start prebuilt images; clone URL
points at the Gitea instance.
The development workflow (`make rebuild-app`, `make test-integration`,
etc.) is functionally unchanged.
Replace hardcoded 'podman' with auto-detected CONTAINER_RUNTIME variable
that prefers docker and falls back to podman. Override with:
CONTAINER_RUNTIME=podman make rebuild-app
Remove the ensure_healthy and compose_up macros that worked around
podman-compose hanging on non-systemd systems (e.g., Void Linux with
runt). These are no longer needed — healthchecks are now handled by
plain wait loops in the targets themselves, and compose up -d no longer
blocks on health conditions.
Podman relies on systemd timers to schedule automatic healthchecks. On
non-systemd systems (e.g., Void Linux with runit), healthchecks never
fire, which causes podman-compose to hang forever waiting for
service_healthy conditions that never resolve.
Add two Make macros to handle this transparently:
- compose_up: runs podman compose up -d normally on systemd, but with
a 15-second timeout on non-systemd to create containers without
hanging. Supports passing compose flags via $(call compose_up,args).
- ensure_healthy: on non-systemd systems, waits for the database to
accept connections, manually triggers its healthcheck, starts the app
container, waits for the app health endpoint, and triggers its
healthcheck. On systemd systems, the runtime check is skipped entirely
(zero overhead).
Both macros use a runtime shell check for /run/systemd/system, so the
same Makefile works identically on all systems without parse-time
conditionals.
Applied to all compose-up targets: up, rebuild, rebuild-force,
rebuild-force-db, rebuild-app, rebuild-app-force, test-integration,
and test-env-up.
Refs: https://github.com/containers/podman/pull/27033
-- Rename 'build' to 'rebuild' for clarity (rebuilds all containers)
-- Rename 'build-force' to 'rebuild-force' for consistency
-- Add 'rebuild-app-force' target for app-only rebuild without cache
-- Add 'rebuild-force-db' target that DELETES database for clean rebuild
-- Improve help text to clarify what each target does
-- Remove circular dependency (rebuild no longer depends on clean)
-- All rebuild targets now preserve database unless explicitly stated
Add --force-recreate flag to all build targets that create containers:
- build: Force recreation when building all containers
- rebuild-app: Force recreation of app container only (fixes template update issue)
- build-force: Force recreation even when using --no-cache
- test-env-up: Force recreation in test environment
This fixes a critical issue where 'make rebuild-app' would build a new image
but continue running the old container, causing template changes to not appear.
Root cause: podman-compose up --build doesn't recreate containers if they're
already running, even when a new image is built. The --force-recreate flag
ensures containers are recreated with the new image.
BuildKit caching still works as expected - cache is used during image build,
while --force-recreate ensures the new image is actually deployed.
Changes:
- build: Add --force-recreate flag
- rebuild-app: Add --force-recreate flag, update success message
- build-force: Add --force-recreate flag
- test-env-up: Add --force-recreate flag
Verified: Template changes now appear immediately after rebuild.
- Optimize Dockerfile layer caching with --mount=type=cache for Go modules and npm
- Reorganize Dockerfile layers for better cache hit rates
- Improve .dockerignore organization with categorized comments
- Add Makefile targets: up, down, rebuild-app, restart, ps
- Enhance Makefile help output with categorized sections
- Add test-runner stage to Dockerfile for isolated test execution
- Refactor Makefile test targets: separate unit and integration tests
- Unit tests now run on host (fast, no containers required)
- Integration tests run in containers matching production environment
- Add dedicated 'tests' service to docker-compose.yml
- Update test-integration target to use containerized test runner
- Improve service health checks and wait conditions
- Add test environment variables for consistent testing
This change separates unit tests (fast, local) from integration tests
(full environment, containerized) for better developer experience
and more reliable CI/CD pipelines.
- Add .env file inclusion for single source of truth
- Update test-integration to build and start all containers
- Add health check waiting for database and application
- Run tests from host against containerized database
- Add test-stop target for manual container cleanup
- Improve help text for better clarity
Makefile Integration:
- Add make verify-quick target for critical-only checks
- Fix verify-guidelines target to call comprehensive script
- Clear separation of usage patterns
AI Behavior Protocol:
- Add comprehensive AI instructions to both scripts
- Enhanced error/warning functions with AI reminders
- Multi-layered safeguards prevent automatic fixing
- Protocol applies to ALL file modifications
verify-quick.sh Enhancements:
- Basic documentation structure validation
- API content placement detection in README.md
- Maintains fast performance for development
Documentation:
- Comprehensive scripts/README.md with usage guidelines
- Bruno API tests validation explained
- Troubleshooting and compliance sections
- Clear AI protocol instructions and examples
This provides dual-script approach: fast critical checks during development,
comprehensive validation for pre-commit/CI, with AI safety across all operations.
Created comprehensive verification script to check codebase against PROJECT_GUIDELINES.md
Features:
- Checks for custom CSS (TailwindCSS requirement)
- Detects JavaScript files that should be TypeScript
- Verifies no secrets committed (.env, credentials.json)
- Validates code compiles (go build)
- Finds local binaries (should use container builds)
- Quick checks with clear pass/fail/warning output
Usage:
make verify-guidelines
./scripts/verify-quick.sh
Current codebase status:
- 12 templates with custom CSS (need Tailwind conversion)
- 2 .js files in web/static/ (need TypeScript conversion)
- 1 binary file (./bookhoard)
This addresses the trust issue: AI now has a tool to prove guideline compliance
- Add Makefile with convenient test targets (test, test-integration, test-env-up, test-env-down)
- Add .env.test with test-specific configuration
- Update .env.example with test configuration options and warnings
- Update README.md with comprehensive testing documentation
- Document all environment variables with safety warnings
This makes it easy to run tests without rate limiting issues while
keeping production security intact.