Skip to content

Commit 0e61231

Browse files
committed
perf: reuse release artifacts for container images
1 parent 5404e24 commit 0e61231

12 files changed

Lines changed: 174 additions & 79 deletions

File tree

.github/workflows/ci.yml

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ permissions:
1212

1313
jobs:
1414
verify:
15-
runs-on: ubuntu-latest
15+
runs-on: ubuntu-24.04
1616

1717
steps:
1818
- uses: actions/checkout@v4
@@ -39,18 +39,13 @@ jobs:
3939
- name: Run go test
4040
run: CGO_ENABLED=1 go test -tags "fts5" ./... -count=1
4141

42-
- name: Build release binaries
43-
run: make build
44-
45-
- name: Build Wiki UI
46-
run: make wiki-build
42+
- name: Prepare container artifacts
43+
run: make container-artifacts
4744

4845
- name: Build production image
4946
run: |
5047
docker build \
51-
--build-arg VERSION=ci \
52-
--build-arg COMMIT=${{ github.sha }} \
53-
--build-arg DATE=unknown \
48+
--build-arg TARGETARCH=amd64 \
5449
--tag ccg:ci .
5550
5651
- name: Capture go build JSON

.github/workflows/release.yml

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ jobs:
2121
goos: darwin
2222
goarch: amd64
2323
artifact: ccg-darwin-amd64
24-
- os: ubuntu-latest
24+
- os: ubuntu-24.04
2525
goos: linux
2626
goarch: amd64
2727
artifact: ccg-linux-amd64
28-
- os: ubuntu-latest
28+
- os: ubuntu-24.04
2929
goos: linux
3030
goarch: arm64
3131
artifact: ccg-linux-arm64
@@ -162,6 +162,32 @@ jobs:
162162
steps:
163163
- uses: actions/checkout@v6
164164

165+
- name: Download Linux AMD64 artifact
166+
uses: actions/download-artifact@v4
167+
with:
168+
name: ccg-linux-amd64
169+
path: artifacts/ccg-linux-amd64
170+
171+
- name: Download Linux ARM64 artifact
172+
uses: actions/download-artifact@v4
173+
with:
174+
name: ccg-linux-arm64
175+
path: artifacts/ccg-linux-arm64
176+
177+
- name: Download Wiki artifact
178+
uses: actions/download-artifact@v4
179+
with:
180+
name: ccg-wiki-dist
181+
path: artifacts/ccg-wiki-dist
182+
183+
- name: Prepare container artifacts
184+
shell: bash
185+
run: |
186+
mkdir -p container-artifacts/amd64 container-artifacts/arm64 container-artifacts/wiki
187+
tar xzf artifacts/ccg-linux-amd64/ccg-linux-amd64.tar.gz -C container-artifacts/amd64
188+
tar xzf artifacts/ccg-linux-arm64/ccg-linux-arm64.tar.gz -C container-artifacts/arm64
189+
tar xzf artifacts/ccg-wiki-dist/ccg-wiki-dist.tar.gz -C container-artifacts/wiki
190+
165191
- name: Set up QEMU
166192
uses: docker/setup-qemu-action@v4
167193

@@ -187,14 +213,6 @@ jobs:
187213
type=semver,pattern={{major}}
188214
type=raw,value=latest,enable=${{ !contains(github.ref_name, '-') }}
189215
190-
- name: Prepare container build metadata
191-
id: build-meta
192-
shell: bash
193-
run: |
194-
echo "version=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
195-
echo "commit=${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
196-
echo "date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_OUTPUT"
197-
198216
- name: Build and publish container image
199217
uses: docker/build-push-action@v7
200218
with:
@@ -203,10 +221,6 @@ jobs:
203221
push: true
204222
tags: ${{ steps.metadata.outputs.tags }}
205223
labels: ${{ steps.metadata.outputs.labels }}
206-
build-args: |
207-
VERSION=${{ steps.build-meta.outputs.version }}
208-
COMMIT=${{ steps.build-meta.outputs.commit }}
209-
DATE=${{ steps.build-meta.outputs.date }}
210224
cache-from: type=gha
211225
cache-to: type=gha,mode=max
212226

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ pyproject.toml
2626
*.db-wal
2727
/web/wiki/dist/
2828
/web/wiki/node_modules/
29+
/container-artifacts/
2930
search-retrieval.md
3031
_workspace/

Dockerfile

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,19 @@
1-
# Wiki UI build stage
2-
FROM node:22-alpine AS wiki-builder
1+
# Runtime stage packages binaries and Wiki assets prepared by the release workflow.
2+
FROM ubuntu:24.04
33

4-
WORKDIR /src/web/wiki
5-
COPY web/wiki/package.json web/wiki/package-lock.json ./
6-
RUN npm ci
7-
COPY web/wiki/ ./
8-
RUN npm run build
4+
ARG TARGETARCH=amd64
95

10-
# Build stage
11-
FROM golang:1.25-alpine AS builder
12-
13-
RUN apk add --no-cache gcc musl-dev git
14-
15-
ARG VERSION=dev
16-
ARG COMMIT=unknown
17-
ARG DATE=unknown
18-
19-
WORKDIR /src
20-
COPY go.mod go.sum ./
21-
RUN go mod download
22-
23-
COPY . .
24-
RUN CGO_ENABLED=1 go build -tags "fts5" -ldflags="-s -w -X main.version=${VERSION} -X main.commit=${COMMIT} -X main.date=${DATE}" -o /usr/local/bin/ccg ./cmd/ccg/ \
25-
&& CGO_ENABLED=1 go build -tags "fts5" -ldflags="-s -w -X main.version=${VERSION} -X main.commit=${COMMIT} -X main.date=${DATE}" -o /usr/local/bin/ccg-server ./cmd/ccg-server/
26-
27-
# Runtime stage
28-
FROM alpine:3.21
29-
30-
RUN apk add --no-cache ca-certificates git \
31-
&& addgroup -S ccg \
32-
&& adduser -S -G ccg -h /home/ccg ccg \
6+
RUN apt-get update \
7+
&& DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y ca-certificates git wget \
8+
&& groupadd --system ccg \
9+
&& useradd --system --gid ccg --create-home --home-dir /home/ccg ccg \
3310
&& mkdir -p /repo /repos /home/ccg/.cache /home/ccg/.config/ccg \
34-
&& chown -R ccg:ccg /repo /repos /home/ccg
11+
&& chown -R ccg:ccg /repo /repos /home/ccg \
12+
&& rm -rf /var/lib/apt/lists/*
3513

36-
COPY --from=builder /usr/local/bin/ccg /usr/local/bin/ccg
37-
COPY --from=builder /usr/local/bin/ccg-server /usr/local/bin/ccg-server
38-
COPY --from=wiki-builder /src/web/wiki/dist /usr/share/ccg/wiki
14+
COPY container-artifacts/${TARGETARCH}/ccg /usr/local/bin/ccg
15+
COPY container-artifacts/${TARGETARCH}/ccg-server /usr/local/bin/ccg-server
16+
COPY container-artifacts/wiki /usr/share/ccg/wiki
3917

4018
WORKDIR /repo
4119
USER ccg

Makefile

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ WIKI_ADDR ?= 127.0.0.1:8080
77
WIKI_DB ?= ccg.db
88
WIKI_REPO ?= .
99
WIKI_TOKEN ?=
10+
HOST_GOOS := $(shell go env GOOS)
11+
CONTAINER_ARCH ?= $(shell go env GOARCH)
1012

11-
.PHONY: build release build-debug build-json install vet test test-integration-helpers wiki-build wiki-db wiki-docs wiki-run wiki-run-indexed clean
13+
.PHONY: build release build-debug build-json install vet test test-integration-helpers wiki-build wiki-db wiki-docs wiki-run wiki-run-indexed container-artifacts clean
1214

1315
build: release
1416

@@ -39,6 +41,24 @@ test-integration-helpers:
3941
wiki-build:
4042
cd web/wiki && npm ci && npm run build
4143

44+
container-artifacts: wiki-build
45+
mkdir -p container-artifacts/$(CONTAINER_ARCH) container-artifacts/wiki
46+
if [ "$(HOST_GOOS)" = "linux" ]; then \
47+
$(MAKE) release; \
48+
else \
49+
docker run --rm --platform linux/$(CONTAINER_ARCH) \
50+
--user "$$(id -u):$$(id -g)" \
51+
-e GOCACHE=/tmp/go-build \
52+
-e VERSION="$(VERSION)" \
53+
-e COMMIT="$(COMMIT)" \
54+
-e DATE="$(DATE)" \
55+
-v "$$(pwd):/src" -w /src golang:1.25-bookworm \
56+
sh -c 'CGO_ENABLED=1 go build -tags "fts5" -ldflags "-s -w -X main.version=$$VERSION -X main.commit=$$COMMIT -X main.date=$$DATE" -o ccg ./cmd/ccg/ && CGO_ENABLED=1 go build -tags "fts5" -ldflags "-s -w -X main.version=$$VERSION -X main.commit=$$COMMIT -X main.date=$$DATE" -o ccg-server ./cmd/ccg-server/'; \
57+
fi
58+
cp ccg container-artifacts/$(CONTAINER_ARCH)/ccg
59+
cp ccg-server container-artifacts/$(CONTAINER_ARCH)/ccg-server
60+
cp -R web/wiki/dist/. container-artifacts/wiki/
61+
4262
wiki-db:
4363
CGO_ENABLED=1 go run -tags "fts5" ./cmd/ccg --db-driver sqlite --db-dsn '$(WIKI_DB)' migrate
4464
CGO_ENABLED=1 go run -tags "fts5" ./cmd/ccg --db-driver sqlite --db-dsn '$(WIKI_DB)' build '$(WIKI_REPO)'

docker-compose.integration.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Full-stack integration test: Gitea + PostgreSQL + ccg
2-
# Usage: docker compose -f docker-compose.integration.yml up -d
2+
# Usage: make container-artifacts
3+
# CONTAINER_ARCH=$(go env GOARCH) docker compose -f docker-compose.integration.yml up -d
34
# ./scripts/integration-test.sh
45
# docker compose -f docker-compose.integration.yml down -v
56

@@ -54,6 +55,8 @@ services:
5455
build:
5556
context: .
5657
dockerfile: Dockerfile
58+
args:
59+
TARGETARCH: ${CONTAINER_ARCH:-amd64}
5760
environment:
5861
- CCG_DB_DRIVER=postgres
5962
- CCG_DB_DSN=host=postgres user=ccg password=ccg dbname=ccg_integration port=5432 sslmode=disable

guide/development.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ MCP initialization and tool responses are strict: malformed JSON, top-level JSON
8585
### Manual Container Management
8686

8787
```bash
88-
docker compose -f docker-compose.integration.yml up -d --build
88+
make container-artifacts
89+
CONTAINER_ARCH="$(go env GOARCH)" docker compose -f docker-compose.integration.yml up -d --build
8990
docker compose -f docker-compose.integration.yml down -v
9091
```
9192

guide/docker.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,15 @@ Each stable release publishes the full semantic version, minor, major, and
1515
## Build Image
1616

1717
```bash
18-
docker build -t ccg .
18+
make container-artifacts
19+
docker build --build-arg TARGETARCH="$(go env GOARCH)" -t ccg .
1920
```
2021

22+
`make container-artifacts` compiles the Linux binaries and Wiki UI once, then
23+
the Dockerfile packages those prepared assets without compiling source. Linux
24+
hosts use the local Go toolchain; other hosts compile the matching Linux
25+
architecture inside `golang:1.25-bookworm`.
26+
2127
## Run as MCP Server
2228

2329
```bash
@@ -177,6 +183,7 @@ docker compose up -d
177183
The full-stack pipeline test can also be run with Docker Compose. See the [Development Guide](development.md#integration-test) for details.
178184

179185
```bash
180-
docker compose -f docker-compose.integration.yml up -d --build
186+
make container-artifacts
187+
CONTAINER_ARCH="$(go env GOARCH)" docker compose -f docker-compose.integration.yml up -d --build
181188
docker compose -f docker-compose.integration.yml down -v
182189
```

guide/ko/development.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ MCP 초기화 및 도구 응답은 엄격하게 체크됩니다: 잘못된 형
8787
### 수동 컨테이너 관리
8888

8989
```bash
90-
docker compose -f docker-compose.integration.yml up -d --build
90+
make container-artifacts
91+
CONTAINER_ARCH="$(go env GOARCH)" docker compose -f docker-compose.integration.yml up -d --build
9192
docker compose -f docker-compose.integration.yml down -v
9293
```
9394

guide/ko/docker.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@
55
## 이미지 빌드 (Build Image)
66

77
```bash
8-
docker build -t ccg .
8+
make container-artifacts
9+
docker build --build-arg TARGETARCH="$(go env GOARCH)" -t ccg .
910
```
1011

12+
`make container-artifacts`는 Linux 바이너리와 Wiki UI를 한 번만 빌드하고,
13+
Dockerfile은 준비된 결과물만 패키징합니다. Linux 호스트에서는 로컬 Go
14+
도구체인을 사용하며, 그 외 호스트에서는 `golang:1.25-bookworm` 컨테이너에서
15+
대상 Linux 아키텍처용 바이너리를 컴파일합니다.
16+
1117
## MCP 서버로 실행 (Run as MCP Server)
1218

1319
```bash
@@ -151,6 +157,7 @@ docker compose up -d
151157
전체 파이프라인 테스트 또한 Docker Compose로 실행할 수 있습니다. 자세한 내용은 [개발 가이드](development.md#integration-test)를 참조하십시오.
152158

153159
```bash
154-
docker compose -f docker-compose.integration.yml up -d --build
160+
make container-artifacts
161+
CONTAINER_ARCH="$(go env GOARCH)" docker compose -f docker-compose.integration.yml up -d --build
155162
docker compose -f docker-compose.integration.yml down -v
156163
```

0 commit comments

Comments
 (0)