diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 187cc11..ff9b24e 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -4,7 +4,6 @@ on: release: types: - published # 当通过 GitHub Releases 页面创建 release 时触发 - - deleted # 当删除 release 时触发 jobs: build-and-push: @@ -12,14 +11,11 @@ jobs: 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) @@ -41,7 +37,6 @@ jobs: echo "Full tag: $TAG_NAME" - name: Set up Docker Buildx - if: github.event.action == 'published' uses: docker/setup-buildx-action@v3 with: # 启用多架构构建支持 @@ -54,7 +49,6 @@ jobs: password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and push Docker image - if: github.event.action == 'published' uses: docker/build-push-action@v5 with: context: . @@ -71,80 +65,3 @@ jobs: 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 - diff --git a/.github/workflows/docker-delete.yml b/.github/workflows/docker-delete.yml new file mode 100644 index 0000000..ce74d48 --- /dev/null +++ b/.github/workflows/docker-delete.yml @@ -0,0 +1,86 @@ +name: Delete Docker Image + +on: + release: + types: + - deleted # 当删除 release 时触发 + +jobs: + delete-image: + runs-on: ubuntu-latest + + steps: + - name: Delete Docker image + 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 + diff --git a/docs/VERSION_MANAGEMENT.md b/docs/VERSION_MANAGEMENT.md index 976a1b4..904356e 100644 --- a/docs/VERSION_MANAGEMENT.md +++ b/docs/VERSION_MANAGEMENT.md @@ -11,7 +11,20 @@ 3. **点击跳转**:点击版本号跳转到对应的 GitHub tag 页面 4. **Docker 推送**:自动构建并推送到 Docker Hub 5. **自动删除**:删除 release 时自动删除对应的 Docker 镜像标签 -6. **版本号验证**:精准匹配版本号格式 `v数字.数字.数字`(例如:`v1.0.0`, `v2.10.102`) +6. **版本号验证**:精准匹配版本号格式 `v数字.数字.数字` 或 `v数字.数字.数字-后缀`(例如:`v1.0.0`, `v1.0.0-beta`) +7. **独立脚本**:构建和删除功能分离到不同的 workflow 文件,便于管理和维护 + +## Workflow 文件说明 + +项目使用两个独立的 GitHub Actions workflow 文件: + +- **`.github/workflows/docker-build.yml`**:负责构建和推送 Docker 镜像 + - 触发条件:`release: published`(创建 release 时) + - 功能:提取版本号、构建多架构镜像、推送到 Docker Hub + +- **`.github/workflows/docker-delete.yml`**:负责删除 Docker 镜像 + - 触发条件:`release: deleted`(删除 release 时) + - 功能:验证版本号格式、删除对应的 Docker 镜像标签 ## 使用方法 @@ -48,6 +61,10 @@ **重要**:只有通过 [GitHub Releases 页面](https://github.com/WrBug/PolyHermes/releases/new) 创建 release 时才会触发自动构建。 +**Workflow 说明**: +- 创建 release 时,会触发 `docker-build.yml` workflow,自动构建并推送镜像 +- 删除 release 时,会触发 `docker-delete.yml` workflow,自动删除对应的镜像标签 + **创建步骤**: 1. 访问 [GitHub Releases 页面](https://github.com/WrBug/PolyHermes/releases/new) 2. 点击 "Choose a tag" 下拉菜单,输入新的 tag 名称(例如:`v1.0.0` 或 `v1.0.0-beta`)