diff --git a/.gitlab/ci.yml b/.gitlab/ci.yml new file mode 100644 index 0000000000..e20c30c3f2 --- /dev/null +++ b/.gitlab/ci.yml @@ -0,0 +1,56 @@ +# GitLab CI: build Docker image and push to Alibaba Cloud ACR. +# Triggers: branch `add-csgclaw-channel-ci-test` (path `changes` commented out for testing). +# +# Runner: use a GitLab Runner with docker executor. For Docker-in-Docker (this job), +# set privileged = true in the runner's config.toml ([runners.docker]), not in +# this file. Optionally add `tags:` to pin a specific runner. +# +# CI images are pulled from ACR (${ACR_REGISTRY}/opencsg_public/...) instead of +# Docker Hub to avoid registry-1.docker.io timeouts in restricted networks. +# +# Required CI/CD variables (Settings → CI/CD → Variables): +# ACR_REGISTRY – registry host only, e.g. opencsg-registry.cn-beijing.cr.aliyuncs.com +# ACR_USERNAME – ACR login name +# ACR_PASSWORD – ACR password or temporary token +# +# Tag format: YYYY.M.D (Asia/Shanghai calendar day, no per-day build index). +# +# Project setting: Settings → CI/CD → General pipelines → CI/CD configuration file +# must be set to this path: .gitlab/ci.yml (GitLab does not auto-detect it). + +variables: + DOCKER_TLS_CERTDIR: "/certs" + GIT_STRATEGY: clone + GIT_DEPTH: "0" + +stages: + - build + +docker-build-push: + stage: build + image: + name: ${ACR_REGISTRY}/opencsg_public/docker-ci:v1.0.1 + entrypoint: [""] + services: + # Same mirror as internal docker-ci template (avoid Docker Hub). + - name: ${ACR_REGISTRY}/opencsg_public/docker:27.3-dind + command: ["--feature=containerd-snapshotter", "--experimental"] + alias: docker + rules: + - if: $CI_COMMIT_BRANCH == "add-csgclaw-channel" + changes: + - docker/csgclaw-cli/**/* + - docker/csgclaw-cli/* + - docker/Dockerfile + variables: + DOCKER_HOST: tcp://docker:2375 + DOCKER_TLS_CERTDIR: "" + before_script: + - export TZ=Asia/Shanghai + - echo "$ACR_PASSWORD" | docker login -u "$ACR_USERNAME" --password-stdin "$ACR_REGISTRY" + - export IMAGE_TAG="$(date +%Y).$(date +%-m).$(date +%-d)" + - export DOCKER_IMAGE="${ACR_REGISTRY}/opencsghq/picoclaw" + - echo "IMAGE_TAG=${IMAGE_TAG}" && echo "DOCKER_IMAGE=${DOCKER_IMAGE}" + script: + - docker build -f docker/Dockerfile -t "${DOCKER_IMAGE}:${IMAGE_TAG}" . + - docker push "${DOCKER_IMAGE}:${IMAGE_TAG}" diff --git a/docker/Dockerfile b/docker/Dockerfile index ae8d82fcbb..241c371df4 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,10 +1,23 @@ +# Base images mirrored to ACR (opencsg_public) so CI can pull without Docker Hub. +# Host: opencsg-registry.cn-beijing.cr.aliyuncs.com — push local pulls with: +# docker tag golang:1.25-alpine .../opencsg_public/golang:1.25-alpine +# docker tag alpine:3.23 .../opencsg_public/alpine:3.23 +# # ============================================================ # Stage 1: Build the picoclaw binary # ============================================================ -FROM golang:1.25-alpine AS builder +FROM opencsg-registry.cn-beijing.cr.aliyuncs.com/opencsg_public/golang:1.25-alpine AS builder + +# Alpine apk: use Aliyun mirror instead of dl-cdn (often slow or flaky in mainland CN). +RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories RUN apk add --no-cache git make +# Go modules: default proxy/sumdb can be slow or unreachable in CN. +ENV GOPROXY=https://goproxy.cn,direct +ENV GOSUMDB=sum.golang.google.cn +ENV GIT_TERMINAL_PROMPT=0 + WORKDIR /src # Cache dependencies @@ -16,16 +29,29 @@ COPY . . RUN make build # ============================================================ -# Stage 1.5: Select the platform-specific csgclaw-cli binary +# Stage 1.5: Download platform-specific csgclaw-cli release tarball # ============================================================ -FROM scratch AS csgclaw-cli +FROM opencsg-registry.cn-beijing.cr.aliyuncs.com/opencsg_public/alpine:3.23 AS csgclaw-cli ARG TARGETARCH -COPY docker/csgclaw-cli/csgclaw-cli_linux_${TARGETARCH} /csgclaw-cli +# Override to pin a release, e.g. https://csgclaw.opencsg.com/releases/v1.0.0 +ARG CSGCLAW_CLI_BASE_URL=https://csgclaw.opencsg.com/releases/latest +RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \ + && apk add --no-cache ca-certificates curl \ + && curl -fSL "${CSGCLAW_CLI_BASE_URL}/linux/${TARGETARCH}?package=csgclaw-cli" -o /tmp/csgclaw-cli.tar.gz \ + && mkdir -p /tmp/extract \ + && tar -xzf /tmp/csgclaw-cli.tar.gz -C /tmp/extract \ + && set -eu; \ + bin="$(find /tmp/extract -type f \( -name csgclaw-cli -o -name "csgclaw-cli_linux_${TARGETARCH}" \) | head -n1)"; \ + if [ -z "$bin" ]; then bin="$(find /tmp/extract -type f -perm -111 | head -n1)"; fi; \ + if [ -z "$bin" ]; then echo "csgclaw-cli binary not found in archive"; ls -laR /tmp/extract; exit 1; fi; \ + install -m0755 "$bin" /csgclaw-cli # ============================================================ # Stage 2: Minimal runtime image # ============================================================ -FROM alpine:3.23 +FROM opencsg-registry.cn-beijing.cr.aliyuncs.com/opencsg_public/alpine:3.23 + +RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories RUN apk add --no-cache ca-certificates curl python3 tini tzdata @@ -54,4 +80,5 @@ COPY --chown=picoclaw:picoclaw docker/config/config.json /home/picoclaw/.picocla ENTRYPOINT ["/sbin/tini", "--"] CMD ["sleep", "infinity"] + # CMD ["picoclaw", "gateway", "-d"]