treewide: replace BuildStatus::Completed with BuildStatus::Succeeded

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I965dfaca211f9fde527a84a54ae972576a6a6964
This commit is contained in:
raf 2026-02-16 00:08:13 +03:00
commit 541cd7832f
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
7 changed files with 39 additions and 22 deletions

View file

@ -0,0 +1,17 @@
-- Fix build_stats view and data after 'completed' -> 'succeeded' status rename
-- Migrate any existing builds still using the old status value
UPDATE builds SET status = 'succeeded' WHERE status = 'completed';
-- Recreate the build_stats view to reference the new status
DROP VIEW IF EXISTS build_stats;
CREATE VIEW build_stats AS
SELECT
COUNT(*) as total_builds,
COUNT(CASE WHEN status = 'succeeded' THEN 1 END) as completed_builds,
COUNT(CASE WHEN status = 'failed' THEN 1 END) as failed_builds,
COUNT(CASE WHEN status = 'running' THEN 1 END) as running_builds,
COUNT(CASE WHEN status = 'pending' THEN 1 END) as pending_builds,
AVG(EXTRACT(EPOCH FROM (completed_at - started_at))) as avg_duration_seconds
FROM builds
WHERE started_at IS NOT NULL;

View file

@ -81,7 +81,7 @@ pub async fn all_deps_completed(pool: &PgPool, build_id: Uuid) -> Result<bool> {
let row: (i64,) = sqlx::query_as(
"SELECT COUNT(*) FROM build_dependencies bd JOIN builds b ON \
bd.dependency_build_id = b.id WHERE bd.build_id = $1 AND b.status != \
'completed'",
'succeeded'",
)
.bind(build_id)
.fetch_one(pool)

View file

@ -40,7 +40,7 @@ pub async fn get_completed_by_drv_path(
drv_path: &str,
) -> Result<Option<Build>> {
sqlx::query_as::<_, Build>(
"SELECT * FROM builds WHERE drv_path = $1 AND status = 'completed' LIMIT 1",
"SELECT * FROM builds WHERE drv_path = $1 AND status = 'succeeded' LIMIT 1",
)
.bind(drv_path)
.fetch_optional(pool)
@ -276,13 +276,13 @@ pub async fn cancel_cascade(pool: &PgPool, id: Uuid) -> Result<Vec<Build>> {
}
/// Restart a build by resetting it to pending state.
/// Only works for failed, completed, or cancelled builds.
/// Only works for failed, succeeded, or cancelled builds.
pub async fn restart(pool: &PgPool, id: Uuid) -> Result<Build> {
sqlx::query_as::<_, Build>(
"UPDATE builds SET status = 'pending', started_at = NULL, completed_at = \
NULL, log_path = NULL, build_output_path = NULL, error_message = NULL, \
retry_count = retry_count + 1 WHERE id = $1 AND status IN ('failed', \
'completed', 'cancelled') RETURNING *",
'succeeded', 'cancelled') RETURNING *",
)
.bind(id)
.fetch_optional(pool)
@ -315,7 +315,7 @@ pub async fn get_completed_by_drv_paths(
}
let builds = sqlx::query_as::<_, Build>(
"SELECT DISTINCT ON (drv_path) * FROM builds WHERE drv_path = ANY($1) AND \
status = 'completed' ORDER BY drv_path, completed_at DESC",
status = 'succeeded' ORDER BY drv_path, completed_at DESC",
)
.bind(drv_paths)
.fetch_all(pool)

View file

@ -153,7 +153,7 @@ pub async fn auto_promote_if_complete(
) -> Result<()> {
// Check if all builds for this evaluation are completed
let row: (i64, i64) = sqlx::query_as(
"SELECT COUNT(*), COUNT(*) FILTER (WHERE status = 'completed') FROM \
"SELECT COUNT(*), COUNT(*) FILTER (WHERE status = 'succeeded') FROM \
builds WHERE evaluation_id = $1",
)
.bind(evaluation_id)

View file

@ -98,7 +98,7 @@ async fn prometheus_metrics(State(state): State<AppState>) -> Response {
// Per-project build counts
let per_project: Vec<(String, i64, i64)> = sqlx::query_as(
"SELECT p.name, COUNT(*) FILTER (WHERE b.status = 'completed'), COUNT(*) \
"SELECT p.name, COUNT(*) FILTER (WHERE b.status = 'succeeded'), COUNT(*) \
FILTER (WHERE b.status = 'failed') FROM builds b JOIN evaluations e ON \
b.evaluation_id = e.id JOIN jobsets j ON e.jobset_id = j.id JOIN \
projects p ON j.project_id = p.id GROUP BY p.name",
@ -133,7 +133,7 @@ async fn prometheus_metrics(State(state): State<AppState>) -> Response {
output.push_str("# TYPE fc_builds_total gauge\n");
let _ = writeln!(
output,
"fc_builds_total{{status=\"completed\"}} {}",
"fc_builds_total{{status=\"succeeded\"}} {}",
stats.completed_builds.unwrap_or(0)
);
let _ = writeln!(

View file

@ -679,8 +679,8 @@ async fn test_metrics_endpoint() {
"Missing TYPE header for fc_builds_total"
);
assert!(
body_str.contains("fc_builds_total{status=\"completed\"}"),
"Missing completed status label"
body_str.contains("fc_builds_total{status=\"succeeded\"}"),
"Missing succeeded status label"
);
assert!(
body_str.contains("fc_builds_total{status=\"failed\"}"),