No failed scheduled run every minute for a pipeline that does not parse 5f3fa151688e
A scheduled tick cannot tell whether a pipeline it cannot read has a schedule, so it starts nothing; the push's run already reports the problem. oxygenhub-android had about 1,500 such runs. closes #321
- Author
- Andy McCall @andymccall <[email protected]>
- When
- · 2026-10-26 00:48 UTC
- Signature
- ◈ sealed by Andy McCall
- Hash
5f3fa151688e8b1d91d5cd3dfe316416683c13a6d1244fc1ea4859dce74b4e99- Depends on
- 1edac4b68c6d 348f8c4baccf 42fa95540468 a7e6e8e6094c b5668108487f c889911bec12 d2263e299da7
- Depended on by
- f87a74fffc87 c2efc0b4674d
- In bookmarks
- api-unknown-fields diffusion-pin-bookmark main proposal-list-fast
- In tags
- v0.9.11 v0.9.15 v0.9.16 v0.9.19 v0.9.20 v0.9.21 v0.9.22 v0.9.23 v0.9.24 v0.9.5 v0.9.6 v0.9.7 v0.9.8 v0.9.9
- Edits
- 3 atoms, 0 tree operations, 3 files
Browse the tree at this change
modified CHANGELOG.md +1 −0
| … | 3 unchanged lines |
||
| 4 | 4 | ||
| 5 | 5 | ## Unreleased |
|
| 6 | 6 | ||
| 7 | + | - **No failed run every minute for a pipeline that does not parse (#321):** the scheduler asked each repository's pipeline every minute and, for one it could not read (a mistake, or no jobs yet), recorded a failed `schedule` run each time: oxygenhub-android had about 1,500. A scheduled tick now starts nothing for such a pipeline; its push's run still says what is wrong. |
|
| 7 | 8 | - **A change's diff through the API (#320):** `GET /api/v1/repos/{owner}/{name}/changes/{hash}` gives each file's diff lines too (`lines`: `kind` context, add, del or gap, `old` and `new` line numbers, `text`), with three lines of context, up to 2000 lines a file (`truncated` says when it stops short), so the Android app can show a diff itself. |
|
| 8 | 9 | - **JaCoCo coverage is read (#308):** Gradle's `jacocoTestReport` and Kover write JaCoCo XML, which a `coverage` artifact (or `POST /coverage`) may now be, beside LCOV and Cobertura: lines hit when an instruction ran, branches, methods. Its paths are relative to a source root (`io/oxygenhub/…/X.kt`), so a report's path not in the state is matched by its ending to the one file it can be. |
|
| 9 | 10 | ## 0.9.4 (2026-10-25) |
|
| … | 328 unchanged lines |
modified crates/hub/src/flow.rs +4 −0
| … | 743 unchanged lines |
||
| 744 | 744 | let heads_s = hex.join("+"); |
|
| 745 | 745 | let base = db::flow::NewRun { repo_id: row.id, bookmark, state, heads: &heads_s, pipeline_hash: "", actor, trigger, error: None }; |
|
| 746 | 746 | let id = match Pipeline::parse(&text) { |
|
| 747 | + | // A scheduled tick cannot tell whether a pipeline it cannot read |
|
| 748 | + | // has a schedule, so it starts nothing (#321): the push's run |
|
| 749 | + | // already says what is wrong, once rather than every minute. |
|
| 750 | + | Err(_) if at.is_some() => return Ok(None), |
|
| 747 | 751 | Err(problems) => { |
|
| 748 | 752 | let msg = problems.to_string(); |
|
| 749 | 753 | db::flow::create_run(&app.db, db::flow::NewRun { error: Some(&msg), ..base }, &[]).await.map_err(|e| e.to_string())? |
|
| … | 2186 unchanged lines |
modified crates/hub/tests/flow.rs +12 −0
| … | 2225 unchanged lines |
||
| 2226 | 2226 | let names: Vec<String> = db::flow::jobs(&h.app.db, runs[0].id).await.unwrap().into_iter().map(|j| j.name).collect(); |
|
| 2227 | 2227 | assert_eq!(names, ["nightly"]); |
|
| 2228 | 2228 | assert_eq!(runs[0].bookmark, "main", "on the default bookmark"); |
|
| 2229 | + | // #321: a pipeline that does not parse fails its push's run once, and |
|
| 2230 | + | // the scheduler records nothing for it, minute after minute. |
|
| 2231 | + | write(work.path(), ".flow/pipeline.kdl", "schema-version 1\n"); |
|
| 2232 | + | c.commit("No jobs", &[]).unwrap(); |
|
| 2233 | + | assert!(c.push("origin", false).unwrap().iter().all(|r| r.ok)); |
|
| 2234 | + | tokio::time::sleep(std::time::Duration::from_millis(300)).await; |
|
| 2235 | + | let runs = runs_of(&h.app, "andy", "nightly").await; |
|
| 2236 | + | assert_eq!(runs.len(), 3); |
|
| 2237 | + | assert!(runs[0].error.contains("at least one job"), "{}", runs[0].error); |
|
| 2238 | + | assert_eq!(oxygenhub::flow::run_due(&h.app, due).await, 0); |
|
| 2239 | + | assert_eq!(oxygenhub::flow::run_due(&h.app, not_yet).await, 0); |
|
| 2240 | + | assert_eq!(runs_of(&h.app, "andy", "nightly").await.len(), 3, "no scheduled runs of a broken pipeline"); |
|
| 2229 | 2241 | } |
|
| 2230 | 2242 | ||
| 2231 | 2243 | #[tokio::test(flavor = "multi_thread")] |
|
| … | 4318 unchanged lines |