Reconcile obsolete staging assets before verifying a new Nightly generation
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
調査の方向性
Start with the staging upload, verification and cleanup flow in tools/src/publication.rs near line 777, then read the Remote and generation helpers in tools/tests/publication.rs. Run the focused audit_stale_staging_generation test with the provided Cargo command to reproduce the extra-asset failure. Done means mocked regressions cover interrupted, repeated, stale and conflicting attempts plus cleanup failures, while final verification still checks all 29 assets and preserves the previous public Nightly.
索引モデルが issue の本文から書いたものです。
説明
Problem
A partial upload to the private nightly-staging draft can prevent a later Nightly generation from being published. The publisher uploads the new generation and verifies an exact remote asset set before it removes obsolete assets from the previous staging generation. Any leftover old filename therefore makes verification fail before cleanup can run.
Starting point: staging upload, verification and cleanup.
Reproduction
Audited canonical master e1f8effd195b6339c3979b1e091e63c25f1da983 on Linux amd64 with checkout-built Wave 0.0.1-alpha-dev, matching std, Rust 1.89.0, Cargo jobs=2 and LLVM 21.1.8. The master SHA was rechecked before registration. Publication was exercised through the existing stateful mock API, without creating or changing any real GitHub release.
Using the Remote and generation helpers in tools/tests/publication.rs, append this focused test to an isolated copy of that integration-test fixture:
#[test]
fn audit_stale_staging_generation() {
let temporary = tempfile::tempdir().unwrap();
let mut remote = Remote::new();
let (directory, mut first) = generation(temporary.path(), 'a', 1);
publication::promote(&mut remote, &directory, &mut first).unwrap();
let previous_public = remote.releases[&1].clone();
let (directory, mut partial) = generation(temporary.path(), 'b', 2);
remote.fault = Some((
"GET".into(),
"releases/2/assets?per_page=100&page=1".into(),
false,
));
assert!(publication::promote(&mut remote, &directory, &mut partial).is_err());
let asset = storage::files(&directory).unwrap().into_iter().next().unwrap();
remote.upload(&asset, "nightly-staging").unwrap();
let (directory, mut next) = generation(temporary.path(), 'c', 3);
let result = publication::promote(&mut remote, &directory, &mut next);
println!("result={result:?}");
println!("staging assets={}", remote.assets[&2].len());
println!("previous public retained={}", remote.releases[&1] == previous_public);
println!("obsolete deletions={:?}", remote.calls.iter()
.filter(|call| call.starts_with("DELETE releases/assets"))
.collect::<Vec<_>>());
}
Run the focused test against the audited wave-tools crate. For a temporary local test added to that fixture, the equivalent Cargo command is:
cargo +1.89.0 test --locked --jobs 2 -p wave-tools --test publication audit_stale_staging_generation -- --nocapture
The audit ran the same fixture-based sequence from an isolated test harness linked against the current crate. It first creates a valid published generation, leaves one real staged asset from a partial later generation, and then promotes a newer generation.
Observed:
result=Err("remote Nightly asset set differs from the verified generation")
staging assets=30
previous public retained=true
obsolete deletions=[]
The simulated partial upload is intentional: one old-generation artifact remains alongside the 29 artifacts of the new generation. The final exact-set verifier rejects the extra artifact, so the subsequent deletion loop is unreachable. Repeating the new promotion does not remove the obsolete asset.
Scope
Reconcile obsolete assets owned by the staging draft before final exact-set verification, or use an equivalent retry-safe generation transition. Preserve digest/size/source/run/attempt identity checks and fail on conflicting current-generation assets. Never delete assets from the active public generation to repair staging.
Related: #831 owns the broader Nightly publication contract and final-cutover recovery. This issue isolates the independently reproducible stale-draft asset ordering defect.
Completion criteria
- A partial older staging generation does not permanently block a valid newer generation or workflow attempt.
- Final verification still requires exactly the expected 29 assets for all nine package targets with correct digests, sizes and identity.
- Interrupted upload, repeated identical attempts, stale attempts, conflicting current filenames and cleanup failures have deterministic mocked regressions.
- Failures preserve the previously usable public Nightly and all canonical CI/installer approval gates.
- 主要言語
- Rust
- スター
- 56
- フォーク
- 21
- 平均マージ
- 22時間 57分
- マージ済み PR(30日)
- 46
環境構築
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
wavefnd/Wave のほかの issue
-
Reject unrepresentable POSIX listener descriptors before Unix-domain accept対応中かも @ShahadatTest が 3 日前に担当しました。 オープンbug good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
wavefnd/Wave#1082 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
bug help wanted
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
メンテナーはふだん 1 日以内に返信
-
bug help wanted
難易度 4/5 3〜5日 初心者へのやさしさ 53/100
メンテナーはふだん 1 日以内に返信
-
bug build help wanted
難易度 4/5 3〜5日 初心者へのやさしさ 56/100
メンテナーはふだん 1 日以内に返信
-
Prevent compiler stack overflow on long acyclic forward type-alias chains対応中かも @hiyouwhatsapp が 3 日前に担当しました。 オープンbug
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
メンテナーはふだん 1 日以内に返信
似ている issue
-
bug i18n priority: medium ui
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
storytold/craft-anything#983 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
Dinnerbone/Rascal#91 · リアクション 2 件 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
higress-group/HiRoute#405 ·
メンテナーはふだん 1 日以内に返信
-
rust_analyzer flycheck: no CLI way to enable clippy from `check.overrideCommand`対応中かも @TrapsterDK が今日担当しました。 オープンneeds-triage
難易度 2/5 1〜3時間 初心者へのやさしさ 77/100
bazelbuild/rules_rust#4392 ·
メンテナーはふだん 2 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信