构建出一个 JAR 并不等于完成发布。版本标签、校验和、发布说明、GitHub Release、制品上传与通知,往往散落在脚本和人工操作中。以 JReleaser 创建者、Java Champion Andres Almiray 为主角的这期访谈,提供了一个重新审视发布工程的切入口:发布也应该是一条可重复、可审查、可自动化的流水线。
JReleaser 管的是“构建之后”
JReleaser 的价值不在于代替 Maven 或 Gradle 编译代码,而在于接管构建完成后的交付工作。可以把一条典型流水线拆成三层:
- 构建层:运行测试,生成 JAR、ZIP、原生可执行文件或容器镜像。
- 发布层:生成校验和与变更说明,创建标签和托管平台 Release,上传制品。
- 分发层:把制品推送到包管理器、制品仓库或其他发布渠道。
传统脚本通常把这三层混在一起。JReleaser 则鼓励用声明式配置描述项目、制品和目标渠道,让发布规则进入版本控制。
这类工具带来的关键变化不是“少写几条命令”,而是让发布具备工程属性:同一个版本可以在本地检查、在 CI 中执行,并留下配置与日志作为审计依据。
一个最小的 GitHub Release 配置
下面给出一个可以改造的最小示例。假设条件如下:
- 项目托管在 GitHub;
- Maven 已经生成
target/release-demo-1.0.0.jar; - 准备发布的 Git 标签为
v1.0.0; - 本机或 CI 中已经安装 JReleaser CLI。
在仓库根目录创建 jreleaser.yml:
project:
name: release-demo
version: 1.0.0
description: Minimal JReleaser demonstration
authors:
- Your Name
license: Apache-2.0
inceptionYear: 2025
stereotype: CLI
links:
homepage: https://github.com/YOUR_ACCOUNT/release-demo
release:
github:
owner: YOUR_ACCOUNT
overwrite: false
draft: true
sign: false
distributions:
release-demo:
type: SINGLE_JAR
artifacts:
- path: target/release-demo-1.0.0.jar
运行前需要修改三处内容:
- 把
YOUR_ACCOUNT换成 GitHub 用户名或组织名; - 确保
project.version与实际版本一致; - 确保
artifacts.path指向 Maven 或 Gradle 真正生成的文件。
先构建并检查配置,不要一上来就发布:
mvn -B -DskipTests package
jreleaser config
如果使用 SDKMAN,可以这样安装 CLI:
sdk install jreleaser
jreleaser --version
接下来使用受限的 GitHub Token 做一次试运行:
export JRELEASER_GITHUB_TOKEN='replace-with-a-short-lived-token'
jreleaser full-release --dry-run
确认生成的发布说明、制品路径和版本信息正确后,再执行真实发布:
jreleaser full-release
示例将 draft 设为 true,目的是先创建草稿 Release,保留人工复核环节。流程稳定后,可以根据团队政策决定是否改为自动公开。
把同一套规则放进 GitHub Actions
发布不应依赖某位维护者的笔记本电脑。可以在 .github/workflows/release.yml 中加入以下工作流:
name: release
on:
push:
tags:
- 'v*'
permissions:
contents: write
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
cache: maven
- name: Build artifact
run: mvn -B verify
- name: Validate JReleaser configuration
uses: jreleaser/release-action@v2
with:
distribution: jreleaser
arguments: config
- name: Publish release
uses: jreleaser/release-action@v2
with:
distribution: jreleaser
arguments: full-release
env:
JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
这个工作流保留了清晰的责任边界:Maven 负责验证和构建,JReleaser 负责发布。fetch-depth: 0 让发布工具能够读取完整标签与提交历史;contents: write 则允许工作流创建 GitHub Release 和上传附件。
示例中的版本仍写在 jreleaser.yml 中,因此创建标签之前必须保证配置版本、构建版本和标签一致。实际项目可以在现有版本管理流程中统一更新这些值,而不是在发布阶段临时猜测版本。
自动化不等于取消控制
发布工具会放大正确配置,也会放大错误配置。接入生产仓库前,至少检查以下事项:
- 令牌权限:只授予目标仓库所需的最小权限,不要把个人长期 Token 写进配置文件。
- 版本一致性:Git 标签、Maven/Gradle 版本、JReleaser 项目版本和制品文件名必须对应。
- 幂等策略:明确重复运行时应该失败、覆盖还是跳过。稳定前建议保持
overwrite: false。 - 制品来源:只发布当前 CI 任务构建并验证过的文件,避免上传开发机遗留产物。
- 签名与供应链:示例关闭了签名,仅适合最小演示。正式开源项目应评估制品签名、SBOM、来源证明和依赖安全策略。
- 失败恢复:区分“制品已上传但公告失败”和“Release 尚未创建”等状态,不要盲目重跑整条流水线。
采用建议:先固定一个渠道,再逐步扩展
最稳妥的落地方式,是先让 JReleaser 只负责一个 GitHub 草稿 Release。待团队验证版本规则、Token 权限和重复执行行为后,再逐步增加签名、包管理器发布和通知渠道。
判断自动化是否成功,不应只看发布是否更快,还要看它是否更容易复现和排错。如果新维护者只需查看 jreleaser.yml、CI 配置和一次运行日志,就能理解制品从构建到公开的全过程,那么发布流程才真正从个人经验变成了项目能力。