Skip to content

Instantly share code, notes, and snippets.

@HarlemSquirrel
Last active September 1, 2022 21:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HarlemSquirrel/55f244e2e322e0fffcfe74e458261bd9 to your computer and use it in GitHub Desktop.
Save HarlemSquirrel/55f244e2e322e0fffcfe74e458261bd9 to your computer and use it in GitHub Desktop.
Send SimpleCov or CodeClimate test coverage summary metrics to Datadog
# /usr/bin/env ruby
begin
require "git"
require "datadog_api_client"
rescue LoadError
Gem.install "git"
Gem.install "datadog_api_client"
require "git"
require "datadog_api_client"
end
# Read the app name from CircleCI project environment variables
# https://circleci.com/docs/variables
APP_NAME = ENV.fetch("CIRCLE_PROJECT_REPONAME").freeze
if File.file?(".codeclimate/codeclimate.json")
summary = JSON.parse(File.read(".codeclimate/codeclimate.json"))
line_coverage_percent = summary["covered_percent"]
elsif File.file?("coverage/.last_run.json")
# Read SimpleCov coverage summary results
summary = JSON.parse(File.read("coverage/.last_run.json"))
line_coverage_percent = summary["result"]["line"]
branch_coverage_percent = summary["result"]["branch"]
else
raise "Could not find coverage file!"
end
# Read timestamp of latest commit
git = Git.open(".")
last_commit_timestamp = git.log.first.author_date
# Send line coverage metric to Datadog
# https://docs.datadoghq.com/api/latest/metrics/?code-lang=ruby
# These are used internally by DatadogAPIClient so throw an error if they are not set.
ENV.fetch("DD_API_KEY")
ENV["DD_SITE"] ||= "datadoghq.com"
METRIC_NAME = "test.coverage.line".freeze
api_instance = DatadogAPIClient::V2::MetricsAPI.new
body = DatadogAPIClient::V2::MetricPayload.new({
series: [
DatadogAPIClient::V2::MetricSeries.new({
metric: METRIC_NAME,
type: DatadogAPIClient::V2::MetricIntakeType::GAUGE,
points: [
DatadogAPIClient::V2::MetricPoint.new({
timestamp: last_commit_timestamp.to_i,
value: line_coverage_percent
}),
],
resources: [
DatadogAPIClient::V2::MetricResource.new({
name: APP_NAME,
type: "host",
}),
],
tags: [
"branch:#{git.current_branch}"
]
}),
],
})
# Should we only send this on the main branch?
puts "\nSending metrics:", body, ""
response = api_instance.submit_metrics(body)
case response
when DatadogAPIClient::V2::IntakePayloadAccepted
puts "OK"
else
raise RuntimeError, response.inspect
end
##
# Query metrics to find the highest recent coverage from main and compare current
# Should we skip this on the main branch?
#
ENV.fetch("DD_APP_KEY") # This is required to query metrics
api_instance = DatadogAPIClient::V1::MetricsAPI.new
time_1_week_ago = Time.now - (60*60*24*7)
metrics_response = api_instance.query_metrics(time_1_week_ago.to_i, Time.now.to_i, "max:#{METRIC_NAME}{branch:main,host:#{APP_NAME}}")
historic_coverage_percentages = metrics_response.series.first.pointlist.map(&:last)
last_highest_coverage_percent = historic_coverage_percentages.max
if line_coverage_percent < last_highest_coverage_percent
raise "😖 Line code coverage fell! #{line_coverage_percent}% < #{last_highest_coverage_percent}%"
elsif line_coverage_percent == last_highest_coverage_percent
puts "👍 Line code coverage is unchanged at #{line_coverage_percent}%"
else
difference = line_coverage_percent - last_highest_coverage_percent
puts "🚀 Line code coverage increased #{difference}% to #{line_coverage_percent}%"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment