58 lines
7.8 KiB
Markdown
58 lines
7.8 KiB
Markdown
---
|
|
id: "dcy-0002"
|
|
status: confirmed
|
|
---
|
|
|
|
# trex-core 검증 컨테이너 이미지의 GHCR 게시
|
|
|
|
## Problem
|
|
|
|
`trex-core`는 Python 패키지와 daemon entrypoint를 제공하지만 저장소 자체에는 운영자가 가져다 실행할 수 있는 컨테이너 이미지 정의와 GitHub 게시 자동화가 없다. 따라서 특정 source commit으로부터 어떤 이미지가 만들어졌는지, 그 이미지가 repository 검증과 컨테이너 검사를 통과했는지, 운영자가 어떤 불변 식별자로 같은 이미지를 가져와야 하는지에 대한 공통 배포 계약이 없다.
|
|
|
|
`kis-data-hub`는 GitHub Actions에서 source 검증, 이미지 빌드, built-container 검사, 검증 이미지 artifact 전달, GHCR 게시를 분리하고 source commit·tag·digest를 기록한다. 요청자는 `trex-core`도 같은 방식을 채택하고 그 배포 방식을 일회성 구현 메모가 아니라 장기 active Acceptance Criteria로 보존하기로 결정했다.
|
|
|
|
기대 상태는 `trex-core`의 정확한 source commit에서 만든 컨테이너가 repository 및 built-image 검증을 모두 통과한 경우에만 `ghcr.io/fourblocks2020/trex-core`에 게시되고, 운영자가 source commit과 digest를 역추적하며 불변 이미지로 배포·롤백할 수 있는 것이다.
|
|
|
|
## Evidence
|
|
|
|
- 현재 기준 `trex-core` source commit은 `c0f36946a3a06ec0d2bde2e9f40686d602754f50`이고 `main`은 `origin/main`과 동기화되어 있다. `git status --short --branch`는 변경 전 `## main...origin/main`을 반환했다.
|
|
- `pyproject.toml:1-12,20-23`은 배포명 `trex-core`, Python `>=3.12`, runtime dependencies와 `trex-core-daemon`·`trex-core`·`trex-core-reset` entrypoint를 선언한다.
|
|
- `trex_core/runtime/daemon.py:562-585`에서 daemon은 `--config`를 필수로 받고 `--config-path` 또는 explicit path로 per-instance TOML을 읽는다. 따라서 운영 config와 credential을 이미지에 고정하지 않고 런타임에 주입하는 계약이 필요하다.
|
|
- 현재 저장소 검색과 파일 존재 검사에서 repository-root `Dockerfile`과 `.github/workflows/publish-image.yml`은 모두 존재하지 않았다. `.github/` workflow도 없다.
|
|
- `trex-sim/compose/dockerfiles/Dockerfile.trex-core:1-29`에는 simulation 전용 이미지 정의가 있으나 workspace-root build context, sim config, `/start.sh`에 결합되어 있고 `trex-sim` 격리 스택만을 위한 것이므로 `trex-core`의 독립 게시 이미지 계약을 대신하지 않는다.
|
|
- 비교 기준인 `kis-data-hub/.github/workflows/publish-image.yml:3-8,14-78`은 `main`과 `v*` push에서 test→build→built-container liveness→tested-image artifact 업로드를 수행한다. 같은 파일 `80-141`은 publish job이 artifact를 로드하고 GHCR에 commit SHA tag를 게시하며 tag event에서는 release tag를 추가하고 digest와 source commit을 기록한다.
|
|
- `kis-data-hub/Dockerfile:1-16`은 서비스의 Python version에 맞는 slim base에서 package를 설치하고 runtime command를 선언한다. 현재 `kis-data-hub` checkout은 `c38b975b37a44d93f3728389d47efcfe696bd895`이며 관련 게시 구현의 마지막 수정은 `77a3bcc1cc9d4304e82abdd9ca277786bd30c4ad`다.
|
|
- `HOME=/home/genichin gh run list --repo fourblocks2020/kis-data-hub --workflow publish-image.yml --limit 5`에서 최근 `main` push의 workflow 성공 실행 `30742432705`, `30742417884`, `30742101305`가 확인되어 비교 대상 방식이 GitHub에서 실제 실행됨을 확인했다.
|
|
|
|
## Scope
|
|
|
|
- AC admission 분류는 새로운 장기 active 동작을 정의하는 `create`다. 기존 `ac-0001`~`ac-0003`은 KIS 잔고 snapshot 완전성과 reconciliation 회귀를 소유하므로 수정하거나 이 배포 계약을 결합하지 않는다.
|
|
- repository-root에서 독립적으로 빌드되는 Python 3.12 기반 `trex-core` 컨테이너 이미지 계약을 정의한다. 이미지에는 package와 세 console entrypoint를 포함하되 운영 TOML, `.env`, credential, token, 실제 connection string은 포함하지 않는다.
|
|
- GitHub Actions는 정확한 source commit을 checkout하고 repository 검증을 통과한 뒤 이미지를 한 번 빌드한다. built-container 검사까지 통과한 동일 이미지를 artifact로 publish job에 전달하며 publish job은 이미지를 다시 빌드하지 않는다.
|
|
- 게시 대상은 `ghcr.io/fourblocks2020/trex-core`다. `main` push에는 source commit에서 파생된 불변 SHA tag를 게시하고 `v*` tag push에는 같은 이미지에 해당 release tag를 추가한다. 이동 가능한 `latest` tag는 게시하지 않는다.
|
|
- 게시 이미지에는 최소한 `org.opencontainers.image.revision`으로 전체 source commit을 기록하고, GitHub Actions summary 또는 output에 게시 tag, digest, source commit을 남긴다.
|
|
- repository 검증, image build, built-container 검사, artifact 전달 또는 digest 확인 중 하나라도 실패하면 publish 단계는 실패하거나 실행되지 않아야 하며 검증되지 않은 이미지를 정상 게시 결과로 보고하지 않는다.
|
|
- built-container 검사는 `trex-core`의 daemon 특성에 맞춰 package import와 세 console entrypoint의 실행 가능성을 확인하고, 운영 서비스·운영계좌·실제 credential을 사용하지 않는 deterministic synthetic 경계에서 수행한다. HTTP `/health`가 있는 `kis-data-hub`의 probe를 그대로 복제하지 않는다.
|
|
- runtime 사용 문서는 per-instance config와 secret을 외부에서 주입하는 방법, SHA tag 또는 digest pin, 이전 digest로의 rollback 원칙을 기록한다. 파괴적인 `trex-core-reset`은 자동 rollback 절차에 포함하지 않는다.
|
|
- 구현 검증은 repository-local test, workflow 정적/단위 검증, local Docker build와 built-image smoke까지 포함한다. GitHub `main` 반영과 최초 GHCR 게시 같은 외부 쓰기는 별도 승인 이후의 integration/release evidence로 구분한다.
|
|
|
|
## Out of Scope
|
|
|
|
- 운영 서버 또는 production Compose에서 이미지 pull·교체·재시작 수행
|
|
- 실제 KIS 계좌, 운영 credential, 운영 PostgreSQL·RabbitMQ·Redis·portfolio-hub를 이용한 smoke test
|
|
- DB schema 변경, migration 실행, `trex-core-reset`, 운영 데이터 rollback
|
|
- `kis-data-hub`, `portfolio-hub`, 전략 daemon 또는 `trex-sim` 저장소 변경
|
|
- multi-architecture image, public package visibility 변경, image signing·SBOM·provenance attestation 도입
|
|
- 새로운 애플리케이션 health HTTP endpoint 추가
|
|
- 특정 release version 결정, release tag 생성, 운영 배포 완료 또는 production 검증 주장
|
|
|
|
## Risks and Unknowns
|
|
|
|
### Risks
|
|
|
|
- publish job이 이미지를 다시 빌드하면 검증한 bytes와 게시한 bytes가 달라질 수 있다. 완화책은 verify job의 tested image를 artifact로 넘겨 publish job이 그대로 load·tag·push하도록 강제하는 것이다.
|
|
- 모든 `main` push가 게시 trigger이면 문서-only commit도 새 SHA image를 만든다. 이는 현재 `kis-data-hub`와 동일한 단순·일관된 정책으로 수용하고, 향후 비용이나 보존 문제가 관찰되면 path filter 또는 retention을 별도 변경으로 다룬다.
|
|
- daemon startup은 외부 서비스에 의존하므로 운영 의존성을 CI에 연결하면 credential 노출이나 비결정적 실패가 생길 수 있다. 완화책은 synthetic config와 local disposable dependencies 또는 외부 연결 없는 entrypoint smoke를 사용하고 실제 운영 연결을 금지하는 것이다.
|
|
- mutable `latest`나 version tag만 사용하면 source와 rollback 지점이 불명확해질 수 있다. 완화책은 모든 게시에서 commit SHA tag와 digest를 남기고 운영 배포에는 digest pin을 우선하는 것이다.
|
|
- 이미지에 운영 config나 secret이 복사되면 registry 접근자가 이를 회수할 수 있다. 완화책은 좁은 Docker build context, `.dockerignore`, 금지 파일 검사와 runtime-only 주입 계약이다.
|