How to Monitor Credo with Vigilmon
Credo is the code quality guardian for Elixir projects. It checks for consistency issues, anti-patterns, refactoring opportunities, and style violations across your entire codebase — giving every PR a uniform quality gate before it reaches review.
The problem is that static analysis is easy to accidentally skip. A .credo.exs configuration change can silently disable checks. A --ignore flag slips into a script. A CI step is commented out to fix a flaky build and never re-enabled. When Credo stops running, code quality degrades invisibly — and you only notice months later when the codebase has accumulated significant technical debt.
Vigilmon heartbeat monitors alert your team the moment Credo checks go dark.
Why Monitor Credo?
Credo catches issues humans miss in review:
- Cyclomatic complexity — functions that branch too many ways and become untestable
- Pipe chain abuse — pipes that break the
|>contract by taking multiple arguments mid-chain - Unused variables and aliases — dead code accumulation that confuses future readers
- Inconsistent module naming — conventions that diverge and make the codebase harder to navigate
- Missing documentation — public modules without
@moduledocor@docattributes
But those checks only help if they run on every commit. Monitoring Credo's CI integration ensures the quality gate is always active.
Key Metrics to Track
| Metric | What it tells you | |--------|-------------------| | Credo CI step pass rate | Whether quality checks are running and passing | | Issue count trend | Whether technical debt is growing or shrinking over time | | Check categories failing | Which types of issues (consistency, readability, warning) are accumulating | | Time since last Credo run | Whether the check has been silently disabled | | Strict mode pass/fail | Whether stricter enforcement is achievable |
Step 1: Add Credo to Your Project
# mix.exs
defp deps do
[
{:credo, "~> 1.7", only: [:dev, :test], runtime: false},
# rest of your deps
]
end
mix deps.get
mix credo gen.config
The generated .credo.exs gives you a starting point you can tune per project. The defaults catch the most impactful issues immediately.
Step 2: Configure Credo for CI
Create a strict CI configuration alongside your development config:
# .credo.ci.exs
%{
configs: [
%{
name: "ci",
files: %{
included: ["lib/", "test/"],
excluded: ["test/support/"]
},
strict: true,
color: false,
checks: %{
enabled: [
{Credo.Check.Consistency.ExceptionNames, []},
{Credo.Check.Consistency.LineEndings, []},
{Credo.Check.Consistency.MultiAliasImportRequireUse, []},
{Credo.Check.Design.AliasUsage, [priority: :low, if_nested_deeper_than: 2]},
{Credo.Check.Readability.ModuleDoc, []},
{Credo.Check.Refactor.CyclomaticComplexity, [max_complexity: 9]},
{Credo.Check.Warning.UnusedEnumOperation, []},
{Credo.Check.Warning.UnusedKeywordOperation, []},
]
}
}
]
}
Run it in CI:
mix credo --config-file .credo.ci.exs --strict
Step 3: Emit a Heartbeat After Successful Credo Run
The key integration: only ping Vigilmon when Credo passes. No ping means the quality gate failed or didn't run.
#!/bin/bash
# scripts/ci_quality.sh
set -e
echo "Running Credo analysis..."
mix credo --config-file .credo.ci.exs --strict
echo "Credo passed. Pinging Vigilmon..."
if [ -n "$VIGILMON_CREDO_HEARTBEAT_URL" ]; then
curl -fsS "$VIGILMON_CREDO_HEARTBEAT_URL" > /dev/null
echo "Heartbeat sent."
fi
GitHub Actions workflow:
# .github/workflows/quality.yml
name: Code Quality
on:
push:
branches: [main, develop]
pull_request:
jobs:
credo:
name: Credo Static Analysis
runs-on: ubuntu-latest
env:
VIGILMON_CREDO_HEARTBEAT_URL: ${{ secrets.VIGILMON_CREDO_HEARTBEAT_URL }}
steps:
- uses: actions/checkout@v4
- uses: erlef/setup-beam@v1
with:
elixir-version: '1.16'
otp-version: '26'
- name: Cache deps
uses: actions/cache@v3
with:
path: deps
key: ${{ runner.os }}-deps-${{ hashFiles('mix.lock') }}
- run: mix deps.get
- name: Run Credo
run: mix credo --config-file .credo.ci.exs --strict
- name: Ping Vigilmon heartbeat
if: success()
run: curl -fsS "$VIGILMON_CREDO_HEARTBEAT_URL"
Step 4: Create a Heartbeat Monitor in Vigilmon
- Sign in at vigilmon.online
- Click New Monitor → Heartbeat
- Name it
Credo — main branch - Set the expected interval to slightly more than your longest CI run, e.g. 2 hours for active teams
- Copy the URL and store it as
VIGILMON_CREDO_HEARTBEAT_URLin your CI secrets
If Credo fails or CI is broken, the heartbeat misses and Vigilmon alerts you.
Step 5: Track Issue Trends with a Custom Exporter
For teams that want to track Credo issue counts over time, add a step that exports the JSON report:
# lib/mix/tasks/credo_report.ex
defmodule Mix.Tasks.CredoReport do
use Mix.Task
@shortdoc "Run Credo and output a summary JSON for CI tracking"
def run(_args) do
{output, exit_code} = System.cmd("mix", ["credo", "--format", "json"], stderr_to_stdout: true)
case Jason.decode(output) do
{:ok, report} ->
issues = report["issues"] || []
summary = %{
total: length(issues),
by_category: Enum.group_by(issues, & &1["category"]) |> Map.new(fn {k, v} -> {k, length(v)} end),
exit_code: exit_code
}
IO.puts(Jason.encode!(summary, pretty: true))
if exit_code != 0, do: exit({:shutdown, exit_code})
{:error, _} ->
IO.puts("Failed to parse Credo JSON output")
exit({:shutdown, 1})
end
end
end
Pipe this into a CI artifact or external metrics dashboard to track issue count trends over time.
Step 6: Production Health Check + Alerting
Add an HTTP monitor on your app's /health endpoint to cover production uptime alongside code quality monitoring:
# lib/my_app_web/plugs/health_check.ex
defmodule MyAppWeb.Plugs.HealthCheck do
import Plug.Conn
def init(opts), do: opts
def call(%Plug.Conn{request_path: "/health"} = conn, _opts) do
checks = %{database: check_db()}
status = if Enum.all?(checks, fn {_, v} -> v == :ok end), do: 200, else: 503
conn
|> put_resp_content_type("application/json")
|> send_resp(status, Jason.encode!(%{status: if(status == 200, do: "ok", else: "degraded"), checks: checks}))
|> halt()
end
def call(conn, _opts), do: conn
defp check_db do
case Ecto.Adapters.SQL.query(MyApp.Repo, "SELECT 1", []) do
{:ok, _} -> :ok
_ -> :error
end
end
end
In Vigilmon, add:
- HTTP monitor →
https://yourdomain.com/healthfor production uptime - Heartbeat monitor → Credo CI pipeline health
Step 7: Alerting Configuration
In Vigilmon, go to Notifications → New Channel and configure Slack:
🔴 MISSED: Credo — main branch
Last heartbeat: 3 hours ago (expected every 2 hours)
Action: Check CI pipeline for Credo failures or disabled steps
For critical projects, escalate to PagerDuty or email when the Credo heartbeat misses twice in a row.
What You've Built
| What | How |
|------|-----|
| Credo CI integration | mix credo --strict in dedicated CI job |
| Pipeline health monitoring | Vigilmon heartbeat monitor |
| Failure alerting | Slack/email notification channel |
| Issue trend tracking | Custom Mix task with JSON output |
| Production uptime monitoring | Vigilmon HTTP monitor on /health |
| Team status page | Vigilmon public status page |
Credo keeps your code quality honest. Vigilmon keeps your Credo honest.
Next Steps
- Add separate heartbeat monitors for
mainand your release branches - Export Credo JSON reports to a time-series store (InfluxDB, Grafana) to visualize technical debt trends
- Use Vigilmon's incident history to correlate production incidents with Credo check regressions
- Configure different
.credo.exsstrictness per environment (dev permissive, CI strict)
Get started free at vigilmon.online.