重新发布Maven制品至GitHub Packages引发构建失败及相关问题求助
针对GitHub Packages与Gradle发布问题的解决方案
问题1:合并master分支时重复发布GitHub Packages导致构建失败
方案1:按分支触发不同发布逻辑
- 在GitHub Actions工作流中添加分支判断,仅在
version/*分支执行完整发布(Nexus + GitHub Packages),master分支只推送到Nexus:- 核心思路:master分支仅作为版本归档,不需要重复发布已在version分支推过的制品
- 示例工作流片段:
jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' - name: Publish to Nexus run: ./gradlew publishToNexusRepository - name: Publish to GitHub Packages # 仅在version开头的分支执行此步骤 if: startsWith(github.ref, 'refs/heads/version/') run: ./gradlew publishToGitHubPackagesRepository
方案2:发布前检查并清理已存在的版本
- 利用GitHub API提前检查目标版本是否存在,存在则删除后再发布:
- 需给GitHub Actions的
GITHUB_TOKEN配置packages:write权限 - 示例脚本片段(可加入Actions步骤):
- 需给GitHub Actions的
# 定义变量 VERSION=${{ env.PROJECT_VERSION }} OWNER=${{ github.repository_owner }} PACKAGE_NAME="your-package-name" # 检查版本是否存在 PACKAGE_VERSION_ID=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ "https://api.github.com/users/$OWNER/packages/maven/$PACKAGE_NAME/versions" | \ jq -r --arg ver "$VERSION" '.[] | select(.name == $ver) | .id') # 存在则删除 if [ -n "$PACKAGE_VERSION_ID" ]; then curl -X DELETE -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ "https://api.github.com/users/$OWNER/packages/maven/$PACKAGE_NAME/versions/$PACKAGE_VERSION_ID" fi
- 注意:删除操作不可逆,建议仅在确认需要重发布(如旧版本Bug修复)时使用。
问题2:单个发布任务失败导致的制品清理麻烦
方案1:任务级版本校验+Gradle持续执行
- 给每个Gradle发布任务添加前置校验:检查远程仓库是否已存在当前版本,存在则跳过该任务;同时执行时加上
--continue参数,让后续任务继续运行- 示例Gradle配置(针对单个发布任务):
tasks.named('publishMyLibPublicationToGitHubPackages').configure { doFirst { def currentVersion = project.version.toString() // 这里实现检查GitHub Packages版本是否存在的逻辑(可通过HTTP请求调用API) boolean versionExists = checkRemotePackageExists(currentVersion) if (versionExists) { println "Version $currentVersion already exists, skipping publish" enabled = false } } }
- 执行命令:
./gradlew publishAll --continue - 优势:重新执行时只会发布未成功的制品,无需手动删除已发布内容
方案2:原子化发布流程
- 先完成所有制品的本地构建与校验,确认全部成功后再批量推送到远程仓库:
- 核心思路:避免部分发布成功、部分失败的中间状态
- 示例Gradle配置思路:
// 第一步:将所有制品打包到本地临时仓库 task assembleAllArtifacts(type: Copy) { from configurations.archives.allArtifacts.files from tasks.withType(GeneratePomFile).map { it.outputFile } into "$buildDir/tempMavenRepo/com/your-org/${project.name}/${project.version}" preserveFileTimestamps = false } // 第二步:批量发布临时仓库的制品 task publishAllAtomic { dependsOn assembleAllArtifacts doLast { // 调用maven-publish插件或curl工具,将临时仓库内容批量推送到Nexus和GitHub Packages // 示例:使用curl批量上传 def repoUrl = System.getenv("GITHUB_PACKAGES_URL") def auth = "Bearer ${{ secrets.GITHUB_TOKEN }}" fileTree("$buildDir/tempMavenRepo").each { file -> def relativePath = file.relativeTo("$buildDir/tempMavenRepo").path curl -X PUT -H "Authorization: $auth" -T "$file" "$repoUrl/$relativePath" } } }
- 优势:要么全部发布成功,要么全部不发布,彻底避免手动清理的麻烦
内容的提问来源于stack exchange,提问作者apann
相关产品推荐
相关产品推荐

