name: Release
on:
push:
tags: ["v*"]
permissions:
contents: read
jobs:
gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - name: 태그와 Cargo.toml 버전 일치 확인
run: |
crate_version="$(grep -m1 '^version' Cargo.toml | cut -d '"' -f 2)"
if [ "v${crate_version}" != "${GITHUB_REF_NAME}" ]; then
echo "태그 ${GITHUB_REF_NAME} ≠ Cargo.toml v${crate_version} — 버전을 맞추고 다시 태그하세요" >&2
exit 1
fi
- run: cargo fmt --check
- run: cargo clippy --all-targets -- -D warnings
- name: 채점표 게이트 (유닛 + 통합 + 코퍼스)
run: cargo test
- name: 자기 검사 (dogfood)
run: cargo run --quiet -- scan . --strict
build:
needs: gate
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-musl
runner: ubuntu-latest
- target: aarch64-unknown-linux-musl
runner: ubuntu-24.04-arm
- target: x86_64-apple-darwin
runner: macos-latest
- target: aarch64-apple-darwin
runner: macos-latest
- target: x86_64-pc-windows-msvc
runner: windows-latest
- target: aarch64-pc-windows-msvc
runner: windows-latest
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - name: musl 링커 설치 (Linux)
if: contains(matrix.target, 'musl')
run: sudo apt-get update && sudo apt-get install -y musl-tools
- run: rustup target add ${{ matrix.target }}
- run: cargo build --release --locked --target ${{ matrix.target }}
- name: 아카이브 작성 (tar.gz)
if: runner.os != 'Windows'
run: |
name="just-shield-${GITHUB_REF_NAME}-${{ matrix.target }}"
mkdir "${name}"
cp "target/${{ matrix.target }}/release/just-shield" README.md LICENSE-MIT LICENSE-APACHE "${name}/"
tar -czf "${name}.tar.gz" "${name}"
- name: 아카이브 작성 (zip)
if: runner.os == 'Windows'
shell: pwsh
run: |
$name = "just-shield-$env:GITHUB_REF_NAME-${{ matrix.target }}"
New-Item -ItemType Directory $name | Out-Null
Copy-Item "target/${{ matrix.target }}/release/just-shield.exe", "README.md", "LICENSE-MIT", "LICENSE-APACHE" $name
Compress-Archive -Path $name -DestinationPath "$name.zip"
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a with:
name: ${{ matrix.target }}
path: |
just-shield-*.tar.gz
just-shield-*.zip
if-no-files-found: error
release:
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
attestations: write
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c with:
path: dist
merge-multiple: true
- name: SHA256SUMS 생성
working-directory: dist
run: sha256sum * > SHA256SUMS
- name: 빌드 출처 증명 발급
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 with:
subject-path: dist/*
- name: GitHub 릴리스 생성
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "${GITHUB_REF_NAME}" dist/* \
--repo "${GITHUB_REPOSITORY}" \
--title "${GITHUB_REF_NAME}" \
--generate-notes
image:
needs: release
runs-on: ubuntu-latest
outputs:
digest: ${{ steps.push.outputs.digest }}
permissions:
contents: write packages: write steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c with:
path: dist
merge-multiple: true
- name: 빌드 컨텍스트 구성 (아치별 바이너리 배치)
run: |
mkdir -p ctx/amd64 ctx/arm64
for pair in "x86_64:amd64" "aarch64:arm64"; do
triple="${pair%%:*}-unknown-linux-musl"
arch="${pair##*:}"
name="just-shield-${GITHUB_REF_NAME}-${triple}"
tar -xzf "dist/${name}.tar.gz"
mv "${name}/just-shield" "ctx/${arch}/just-shield"
done
cp Dockerfile ctx/
- name: ghcr.io 로그인
run: echo "${{ github.token }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
- name: 멀티 아치 빌드 + 푸시
id: push
run: |
docker buildx create --use
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag "ghcr.io/kihyun1998/just-shield:${GITHUB_REF_NAME}" \
--tag "ghcr.io/kihyun1998/just-shield:latest" \
--provenance=false \
--metadata-file meta.json \
--push \
ctx
digest="$(jq -r '."containerimage.digest"' meta.json)"
echo "digest=${digest}" >> "$GITHUB_OUTPUT"
- name: 릴리스 노트에 다이제스트 기록
env:
GH_TOKEN: ${{ github.token }}
DIGEST: ${{ steps.push.outputs.digest }}
run: |
gh release view "${GITHUB_REF_NAME}" --json body --jq .body > notes.md
printf '\n## 컨테이너 이미지\n\n`ghcr.io/kihyun1998/just-shield@%s` (linux amd64·arm64, FROM scratch 단일 바이너리)\n' "$DIGEST" >> notes.md
gh release edit "${GITHUB_REF_NAME}" --notes-file notes.md
image-verify:
needs: image
strategy:
matrix:
runner: [ubuntu-latest, ubuntu-24.04-arm]
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - name: 다이제스트 핀 pull + scan (우리 R4를 우리가 지킨다)
run: |
echo "${{ github.token }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
docker run --rm -v "${PWD}:/work" \
"ghcr.io/kihyun1998/just-shield@${{ needs.image.outputs.digest }}" \
scan /work --strict