Commit graph

93 commits

Author SHA1 Message Date
2a84df471d fix: use legacy Docker build to avoid permission errors in CI (#206)
- Replace BuildKit with legacy docker build (DOCKER_BUILDKIT=0)
- Use plain docker login instead of docker/login-action
- Remove BuildKit setup action entirely
- Works with VFS storage driver on unprivileged runners

Reviewed-on: graham/towerops-web#206
2026-03-28 12:16:20 -05:00
a3cdf02114 fix/remove-gleam-dockerfile-refs (#204)
Reviewed-on: graham/towerops-web#204
2026-03-28 12:09:01 -05:00
efaf5558ff refactor: convert 6 Gleam modules to idiomatic Elixir with TDD (#196)
Phase 1: Foundation Types (100% complete)
- query_helpers: SQL LIKE sanitization with pipe operators
- numeric: Integer parsing with pattern matching guards
- result: Pure Elixir Result monad (map, and_then, unwrap_or)

Phase 2: Ecto Domain Types (100% complete)
- ip_address: IPv4/IPv6 validation using :inet directly
- mac_address: Multi-format MAC parsing (colon/hyphen/dot/compact)
- snmp_oid: OID parsing/manipulation with recursive pattern matching

All 198 tests passing across converted modules.
API changed from Gleam-style {:some/:none to idiomatic {:ok/:error.
Refactored parse_numeric_oid to use with statement, reducing nesting depth.

Reviewed-on: graham/towerops-web#196
2026-03-28 09:52:07 -05:00
7606efc635 fix: use docker-container buildx driver to resolve mount permission errors (#191)
The production deployment was failing with "operation not permitted" errors
when BuildKit tried to perform bind mounts during Docker image builds.

Root cause:
- The workflow starts Docker with --storage-driver=vfs for unprivileged runners
- VFS storage driver doesn't support the advanced mount operations needed by BuildKit
- The Dockerfile uses --mount=type=cache for build performance
- Using buildx driver=docker tried to use the daemon's VFS storage directly

Solution:
- Switch to driver=docker-container which runs BuildKit in an isolated container
- This container has its own storage layer that properly supports BuildKit features
- BuildKit container uses overlay2 internally regardless of host storage driver

This is the recommended approach for CI/CD environments with storage limitations.

Reviewed-on: graham/towerops-web#191
2026-03-27 13:44:22 -05:00
f703e61b12 fix: code quality improvements and test reliability (#139)
Various code quality improvements and fixes:

- Settings: return error instead of auto-creating unknown settings
- PagerDuty: proper backoff timing with to_timeout()
- Gaiia sync: remove unnecessary transaction wrapper
- HTTP/UISP: simplify test plug setup
- Agent channel: tagged tuple config for check types
- SNMP: fix Task.yield/shutdown pattern, remove stale preload
- Discovery: simplify error handling
- Tests: bump executor timeouts for CI reliability
- Dockerfile: remove unnecessary --force compile
- Renovate/CI: config cleanup

Split from #135.

Reviewed-on: graham/towerops-web#139
2026-03-24 09:12:59 -05:00
fbbd3402b3 chore: skip staging deploy for Renovate PRs (#124)
Dependency update PRs from Renovate don't need to be deployed to
staging. Uses job-level condition to check head branch prefix.

Reviewed-on: graham/towerops-web#124
2026-03-23 09:58:48 -05:00
e54ee75513 Rewrite protobuf encoding/decoding in pure Gleam with integrated validation (#104)
Replace the protobuf hex package (agent.pb.ex) and hand-written validator
(validator.ex) with a pure Gleam implementation: wire format primitives,
all 23 message types, encode/decode functions, and validation merged into
decode. Thin Elixir wrappers in agent.ex preserve the existing struct API.

- Wire format: varint, length-delimited, double (IEEE 754 via FFI), tag encode/decode
- Types: all proto3 message types as Gleam custom types with enums and oneof
- Decode: field-level parsing with integrated validation (UUID, IP, hostname, limits)
- Encode: proto3 default omission, bytes_tree concatenation, map/repeated fields
- Wrappers: Elixir structs with encode/decode delegating to Gleam, enum atom conversion
- Remove {:protobuf, "~> 0.12"} dependency

Reviewed-on: graham/towerops-web#104
2026-03-21 16:08:40 -05:00
6859525a1b Integrate Gleam into the build pipeline and rewrite three pure-function modules (#98)
Set up mix_gleam archive, gleam_stdlib, and gleeunit deps. Add Gleam
compiler to all Dockerfiles, CI workflows, nix shell, and .tool-versions.

Rewrite Numeric, QueryHelpers, and URLValidator from Elixir to Gleam with
full ExUnit test coverage. Update all callers to use the Gleam modules
directly via :towerops@module syntax. Remove duplicate sanitize_like/1
private functions in snmp.ex and trace.ex.

Reviewed-on: graham/towerops-web#98
2026-03-21 07:30:36 -05:00
3c935ed56e e2e-workflow-separate (#67)
Reviewed-on: graham/towerops-web#67
2026-03-17 16:30:45 -05:00
f897b32999 Separate E2E tests into manual workflow (#66)
Moves e2e tests from production workflow into a separate workflow that requires manual triggering. This allows e2e tests to be run on-demand without blocking production deployments.

Changes:
- Created new .forgejo/workflows/e2e-tests.yaml with workflow_dispatch trigger
- Removed disabled e2e job from production.yaml workflow
- E2E tests can now be triggered manually from Actions tab with browser selection (all, chromium, firefox, webkit)
- Test results and videos uploaded as artifacts on all runs

Reviewed-on: graham/towerops-web#66
2026-03-17 16:26:41 -05:00
0f9ce9b711 feat/ssl-certificate-check (#65)
Reviewed-on: graham/towerops-web#65
2026-03-17 16:21:44 -05:00
b724aa4ab8 remove docker build cache options for docker driver (#62)
The docker buildx driver (required on unprivileged ci runner) does not
support registry cache export/import. Remove cache-from and cache-to
options to unblock builds.

Reviewed-on: graham/towerops-web#62
2026-03-17 13:40:54 -05:00
f4e75689d4 fix docker on unprivileged ci: use vfs storage driver (#61)
overlayfs requires mount/unmount capabilities not available on the
unprivileged ci runner. Switch to vfs storage driver and use buildx
docker driver (not docker-container) to avoid nested mount issues.

Reviewed-on: graham/towerops-web#61
2026-03-17 13:34:53 -05:00
cd19db0680 fix-sticky-header-overlap (#60)
Reviewed-on: graham/towerops-web#60
2026-03-17 13:21:58 -05:00
b03f280b65 fix-ci-docker (#59)
Co-authored-by: Forgejo Actions <actions@git.mcintire.me>
Reviewed-on: graham/towerops-web#59
2026-03-17 13:13:09 -05:00
f807eb1e78 fix: add Docker daemon startup to production workflow (#57)
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
2026-03-17 11:02:49 -05:00
0154da18fe remove: cancel-on-merge workflow (#38)
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
2026-03-15 18:48:18 -05:00
dcf2a2500f fix: add access token to cancel-workflow-action (#36)
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
2026-03-15 18:39:25 -05:00
b8e56ee88c ci-stop-tests-on-merge (#33)
Reviewed-on: graham/towerops-web#33
2026-03-15 18:21:59 -05:00
b183351933
ci: compile C NIF before tests to avoid warnings 2026-03-15 16:51:39 -05:00
9fffa28b00
ci: add ExUnit test workflow for pull requests 2026-03-15 16:41:35 -05:00
fbcf7ee1ae
chore: upgrade Node.js from 20.13.1 to 22.17.1 (LTS)
- 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
2026-03-10 10:35:22 -05:00
b969a0fe6e
ci: temporarily disable e2e tests in production workflow 2026-03-10 10:01:32 -05:00
0943df9956
fix: use correct secret names for container registry login 2026-03-08 14:57:47 -05:00
28c8e6f9ae
fix: remove redundant if: success() condition from deploy job
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.
2026-03-08 14:14:16 -05:00
8fd18b08ab
fix: run auth tests unauthenticated, deploy on ExUnit pass only
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
2026-03-08 13:46:34 -05:00
a102918455
feat: add e2e test user seeding for CI
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
2026-03-08 10:57:18 -05:00
0694f724e1
debug: increase startup wait and show full logs on failure 2026-03-08 09:00:34 -05:00
280ac70c1a
perf: use ecto.load instead of ecto.migrate for faster e2e database setup 2026-03-07 16:39:44 -06:00
4665ee6b53
fix: show Phoenix logs after startup delay 2026-03-07 16:38:59 -06:00
51e35182c1
fix: capture and display Phoenix startup logs in e2e tests 2026-03-07 16:24:08 -06:00
ffc937821c
fix: fetch dokku refs before force push to prevent race condition 2026-03-07 16:10:04 -06:00
04c6bcc2d2
fix: cleanup buildx builders after jobs 2026-03-07 15:15:58 -06:00
5257b2ff34
perf: run test-exunit and test-e2e in parallel 2026-03-07 15:02:17 -06:00
abcca08f0b
fix: upgrade to PostgreSQL 17 for transaction_timeout support 2026-03-07 14:27:43 -06:00
4acf0d5248
fix: use DATABASE_URL instead of DATABASE_HOST 2026-03-07 14:02:23 -06:00
24cfbc44af
fix: set DATABASE_HOST at job level for all steps 2026-03-07 13:39:36 -06:00
d1591d3e6c
perf: add comprehensive caching to production workflow 2026-03-07 13:21:47 -06:00
1b606534c5
fix: set DATABASE_HOST for compile step 2026-03-07 13:16:27 -06:00
d0fe39b0af
fix: remove libssl1.1 for ubuntu-22.04 compatibility 2026-03-07 13:01:29 -06:00
16a9657807
fix: use ubuntu-22.04 for production workflow 2026-03-07 12:56:19 -06:00
f88050203b
fix: refresh library cache after OpenSSL install in CI
- 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
2026-03-07 12:52:13 -06:00
db96845250
refactor: remove test.yaml workflow
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.
2026-03-07 12:45:19 -06:00
d52ab0eceb
refactor: remove e2e tests from main branch CI
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.
2026-03-07 12:44:23 -06:00
40b3ea87f2
refactor: consolidate workflows and rename to .yaml extension
- 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.
2026-03-07 12:40:41 -06:00
5e0ac897f3
fix: add full OpenSSL 1.1 packages to CI for ubuntu-20.04 compatibility
- Added openssl and libssl1.1 packages alongside libssl-dev
- Fixes 'libcrypto.so.1.1: cannot open shared object file' error
- Required for Erlang crypto library on ubuntu-20.04 runners
2026-03-07 12:32:49 -06:00
834cb7d95a
fix: configure FluxCD to use production branch and add OpenSSL deps to CI
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
2026-03-07 12:17:31 -06:00
480f8b17c5
fix: use full GitHub URLs for Forgejo Actions
Forgejo Actions runner can't find actions in its mirror registry.
Changed all action references from short names to full GitHub URLs:
- actions/checkout@v4 → https://github.com/actions/checkout@v4
- erlef/setup-beam@v1 → https://github.com/erlef/setup-beam@v1
- actions/cache@v4 → https://github.com/actions/cache@v4
- actions/setup-node@v4 → https://github.com/actions/setup-node@v4
- actions/upload-artifact@v4 → https://github.com/actions/upload-artifact@v4
- docker/* actions → https://github.com/docker/*

This fixes the 'repository not found' errors when Forgejo tries
to clone actions from data.forgejo.org.
2026-03-06 17:52:15 -06:00
f68b828c8f
ci: add test gates for production deployments
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.
2026-03-06 17:40:50 -06:00
2ae7a2680a
fix: clear stale Dokku deploy lock before pushing
cancel-in-progress kills the CI job mid-deploy but Dokku's server-side
lock persists, causing subsequent deploys to hang indefinitely.
2026-03-06 13:06:18 -06:00