Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ Set these in a `.env` file in your project root:
| `DIFFDASH_GRAFANA_FOLDER_ID` | No | Target folder ID for dashboards |
| `DIFFDASH_OUTPUTS` | No | Comma-separated outputs (default: `grafana`) |
| `DIFFDASH_DRY_RUN` | No | Set to `true` to force dry-run mode |
| `DIFFDASH_PR_DEPLOY_ANNOTATION_EXPR` | No | PromQL expr for PR deployment annotation |

Legacy `GRAFANA_*` env vars are still supported as fallbacks for now.

Expand Down
11 changes: 6 additions & 5 deletions lib/diffdash/cli/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,12 @@ def print_help
--help Show this help message

Environment Variables (set in .env file):
DIFFDASH_GRAFANA_URL Grafana instance URL (required)
DIFFDASH_GRAFANA_TOKEN Grafana API token (required)
DIFFDASH_GRAFANA_FOLDER_ID Target folder ID (optional)
DIFFDASH_OUTPUTS Comma-separated outputs (default: grafana)
DIFFDASH_DRY_RUN Set to 'true' to force dry-run mode
DIFFDASH_GRAFANA_URL Grafana instance URL (required)
DIFFDASH_GRAFANA_TOKEN Grafana API token (required)
DIFFDASH_GRAFANA_FOLDER_ID Target folder ID (optional)
DIFFDASH_OUTPUTS Comma-separated outputs (default: grafana)
DIFFDASH_DRY_RUN Set to 'true' to force dry-run mode
DIFFDASH_PR_DEPLOY_ANNOTATION_EXPR PromQL for PR deployment annotation

Output:
Prints output JSON to STDOUT (Grafana first if configured).
Expand Down
60 changes: 46 additions & 14 deletions lib/diffdash/outputs/grafana.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def build_dashboard(signal_bundle)
},
templating: build_templating,
panels: build_panels(signal_bundle),
annotations: build_annotations
annotations: build_annotations(signal_bundle)
}
end

Expand Down Expand Up @@ -107,19 +107,12 @@ def app_variable
}
end

def build_annotations
{
list: [
{
name: "Deployments",
datasource: { type: "prometheus", uid: "${datasource}" },
enable: true,
expr: "changes(deploy_timestamp[5m]) > 0",
tagKeys: "app,env",
titleFormat: "Deploy"
}
]
}
def build_annotations(signal_bundle)
annotations = [deployment_annotation]
pr_annotation = pr_deployment_annotation(signal_bundle)
annotations << pr_annotation if pr_annotation

{ list: annotations }
end

def build_panels(signal_bundle)
Expand Down Expand Up @@ -323,6 +316,10 @@ def escape_log_value(value)
value.to_s.gsub("\\", "\\\\").gsub("\"", "\\\"")
end

def escape_promql_label(value)
value.to_s.gsub("\\", "\\\\").gsub("\"", "\\\"")
end

def sanitize_metric_name(name)
name.to_s.gsub(/[^a-zA-Z0-9_:]/, "_")
end
Expand All @@ -338,6 +335,41 @@ def relative_path(path)
def log_verbose(message)
warn "[diffdash] #{message}" if @verbose
end

def deployment_annotation
{
name: "Deployments",
datasource: { type: "prometheus", uid: "${datasource}" },
enable: true,
expr: "changes(deploy_timestamp[5m]) > 0",
tagKeys: "app,env",
titleFormat: "Deploy"
}
end

def pr_deployment_annotation(signal_bundle)
expr = pr_deployment_expr(signal_bundle)
return nil if expr.nil? || expr.empty?

{
name: "PR Deployments",
datasource: { type: "prometheus", uid: "${datasource}" },
enable: true,
expr: expr,
tagKeys: "app,env,branch",
titleFormat: "PR Deploy"
}
end

def pr_deployment_expr(signal_bundle)
override = ENV["DIFFDASH_PR_DEPLOY_ANNOTATION_EXPR"].to_s.strip
return override unless override.empty?

branch = signal_bundle.metadata.dig(:change_set, :branch_name).to_s.strip
return nil if branch.empty?

"changes(deploy_timestamp{branch=\"#{escape_promql_label(branch)}\"}[5m]) > 0"
end
end
end
end
5 changes: 4 additions & 1 deletion spec/diffdash/renderers/grafana_contract_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ def stringify_keys(value)
logs: [signal],
metrics: [],
traces: [],
metadata: { time_range: { from: "now-1h", to: "now" } }
metadata: {
time_range: { from: "now-1h", to: "now" },
change_set: { branch_name: "contract-dashboard" }
}
)
renderer = Diffdash::Outputs::Grafana.new(
title: "contract-dashboard",
Expand Down
22 changes: 19 additions & 3 deletions spec/diffdash/renderers/grafana_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@
describe "#render" do
context "with empty signals" do
subject(:renderer) { described_class.new(title: "Empty Dashboard", folder_id: nil) }
let(:bundle) { Diffdash::Engine::SignalBundle.new(metadata: { time_range: { from: "now-1h", to: "now" } }) }
let(:bundle) do
Diffdash::Engine::SignalBundle.new(
metadata: {
time_range: { from: "now-1h", to: "now" },
change_set: { branch_name: "feature/pr-123" }
}
)
end

it "returns valid Grafana JSON structure" do
result = renderer.render(bundle)
Expand Down Expand Up @@ -296,7 +303,14 @@

context "dashboard metadata" do
subject(:renderer) { described_class.new(title: "Test Dashboard", folder_id: nil) }
let(:bundle) { Diffdash::Engine::SignalBundle.new(metadata: { time_range: { from: "now-1h", to: "now" } }) }
let(:bundle) do
Diffdash::Engine::SignalBundle.new(
metadata: {
time_range: { from: "now-1h", to: "now" },
change_set: { branch_name: "feature/pr-123" }
}
)
end

it "includes Grafana tags" do
result = renderer.render(bundle)
Expand All @@ -321,8 +335,10 @@
result = renderer.render(bundle)
annotations = result[:dashboard][:annotations][:list]

expect(annotations.size).to eq(1)
expect(annotations.size).to eq(2)
expect(annotations.first[:name]).to eq("Deployments")
expect(annotations.last[:name]).to eq("PR Deployments")
expect(annotations.last[:expr]).to eq("changes(deploy_timestamp{branch=\"feature/pr-123\"}[5m]) > 0")
end

it "sets schema version" do
Expand Down
11 changes: 11 additions & 0 deletions spec/fixtures/grafana/dashboard_v1_fixture.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,17 @@
"expr": "changes(deploy_timestamp[5m]) > 0",
"tagKeys": "app,env",
"titleFormat": "Deploy"
},
{
"name": "PR Deployments",
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"enable": true,
"expr": "changes(deploy_timestamp{branch=\"contract-dashboard\"}[5m]) > 0",
"tagKeys": "app,env,branch",
"titleFormat": "PR Deploy"
}
]
}
Expand Down
Loading