Versioning

이 문서는 source repo의 버전 계산과 artifact tag 기준을 설명합니다.

언제 dev version을 계산하고 언제 release artifact로 publish하는지는 CI/CDRelease Policy를 따릅니다. 이 문서는 그 과정에서 package manager와 container/firmware artifact가 어떤 version string을 사용하는지에 집중합니다.

1. 기본 정책

이 repo의 versioning strategy는 lockstep/fixed versioning입니다. Root release tag 하나가 source repo 전체 release set의 version을 결정합니다. Independent versioning은 package별 SemVer를 따로 관리하는 방식이지만, 이 repo에서는 SaMD system baseline 추적성을 우선해 사용하지 않습니다.

release tag가 있으면 tag 기반 SemVer를 사용합니다. release tag가 없으면 commit distance와 short SHA를 포함한 dev version을 사용합니다.

각 workflow는 먼저 .github/actions/compute-version으로 Git tag와 commit distance를 읽어 이번 run의 version을 계산합니다. 이 action의 output은 모두 같은 root release tag 또는 같은 dev source revision에서 파생되어야 합니다.

Release tag(v0.1.0)에서는 package metadata와 firmware path에 0.1.0을 쓰고, container image tag에는 Git tag와 같은 v0.1.0을 씁니다. Branch/dev build에서는 다음 minor의 prerelease/dev version을 만듭니다. Commit마다 Git tag를 자동 생성하지 않고 CI run 안에서만 dev version을 계산하는 이유는 tag 폭증을 막으면서도 artifact 추적성을 남기기 위해서입니다.

예를 들어 최신 release가 v0.1.0이고 그 뒤로 37개의 commit이 있다면 SemVer 생태계는 0.2.0-dev.37을 사용합니다. Python은 PEP 440 규칙 때문에 0.2.0.dev37을 사용합니다. Container image는 registry에서 사람이 source를 추적하기 쉽도록 dev-37-g<short_sha> 형태를 씁니다.

Dev version을 계산한다는 것은 항상 모든 artifact를 registry에 publish한다는 뜻이 아닙니다. CI는 main/dev run에서도 추적 가능한 version을 계산합니다. 이 repo는 main merge에서 container dev image를 자동 publish하지만, package publish는 release 또는 명시적인 dev package policy가 있을 때만 수행합니다.

2. 생태계별 버전

Version을 package metadata에 반영할 때는 생태계별 도구를 사용합니다. 직접 sed로 파일을 고치지 않는 이유는 각 package manager가 lockfile, metadata, registry 규칙을 가장 잘 알고 있기 때문입니다.

Ecosystem CI version command Why
TypeScript/npm npm version --no-git-tag-version --allow-same-version npm package metadata를 표준 방식으로 갱신하고 Git tag는 CI가 만들지 않습니다.
Python/uv uv version --package ... --frozen 또는 uv version --project ... --frozen PEP 440 version을 pyproject.toml에 반영하되 lockfile을 CI에서 임의 갱신하지 않습니다. Workspace package는 --package, standalone package는 --project를 사용합니다.
Rust/Cargo cargo set-version from cargo-edit Cargo manifest version 갱신은 Cargo 생태계 도구에 맡깁니다.
Go module-path semver tag 또는 pseudo-version Go module은 package file upload보다 VCS tag와 module proxy가 배포 단위입니다.
C/Conan conan create --version ... C library package version은 Conan recipe invocation에서 명시합니다.
Container/Firmware computed image/artifact tag Docker image와 firmware binary는 package metadata가 없으므로 CI가 계산한 immutable tag/path를 사용합니다.

3. 구현 위치

  • GitHub Action: .github/actions/compute-version/action.yml
  • Script: scripts/compute-version.sh

CI workflow는 이 결과를 package build와 publish step에 전달합니다.

PyO3/maturin Rust Python wheel처럼 Rust crate metadata와 Python wheel metadata가 함께 있는 package는 두 version output을 모두 사용합니다. Cargo manifest에는 rust_version을 적용하고, Python pyproject.toml에는 python_version을 적용합니다. 두 문자열은 표기가 다르지만 같은 source revision에서 계산된 대응 version입니다.

4. Computed Version Outputs

compute-version action의 output은 workflow 사이의 contract입니다. Workflow나 composite action이 output 이름을 직접 공유하므로, 이 표는 CI contract 문서 역할도 합니다.

Output Example Used by
channel release, dev release/dev 분기 판단
base_version 0.1.0 latest release 기준 표시
commits_since_release 37 dev version distance
short_sha abc1234def56 traceable dev tag
semver 0.2.0-dev.37 npm, Rust, Conan dev version
npm_version 0.2.0-dev.37 npm version
python_version 0.2.0.dev37 uv version, PEP 440
rust_version 0.2.0-dev.37 cargo set-version
conan_version 0.2.0-dev.37 conan create --version
image_tag dev-37-gabc1234def56 container publish tag
firmware_version 0.2.0-dev.37 firmware artifact path/name
go_module_tag source-repo/packages/patient-risk-go-core/v0.2.0-dev.37 Go module release tag 안내

5. Release Tag와 Dev Build의 차이

Release tag는 사람과 CD repo가 기준으로 삼는 고정된 release marker입니다. Dev build는 CI가 매번 계산하는 추적 가능한 artifact name입니다.

Release tag는 개별 package 하나의 publish trigger가 아니라 package, image, firmware, contract를 같은 검증 baseline으로 묶는 anchor입니다. Dev build는 이 anchor를 만들지 않고 source revision을 추적할 수 있는 임시 artifact name만 계산합니다.

Case Version behavior
v0.1.0 tag package와 firmware는 0.1.0, container image는 v0.1.0 release tag로 publish됩니다.
main push container dev image를 dev, dev-N-g<sha>, sha-<sha> tag로 publish하고, package는 기본적으로 build/test만 수행합니다.
branch push publish하지 않거나 manual dev channel로 0.2.0-dev.N artifact를 만들 수 있습니다.
pull request package/app/image build 가능 여부를 검증하지만 protected publish는 수행하지 않습니다.
manual workflow 필요하면 dev publish를 수행하되 release tag를 만들지 않습니다.