name: Build and Push Docker Image on: release: types: - published # 当通过 GitHub Releases 页面创建 release 时触发 - deleted # 当删除 release 时触发 jobs: build-and-push: runs-on: ubuntu-latest steps: - name: Checkout code if: github.event.action == 'published' uses: actions/checkout@v4 with: ref: ${{ github.event.release.tag_name }} # 使用 release 对应的 tag # 构建和推送镜像(仅在发布 release 时) - name: Extract version from release if: github.event.action == 'published' id: extract_version run: | # 从 release tag 中提取版本号(例如 v1.0.0 -> 1.0.0) TAG_NAME="${{ github.event.release.tag_name }}" if [ -z "$TAG_NAME" ]; then TAG_NAME=${GITHUB_REF#refs/tags/} fi # 验证版本号格式:v数字.数字.数字[-后缀](例如 v1.0.0, v2.10.102, v1.0.0-beta) if [[ ! "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$ ]]; then echo "错误: 版本号格式不正确,应为 v数字.数字.数字 或 v数字.数字.数字-后缀 (例如: v1.0.0, v1.0.0-beta)" exit 1 fi VERSION=${TAG_NAME#v} # 移除 v 前缀 echo "VERSION=$VERSION" >> $GITHUB_OUTPUT echo "TAG=$TAG_NAME" >> $GITHUB_OUTPUT echo "Extracted version: $VERSION" echo "Full tag: $TAG_NAME" - name: Set up Docker Buildx if: github.event.action == 'published' uses: docker/setup-buildx-action@v3 with: # 启用多架构构建支持 platforms: linux/amd64,linux/arm64 - name: Log in to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and push Docker image if: github.event.action == 'published' uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile push: true # 多架构构建:支持 amd64 和 arm64 platforms: linux/amd64,linux/arm64 tags: | wrbug/polyhermes:${{ steps.extract_version.outputs.TAG }} wrbug/polyhermes:latest build-args: | VERSION=${{ steps.extract_version.outputs.VERSION }} GIT_TAG=${{ steps.extract_version.outputs.TAG }} GITHUB_REPO_URL=https://github.com/WrBug/PolyHermes cache-from: type=registry,ref=wrbug/polyhermes:latest cache-to: type=inline # 删除镜像(仅在删除 release 时) - name: Delete Docker image (when release is deleted) if: github.event.action == 'deleted' run: | TAG_NAME="${{ github.event.release.tag_name }}" # 验证版本号格式:v数字.数字.数字[-后缀](精准匹配) if [[ ! "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$ ]]; then echo "警告: 版本号格式不正确 ($TAG_NAME),应为 v数字.数字.数字 或 v数字.数字.数字-后缀 (例如: v1.0.0, v1.0.0-beta)" echo "跳过删除操作" exit 0 fi IMAGE_NAME="wrbug/polyhermes" DOCKER_USERNAME="${{ secrets.DOCKER_USERNAME }}" DOCKER_PASSWORD="${{ secrets.DOCKER_PASSWORD }}" echo "正在删除 Docker 镜像: ${IMAGE_NAME}:${TAG_NAME}" # 方法 1: 尝试使用 JWT Token 认证(推荐,适用于 Access Token) # 获取 JWT Token echo "正在获取 Docker Hub JWT Token..." TOKEN_RESPONSE=$(curl -s -X POST \ -H "Content-Type: application/json" \ -d "{\"username\": \"${DOCKER_USERNAME}\", \"password\": \"${DOCKER_PASSWORD}\"}" \ "https://hub.docker.com/v2/users/login/") # 提取 Token(支持多种格式) TOKEN=$(echo "$TOKEN_RESPONSE" | grep -oE '"token":"[^"]*"' | head -1 | cut -d'"' -f4) if [ -z "$TOKEN" ]; then # 尝试另一种提取方式 TOKEN=$(echo "$TOKEN_RESPONSE" | python3 -c "import sys, json; print(json.load(sys.stdin).get('token', ''))" 2>/dev/null || echo "") fi if [ -n "$TOKEN" ] && [ "$TOKEN" != "null" ]; then echo "✅ 成功获取 JWT Token,使用 JWT Token 认证" # 使用 JWT Token 删除镜像标签 RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE \ -H "Authorization: JWT ${TOKEN}" \ "https://hub.docker.com/v2/repositories/${IMAGE_NAME}/tags/${TAG_NAME}/") else echo "⚠️ JWT Token 获取失败,尝试使用 Basic Auth" echo " 如果继续失败,请检查 DOCKER_USERNAME 和 DOCKER_PASSWORD 是否正确" # 方法 2: 使用 Basic Auth(适用于密码) RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE \ -u "${DOCKER_USERNAME}:${DOCKER_PASSWORD}" \ "https://hub.docker.com/v2/repositories/${IMAGE_NAME}/tags/${TAG_NAME}/") fi HTTP_CODE=$(echo "$RESPONSE" | tail -n1) BODY=$(echo "$RESPONSE" | head -n-1) if [ "$HTTP_CODE" = "204" ]; then echo "✅ 成功删除 Docker 镜像标签: ${IMAGE_NAME}:${TAG_NAME}" elif [ "$HTTP_CODE" = "404" ]; then echo "⚠️ 镜像标签不存在: ${IMAGE_NAME}:${TAG_NAME},可能已被删除或不存在" elif [ "$HTTP_CODE" = "401" ]; then echo "❌ 认证失败 (HTTP 401): 未授权" echo " 请检查以下内容:" echo " 1. DOCKER_USERNAME 和 DOCKER_PASSWORD 是否正确" echo " 2. 如果使用 Access Token,确保有删除镜像的权限" echo " 3. 访问令牌是否过期" echo " 响应详情: $BODY" exit 1 elif [ "$HTTP_CODE" = "403" ]; then echo "❌ 权限不足 (HTTP 403): 没有删除镜像的权限" echo " 请确保 Docker Hub 访问令牌具有以下权限:" echo " - Delete repository tags" echo " 响应详情: $BODY" exit 1 else echo "❌ 删除失败 (HTTP $HTTP_CODE): $BODY" exit 1 fi