11 KiB
11 KiB
id, status
| id | status |
|---|---|
| dcy-0004 | confirmed |
requester-versioned·runtime-locked image publication
Problem
현재 .github/workflows/publish-image.yml은 main과 v* push 모두에서 GHCR publication을 실행한다. 이 때문에 문서·governance-only main commit도 새 registry artifact를 만들며, publication을 요청자가 선택한 release version과 분리해서 통제할 수 없다.
repository verification은 uv sync --extra dev --locked를 사용하지만 현재 Dockerfile은 pyproject.toml만 복사한 뒤 pip install .을 실행한다. 따라서 CI 검증 환경과 built image의 runtime dependency graph가 동일한 repository-owned uv.lock resolution을 사용한다는 보장이 없다.
이 Discovery는 기존의 single build, built-image smoke, image ID, archive SHA-256, canary scan, OCI source revision, rebuild 없는 publish와 multi-tag same-digest 계약을 유지하면서 publication authority를 strict requester-selected version tag로 제한하고 runtime dependency identity를 lockfile에 결속한다.
Evidence
- GitHub issue #57
https://github.com/fourblocks2020/trex-core/issues/57은 requester-versioned·runtime-locked publication 변경과 완료 조건을 기록한 원본 제안이다. - 요청자는 모든 OQ에서 정확히 하나의 선택지를 선택한 뒤 이슈 본문 갱신과 Discovery 승인을 명시적으로 지시했다.
- 승인 결정에 따라
vX.Y.ZGit tag는 container publication version authority이며pyproject.toml의[project].version과 독립적이다. 두 값을 일치시키는 검증이나 package version 변경은 요구하지 않는다. - 승인 결정에 따라 별도 비게시 CI를 추가하지 않는다. full Ruff와 full pytest는 strict version-tag publication gate에서 실행하고, 일반
main/branch push에는 이 Discovery가 별도 CI workflow를 추가하지 않는다. - 조사 기준 source revision은
1a2b50072238ea72186d99b3ec951fc9511100aa이며 조사 시main과origin/main은 동기화되어 있고 worktree는 clean이었다. .github/workflows/publish-image.yml은 현재main과v*push를 모두 trigger로 사용하고, exactgithub.shacheckout 후uv sync --extra dev --locked, full Ruff, full pytest, single Docker build, built-image smoke, image ID 기록, archive export·canary scan·SHA-256 기록과 immutable artifact handoff를 수행한다. 별도 publish job만packages: write를 가지며 tested artifact를 재빌드 없이 게시한다.Dockerfile은 현재pyproject.toml과trex_core/만 copy한 뒤pip install --no-cache-dir .을 실행하므로uv.lock을 runtime dependency installation input으로 사용하지 않는다.scripts/image_release.py::release_tags()는 현재refs/heads/main을 허용하고v로 시작하는 넓은 tag 형식을 허용한다. publish helper는 archive checksum, tested/loaded image ID, OCI revision, registry credential 경계, 두 tag의 same-digest와 성공 evidence 생성을 검증하지만 strictvX.Y.Zevent만 허용하지는 않는다.tests/release/test_image_contracts.py는 현재main/v*trigger와 Dockerfile의 기존 COPY allowlist를 고정하고 있어 승인된 trigger·runtime lock 계약에 맞춰 변경해야 한다.docs/operations.md는 source-derived tag를 stable selector로, registry digest를 immutable deployment/rollback identity로 설명하고 runtime config·secret 외부 주입 및 reset 분리 경계를 보존한다. version tag 생성·push가 별도 사용자 승인 외부 쓰기라는 절차는 아직 설명하지 않는다.- 기존 active AC 중 AC-0004는
main또는v*event의 verification-gated publication, AC-0006은 source tag·release tag·digest 추적성, AC-0008은 Docker COPY allowlist와 secret/config 비포함을 소유한다. AC-0005의 tested-artifact identity와 AC-0007의 built-container smoke는 이번 변경에서도 의미를 유지한다. - 비교 기준
trex-mega-swing-v2revision88e90caea7e4ab740ed785fc1f57aed8b6f2da5f의 workflow는 strictvX.Y.Ztag-only trigger, event/ref/commit fail-closed validation, exact tagged commit checkout, locked verify, single build와 tested-artifact publication을 사용한다. workflow run31468042611은v0.1.0tag에서 성공했다. - 기준 revision에서
proofline validate는 exit0,uv run ruff check .은All checks passed!,uv run pytest -q는1040 passed, 51 skipped를 반환했다. skip은 환경 의존 integration 경계이며 현재 repository baseline이 승인된 변경을 이미 구현했다는 의미는 아니다.
Scope
- AC admission은 기존 동작의 권한·식별자·build input을 변경하는
update와 새로운 runtime lock 동작을 정의하는create다.update: AC-0004의 publication event를 일반main/v*에서 strict version-tag-only로 변경하고 malformed/non-version event가 registry credential·write 전에 실패하도록 한다.update: AC-0006에 strict requester-selectedvX.Y.Zversion tag, source-derived tag와 version tag의 same-digest, version을 포함한 publication evidence를 반영한다.update: AC-0008의 좁은 Docker build input allowlist에 repository-owneduv.lock과 locked installation에 필요한 도구만 추가하면서 기존 config·credential·canary 비포함 경계를 보존한다.create: repository verification과 runtime image가 동일한 repository-owned lock resolution을 사용하고 lock mismatch 또는 unlocked runtime install을 거부하는 독립적인 장기 AC를 추가한다.- AC-0005의 tested-artifact identity와 AC-0007의 built-container package·entrypoint smoke는 변경 없이 유지한다.
- GHCR publication workflow의 유일한 trigger는 requester가 exact source commit에 생성·push한 strict
vX.Y.Ztag다. 각 숫자 구성요소는0또는 leading zero가 없는 non-negative decimal integer여야 하며 prerelease/build suffix, malformed tag, branch ref와 non-push event는 허용하지 않는다. - workflow는 event·ref·40자리 lowercase source commit을 registry credential 사용 전에 fail-closed로 검증하고, exact tagged commit을 checkout했음을 다시 확인한다.
- version tag는 container publication identity이며
pyproject.toml의[project].version과 독립적으로 취급한다. package version 일치 검사, 자동 version 증분과 package metadata 변경을 수행하지 않는다. - 일반
main과 branch push는 registry login,docker push,packages: write또는 image publication을 수행하지 않는다. 요청자 결정에 따라 이번 Scope는 일반main/branch push를 위한 별도 비게시 CI workflow를 추가하지 않는다. - 허용된 version-tag event는 exact source checkout 후 pinned
uv와 repository-owneduv.lock으로 full Ruff와 full pytest를 실행하고, 성공한 경우에만 이미지를 한 번 빌드한다. - Docker build는
pyproject.toml,uv.lock과 allowlisted package source로 runtime environment를uv sync --locked --no-dev --no-editable또는 의미상 동등한 locked 방식으로 설치한다. lock mismatch, missing lockfile 또는 lock을 우회한 runtime dependency install은 build/publication 전에 실패한다. - 동일한 tested image에
:<source-commit-first-12>와:vX.Y.Z를 부여하고 두 tag가 동일한 registry digest를 가리키는지 확인한다. immutable deployment·rollback identity는@sha256:<digest>다. - 기존
scripts/image_release.py의 archive checksum, tested/loaded image ID, OCI revision, canary surface scan, no-rebuild publication, registry credential 경계와 multi-tag same-digest 검증을 유지한다. latest를 생성하지 않으며 성공 evidence에는 source revision, immutable image reference, digest와 selected version tag를 함께 기록한다.- workflow contract와 helper tests는 일반 branch/main non-publication, strict event validation, exact checkout, lock mismatch, locked runtime build, same-digest tags, no-
latest, no-rebuild 및 기존 failure boundaries를 검증한다. - operator documentation은 version 선택과 Git tag 생성·push가 구현과 분리된 사용자 승인 외부 쓰기이고, tag push가 verify/publication을 시작한다는 점을 설명한다.
Out of Scope
- 이 Discovery 또는 후속 구현 중 concrete version 선택, version tag 생성·push, 최초·후속 GHCR package write, production deployment 또는 운영 서버 pull/restart
- 일반
main/branch push를 위한 별도 lint/test CI workflow 신설 또는 기존 publication workflow 외 CI 정책 변경 pyproject.tomlpackage version 변경, version tag와 package version의 일치 강제 또는 자동 version 증분- 기존 published tag·digest 삭제, 이동 또는 registry retention 변경
- live credential, 실제 account·database·RabbitMQ·Redis·KIS·portfolio-hub 연결, database migration/reset 또는 운영 데이터 변경
- image signing, SBOM, provenance attestation, multi-architecture build와 moving
latest - 다른 TREX repository의 workflow, image 또는 release policy 변경
Risks and Unknowns
Risks
- trigger 변경 후 일반
mainpush는 새 runtime image뿐 아니라 현재 publication workflow가 제공하던 full Ruff/pytest도 실행하지 않는다. 이는 요청자가 선택한 정책이며, branch protection 또는 지속적 검증이 필요해지면 registry 권한이 없는 별도 CI 변경으로 다룬다. - version tag와 package version을 독립적으로 두면 image
:vX.Y.Z와 installed Python package metadata version이 다를 수 있다. container publication version authority는 Git tag임을 문서화하고, package version synchronization이 필요해지면 별도 변경으로 다룬다. - GitHub trigger glob만으로는 malformed
v*.*.*를 모두 배제할 수 없다. workflow 내부 helper가 strict ref/event/commit을 registry credential 전에 재검증해야 한다. - Docker build가 lockfile을 copy만 하고 실제 runtime install에 소비하지 않으면 CI lock PASS만으로 runtime reproducibility를 주장할 수 없다. build contract와 tests가 locked runtime command 및 mismatch failure를 직접 검증한다.
- version tag와 source-derived tag를 별도 build에서 만들면 같은 release identity가 서로 다른 image를 가리킬 수 있다. 단일 tested artifact를 재빌드 없이 두 tag로 push하고 registry digest equality를 확인한다.
- 기존 commit-derived selector와 immutable digest는 보존해야 하며 migration 과정에서 과거 tag를 삭제하거나 이동하지 않는다.
- tag 생성·push는 즉시 publication workflow와 registry write를 유발할 수 있다. operator 문서가 이를 별도 사용자 승인 외부 쓰기로 명시하고 구현·테스트 중 실제 tag push를 금지한다.
Approval State
- Discovery status:
confirmed - 승인 근거: 요청자가 이슈의 모든 OQ에서 하나의 선택지를 명시적으로 선택한 뒤 이슈 본문 업데이트와 승인을 지시했다.
- 채택 결정: version tag와 package version은 독립적으로 취급하며, 일반
main/branch push용 별도 비게시 CI는 추가하지 않는다. - 추가로 필요한 제품 결정: 없음
- 이 승인은 Discovery 범위 확인이며 Requirement/AC 승인, 구현, tag 생성·push, GHCR publication, delivery, release 또는 deployment 완료를 의미하지 않는다.