Skip to content

ci: version.json の commit-back を廃止しビルド時に焼き込む (aicshud/WHEEL#1014) - #136

Merged
so5 merged 1 commit into
mainfrom
fix/version-json-no-commit-back
Sep 11, 2026
Merged

so5 merged 1 commit into
mainfrom
fix/version-json-no-commit-back

Conversation

@so5

@so5 so5 commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

背景

内部管理 issue: aicshud/WHEEL#1014

run_test.yml は main 以外への push のたびに server/app/db/version.json
YYYY-MMDD-HHMMSS-beta で書き換え、[skip ci] update version number として
そのブランチへ commit-push しています。このため次の問題が起きていました。

  1. 並行 PR が version.json で必ず conflict します。 各 feature branch が
    このファイルへ独自の bot commit を持つためです。
  2. stale なバージョンが main / maintenance に載ります。 commit される値は
    「最後に CI が回ったブランチのタイムスタンプ」で常に -beta 固定であり、
    どのリリースタグとも対応しません。PR を merge するとこの値が main に載り、
    ソースから起動した場合の starting WHEEL server (version ...) ログが
    リリースタグと食い違います。
  3. source.tar.gz リリース物件が古いバージョンを積みます。
    build_and_deploy.ymlgit archive HEAD は commit 済みツリーを固めるため、
    同 workflow がその場で行う version.json 書き換えが反映されません。
    Docker / Singularity イメージは正しい値、source.tar.gz だけ stale でした。

方針

バージョン文字列は 静的データとして扱い、実行コード
(server/app/core/versionInfo.js) は version.json を読むだけとします
(変更なし)。値の確定は ビルド/パッケージング処理の中で行い、成果物へ
焼き込みます。サーバ起動時にアプリが値を計算する方式は採用しません。

変更内容

server/app/db/version.json

commit される値を固定のプレースホルダにします。

{"version": "not defined - this is a development build"}

以降 CI を含め何もこの追跡ファイルを書き換えません。 全ブランチで値が一致し、
分岐しないため conflict しません。

.github/workflows/run_test.yml

determine release type from branch name / update version.json /
commit and push version.json および関連の cat ステップを削除しました。
この push 専用だった test ジョブの GITHUB_TOKEN も削除しています
backup ジョブの GITLAB_ACCESS_TOKEN は別用途のため残置)。

.github/workflows/build_and_deploy.yml

  • worktree 書き換えをやめ、算出した VERSION_NUMBER
    YYYY-MMDD-HHMMSS-{release|maintenance|beta}、ブランチ判定は現行どおり)を
    docker build --build-arg WHEEL_VERSION=... で渡します。apptainer build
    同じ Docker イメージを変換するため変更不要です。Release の tag_name / name
    は従来どおり VERSION_NUMBER なので一致します。
  • source.tar.gzgit archive の出力を一旦展開し、version.json に実バージョンを
    書いてから再度 tar に固めます。これで Docker / Singularity / source tarball の
    3 つが同じバージョンを持ちます。

Dockerfile

  • git describe を実行してバージョンを 1 つ確定させる捨てステージ versioner
    追加しました。ビルド時に確定しイメージへ固定されるため「静的(焼き込み)」です。
    COPY --from=versioner で渡るのは /wheel-version(数十バイト)のみで、
    コピーした .git を含めそれ以外は最終イメージに入りません。
  • dev / exec ステージで version.json を焼き込みます。優先順位は
    1. --build-arg WHEEL_VERSION(CI が渡すリリース/ベータ文字列)
    2. versionergit describe 結果に -local を付与
    3. どちらも無ければ COPY してきた version.json をそのまま維持
      (commit 済みプレースホルダ、または source.tar.gz の焼き込み値)

.dockerignore

.git を除外すると versioner が常に unknown に落ちるため、その旨の注意書きを
追記しました(動作変更はありません)。

ドキュメント

version.json は GitHub Workflow が自動更新する」という、今回廃止した旧挙動の
記述が複数箇所に残っていたため合わせて修正しました。

  • documentMD/design/design.md: 新しい挙動(実行経路ごとの表を含む)を
    「バージョン番号の管理」として新規追加。
  • AGENTS.md / documentMD/design/developer_guide.md: 「変更しない」ルール自体は
    維持しつつ、理由を「CIが自動更新する」→「ビルド時に焼き込まれる固定
    プレースホルダ」に修正。
  • documentMD/design/testing.md / TEST_GUIDE.md: run_test.yml の説明から
    「成功後 version.json を自動更新」の行を削除(当該ステップ自体を削除したため)。
  • README.md: 「push すると version.json が更新されるので次の commit 前に pull
    すること」という注意書きを削除(この運用自体が無くなったため)。

実行経路ごとのバージョン表記

実行のしかた version.json を書くのは 表示される文字列
公式リリース(CI build_and_deploy CI の --build-arg 2026-MMDD-HHMMSS-{release|maintenance|beta}(= Release タグ)
ローカル docker build ..git あり)を配布 versioner ステージ 2026-0910-113917-release-42-g25ed44acb387-local
ソース持出し docker build --build-arg WHEEL_VERSION=... . Dockerfile(arg 優先) 渡した値
source.tar.gz を展開して docker build 既存の焼き込み値を維持 2026-MMDD-HHMMSS-{type}
ソースから直接 npm start(ビルドなし) 誰も書かない not defined - this is a development build

動作確認

rootless Docker + buildx 0.30.1 で実ビルドして確認しました。

  • docker build --target versioner: git describe--dirty なし)が
    clean な checkout で正しく動くこと。--no-cache でも再現。
    (最初 --dirty 付きで試したところ、.dockerignoredocumentMD/
    以下 449 個の tracked file を versionerCOPY . . から隠すため
    clean な checkout でも常に -dirty と誤判定される問題が出たため、
    --dirty は外しています。)
  • docker build --target dev(build-arg なし): <git describe>-local
    が焼き込まれること。
  • docker build --target exec --build-arg WHEEL_VERSION=...: 渡した値が
    そのまま焼き込まれること。
  • docker compose -f compose.dev.yml build && up: 起動し、
    starting WHEEL server (version not defined - this is a development build)
    がログに出ること(server/app を bind mount するため、イメージに焼き込んだ
    値ではなくプレースホルダが見える。設計どおり)。
  • run_test.yml / build_and_deploy.yml の YAML 妥当性、source.tar.gz
    再梱包(version 差し替え・.git 非混入・prefix 維持)を確認しました。

移行時の注意

  • この PR を merge した直後、その時点で open な他の PR は version.json
    プレースホルダ化差分で 1 回だけ conflict します。main 側を採用すれば
    以降は発生しません。
  • 履歴上の約 232 個の [skip ci] update version number commit は書き換えません。
  • maintenance 系ブランチへは別途 cherry-pick が必要です。

補足

package.json の version(root 2.1.0 / server 2.0.1)は今回変更していません。
将来 semver を併記したくなった場合は versionergit describe 結果へ
前置するだけで対応できます。

🤖 Generated with Claude Code

https://claude.ai/code/session_01C3jKNM1qubomM8UTRdkEWu

@so5
so5 force-pushed the fix/version-json-no-commit-back branch from 02f0a6b to 307f2e2 Compare September 11, 2026 00:55
The `[skip ci] update version number` step in run_test.yml rewrote
server/app/db/version.json and pushed it to every feature branch, so
parallel PRs conflicted on that file and a stale `-beta` value rode onto
main/maintenance at merge (issue #1014).

- run_test.yml: drop the version-stamp / commit / push steps and the
  now-unused GITHUB_TOKEN from the test job. CI no longer touches the file.
- version.json: the committed value is a fixed placeholder
  ("not defined - this is a development build"). Nothing in CI edits the
  tracked file, so it never diverges between branches -> no more conflicts.
- build_and_deploy.yml: pass the computed version through the
  WHEEL_VERSION build-arg instead of editing the worktree; repack
  source.tar.gz from a clean tree with the real version dropped in
  (git archive shipped the placeholder before).
- Dockerfile: a throwaway `versioner` stage runs `git describe` on the
  build context, so a plain `docker build .` still bakes a
  commit-identifying version (`<describe>-local`). `--build-arg
  WHEEL_VERSION` overrides it; an un-stamped source build keeps whatever
  version.json ships. No --dirty: .dockerignore hides tracked paths
  (documentMD/) from the stage's `COPY . .`, so --dirty would always fire.

versionInfo.js is unchanged - it still statically imports version.json.

Verified with rootless Docker + buildx 0.30.1: dev build with no build-arg
bakes `<describe>-local`; exec build with --build-arg bakes the exact
value; `docker compose -f compose.dev.yml build && up` starts and logs
`starting WHEEL server (version not defined - this is a development build)`
(bind mount shadows the baked file, as intended for dev).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C3jKNM1qubomM8UTRdkEWu
@so5
so5 force-pushed the fix/version-json-no-commit-back branch from 307f2e2 to 3d002b1 Compare September 11, 2026 03:48
@so5
so5 merged commit 931f0ae into main Sep 11, 2026
@so5
so5 deleted the fix/version-json-no-commit-back branch September 11, 2026 09:51
so5 added a commit that referenced this pull request Sep 11, 2026
…ime (#136) (#138)

Backport of PR #136 (main) to maintenance2023. This branch's Dockerfile
predates the run_base/dev/versioner-friendly layout on main (it's
builder -> base -> {UT, exec}, node:hydrogen-slim, no separate dev
stage), so the backport is adapted rather than a literal copy:
- versioner is `FROM base AS versioner` (base already has git installed)
  followed by `COPY . .` + `git describe`, same idea as main.
- the version is baked only in the `exec` stage (there is no `dev` stage
  here); paths use this stage's WORKDIR (/usr/src/server, so
  app/db/version.json, not server/app/db/version.json).
- kept "master" branch naming used in this line's run_test.yml /
  build_and_deploy.yml comments (unlike main, not yet renamed here).
- did not add the entrypoint.sh ssh-agent block (PR #135, not backported
  to this branch) or the doc files that don't exist here yet (AGENTS.md,
  TEST_GUIDE.md, documentMD/design/{developer_guide,testing}.md).

The `[skip ci] update version number` step in run_test.yml rewrote
server/app/db/version.json and pushed it to every feature branch, so
parallel PRs conflicted on that file and a stale `-beta` value rode onto
main/maintenance at merge (issue #1014).

- run_test.yml: drop the version-stamp / commit / push steps.
- version.json: the committed value is a fixed placeholder
  ("not defined - this is a development build"). Nothing in CI edits the
  tracked file, so it never diverges between branches -> no more conflicts.
- build_and_deploy.yml: pass the computed version through the
  WHEEL_VERSION build-arg instead of editing the worktree; repack
  source.tar.gz from a clean tree with the real version dropped in
  (git archive shipped the placeholder before).

versionInfo.js is unchanged - it still statically imports version.json.

(cherry picked from commit 931f0ae)


Claude-Session: https://claude.ai/code/session_01C3jKNM1qubomM8UTRdkEWu

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
so5 added a commit that referenced this pull request Sep 11, 2026
…ime (#136) (#137)

Backport of PR #136 (main) to maintenance2026. Adjusted for this branch:
- kept "master" branch naming used in this line's run_test.yml /
  build_and_deploy.yml comments (unlike main, not yet renamed here)
- kept `RUN npm prune --production` in the exec stage as-is (this branch
  still prunes; main's "don't prune" comment doesn't apply here)
- did not add the entrypoint.sh ssh-agent block (PR #135, not backported
  to this branch) or the doc files that don't exist here yet (AGENTS.md,
  TEST_GUIDE.md, documentMD/design/{developer_guide,testing}.md)

The `[skip ci] update version number` step in run_test.yml rewrote
server/app/db/version.json and pushed it to every feature branch, so
parallel PRs conflicted on that file and a stale `-beta` value rode onto
main/maintenance at merge (issue #1014).

- run_test.yml: drop the version-stamp / commit / push steps and the
  now-unused GITHUB_TOKEN from the test job. CI no longer touches the file.
- version.json: the committed value is a fixed placeholder
  ("not defined - this is a development build"). Nothing in CI edits the
  tracked file, so it never diverges between branches -> no more conflicts.
- build_and_deploy.yml: pass the computed version through the
  WHEEL_VERSION build-arg instead of editing the worktree; repack
  source.tar.gz from a clean tree with the real version dropped in
  (git archive shipped the placeholder before).
- Dockerfile: a throwaway `versioner` stage runs `git describe` on the
  build context, so a plain `docker build .` still bakes a
  commit-identifying version (`<describe>-local`). `--build-arg
  WHEEL_VERSION` overrides it; an un-stamped source build keeps whatever
  version.json ships. No --dirty: .dockerignore hides tracked paths
  (documentMD/) from the stage's `COPY . .`, so --dirty would always fire.

versionInfo.js is unchanged - it still statically imports version.json.

(cherry picked from commit 931f0ae)


Claude-Session: https://claude.ai/code/session_01C3jKNM1qubomM8UTRdkEWu

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
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