- 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
- Test empty activity list
- Test preseem sync logs with correct DateTime format
- Test duration formatting with integer precision
- Test sync logs without duration
- Test grouping by minute
- Test sorting by timestamp descending
- Test limit parameter
- Test date range filtering
- Test organization isolation
- Test different sync statuses (success, failed, partial)
- Test count_by_type functionality
- date_trunc fragment returns NaiveDateTime without timezone
- Convert to UTC DateTime before returning from preseem sync query
- Fixes DateTime.compare/2 function clause error when sorting activities
- All activity timestamps now consistently use DateTime with timezone
- PostgreSQL's max() function doesn't work on UUID types
- Use array_agg to get first ID from grouped results instead
- Matches pattern already used for status field
- Fixes crash on /activity page when preseem sync logs exist
- Accept both sk_test_ and sk_live_ API keys
- Show mode indicator (TEST/LIVE) in output
- Adjust webhook URL based on mode (localhost for test, towerops.net for live)
- Add warning when using test mode
- Useful for testing billing setup before going live
- Update grep patterns to match JSON with spaces after colons
- Fixes false 'Error creating meter' message when meter created successfully
- Applies to meter ID and price ID extraction
- First check if a meter with 'devices_monitored' event exists
- Reuse existing meter ID if found
- Only create new meter if none exists
- Fixes error when meter already exists in Stripe account
- Interactive script to create production billing meter and price
- Prompts for live API key and product ID
- Creates billing meter with 'devices_monitored' event
- Creates metered price at $1/device/month
- Outputs kubectl command for creating k8s secret
- Includes setup instructions for webhook configuration
- Add stripe_meter_id to dev, runtime, and test configs
- Add STRIPE_METER_ID to k8s deployment secret references
- Use real Stripe meter and price IDs from Stripe setup
- Meter: mtr_test_61UHPU067veEZ7bhl41S77kvnTfgyODY
- Price: price_1T81XBS77kvnTfgyPlw1jF8N ($1/device/month)
- Include setup script for Stripe billing configuration
- Changed from hardcoded placeholder values to secretKeyRef
- References towerops-billing secret (with optional: true)
- Won't crash if secret doesn't exist yet
- User can create secret later with real Stripe keys
- Add Stripe test API keys to dev.exs for local development
- Add placeholder Stripe env vars to k8s deployment to prevent startup crashes
- Includes secret_key, webhook_secret, and price_id configuration
Implements Phase 6 of Stripe billing integration:
- Add Billing tab to organization settings page
- Display subscription status, device usage, and estimated costs
- "Upgrade to Paid Plan" button for free tier orgs
- "Manage Billing" button to access Stripe Customer Portal
- Billing information panel showing subscription details
- Support for dark mode and responsive design
Also fixes organization name truncation in top navigation:
- Long organization names now show with ellipsis instead of being cut off
- Added max-w-xs constraint and truncate class to org switcher button
Reduce Process.sleep delays in event_logger_test from 25ms to 10ms.
These sleeps wait for async event logging to complete.
All tests still pass with shorter delay.
Reduce various test timeouts that were unnecessarily long:
- assert_push timeouts: 150ms → 75ms (6 tests in agent_channel_test)
- refute_receive timeouts: 200ms → 50ms (3 tests in worker tests)
With 50ms channel debounce, 75ms is sufficient for assert_push.
For refute_receive (expecting no message), 50ms is plenty.
Estimated savings: ~600ms across affected tests
Make the 500ms device deletion delay configurable via application config.
Set to 10ms in test environment (vs 500ms in production).
This sleep waits for in-flight polling jobs to complete before deleting
a device. In tests with mocked jobs, this delay is unnecessary.
Affected tests:
- All device deletion tests (were 500-650ms, now ~100-150ms)
- Equipment context tests
- API controller tests
- LiveView tests with device deletion
Performance: 28.3s → 25.2s (11% faster)
Total improvement from baseline: 52s → 25.2s (51.5% faster)
- Remove all 25ms and 50ms sleeps from agent_channel_test
- Add poll_until helper for async DB operations (early exit on success)
- Reduce timeout test sleeps from 100ms to 60ms
- Reduce polling delays from 10ms to 5ms in multiple tests
- Remove unnecessary timestamp and background task sleeps
- Reduce circuit breaker recovery sleep from 150ms to 110ms
Performance: 30.3s → 28.3s (6.6% faster)
Total improvement from baseline: 52s → 28.3s (45.6% faster)
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.
The FilterNoisyLogs plug wasn't completely preventing logs in Phoenix 1.8.
Added metadata_filter to Plug.Telemetry to explicitly skip logging for:
- GET /health
- GET /health/time
- HEAD /
This works at the Telemetry level before logs are emitted.
- Set MIX_OS_DEPS_COMPILE_PARTITION_COUNT to 3 (match available cores)
- Enable Erlang JIT perf improvements
- Remove redundant hex/rebar installation calls (already done earlier)
This won't eliminate Docker compile time but should make better use of
the 3 available cores. Estimated savings: 1-2 minutes on build.
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.
My changes added database queries for stuck alert resolution on every poll,
which slightly increased processing time. Increased timeouts from 500ms to 1000ms
and 100ms to 200ms to account for this.
Previous fix only resolved alerts when device status changed from down to up.
This didn't help devices already marked as 'up' with stuck unresolved alerts.
Now:
- Always check for stuck device_down alerts after successful SNMP poll
- Also check for stuck device_up alerts (should always be auto-resolved)
- Logs when stuck alerts are found and resolved
- Works for existing stuck alerts without waiting for status to change
This fixes the 8 stuck alerts in production - they'll auto-resolve on next poll.
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