Skip to content

fix(sync): publish without force under the ruleset - #2

Open
shmpwk wants to merge 3 commits into
cifrom
feat/sources-yaml-deterministic-mirror
Open

fix(sync): publish without force under the ruleset#2
shmpwk wants to merge 3 commits into
cifrom
feat/sources-yaml-deterministic-mirror

Conversation

@shmpwk

@shmpwk shmpwk commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

ルールセットが force push を禁じていても、このリポジトリのミラーを publish できるようにする。土台は次の三つで、どれも同じ筋に乗る。

  1. フラットなブランチ名を維持するawf-latest/universeawf-latest が残っていると作れない。組織ルールセットが既存ブランチの削除を拒むので、以前の workflow と同じ平坦な名前のままにする。
  2. 本当に必要なときだけ force するforce: true でも fast-forward には --force を付けない。付けていたせいで、ルールセットが受け入れる更新まで落ちていた。
  3. 結合ブランチを追記専用にする — ゼロから作り直すたびに公開済み commit id が書き換わっていた。公開済み tip から再開し、未反映のメンバー commit だけを積む。

保証の入れ替え(結合ブランチ)

毎回ゼロから再構築(旧) 追記専用(新)
ゼロから作り直して同じ id
公開済み commit id が未来永劫変わらない ❌ 順序が変わるたび全書き換え ✅ 構造的に保証
同じ入力から 2 台で同じ結果 ✅(同じ公開済み tip からなら一致)
force 片方が追いつくたびに必要 不要

実運用で効くのは 2 行目。awf-combined-latest は既に一度書き換わる状況になっており、ブランチを切る・コミットを参照する利用者から見ると、公開済み id の不変性の方が強い。失う「再構築で一致」は監査用の性質で、運用上の性質を犠牲にして得ていたものだった。

内容の検証は維持する

結合ブランチは 3 つのミラーからの派生物で、ミラー自体は完全に決定的。したがって「持つべき内容」はいつでも再計算でき、--verify は tip のツリーが現在のメンバー tip の合成と一致すること(および同じ公開済み tip からの append が再現すること)を見る。id ではなく内容で照合する。

外部状態は不要

「どこまで replay 済みか」は公開済み tip から復元する。tip には各メンバーのサブツリーがリネーム後のパスで入っており、その oid をメンバー履歴と突き合わせれば再開位置が一意に決まる。別ブランチや別 ref は持たない。

変わらないもの

  • universe / core / launch のミラー履歴は完全に決定的で、ここは何も変えない
  • フラット名のままなので、既に awf-latest / awf-core-latest を指しているものも動かさない

Test plan

  • tools/sync_config.py validate
  • dry-run: tools/mirror.py combine awf-combined-latest --work /tmp/combine --downstream <url> --verify
  • 公開済み tip がある状態で、メンバーが進んでいなければ unchanged / 進んでいれば fast-forward のみ
  • --force なしで ruleset 下の publish が通ること

shmpwk and others added 3 commits September 11, 2026 15:59
Publishing to awf-latest/universe needs refs/heads/awf-latest gone, because git
cannot hold a branch and a namespace of the same name. Deleting it here is
refused by the organisation rulesets, so the push failed with a ref lock error
even though the rule violations themselves were bypassed.

Keep the names the previous workflows used instead: awf-latest for the universe
mirror and awf-core-latest for the core one, both already present, plus a new
awf-launch-latest. Nothing that already points at those branches has to move,
and the namespace can still be adopted later: every branch is a deterministic
function of its inputs, so renaming costs one configuration change and one
rerun rather than a history rewrite.

Also carries the optional-source support the launch mirror depends on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Shumpei Wakabayashi <shumpei.wakabayashi@tier4.jp>
Publishing always passed --force for sources configured with force: true, even
when the update was a plain fast-forward. That is pointless, and it trips
rulesets that forbid non-fast-forward updates but would have accepted the very
same update without the flag.

Classify the update first. An unchanged branch is not pushed at all, a
fast-forward is pushed without --force, and only a genuinely diverged history
forces. A diverged history on a source that does not allow forcing now fails
with that as the reason instead of letting git report a non-fast-forward.

When the remote does reject a push, match its message and say which knob is
involved: a ref name colliding with an existing branch, a ruleset whose bypass
list does not include the pushing identity, or a history that diverged. These
took a while to tell apart by hand, and the raw git output names none of them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Shumpei Wakabayashi <shumpei.wakabayashi@tier4.jp>
Rebuilding awf-combined-latest from scratch reordered history whenever a
member advanced, which rewrote published commit ids and tripped rulesets
that forbid force pushes. Resume from the published tip by matching each
member's renamed subtree oids, append only the pending commits, and verify
the tip tree against the current member tips instead of rebuild identity.

Per-source mirrors stay fully deterministic; combined force stays off.

Signed-off-by: Shumpei Wakabayashi <shumpei.wakabayashi@tier4.jp>
Co-authored-by: Cursor <cursoragent@cursor.com>
@shmpwk shmpwk changed the title fix(sync): keep the flat branch names, and force only when needed fix(sync): publish without force under the ruleset Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant