Skip to content

Instantly share code, notes, and snippets.

@C-Saunders
Last active August 15, 2023 14:20
Show Gist options
  • Save C-Saunders/a91942593e7a85501ca98ba322736e85 to your computer and use it in GitHub Desktop.
Save C-Saunders/a91942593e7a85501ca98ba322736e85 to your computer and use it in GitHub Desktop.
GitHub Action Job Runtime Data Extractor
require 'date'
require 'json'
def get_seconds_difference(start, finish)
((finish - start) * 24 * 60 * 60).to_i
end
# from gh run list --branch main --event push --status completed --json displayTitle,headSha,name,databaseId,startedAt,updatedAt,workflowName --limit 1000 > run_list.json
data = JSON.parse(File.read('./run_list.json'))
puts "Workflow Name,Job Name,Start Time,Finish Time,Elapsed Time"
for run in data do
run_details = JSON.parse(`gh run view #{run['databaseId']} --json name,workflowName,jobs,createdAt,updatedAt`)
for job in run_details['jobs'] do
start = DateTime.parse(job['startedAt'])
finish = DateTime.parse(job['completedAt'])
puts "\"#{run_details['workflowName']}\",\"#{job['name']}\",#{start},#{finish},#{get_seconds_difference(start, finish)}"
end
end

This is a quick and dirty script to get some data about GitHub action job running time for ad hoc analysis. It uses the GitHub CLI rather than the real API library because it simplified auth and made experimentation super simple and easy.

I found the JSON data didn't give accurate results, though it's not clear how or why. The "unstructured" version of the code uses the non-JSON data and parses the strings to get the time data.

require 'date'
require 'json'
def get_seconds(minutes, seconds)
mins = if minutes.nil?
0
else
minutes.chop().to_i
end
mins * 60 + seconds.chop().to_i
end
# from gh run list --branch main --event push --status completed --json displayTitle,headSha,name,databaseId,startedAt,updatedAt,workflowName --limit 500 > run_list.json
data = JSON.parse(File.read('./run_list.json'))
puts "Workflow Name,Job Name,Duration"
for run in data do
run_details = `gh run view #{run['databaseId']}`.split("\n").map(&:strip)
for line in run_details do
if /^[^ ]+ (?<job>.*) in (?<minutes>\d+m)?(?<seconds>\d{1,2}s) \(ID \d+\)$/ =~ line
puts "\"#{run['workflowName']}\",\"#{job}\",#{get_seconds(minutes, seconds)}"
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment