The new CI server doesn't have Docker daemon running by default,
causing buildx setup to fail with:
ERROR: failed to connect to the docker API at unix:///var/run/docker.sock
This fix:
- Adds explicit Docker daemon startup check and initialization
- Configures buildx with docker-container driver
- Adds install: true to ensure proper buildx installation
This was already fixed in build-deploy.yml (commit 54280fd7) but
was missing from production.yaml.
Reviewed-on: graham/towerops-web#57
The styfle/cancel-workflow-action is not compatible with Forgejo Actions,
causing failures with 'Cannot read properties of undefined (reading id)'.
The pr-tests.yaml workflow already has concurrency control that cancels
in-progress runs when new commits are pushed, which handles most cases.
Removing this workflow to eliminate CI errors.
Reviewed-on: graham/towerops-web#38
The cancel-workflow-action requires an access_token to query and cancel
running workflows. Without it, the action fails with 'Cannot read properties
of undefined' error when trying to access workflow information.
Reviewed-on: graham/towerops-web#36
- Updated .tool-versions to use Node 22.17.1
- Updated CI workflow to use Node 22
- Rebuilt package-lock.json with Node 22
- Fixes engine compatibility warnings from @noble/hashes
The if: success() might be causing issues with Forgejo's secret handling.
Jobs with 'needs' automatically wait for dependencies to succeed, making
the condition redundant.
Playwright config:
- Added chromium-unauthenticated project for registration/login tests
- These tests run without saved auth state (as intended)
- Other tests continue using authenticated state
Workflow:
- build-and-deploy now only requires test-exunit to pass
- test-e2e runs in parallel but doesn't block deployment
- Allows faster deployments while e2e tests provide additional validation
Created seeds_e2e.exs to automatically create a test user with TOTP enabled
for Playwright e2e tests. This ensures tests can authenticate in CI without
requiring manual user setup.
Test credentials (for CI only):
- Email: test@example.com
- Password: TestPassword123!
- TOTP Secret: JBSWY3DPEHPK3PXP (fixed for reproducibility)
The workflow now:
1. Loads database structure
2. Seeds test user with TOTP
3. Passes credentials to e2e tests via environment variables
- Run ldconfig after installing OpenSSL packages
- Add verification steps to check OpenSSL installation
- Should resolve 'libcrypto.so.1.1: cannot open shared object file' error
Simplified CI/CD to two workflows:
- staging.yaml: Deploys to Dokku on main push (no tests)
- production.yaml: Full test suite + deploy on production push
Main branch deploys immediately to staging for fast iteration.
Production branch has comprehensive test gates before deployment.
E2E tests now only run before production deploys for faster feedback:
- test.yaml (main branch): ExUnit, formatting, Credo only
- staging.yaml (main branch): Immediate Dokku deploy
- production.yaml (production branch): Full test suite including e2e
This allows staging to deploy quickly while ensuring production
has comprehensive test coverage including browser automation.
- Renamed test.yml → test.yaml
- Renamed production.yml → production.yaml
- Split build.yaml into staging.yaml (Dokku only)
- Removed duplicate production build from build.yaml
Production deployments now use production.yaml which includes:
- Test gates (ExUnit + e2e tests must pass)
- Docker build and push
- k8s deployment.yaml update
- FluxCD auto-deployment
Staging deployments use staging.yaml:
- Deploys to Dokku on push to main
- No test gates (tests run via test.yaml)
This eliminates the duplicate production builds that were running
from both build.yaml and production.yml simultaneously.
FluxCD Changes:
- Updated GitRepository resource to watch 'production' branch instead of 'main'
- Deployment now automatically pulls from production branch where CI updates image tags
CI Changes:
- Added libssl-dev to system dependencies in both test.yml and production.yml
- Fixes "libcrypto.so.1.1: cannot open shared object file" error in CI runners
This ensures production deployments work end-to-end:
1. Push to production branch triggers CI
2. CI tests pass, builds image, updates k8s/deployment.yaml
3. FluxCD detects change in production branch and applies to cluster
Adds Forgejo Actions CI/CD workflows:
Production deployment (.forgejo/workflows/production.yml):
- Runs on push to 'production' branch
- Test gates (must pass before deploy):
* All ExUnit tests with coverage
* All e2e Playwright tests
- Only deploys if both test suites pass
- Builds Docker image
- Pushes to git.mcintire.me registry
- Updates k8s/deployment.yaml with new image tag
- FluxCD auto-applies changes
Main branch testing (.forgejo/workflows/test.yml):
- Runs on push to 'main' or pull requests
- Runs ExUnit tests with coverage
- Runs e2e tests
- No deployment (staging still via Dokku)
Updated CLAUDE.md with CI/CD pipeline documentation.
- main branch: auto-deploy to Dokku staging
- production branch: build Docker image and deploy to K8s production
- Add DEPLOYMENT.md with workflow documentation
- Create production branch for manual production deployments
Breaking change: pushing to main no longer deploys to production
Tests are still enforced locally via precommit hooks (mix precommit).
CI now only:
- Builds Docker image
- Pushes to registry
- Updates deployment
Expected CI time: 10-12 minutes (down from 26 minutes)
Trade-off: Faster CI feedback vs relying on local testing before push.
Eliminates duplicate job overhead:
- No separate job startup time
- No duplicate code checkout
- No runner scheduling delay
- Runs sequentially in same environment
Docker build still compiles from scratch (Docker isolation) but saves ~2-3min
in job overhead. Next step: optimize Dockerfile for better layer caching.
Removes:
- Separate compile/quality/test jobs
- Format and Credo checks
- Artifact upload/download between jobs
Now:
- Single test job that compiles and tests
- Build job runs after test passes
- All caching preserved for performance
- Compile with warnings-as-errors still enforced
Add 'mix deps.get --only test' to quality and test jobs after
downloading artifacts to ensure dependencies are current and
prevent 'lock mismatch' errors.
Fast when deps cached, but ensures consistency across all jobs.
Issue: Credo failed with 'lock mismatch' errors because deps.get was
skipped when cache hit, but dependencies were out of date
Fix: Remove cache-hit conditional from deps.get step
- mix deps.get is fast when deps are already downloaded
- Ensures mix.lock is always respected
- Prevents dependency mismatch errors in quality checks
Health Check Logging:
- Update TelemetryFilter to catch both request and response logs
- Filter /health and /health/time endpoints completely
- Check phoenix_log metadata to suppress response logs
- Prevents log flooding from Kubernetes probes (every 5s)
- Refactor to reduce cyclomatic complexity (Credo compliant)
CI Artifact Actions:
- Downgrade upload-artifact from v4 to v3
- Downgrade download-artifact from v4 to v3
- v4 is not supported on Forgejo/GHES
Fixes:
- Production logs no longer flooded with health check entries
- CI pipeline works on self-hosted Forgejo instance
Replace sequential migration execution (4m8s for 172 migrations) with
structure.sql loading (416ms), reducing CI database setup time by 99.7%.
Changes:
- Configure Ecto to dump/load schema from priv/repo/structure.sql
- Update test alias: ecto.migrate → ecto.load
- Remove redundant database setup step from CI workflow
- Commit structure.sql to repository for version control
Benefits:
- CI database setup: 4m8s → 416ms (248s → 0.4s)
- Consistent schema snapshots across environments
- Faster local test runs
Maintenance:
- Run 'mix ecto.dump' after adding new migrations
- Structure file auto-updates with schema changes
- Add init container to run migrations before app starts
- Uses /app/bin/migrate script (runs Towerops.Release.migrate())
- Migrations run once per deployment, before any pods start
- Update CI/CD to set both migrate and towerops container images
- Prevents issues like missing severity column in production