Skip to content

Release to Maven Central #24

Release to Maven Central

Release to Maven Central #24

Workflow file for this run

name: Release to Maven Central
on:
workflow_dispatch:
release:
types: [published]
permissions:
contents: read
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '11'
cache: maven
# 可选:快速检查必需的 Secrets 是否存在(避免空跑)
- name: Check required secrets
run: |
[ -z "${{ secrets.GPG_PRIVATE_KEY }}" ] && echo "GPG_PRIVATE_KEY is EMPTY" && exit 1 || echo "GPG_PRIVATE_KEY is SET"
[ -z "${{ secrets.CENTRAL_USERNAME }}" ] && echo "CENTRAL_USERNAME is EMPTY" && exit 1 || echo "CENTRAL_USERNAME is SET"
[ -z "${{ secrets.CENTRAL_TOKEN }}" ] && echo "CENTRAL_TOKEN is EMPTY" && exit 1 || echo "CENTRAL_TOKEN is SET"
[ -z "${{ secrets.GPG_PASSPHRASE }}" ] && echo "GPG_PASSPHRASE is EMPTY (OK if your key has no passphrase)" || echo "GPG_PASSPHRASE is SET"
# 仅在 CI 导入私钥(你已把 private.asc 转成单行 base64 存在 GPG_PRIVATE_KEY)
- name: Import GPG private key (base64)
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
run: |
set -e
mkdir -p ~/.gnupg
chmod 700 ~/.gnupg
printf "pinentry-mode loopback\n" >> ~/.gnupg/gpg.conf
printf "allow-loopback-pinentry\n" >> ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agent || true
echo "$GPG_PRIVATE_KEY" > "$RUNNER_TEMP/priv.b64"
base64 -d "$RUNNER_TEMP/priv.b64" > "$RUNNER_TEMP/private.asc"
gpg --batch --import "$RUNNER_TEMP/private.asc"
echo "== Secret keys in keyring =="
gpg --batch --list-secret-keys --keyid-format LONG || true
# 仅在 CI 生成 settings.xml(开发者本地无需配置)
- name: Create temporary Maven settings.xml (CI-only)
env:
CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
CENTRAL_TOKEN: ${{ secrets.CENTRAL_TOKEN }}
run: |
mkdir -p ~/.m2
{
printf '<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">\n'
printf ' <servers>\n'
printf ' <server>\n'
printf ' <id>ossrh</id>\n'
printf ' <username>${env.CENTRAL_USERNAME}</username>\n'
printf ' <password>${env.CENTRAL_TOKEN}</password>\n'
printf ' </server>\n'
printf ' </servers>\n'
printf '</settings>\n'
} > ~/.m2/settings.xml
- name: Probe Central auth with username guess
env:
U1: welsir # 如果你在 Profile 里找到了 Username,就改成那个
TOK: ${{ secrets.CENTRAL_TOKEN }} # Publishing/Deployment Token 的明文
run: |
set -e
url=https://s01.oss.sonatype.org/service/local/staging/profiles
code=$(curl -s -o /dev/null -w "%{http_code}" -u "$U1:$TOK" "$url")
echo "probe($U1) => HTTP $code"
- name: Diagnose Maven settings
run: |
echo "Show ~/.m2/settings.xml:"
sed -n '1,200p' ~/.m2/settings.xml || true
echo "Effective server IDs found in settings.xml:"
awk -F'[<>]' '/<id>/{print "id=" $3}' ~/.m2/settings.xml || true
# 合并:检查 Secrets 长度 + 用最小项目做一次 auth 调试(-X)
- name: Check CENTRAL secrets length (no leak) and auth debug deploy
env:
CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
CENTRAL_TOKEN: ${{ secrets.CENTRAL_TOKEN }}
run: |
set -e
# 1) 检查 Secrets 长度(不泄露明文)
USER_LEN=$(printf "%s" "$CENTRAL_USERNAME" | wc -c | tr -d ' ')
TOKEN_LEN=$(printf "%s" "$CENTRAL_TOKEN" | wc -c | tr -d ' ')
echo "USER_LEN=$USER_LEN"
echo "TOKEN_LEN=$TOKEN_LEN"
if [ "$USER_LEN" -eq 0 ] || [ "$TOKEN_LEN" -eq 0 ]; then
echo "ERROR: CENTRAL_USERNAME or CENTRAL_TOKEN is empty. Fix Secrets before continuing."
exit 1
fi
# 2) 用一个最小项目做一次 auth 检查(不影响你的主项目配置)
mkdir -p /tmp/miniproj && cd /tmp/miniproj
cat > pom.xml <<'XML'
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.timemachinelab</groupId>
<artifactId>auth-check</artifactId>
<version>0.0.1</version>
<distributionManagement>
<repository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
<snapshotRepository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
</project>
XML
# 3) 显式指定 settings,并开启 -X 抓取认证细节
# 用 || true 避免 401 时整个 Job 直接失败,中断后续日志收集。
mvn -X -B -U -s ~/.m2/settings.xml -DskipTests=true deploy || true
# 确认版本不是 SNAPSHOT(发布前置检查)
- name: Ensure release version (non-SNAPSHOT)
run: |
VERSION=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:3.5.0:exec)
echo "Project version: $VERSION"
if echo "$VERSION" | grep -qi SNAPSHOT; then
echo "ERROR: version is SNAPSHOT. Please set a release version."
exit 1
fi
# 先 verify,便于排错;显式指定 KEY_ID(替换为你的 KEY_ID)
- name: Verify with signing (detailed logs)
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
set -e
KEY_ID="6BFD927CC2352BD5" # TODO: 替换为你的长 KEYID
echo "Using KEY_ID=$KEY_ID"
mvn -e -X -s ~/.m2/settings.xml -Dgpg.passphrase="$GPG_PASSPHRASE" -Dgpg.keyname="$KEY_ID" -DskipTests=true clean verify
# 签名并发布到 OSSRH(Maven Central)
- name: Build, sign and deploy
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
set -e
KEY_ID="6BFD927CC2352BD5" # TODO: 同上
mvn -B -U -s ~/.m2/settings.xml -Dgpg.passphrase="$GPG_PASSPHRASE" -Dgpg.keyname="$KEY_ID" clean deploy