Class: Flaky::Repository
- Inherits:
-
Object
- Object
- Flaky::Repository
- Defined in:
- lib/flaky/repository.rb
Instance Method Summary collapse
- #close ⇒ Object
-
#failing_seeds(file:, line: nil) ⇒ Object
— Seeds —.
-
#failure_history(file:, line: nil) ⇒ Object
— History —.
- #failure_trend(branch:, period_days: 7) ⇒ Object
-
#initialize(path = nil) ⇒ Repository
constructor
A new instance of Repository.
- #insert_ci_run(workflow_id:, pipeline_id:, branch:, result:, created_at:, commit_sha: nil) ⇒ Object
-
#insert_job_result(job_id:, workflow_id:, job_name:, block_name:, result:, example_count:, failure_count:, seed:, duration_seconds:) ⇒ Object
— Job Results —.
-
#insert_stress_run(spec_location:, seed:, iterations:, passes:, failures:, ci_simulation:) ⇒ Object
— Stress —.
-
#insert_test_failure(workflow_id:, job_id:, job_name:, spec_file:, line_number:, description:, seed:, branch:, failed_at:) ⇒ Object
— Test Failures —.
-
#rank_failures(branch:, since_days:, min_failures: 1) ⇒ Object
— Ranking —.
- #recent_stress_runs(limit: 3) ⇒ Object
-
#run_stats(branch:) ⇒ Object
— Report —.
- #top_flaky(branch:, limit: 5) ⇒ Object
- #total_runs_count(branch:, since_days:) ⇒ Object
-
#workflow_fetched?(workflow_id) ⇒ Boolean
— CI Runs —.
Constructor Details
#initialize(path = nil) ⇒ Repository
Returns a new instance of Repository.
7 8 9 |
# File 'lib/flaky/repository.rb', line 7 def initialize(path = nil) @db = Database.new(path) end |
Instance Method Details
#close ⇒ Object
11 12 13 |
# File 'lib/flaky/repository.rb', line 11 def close @db.close end |
#failing_seeds(file:, line: nil) ⇒ Object
— Seeds —
152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/flaky/repository.rb', line 152 def failing_seeds(file:, line: nil) conditions = ["spec_file LIKE ?"] params = ["%#{file}%"] if line conditions << "line_number = ?" params << line end connection.execute( "SELECT DISTINCT seed FROM test_failures WHERE #{conditions.join(' AND ')} ORDER BY failed_at DESC", params ).map { |row| row["seed"] } end |
#failure_history(file:, line: nil) ⇒ Object
— History —
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/flaky/repository.rb', line 77 def failure_history(file:, line: nil) conditions = ["tf.spec_file LIKE ?"] params = ["%#{file}%"] if line conditions << "tf.line_number = ?" params << line end connection.execute(<<~SQL, params) SELECT tf.spec_file, tf.line_number, tf.description, tf.seed, tf.job_name, tf.branch, tf.failed_at, cr.workflow_id, cr.commit_sha FROM test_failures tf JOIN ci_runs cr ON cr.workflow_id = tf.workflow_id WHERE #{conditions.join(" AND ")} ORDER BY tf.failed_at DESC SQL end |
#failure_trend(branch:, period_days: 7) ⇒ Object
116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/flaky/repository.rb', line 116 def failure_trend(branch:, period_days: 7) recent = connection.get_first_value( "SELECT COUNT(*) FROM test_failures WHERE branch = ? AND failed_at >= datetime('now', ?)", [branch, "-#{period_days} days"] ).to_i prior = connection.get_first_value( "SELECT COUNT(*) FROM test_failures WHERE branch = ? AND failed_at >= datetime('now', ?) AND failed_at < datetime('now', ?)", [branch, "-#{period_days * 2} days", "-#{period_days} days"] ).to_i { recent: recent, prior: prior } end |
#insert_ci_run(workflow_id:, pipeline_id:, branch:, result:, created_at:, commit_sha: nil) ⇒ Object
21 22 23 24 25 26 |
# File 'lib/flaky/repository.rb', line 21 def insert_ci_run(workflow_id:, pipeline_id:, branch:, result:, created_at:, commit_sha: nil) connection.execute( "INSERT INTO ci_runs (workflow_id, pipeline_id, branch, result, created_at, commit_sha) VALUES (?, ?, ?, ?, ?, ?)", [workflow_id, pipeline_id, branch, result, created_at, commit_sha] ) end |
#insert_job_result(job_id:, workflow_id:, job_name:, block_name:, result:, example_count:, failure_count:, seed:, duration_seconds:) ⇒ Object
— Job Results —
30 31 32 33 34 35 |
# File 'lib/flaky/repository.rb', line 30 def insert_job_result(job_id:, workflow_id:, job_name:, block_name:, result:, example_count:, failure_count:, seed:, duration_seconds:) connection.execute( "INSERT OR IGNORE INTO job_results (job_id, workflow_id, job_name, block_name, result, example_count, failure_count, seed, duration_seconds) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", [job_id, workflow_id, job_name, block_name, result, example_count, failure_count, seed, duration_seconds] ) end |
#insert_stress_run(spec_location:, seed:, iterations:, passes:, failures:, ci_simulation:) ⇒ Object
— Stress —
169 170 171 172 173 174 |
# File 'lib/flaky/repository.rb', line 169 def insert_stress_run(spec_location:, seed:, iterations:, passes:, failures:, ci_simulation:) connection.execute( "INSERT INTO stress_runs (spec_location, seed, iterations, passes, failures, ci_simulation) VALUES (?, ?, ?, ?, ?, ?)", [spec_location, seed, iterations, passes, failures, ci_simulation] ) end |
#insert_test_failure(workflow_id:, job_id:, job_name:, spec_file:, line_number:, description:, seed:, branch:, failed_at:) ⇒ Object
— Test Failures —
39 40 41 42 43 44 |
# File 'lib/flaky/repository.rb', line 39 def insert_test_failure(workflow_id:, job_id:, job_name:, spec_file:, line_number:, description:, seed:, branch:, failed_at:) connection.execute( "INSERT OR IGNORE INTO test_failures (workflow_id, job_id, job_name, spec_file, line_number, description, seed, branch, failed_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", [workflow_id, job_id, job_name, spec_file, line_number, description, seed, branch, failed_at] ) end |
#rank_failures(branch:, since_days:, min_failures: 1) ⇒ Object
— Ranking —
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/flaky/repository.rb', line 48 def rank_failures(branch:, since_days:, min_failures: 1) connection.execute(<<~SQL, [branch, "-#{since_days} days", min_failures]) SELECT tf.spec_file, tf.line_number, tf.description, COUNT(*) as failure_count, MAX(tf.failed_at) as last_failure, GROUP_CONCAT(DISTINCT tf.seed) as seeds, GROUP_CONCAT(DISTINCT cr.commit_sha) as commit_shas FROM test_failures tf JOIN ci_runs cr ON cr.workflow_id = tf.workflow_id WHERE cr.branch = ? AND cr.created_at >= datetime('now', ?) GROUP BY tf.spec_file, tf.line_number HAVING COUNT(*) >= ? ORDER BY failure_count DESC, last_failure DESC SQL end |
#recent_stress_runs(limit: 3) ⇒ Object
146 147 148 |
# File 'lib/flaky/repository.rb', line 146 def recent_stress_runs(limit: 3) connection.execute("SELECT * FROM stress_runs ORDER BY created_at DESC LIMIT ?", limit) end |
#run_stats(branch:) ⇒ Object
— Report —
106 107 108 109 110 111 112 113 114 |
# File 'lib/flaky/repository.rb', line 106 def run_stats(branch:) { total_runs: connection.get_first_value("SELECT COUNT(*) FROM ci_runs WHERE branch = ?", branch).to_i, failed_runs: connection.get_first_value("SELECT COUNT(*) FROM ci_runs WHERE branch = ? AND result = 'failed'", branch).to_i, total_failures: connection.get_first_value("SELECT COUNT(*) FROM test_failures WHERE branch = ?", branch).to_i, unique_specs: connection.get_first_value("SELECT COUNT(DISTINCT spec_file || ':' || line_number) FROM test_failures WHERE branch = ?", branch).to_i, last_fetch: connection.get_first_value("SELECT MAX(fetched_at) FROM ci_runs") } end |
#top_flaky(branch:, limit: 5) ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/flaky/repository.rb', line 130 def top_flaky(branch:, limit: 5) connection.execute(<<~SQL, [branch, limit]) SELECT spec_file, line_number, description, COUNT(*) as failure_count, MAX(failed_at) as last_failure FROM test_failures WHERE branch = ? GROUP BY spec_file, line_number ORDER BY failure_count DESC LIMIT ? SQL end |
#total_runs_count(branch:, since_days:) ⇒ Object
68 69 70 71 72 73 |
# File 'lib/flaky/repository.rb', line 68 def total_runs_count(branch:, since_days:) connection.get_first_value( "SELECT COUNT(DISTINCT workflow_id) FROM ci_runs WHERE branch = ? AND created_at >= datetime('now', ?)", [branch, "-#{since_days} days"] ).to_i end |
#workflow_fetched?(workflow_id) ⇒ Boolean
— CI Runs —
17 18 19 |
# File 'lib/flaky/repository.rb', line 17 def workflow_fetched?(workflow_id) !!connection.get_first_value("SELECT 1 FROM ci_runs WHERE workflow_id = ?", workflow_id) end |