Skip to content

Commit 6a43d14

Browse files
fix(review): keep reviews 14 days and base graphs 30 (#93)
The review artifact is the dominant storage cost, being the one kept for weeks, so it drops from 30 days to 14. Base graphs drop from 60 to 30, which still leaves a 16-day window in which a base is reused rather than republished. Modelled at the largest repository we have, that is roughly 3,700 analyses a month within half a Team allowance, against 1,850 before. The renewal threshold moves with the review retention, because it has to: a review references a base by id for its whole life, so a base with less than that remaining is renewed. Ten days against a fourteen-day review would leave a reference dangling for four. A test now fails if the two drift apart, since nothing else would notice. What a pull request open longer than fourteen days loses is the rendered analysis, until someone asks for it again. That costs one incremental over the pull request: the base graph is kept longer and needs no re-analysis. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 3432ad5 commit 6a43d14

4 files changed

Lines changed: 35 additions & 21 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ Every bundle the action publishes carries a `metadata.json` with a `kind` of
8888
`review`, `base` or `warmstart`. Check it rather than inferring from the
8989
payload: a base bundle is otherwise indistinguishable from a head one.
9090

91-
The action requests 30-day retention; a repository or organisation policy can shorten it, so treat an artifact's own `expired` flag as the truth rather than any fixed window.
91+
The action requests 14-day retention for it; a repository or organisation policy can shorten that, so treat an artifact's own `expired` flag as the truth rather than any fixed window. When a pull request outlives its review artifact, `/codeboarding` regenerates it at the cost of one incremental over the pull request — the base graph is kept longer and does not need re-analyzing.
9292

9393
### Reused analysis
9494

‎action.yml‎

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,9 @@ runs:
222222
REPOSITORY: ${{ github.repository }}
223223
ARTIFACT_NAME: ${{ steps.state.outputs.base_name }}
224224
DEST: ${{ runner.temp }}/cb-state/${{ github.action }}/base
225-
RENEW_WITHIN_DAYS: '30'
225+
# Must match the review retention below: a review references a base by
226+
# id for its whole life, so a base with less than that left is renewed.
227+
RENEW_WITHIN_DAYS: '14'
226228
run: "$GITHUB_ACTION_PATH/scripts/action/fetch-state.sh"
227229

228230
- name: Fetch this pull request's last analysis
@@ -283,14 +285,13 @@ runs:
283285
with:
284286
name: codeboarding-base-${{ steps.state.outputs.cfg_hash }}-${{ steps.sync_commit.outputs.baseline_sha }}
285287
path: ${{ runner.temp }}/cb-state/${{ github.action }}/out/base
286-
# Longer than a review's 30 days on purpose, and the margin is the whole
288+
# Longer than a review's 14 days on purpose, and the margin is the whole
287289
# point: correctness comes from the renewal check, which republishes any
288290
# base with less than a review's lifetime left, while this surplus
289291
# decides how often that fires. Equal lifetimes renew on every run and
290292
# publish a base per run rather than per merge base — more storage, not
291-
# less. 60 leaves a 30-day reuse window, so a pull request open a month
292-
# never triggers one.
293-
retention-days: 60
293+
# less. 30 leaves a 16-day reuse window.
294+
retention-days: 30
294295
if-no-files-found: ignore
295296

296297
- name: Publish baseline analysis for the analyzed commit
@@ -300,14 +301,13 @@ runs:
300301
with:
301302
name: codeboarding-base-${{ steps.state.outputs.cfg_hash }}-${{ steps.sync_commit.outputs.analyzed_sha }}
302303
path: ${{ runner.temp }}/cb-state/${{ github.action }}/out/base
303-
# Longer than a review's 30 days on purpose, and the margin is the whole
304+
# Longer than a review's 14 days on purpose, and the margin is the whole
304305
# point: correctness comes from the renewal check, which republishes any
305306
# base with less than a review's lifetime left, while this surplus
306307
# decides how often that fires. Equal lifetimes renew on every run and
307308
# publish a base per run rather than per merge base — more storage, not
308-
# less. 60 leaves a 30-day reuse window, so a pull request open a month
309-
# never triggers one.
310-
retention-days: 60
309+
# less. 30 leaves a 16-day reuse window.
310+
retention-days: 30
311311
if-no-files-found: ignore
312312

313313
- name: Write sync summary
@@ -371,14 +371,13 @@ runs:
371371
with:
372372
name: ${{ steps.state.outputs.base_name }}
373373
path: ${{ runner.temp }}/cb-state/${{ github.action }}/out/base
374-
# Longer than a review's 30 days on purpose, and the margin is the whole
374+
# Longer than a review's 14 days on purpose, and the margin is the whole
375375
# point: correctness comes from the renewal check, which republishes any
376376
# base with less than a review's lifetime left, while this surplus
377377
# decides how often that fires. Equal lifetimes renew on every run and
378378
# publish a base per run rather than per merge base — more storage, not
379-
# less. 60 leaves a 30-day reuse window, so a pull request open a month
380-
# never triggers one.
381-
retention-days: 60
379+
# less. 30 leaves a 16-day reuse window.
380+
retention-days: 30
382381
if-no-files-found: ignore
383382

384383
- name: Render review diagram
@@ -419,9 +418,11 @@ runs:
419418
name: codeboarding-review-${{ github.run_id }}-${{ github.run_attempt }}
420419
path: ${{ steps.review_artifact.outputs.artifact_dir }}
421420
if-no-files-found: error
422-
# Each run carries its own copy of the base graph, and the webview only
423-
# ever reads a pull request's latest artifact, so value drops off fast.
424-
retention-days: 30
421+
# The dominant storage cost, since it is the one kept for weeks. A pull
422+
# request open longer than this loses its rendered analysis until someone
423+
# asks for it again, which costs one incremental over the pull request:
424+
# the base graph is still published and needs no re-analysis.
425+
retention-days: 14
425426

426427
- name: Build review comment
427428
id: review_body

‎docs/COMMIT_STRATEGY.md‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ cache was free. Retention is the lever — see below.
2727

2828
| Artifact | Contents | Retention | Read by |
2929
|---|---|---|---|
30-
| `codeboarding-review-<run>-<attempt>` | `analysis.json`, `health_report.json`, `metadata.json` | 30 days | the webview, humans |
30+
| `codeboarding-review-<run>-<attempt>` | `analysis.json`, `health_report.json`, `metadata.json` | 14 days | the webview, humans |
3131
| `codeboarding-base-<cfg>-<merge_base>` | the merge base's own analysis | 30 days, renewed while still referenced | any later review forking from that commit |
3232
| `codeboarding-warmstart-<cfg>-pr<N>` | the working directory: graph, pickle, fingerprint, gate | **1 day**, configurable | only the next run of that pull request |
3333

@@ -71,9 +71,13 @@ that commit has a different merge base.
7171
Artifacts are charged by size × time, so the three windows are set by what reads
7272
them:
7373

74-
- **30 days** for the review artifact — a reader may come back to a pull request.
75-
- **Repository default** for a base graph — it must outlive every review artifact
76-
that names it.
74+
- **14 days** for the review artifact — the dominant cost, since it is the one
75+
kept for weeks. A pull request open longer loses its rendered analysis until
76+
someone asks for it again, which costs one incremental over the pull request:
77+
the base graph is still published, so nothing re-analyzes the base.
78+
- **30 days** for a base graph, which must outlive every review that names it.
79+
The renewal threshold is the review's own retention, so the surplus — 16 days
80+
here — is how long a base is reused before being republished.
7781
- **1 day** for the warm-start bundle, since only the next run reads it. This is
7882
`warmstart_retention_days` if a repository wants longer. It behaves like the
7983
old cache eviction: a pull request left alone longer than the window

‎tests/test_action_state.py‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,15 @@ def test_a_base_outlives_the_reviews_that_reference_it(self) -> None:
497497
f"{step['name']} does not outlive the reviews that reference it",
498498
)
499499

500+
def test_the_renewal_threshold_matches_the_review_retention(self) -> None:
501+
# A review references a base by id for its whole life, so the threshold
502+
# that triggers renewal has to be that same life. If the two drift apart,
503+
# a review can outlive the base it names and nothing catches it.
504+
text = (ROOT / "action.yml").read_text(encoding="utf-8")
505+
renew = next(l for l in text.splitlines() if "RENEW_WITHIN_DAYS:" in l)
506+
review = next(s for s in self._uploads() if "review_artifact.outputs.artifact_dir" in s.get("path", ""))
507+
self.assertIn(f"'{review['retention-days']}'", renew)
508+
500509
def test_the_reusable_analysis_honours_the_configured_retention(self) -> None:
501510
warmstart = [s for s in self._uploads() if "warmstart" in s.get("path", "")]
502511
self.assertTrue(warmstart, "no warm-start publication step found")

0 commit comments

Comments
 (0)