From df958016729a72ead50b566c6bc524ba19f33522 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 11 Oct 2026 13:49:39 +0800 Subject: [PATCH] deploy: add k3s test image pipeline --- .dockerignore | 16 +++++++++++++ .gitea/workflows/deploy.yml | 37 +++++++++++++++++++++++++++++++ Dockerfile | 36 ++++++++++++++++++++++++++++++ tests/test_deployment_contract.py | 32 ++++++++++++++++++++++++++ 4 files changed, 121 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitea/workflows/deploy.yml create mode 100644 Dockerfile create mode 100644 tests/test_deployment_contract.py diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..d8a8142 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,16 @@ +.git +.gitea +.idea +.vscode +**/.DS_Store +web/node_modules +web/dist +server/temp +server/logs +server/storage/cache +server/storage/diskqueue +server/resource/public/admin +docs +tools +*.docx +*.pdf diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..0968567 --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,37 @@ +name: Deploy olons-admin (k3s test cluster) + +on: + workflow_dispatch: + inputs: + image_tag: + description: '镜像 tag,默认 test' + required: false + +jobs: + deploy: + runs-on: deploy-host + steps: + - uses: actions/checkout@v4 + + - name: 确定镜像 tag + id: vars + run: | + TAG="${{ github.event.inputs.image_tag }}" + [ -z "$TAG" ] && TAG=test + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + + - name: 登录镜像仓库 + run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.118im.com -u admin --password-stdin + + - name: 构建并推送前后端一体镜像 + run: | + docker build -t git.118im.com/im_team/olons-admin:${{ steps.vars.outputs.tag }} . + docker push git.118im.com/im_team/olons-admin:${{ steps.vars.outputs.tag }} + + - name: 滚动更新测试集群 + run: | + mkdir -p ~/.kube + echo "${{ secrets.KUBECONFIG }}" > ~/.kube/config + chmod 600 ~/.kube/config + kubectl rollout restart deployment/olons-admin -n olons-admin-system + kubectl rollout status deployment/olons-admin -n olons-admin-system --timeout=180s diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bcd99fa --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +FROM node:20-alpine AS web-build + +WORKDIR /web +RUN corepack enable && corepack prepare pnpm@10.18.3 --activate +COPY web/package.json web/pnpm-lock.yaml web/pnpm-workspace.yaml ./ +RUN pnpm install --frozen-lockfile +COPY web/ ./ +RUN pnpm run build + +FROM golang:1.24-alpine AS server-build + +WORKDIR /src +COPY server/go.mod server/go.sum ./ +RUN go mod download +RUN go install github.com/gogf/gf/cmd/gf/v2@v2.10.0 +COPY server/ ./ +COPY --from=web-build /web/dist/ ./resource/public/admin/ +RUN gf pack resource internal/packed/packed.go --keepPath=true \ + && CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /out/hotgo . + +FROM alpine:3.22 + +RUN apk add --no-cache ca-certificates tzdata \ + && addgroup -S hotgo \ + && adduser -S -G hotgo hotgo +WORKDIR /app +COPY --from=server-build /out/hotgo /app/hotgo +COPY --from=server-build /src/manifest /app/manifest +COPY --from=server-build /src/resource /app/resource +COPY --from=web-build /web/dist/ /app/resource/public/admin/ +RUN mkdir -p /app/storage /app/logs \ + && chown -R hotgo:hotgo /app +USER hotgo +EXPOSE 8000 +ENTRYPOINT ["/app/hotgo"] +CMD ["all"] diff --git a/tests/test_deployment_contract.py b/tests/test_deployment_contract.py new file mode 100644 index 0000000..e49c3cf --- /dev/null +++ b/tests/test_deployment_contract.py @@ -0,0 +1,32 @@ +import unittest +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] + + +class DeploymentContract(unittest.TestCase): + def test_container_builds_web_and_server_in_one_image(self): + dockerfile = (ROOT / "Dockerfile").read_text() + self.assertIn("pnpm install --frozen-lockfile", dockerfile) + self.assertIn("pnpm run build", dockerfile) + self.assertIn("gf pack resource internal/packed/packed.go", dockerfile) + self.assertIn("go build", dockerfile) + self.assertIn("/app/resource/public/admin", dockerfile) + self.assertIn('ENTRYPOINT ["/app/hotgo"]', dockerfile) + + def test_container_excludes_local_and_generated_files(self): + dockerignore = (ROOT / ".dockerignore").read_text().splitlines() + for ignored in (".git", "web/node_modules", "web/dist", "server/temp"): + self.assertIn(ignored, dockerignore) + + def test_manual_workflow_builds_and_rolls_out_test_image(self): + workflow = (ROOT / ".gitea/workflows/deploy.yml").read_text() + self.assertIn("workflow_dispatch:", workflow) + self.assertIn("git.118im.com/im_team/olons-admin", workflow) + self.assertIn("deployment/olons-admin", workflow) + self.assertIn("-n olons-admin-system", workflow) + + +if __name__ == "__main__": + unittest.main()