Skip to content

Commit 7477721

Browse files
Your Nameclaude
andcommitted
fix(ci): add job timeout-minutes + fix indexer/analysis boundary violation
Two CI issues investigated on main: - all-languages job ran for ~6h until GitHub's default job timeout auto-cancelled it (started 08:05, cancelled 14:05:51) — no job in ci.yml had timeout-minutes set, so a hung test could silently eat a runner for the full 6h default instead of failing fast. Added a bounded timeout-minutes to every job. - fitness-check failed on a new architecture boundary violation: indexer/refresh.rs importing analysis::coverage::COVERAGE_SEARCH_PATHS (introduced by 68d268f's watcher supervision work), inverting the indexer-must-stay-upstream-of-analysis rule. Moved the constant to a new indexer::coverage_paths module and re-exported it from analysis::coverage so existing call sites are unaffected. Verified locally: cargo build clean, calm fitness-check now PASSes (boundary violations 0/0), and the coverage/refresh test suites pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent e233776 commit 7477721

5 files changed

Lines changed: 36 additions & 11 deletions

File tree

.github/workflows/ci.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ on:
99
jobs:
1010
verify:
1111
runs-on: ubuntu-latest
12+
timeout-minutes: 20
1213
steps:
1314
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
1415

@@ -32,6 +33,7 @@ jobs:
3233

3334
stack-graphs-corpus:
3435
runs-on: ubuntu-latest
36+
timeout-minutes: 15
3537
steps:
3638
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
3739

@@ -44,6 +46,7 @@ jobs:
4446

4547
embeddings:
4648
runs-on: ubuntu-latest
49+
timeout-minutes: 15
4750
steps:
4851
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
4952

@@ -70,6 +73,7 @@ jobs:
7073

7174
no-stack-graphs-formal:
7275
runs-on: ubuntu-latest
76+
timeout-minutes: 15
7377
steps:
7478
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
7579

@@ -110,6 +114,7 @@ jobs:
110114
111115
all-languages:
112116
runs-on: ubuntu-latest
117+
timeout-minutes: 30
113118
steps:
114119
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
115120

@@ -158,6 +163,7 @@ jobs:
158163
# missing `#[serde(default)]`) the very first time this check ran.
159164
js-client-interop:
160165
runs-on: ubuntu-latest
166+
timeout-minutes: 15
161167
steps:
162168
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
163169

@@ -200,6 +206,7 @@ jobs:
200206
# an unrelated crate whose name happens to contain the same substring.
201207
otel-http-features:
202208
runs-on: ubuntu-latest
209+
timeout-minutes: 15
203210
steps:
204211
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
205212

@@ -244,6 +251,7 @@ jobs:
244251
# own `.calm/index.db`, which a fresh checkout doesn't have yet.
245252
fitness-check:
246253
runs-on: ubuntu-latest
254+
timeout-minutes: 15
247255
steps:
248256
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
249257

crates/calm-core/src/analysis/coverage.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,12 @@ impl CoverageData {
2323
}
2424
}
2525

26-
pub const COVERAGE_SEARCH_PATHS: &[(&str, &str)] = &[
27-
("lcov.info", "lcov"),
28-
("coverage/lcov.info", "lcov"),
29-
(".nyc_output/lcov.info", "lcov"),
30-
(".coverage", "python"),
31-
("coverage.out", "go"),
32-
("coverage/coverage.out", "go"),
33-
("coverage.xml", "cobertura"),
34-
("coverage/coverage.xml", "cobertura"),
35-
];
26+
// Defined in `indexer::coverage_paths`, not here: `indexer::refresh` also
27+
// needs this plain path list (to classify coverage files during a
28+
// watch-triggered refresh), and `indexer` must stay upstream of `analysis`
29+
// per the fitness-check boundary rule -- re-exported here so existing
30+
// `analysis::coverage::COVERAGE_SEARCH_PATHS` call sites are unaffected.
31+
pub use crate::indexer::coverage_paths::COVERAGE_SEARCH_PATHS;
3632

3733
pub fn load_coverage(project_root: &Path) -> CoverageData {
3834
for &(relative, fmt) in COVERAGE_SEARCH_PATHS {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//! Coverage-report search paths — lives in `indexer` (not `analysis`) even
2+
//! though `analysis::coverage::load_coverage` is the only real consumer of
3+
//! the parsing logic, because `indexer::refresh` also needs the plain path
4+
//! list to classify coverage files during a watch-triggered refresh
5+
//! (`RefreshClassifier::coverage_paths`). `indexer` must stay upstream of
6+
//! `analysis` (fitness-check's `[[boundaries]]` rule in `thresholds.toml`
7+
//! enforces this), so the list is defined here and `analysis::coverage`
8+
//! re-exports it — see the 2026-07-28 `hotspot_risk`/`common.rs` split for
9+
//! the same pattern applied to a different boundary violation.
10+
11+
pub const COVERAGE_SEARCH_PATHS: &[(&str, &str)] = &[
12+
("lcov.info", "lcov"),
13+
("coverage/lcov.info", "lcov"),
14+
(".nyc_output/lcov.info", "lcov"),
15+
(".coverage", "python"),
16+
("coverage.out", "go"),
17+
("coverage/coverage.out", "go"),
18+
("coverage.xml", "cobertura"),
19+
("coverage/coverage.xml", "cobertura"),
20+
];

crates/calm-core/src/indexer/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod chunker;
2+
pub mod coverage_paths;
23
pub mod crate_map;
34
pub mod csharp_namespace;
45
pub mod edges;

crates/calm-core/src/indexer/refresh.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use std::collections::{BTreeSet, VecDeque};
99
use std::path::{Component, Path, PathBuf};
1010

11-
use crate::analysis::coverage::COVERAGE_SEARCH_PATHS;
11+
use crate::indexer::coverage_paths::COVERAGE_SEARCH_PATHS;
1212
use crate::indexer::lang_constants::{is_recognized_unparsed_extension, language_for_extension};
1313
use crate::walk::{build_walker, is_ignored_dir_component, matches_ignore_pattern};
1414

0 commit comments

Comments
 (0)