name: Release 镜像 on: push: branches: [main] tags: ["v*", "26.*", "27.*"] workflow_dispatch: env: REGISTRY: registry.cn-hangzhou.aliyuncs.com IMAGE: registry.cn-hangzhou.aliyuncs.com/skymirror/fileshare jobs: test: name: 测试(推送前置门禁) runs-on: ubuntu-latest container: image: golang:1.27.1-alpine timeout-minutes: 30 steps: - name: 安装工具并检出 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories apk add --no-cache git curl bash >/dev/null SCHEME="${GITHUB_SERVER_URL%%://*}" SRV="${GITHUB_SERVER_URL#*://}" echo "clone from ${SCHEME}://${SRV}" git clone --depth=1 --branch "$GITHUB_REF_NAME" \ "${SCHEME}://oauth2:${GITHUB_TOKEN}@${SRV}/${GITHUB_REPOSITORY}.git" . - name: go vet + go test working-directory: server env: GOCACHE: /tmp/.gocache GOMODCACHE: /tmp/.gomodcache CGO_ENABLED: "0" run: | go vet ./... go test ./... -count=1 build-push: name: 多架构构建并推送 ACR needs: test runs-on: ubuntu-latest # dind 自带独立 daemon:不依赖 runner 宿主机 docker.sock 转发配置 container: image: docker:27-dind options: --privileged env: DOCKER_HOST: unix:///var/run/docker.sock DOCKER_TLS_CERTDIR: "" timeout-minutes: 120 steps: - name: 启动 dind daemon 并检出 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories apk add --no-cache git bash >/dev/null # dind daemon 配置国内 registry mirror(docker.io 直连不可达) mkdir -p /etc/docker printf '{"registry-mirrors":["https://docker.m.daocloud.io","https://docker.1ms.run"]}' \ > /etc/docker/daemon.json dockerd --host=unix:///var/run/docker.sock >/tmp/dockerd.log 2>&1 & for i in $(seq 1 30); do docker info >/dev/null 2>&1 && break; sleep 1; done docker info --format 'dind 就绪: {{.ServerVersion}}' SCHEME="${GITHUB_SERVER_URL%%://*}" SRV="${GITHUB_SERVER_URL#*://}" git clone --depth=1 --branch "$GITHUB_REF_NAME" \ "${SCHEME}://oauth2:${GITHUB_TOKEN}@${SRV}/${GITHUB_REPOSITORY}.git" . - name: 安装 QEMU binfmt(跨架构) run: | docker run --rm --privileged tonistiigi/binfmt:latest --install all 2>/dev/null \ || docker run --rm --privileged docker.m.daocloud.io/tonistiigi/binfmt:latest --install all - name: 计算 tag(以 APP_VERSION 为唯一版本源) id: meta env: REF: ${{ gitea.ref }} run: | VER=$(sed -n 's/.*APP_VERSION = "\(.*\)".*/\1/p' server/cmd/server/main.go | head -1) [ -n "$VER" ] || { echo "无法从 main.go 解析 APP_VERSION" >&2; exit 1; } echo "APP_VERSION=$VER" if [[ "$REF" == refs/tags/* ]]; then # tag 触发:要求 tag 名与 APP_VERSION 一致,防错版发布 TAG_VER="${REF#refs/tags/}" TAG_VER="${TAG_VER#v}" [ "$TAG_VER" = "$VER" ] || { echo "tag($TAG_VER) != APP_VERSION($VER),拒绝发布" >&2; exit 1; } fi echo "version=$VER" >> "$GITHUB_OUTPUT" echo "tags=${IMAGE}:${VER} ${IMAGE}:latest" >> "$GITHUB_OUTPUT" - name: 登录阿里云 ACR env: ACR_USER: ${{ secrets.ACR_USERNAME }} ACR_PASS: ${{ secrets.ACR_PASSWORD }} run: | echo "ACR 用户: $ACR_USER (密码 ${#ACR_PASS} 位)" printf '%s' "$ACR_PASS" | docker login "$REGISTRY" -u "$ACR_USER" --password-stdin - name: buildx 多架构构建并推送 env: TAGS: ${{ steps.meta.outputs.tags }} run: | # docker-container 驱动才支持多平台;mirror 注入 buildkitd 配置 # (docker-container 是独立 BuildKit,不读 daemon.json) printf '[registry."docker.io"]\nmirrors = ["docker.m.daocloud.io", "docker.1ms.run"]\n' \ > /tmp/buildkitd.toml docker buildx rm ci >/dev/null 2>&1 || true # --config 是全版本兼容参数;不要吞错误,create 失败要立即暴露 docker buildx create --name ci --driver docker-container --config /tmp/buildkitd.toml docker buildx use ci ARGS="" for t in $TAGS; do ARGS="$ARGS -t $t"; done # provenance/sbom 必须关:阿里云 ACR 不识别 OCI empty manifest(attestation) docker buildx build \ --platform linux/amd64,linux/arm64 \ --provenance=false --sbom=false \ --build-arg NPM_REGISTRY=https://registry.npmmirror.com \ --push \ -f deploy/Dockerfile \ $ARGS \ . - name: 校验远程 manifest(双架构) env: VERSION: ${{ steps.meta.outputs.version }} run: | docker buildx imagetools inspect "${IMAGE}:${VERSION}" | grep -E "linux/amd64|linux/arm64" echo "推送完成: ${IMAGE}:${VERSION} + ${IMAGE}:latest"