GitHub Actions Java 项目构建与发布流程

本文档介绍了一个使用 GitHub Actions 自动构建 Java 项目并发布为 ZIP 文件的完整工作流程。该工作流程基于 Maven 构建工具,能够根据用户输入的配置动态调整 Java 版本、是否跳过测试以及发布类型(草稿或预发布)。配置文件位于项目路径 .github/workflows/build.yml 中。以下是对工作流程的详细说明,并附上完整的 build.yml 配置文件。

工作流程概述

该 GitHub Actions 工作流程名为 Java Jar To Zip Publish,主要用于:

  • 在推送带有 v* 标签的分支或手动触发时运行。
  • 构建 Java 项目,生成 JAR 文件。
  • 将 JAR 文件打包为 ZIP 文件。
  • 将 ZIP 文件及其内容上传到 GitHub Release。

工作流程支持以下用户输入参数:

  • tag_name: Release 标签(如 v1.0.0,默认值为 v-manual)。
  • skip_tests: 是否跳过测试(truefalse,默认值为 false)。
  • java_version: Java 版本(如 81117,默认值为 8)。
  • jar_dir_prefix: JAR 文件路径前缀(如 micro-service,默认值为空)。
  • draft: 是否为草稿 Release(默认值为 false)。
  • prerelease: 是否为预发布 Release(默认值为 false)。

工作流程步骤

以下是工作流程的详细步骤:

1. 检出代码

使用 actions/checkout@v4 动作将代码仓库检出到运行环境中,确保后续步骤能够访问项目文件。

2. 设置 Java 环境

通过 actions/setup-java@v4 配置指定版本的 Java 环境,默认使用 Eclipse Temurin 发行版。Java 版本由用户输入的 java_version 参数决定,默认为 8

3. 缓存 Maven 依赖

使用 actions/cache@v4 缓存 Maven 依赖(位于 ~/.m2/repository),以加快构建速度。缓存的键基于操作系统和 pom.xml 文件的哈希值,确保依赖一致性。

4. 使用 Maven 构建并生成 JAR 文件

根据 skip_tests 参数决定是否跳过测试:

  • 如果 skip_teststrue,运行 mvn clean package -B -DskipTests -Dquickly
  • 否则,运行 mvn clean package -B -Dquickly
    -B 参数启用批处理模式,-Dquickly 用于加速构建。

5. 列出匹配的 JAR 文件

根据 jar_dir_prefix 参数查找生成的 JAR 文件:

  • 如果 jar_dir_prefix 为空,查找路径为 */target/*.jar 的文件。
  • 否则,查找路径为 */${jar_dir_prefix}/*/target/*.jar 的文件。
    使用 find 命令列出匹配的文件,若未找到则输出提示信息。

6. 打包 JAR 文件为 ZIP

将所有匹配的 JAR 文件打包为一个 ZIP 文件,文件名为 jars-${tag_name}.zip。使用 zip -j 命令确保不保留目录结构,仅打包文件内容。

7. 验证 ZIP 文件

列出 ZIP 文件的详细信息并使用 unzip -l 显示其内容,确保打包正确。

8. 解压 ZIP 文件

将 ZIP 文件解压到 extracted-jars 目录,并列出解压后的文件列表,以便后续上传单独的 JAR 文件。

9. 上传到 GitHub Release

使用 softprops/action-gh-release@v2 将 ZIP 文件和解压后的 JAR 文件上传到 GitHub Release。Release 的元数据包括:

  • 标签名称:tag_name 或默认的 github.ref_name
  • Release 名称:根据 draftprerelease 参数动态添加“(Draft)”或“(Pre-release)”标记。
  • Release 描述:包含标签名和 Java 版本等信息。
  • 草稿状态:由 draft 参数决定。
  • 预发布状态:由 prerelease 参数决定。

上传需要使用 GitHub 个人访问令牌(secrets.PAT)以确保权限。

权限配置

工作流程需要以下权限:

  • contents: write:用于创建和上传 Release。
  • actions: read:用于执行 GitHub Actions 操作。

使用场景

该工作流程适用于以下场景:

  • 自动化构建和发布 Java 项目,尤其是微服务架构项目。
  • 需要灵活配置 Java 版本或跳过测试以加速构建。
  • 希望将多个 JAR 文件打包为 ZIP 并同时上传单独的 JAR 文件到 GitHub Release。
  • 支持草稿或预发布版本,便于测试和验证。

注意事项

  1. Maven 配置:确保项目包含有效的 pom.xml 文件。
  2. JAR 文件路径:正确配置 jar_dir_prefix 以匹配项目结构。
  3. GitHub 令牌:需要在 GitHub 仓库的 Secrets 中配置 PAT
  4. 触发方式:支持通过推送标签(如 v1.0.0)或手动触发运行。
  5. 文件路径:配置文件必须位于项目路径 .github/workflows/build.yml 中,以确保 GitHub Actions 能够正确识别和执行。

build.yml 配置文件

以下是位于 .github/workflows/build.yml 的完整配置文件:

# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
name: Java Jar To Zip Publish
run-name: "Jar ${{ github.event.inputs.tag_name || 'v-manual' }} version"

on:
  push:
    tags:
      - 'v*'
  workflow_dispatch:
    inputs:
      tag_name:
        description: '输入 Release 标签 (如 v1.0.0)'
        required: true
        default: 'v-manual'
      skip_tests:
        description: '是否跳过测试 (true/false)'
        required: true
        type: boolean
        default: false
      java_version:
        description: '输入 Java 版本 (如 8, 11, 17)'
        required: true
        default: '8'
      jar_dir_prefix:
        description: 'JAR 文件前缀 (如 micro-service 或留空)'
        default: ''
      draft:
        description: '是否为草稿 Release (true/false)'
        type: boolean
        default: false
      prerelease:
        description: '是否为预发布 Release (true/false)'
        type: boolean
        default: false

jobs:
  build-and-release:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      #releases: write
      actions: read
    steps:
      - name: 1.检出代码
        uses: actions/checkout@v4

      - name: 2.设置 Java 环境 version=${{ github.event.inputs.java_version || '8' }}
        uses: actions/setup-java@v4
        with:
          java-version: ${{ github.event.inputs.java_version || '8' }}
          distribution: 'temurin'

      - name: 3.缓存 Maven 依赖
        uses: actions/cache@v4
        with:
          path: ~/.m2/repository
          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
          restore-keys: |
            ${{ runner.os }}-maven-

      - name: 4.使用 Maven 构建并生成 JAR
        run: |
          if [ "${{ inputs.skip_tests }}" = "true" ]; then
            echo "跳过测试"
            echo "mvn clean package -B -DskipTests -Dquickly"
            mvn clean package -B -DskipTests -Dquickly
          else
            echo "mvn clean package -B -Dquickly"
            mvn clean package -B -Dquickly
          fi
          echo "Maven 构建完成"

      - name: 5.列出匹配的 JAR 文件
        run: |
          if [ "${{ inputs.jar_dir_prefix }}" = "" ]; then
            echo "匹配的 JAR 文件 (*/target/*.jar):"
            find . -type f -path "*/target/*.jar" || echo "未找到匹配的 JAR 文件"
          else
            echo "匹配的 JAR 文件 (*/${{ inputs.jar_dir_prefix }}/*/target/*.jar):"
            find . -type f -path "*/${{ inputs.jar_dir_prefix }}/*/target/*.jar" || echo "未找到匹配的 JAR 文件"
          fi

      - name: 6.打包所有 JAR 文件成 ZIP
        run: |
          if [ "${{ inputs.jar_dir_prefix }}" = "" ]; then
            find . -type f -path "*/target/*.jar" -exec zip -j jars-${{ github.event.inputs.tag_name || github.ref_name }}.zip {} +
          else
            find . -type f -path "*/${{ inputs.jar_dir_prefix }}/*/target/*.jar" -exec zip -j jars-${{ github.event.inputs.tag_name || github.ref_name }}.zip {} +
          fi
          # -j: 仅打包文件,不保留目录结构
          # +: 尽量将多个文件放入一个 zip 命令,减少调用次数
        shell: bash

      - name: 7.验证 ZIP 文件
        run: |
          ls -la jars-${{ github.event.inputs.tag_name || github.ref_name }}.zip
          echo "ZIP 文件内容:"
          unzip -l jars-${{ github.event.inputs.tag_name || github.ref_name }}.zip

      - name: 8.解压 ZIP 文件
        run: |
          mkdir -p extracted-jars
          unzip jars-${{ github.event.inputs.tag_name || github.ref_name }}.zip -d extracted-jars
          echo "解压后的文件:"
          ls -la extracted-jars

      - name: 9.上传 ZIP 到 GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          files: |
            jars-${{ github.event.inputs.tag_name || github.ref_name }}.zip
            extracted-jars/*.jar
          tag_name: ${{ github.event.inputs.tag_name || github.ref_name }}
          name: Release ${{ github.event.inputs.tag_name || github.ref_name }} ${{ github.event.inputs.draft == 'true' && '(Draft)' || '' }} ${{ github.event.inputs.prerelease == 'true' && '(Pre-release)' || '' }}
          body: |
            **Release 信息**
            - 标签: ${{ github.event.inputs.tag_name || github.ref_name }}
            - Java 版本: ${{ github.event.inputs.java_version || '8' }}
#            - 是否跳过测试: ${{ github.event.inputs.skip_tests == 'true' && '是' || '否' }}
#            - Draft 状态: ${{ github.event.inputs.draft == 'true' && '是' || '否' }}
#            - Pre-release 状态: ${{ github.event.inputs.prerelease == 'true' && '是' || '否' }}
          draft: ${{ github.event.inputs.draft == 'true' || false }}
          prerelease: ${{ github.event.inputs.prerelease == 'true' || false }}
        env:
          GITHUB_TOKEN: ${{ secrets.PAT }}

总结

该 GitHub Actions 工作流程提供了一个高效、灵活的方式来自动化 Java 项目的构建、打包和发布流程。通过用户输入参数,可以轻松定制 Java 版本、测试策略和 Release 类型,适合各种规模的 Java 项目开发。确保将 build.yml 放置在项目路径 .github/workflows/ 目录下,以正确触发工作流程。