Ohhnews

分类导航

$ cd ..
foojay原文

action/setup-java 5.4和5.5 新功能:签名验证、Kona JDK与更佳Maven体验

#签名验证#kona jdk#maven优化#graalvm#jdk分发

actions/setup-java 5.5.0 新特性

如果你在 GitHub Actions 上构建 Java,actions/setup-java 几乎可以说是你工作流程中的第一步。它安装 JDK,配置 JAVA_HOMEPATH,设置 Maven 的 settings.xml,配置依赖缓存,并注册 Maven 工具链——这一切都在你的构建开始之前完成。

最近的两个版本 v5.4.0v5.5.0 悄然成为一段时间以来最有趣的更新之一。v5.5.0 尤其带来了 Java 开发者多年来在 CI 上一直期盼的功能:对你下载的 JDK 进行加密验证。此外,还有一个全新的发行版、更智能的版本文件处理,以及一系列 Maven 质量改进,使你的日志更干净,工具链文件更合理。

v5.4.0 发布时没有专门的更新日志,因此本文一次性涵盖了两个版本的亮点。

让我们深入了解一下。


验证下载的 JDK 签名

关于大多数 CI 流水线,有一个令人不安的事实:编译和运行代码的 JDK 是通过网络下载的,长期以来唯一的完整性保障是 TLS。这通常没问题——直到出问题。JDK 成为流水线其余部分信任的 java 二进制文件,它可以访问你的密钥、签名凭据和部署凭证。工具链本身的供应链完整性至关重要。

v5.5.0 为下载的 JDK 归档添加了分离的 GPG 签名验证

$ config
- uses: actions/setup-java@v5.5.0
  with:
    distribution: 'temurin'
    java-version: '21'
    verify-signature: true

verify-signature: true 时,该操作会下载发行版与归档一起发布的分离 GPG 签名,并在安装之前验证 JDK。如果签名不匹配,步骤将失败——损坏的 JDK 永远不会进入运行器。

一些重要细节:

  • 当前支持的发行版: temurinmicrosoft。该操作捆绑了这些发行版的受信任公钥。
  • 快速失败,而非静默: 如果你对尚不支持该功能的发行版设置了 verify-signature: true,操作将失败,而不是假装验证成功。不会产生虚假的安全感。
  • 自带密钥: 如果你内部镜像 JDK 或希望固定到特定的受信任密钥,可以使用 verify-signature-public-key 提供你自己的密钥:
$ config
- uses: actions/setup-java@v5.5.0
  with:
    distribution: 'temurin'
    java-version: '21'
    verify-signature: true
    verify-signature-public-key: ${{ secrets.JDK_TRUSTED_PUBLIC_KEY }}

密钥以 ASCII-armored GPG 公钥的形式传递,并会覆盖所选发行版的默认捆绑密钥。

如果你关心可重现且供应链安全的构建,这就是你需要的标志。预计受支持的发行版列表会随着时间的推移而增长。


Tencent Kona JDK

actions/setup-java 现在原生支持 Tencent Kona JDK

$ config
- uses: actions/setup-java@v5.5.0
  with:
    distribution: 'kona'
    java-version: '21'

Tencent Kona JDK 是一个基于 OpenJDK 的生产级发行版,腾讯大规模运行,并为 LTS 版本提供构建。如果你的组织标准化了 Kona——或者你只是想针对它进行测试——你不再需要自定义的下载和解压步骤。它现在是一个一流的 distribution 值,也可以通过版本文件工作(更多内容见下文)。

这使得受支持的发行版列表扩展到了一个健康的集合:Temurin、Zulu、Adopt (Hotspot/OpenJ9)、Liberica、Microsoft、Corretto、Semeru、Oracle、Dragonwell、SapMachine、GraalVM、GraalVM Community,现在又加入了 Kona。


安装 JDK 而不使其成为默认

默认情况下,每次调用 setup-java 都会设置 JAVA_HOME 并更新 PATH,因此最后安装的 JDK“胜出”并成为作业其余部分的 java。这通常是你要的——但并非总是如此。

有时你需要一个特定的 JDK 仅用于一个步骤(例如,必须在 Java 17 上运行的工具),而不干扰构建使用的主要 Java 版本。set-default: false 登场:

$ config
# 主要的构建 JDK
- uses: actions/setup-java@v5.5.0
  with:
    distribution: 'temurin'
    java-version: '21'

# 额外的 JDK,可用但不作为默认
- uses: actions/setup-java@v5.5.0
  with:
    distribution: 'temurin'
    java-version: '17'
    set-default: false

使用 set-default: false,该操作:

  • 不修改 JAVA_HOMEPATH,因此 Java 21 仍为默认。
  • 仍然导出 JAVA_HOME_<版本>_<架构>(例如 JAVA_HOME_17_X64),因此额外的 JDK 可被发现。
  • 仍然在 Maven 工具链文件中注册该 JDK,因此构建可以通过工具链选择它。

这使得单个作业可以干净地处理多个 JDK,而无需“最后安装你想要的”这种排序游戏。

注意:如果你通过多行 java-version 在一个步骤中安装多个 JDK,set-default: false 适用于所有 JDK——没有一个成为默认,但每个都可通过其 JAVA_HOME_<版本>_<架构> 变量被发现。


更智能的版本文件:自动检测发行版

setup-java 可以从文件中读取你的 Java 版本,而不是在工作流中硬编码。它支持 .java-version.tool-versions (asdf) 和 .sdkmanrc (SDKMAN)。最近的版本教会了它从这些文件中推断发行版,因此你可以停止重复自己。

.sdkmanrc

SDKMAN 标识符带有供应商后缀——-tem 表示 Temurin,-zulu 表示 Zulu,等等。该操作现在自动将该后缀映射到发行版:

$ config
- uses: actions/setup-java@v5.5.0
  with:
    java-version-file: '.sdkmanrc'
$ properties
# .sdkmanrc
java=21.0.5-tem

这个 -tem 就足够了——不需要 distribution 输入。实际上,当你的 .sdkmanrc 使用可识别的后缀时,distribution 现在是可选的


更好的 Maven 体验

这些版本中的几个更改直接针对最常见的 Java 构建工具之一。

默认更安静的日志

Maven 喜欢为每一个下载的工件打印一行。在冷缓存上,这是数百行嘈杂的输出,掩盖了你真正关心的内容。setup-java 现在默认在 MAVEN_ARGS 环境变量中设置 --no-transfer-progress (-ntp):

$ config
- uses: actions/setup-java@v5.5.0
  with:
    distribution: 'temurin'
    java-version: '21'
# 后续的 `mvn` / `./mvnw` 调用自动继承 -ntp

值得知道的细节:

  • 适用于 Maven 3.9.0+Maven Wrapper (mvnw),它们都尊重 MAVEN_ARGS。旧版 Maven 会忽略它——你可以在命令行传递 --no-transfer-progress
  • 任何现有的 MAVEN_ARGS 值都会保留,不会被覆盖。
  • 想要进度信息?设置 show-download-progress: true
$ config
- uses: actions/setup-java@v5.5.0
  with:
    distribution: 'temurin'
    java-version: '21'
    show-download-progress: true  # 保留下载/传输的详细输出

非交互式 settings.xml

生成的 settings.xml 现在禁用了 Maven 的交互模式。换句话说:Maven 永远不会在 CI 运行中阻塞,等待一个没有人会回答的提示。

阻止工具链失控增长

这是一个真正的错误修复,会让一些人非常高兴。如果你在作业中多次调用 setup-java,每次调用都会追加toolchains.xml——包括重复条目。在几次安装后,你会得到一个充满重复的工具链文件。

生成的 toolchains.xml 现在按工具链类型和 id 去重。而且关键的是,它保留了你现有的根属性和任何非 JDK 的工具链。因此,你可以在多个步骤中安装任意数量的 JDK,最终得到一个干净、正确的工具链文件。


不要忘记这些 v5.4.0 的补充

该版本还有三件事值得一提:

  • 免费的 GraalVM Community 发行版 (graalvm-community):直接安装 GraalVM Community Edition 构建(稳定 JDK 17+),无需许可证操作。

    $ config
    - uses: actions/setup-java@v5.5.0
    with:
      distribution: 'graalvm-community'
      java-version: '21'
    
  • javac 问题匹配器: 该操作在安装 JDK 后注册了一个问题匹配器,将 javac 错误和警告转化为你拉取请求和运行摘要中的内联注释。编译器失败直接显示在有问题的行上,而不是被埋没在日志中。(如果你更喜欢,可以禁用它——请参阅高级用法文档。)

  • Maven Wrapper 缓存: 使用 cache: maven,该操作现在还缓存 Maven Wrapper,从而缩短使用 ./mvnw 的作业的时间。


综合起来

以下是一个工作流,同时使用了其中几个功能——签名验证的 Temurin 作为默认、用于工具的辅助 JDK、由 .sdkmanrc 驱动的版本、Maven 缓存,以及开箱即用的干净日志:

$ config
name: build
on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Java (verified, from .sdkmanrc)
        uses: actions/setup-java@v5.5.0
        with:
          java-version-file: '.sdkmanrc'   # e.g. java=21.0.5-tem
          verify-signature: true            # 如果 JDK 签名错误则失败
          cache: maven

      - name: Add a Java 17 toolchain (not the default)
        uses: actions/setup-java@v5.5.0
        with:
          distribution: 'temurin'
          java-version: '17'
          set-default: false

      - name: Build
        run: ./mvnw verify   # 已应用 -ntp;javac 错误会注释 PR

关于固定版本的建议

维护者反复推荐,也是任何第三方操作的良好实践:固定版本。为了可重现且供应链安全的构建,请引用确切的发布标签 v5.5.0(现在这些标签是不可变的),或者为了最强保证,引用完整的提交 SHA:

$ config
- uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a  # v5.5.0

浮动的主要标签 v5 虽然方便但会随着时间移动。固定到 SHA 意味着你审计的字节就是运行的字节。结合新的 verify-signature 支持,你现在可以信任操作本身以及它安装的 JDK


获取详细信息请参阅高级用法指南v5.5.0 发布说明。一如既往,欢迎在 actions/setup-java 仓库中提供反馈和报告问题。

祝你构建愉快(且验证安全)。

本文最初发表于 foojay