はじめに
自作のJava/Kotlinライブラリを広く公開したい場合、Maven Centralへのデプロイが一般的な選択肢となります。本記事では、GitHubの個人アカウントを持つ開発者がMaven Centralへライブラリを公開するための手順を解説します。
本記事の内容は、筆者が公開している DB Tester(JUnit/Spock向けのデータベーステストフレームワーク)のリリース手順に基づいています。
- GitHub: https://github.com/seijikohara/db-tester
- Maven Central: https://central.sonatype.com/artifact/io.github.seijikohara/db-tester-bom
前提条件
- GitHubアカウント
- GPGキーの基本的な知識
- Gradleプロジェクト(Gradle 8.x以降推奨)
全体の流れ
- Central Portalでアカウント作成・名前空間の検証
- APIトークンの生成
- GPGキーの作成・公開
- Gradleプロジェクトの設定
- リリース実行
1. Central Portalアカウントの設定
アカウント作成
Central Portalにアクセスし、アカウントを作成します。
GitHubアカウントでのログインも可能です。
名前空間の検証
GitHubの個人ユーザーの場合、io.github.<username> 形式の名前空間を使用します。
GitHubアカウントでログインした場合、io.github.<username> の名前空間は自動的に検証されます。手動での検証作業は不要です。
独自ドメインを使用する場合は、Central Portalの「Namespaces」からドメインを追加し、TXT DNSレコードによる検証が必要です。
2. APIトークンの生成
Maven Centralへのデプロイに必要な認証情報を生成します。
- Central Portalにログイン
- 「Account」→「Generate User Token」を選択
- 表示されるUsernameと**Password(Token)**を安全に保存
トークンは一度しか表示されません。紛失した場合は再生成が必要です。
3. GPGキーのセットアップ
Maven Centralでは、すべてのアーティファクトにGPG署名が必須です。
キーの生成
# GPGキーの生成(RSA 4096ビット推奨)
gpg --full-generate-key
# 選択肢:
# - (1) RSA and RSA
# - 4096 bits
# - 0 = key does not expire(または任意の有効期限)
# - 名前とメールアドレスを入力(GitHubアカウントと一致させる)
キーIDの確認
gpg --list-secret-keys --keyid-format=short
# 出力例:
# sec rsa4096/ABCD1234 2024-01-01 [SC]
# 1234567890ABCDEF1234567890ABCDEF12345678
# uid [ultimate] Your Name <your@email.com>
ABCD1234 がキーID(短縮形)です。
公開鍵のアップロード
Maven Centralが署名を検証できるよう、公開鍵をキーサーバーに登録します。
# 複数のキーサーバーに登録(推奨)
gpg --keyserver keyserver.ubuntu.com --send-keys ABCD1234
gpg --keyserver keys.openpgp.org --send-keys ABCD1234
署名のテスト
echo "test" | gpg --clearsign
パスフレーズを入力して署名が成功すれば準備完了です。
4. Gradleプロジェクトの設定
使用するプラグイン
本記事では以下のプラグインを使用します。
| プラグイン | 用途 |
|---|---|
| gradle-maven-publish-plugin | Maven Central公開の自動化 |
| axion-release-plugin | Gitタグベースのバージョン管理 |
プラグインの追加
pluginManagement {
repositories {
gradlePluginPortal()
}
}
plugins {
alias(libs.plugins.axion.release)
alias(libs.plugins.maven.publish)
}
[versions]
axion-release = "1.18.20"
maven-publish = "0.30.0"
[plugins]
axion-release = { id = "pl.allegro.tech.build.axion-release", version.ref = "axion-release" }
maven-publish = { id = "com.vanniktech.maven.publish", version.ref = "maven-publish" }
バージョン管理の設定(axion-release-plugin)
Gitタグからバージョンを自動的に導出します。
group = "io.github.<username>"
scmVersion {
useHighestVersion = true
tag {
prefix = "v"
versionSeparator = ""
}
versionCreator("simple")
repository {
pushTagsOnly = true
}
checks {
uncommittedChanges = false
aheadOfRemote = false
}
}
version = scmVersion.version
バージョンの動作:
- タグ
v1.2.0→ バージョン1.2.0 - タグ後のコミット → バージョン
1.2.1-SNAPSHOT
# 現在のバージョンを確認
./gradlew currentVersion
Maven公開設定(gradle-maven-publish-plugin)
mavenPublishing {
publishToMavenCentral()
signAllPublications()
pom {
name = "Your Library Name"
description = "A brief description of your library"
url = "https://github.com/<username>/<repository>"
inceptionYear = "2024"
licenses {
license {
name = "MIT License"
url = "https://opensource.org/licenses/MIT"
}
}
developers {
developer {
id = "<username>"
name = "Your Name"
email = "your@email.com"
}
}
scm {
connection = "scm:git:git://github.com/<username>/<repository>.git"
developerConnection = "scm:git:ssh://github.com/<username>/<repository>.git"
url = "https://github.com/<username>/<repository>"
}
}
}
Maven Centralでは、POMにname、description、url、licenses、developers、scmの記載が必須です。これらが不足している場合、公開時にバリデーションエラーが発生します。
認証情報の設定
~/.gradle/gradle.properties に認証情報を追加します。
# Maven Central Portal認証情報
mavenCentralUsername=your-username-from-central-portal
mavenCentralPassword=your-token-from-central-portal
# GPG署名設定(GPGエージェント使用)
signing.gnupg.keyName=ABCD1234
signing.gnupg.passphrase=your-gpg-passphrase
CI環境での設定(環境変数)
CI環境では環境変数で認証情報を渡します。
export ORG_GRADLE_PROJECT_mavenCentralUsername="your-username"
export ORG_GRADLE_PROJECT_mavenCentralPassword="your-token"
export ORG_GRADLE_PROJECT_signingInMemoryKeyId="ABCD1234"
export ORG_GRADLE_PROJECT_signingInMemoryKeyPassword="your-passphrase"
export ORG_GRADLE_PROJECT_signingInMemoryKey="$(gpg --armor --export-secret-keys ABCD1234)"
5. リリースの実行
ローカルリリース
# 1. テストの実行
./gradlew clean build
# 2. ローカルMavenリポジトリで確認(任意)
./gradlew publishToMavenLocal -Prelease.forceVersion=1.0.0
# 3. Gitタグの作成
git tag v1.0.0
# 4. バージョン確認
./gradlew currentVersion # 1.0.0 と表示されること
# 5. Maven Centralへ公開
./gradlew publishAndReleaseToMavenCentral --no-configuration-cache
# 6. タグをプッシュ(公開成功後)
git push origin v1.0.0
# 7. GitHub Releaseの作成
gh release create v1.0.0 --title "Release 1.0.0" --generate-notes
--no-configuration-cache オプションは、gradle-maven-publish-pluginの制約により必須です。
GitHub Actionsによる自動リリース(推奨)
継続的なリリースには、GitHub Actionsワークフローの構築をお勧めします。
GitHub Actions設定例
name: Release
on:
workflow_dispatch:
inputs:
version:
description: 'Release version (e.g., 1.2.0)'
required: true
type: string
dry-run:
description: 'Dry-run mode'
required: false
type: boolean
default: true
env:
JAVA_VERSION: '21'
jobs:
validate:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
tag: ${{ steps.version.outputs.tag }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Validate version format
run: |
VERSION="${{ github.event.inputs.version }}"
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Invalid version format"
exit 1
fi
- name: Check tag does not exist
run: |
TAG="v${{ github.event.inputs.version }}"
if git rev-parse "$TAG" >/dev/null 2>&1; then
echo "::error::Tag $TAG already exists"
exit 1
fi
- id: version
run: |
echo "version=${{ github.event.inputs.version }}" >> "$GITHUB_OUTPUT"
echo "tag=v${{ github.event.inputs.version }}" >> "$GITHUB_OUTPUT"
release:
needs: validate
runs-on: ubuntu-latest
if: ${{ !inputs.dry-run }}
environment: maven-central
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: ${{ env.JAVA_VERSION }}
cache: 'gradle'
- name: Create local tag
run: git tag ${{ needs.validate.outputs.tag }}
- name: Build
run: ./gradlew clean build
- name: Publish to Maven Central
run: ./gradlew publishAndReleaseToMavenCentral --no-configuration-cache
env:
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_TOKEN }}
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_PRIVATE_KEY }}
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.GPG_PASSPHRASE }}
- name: Push tag
run: git push origin ${{ needs.validate.outputs.tag }}
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.validate.outputs.tag }}
name: Release ${{ needs.validate.outputs.version }}
generate_release_notes: true
必要なシークレット:
| シークレット | 説明 |
|---|---|
GPG_PRIVATE_KEY |
gpg --armor --export-secret-keys KEY_ID の出力 |
GPG_PASSPHRASE |
GPGキーのパスフレーズ |
MAVEN_CENTRAL_USERNAME |
Central Portalのユーザー名 |
MAVEN_CENTRAL_TOKEN |
Central Portalのトークン |
GitHub Environment:
- リポジトリの「Settings」→「Environments」→「New environment」
- 名前:
maven-central - 「Required reviewers」を設定(誤操作防止)
6. 公開の確認
Maven Central
公開後、10〜30分程度で以下のURLで確認できます。
https://central.sonatype.com/artifact/io.github.<username>/<artifact-id>
依存関係として使用
dependencies {
implementation("io.github.<username>:<artifact-id>:1.0.0")
}
トラブルシューティング
GPG署名エラー: "Inappropriate ioctl for device"
TTYがない環境(CI等)でGPGがパスフレーズを要求できない場合に発生します。
解決策: インメモリ署名を使用
signing.keyId=ABCD1234
signing.password=your-gpg-passphrase
signing.secretKeyRingFile=/path/to/secring.gpg
または環境変数:
export ORG_GRADLE_PROJECT_signingInMemoryKey="$(gpg --armor --export-secret-keys ABCD1234)"
export ORG_GRADLE_PROJECT_signingInMemoryKeyPassword="your-passphrase"
POMバリデーションエラー
Maven Centralでは以下の要素が必須です:
namedescriptionurllicensesdevelopersscm
gradle-maven-publish-pluginは自動的にこれらを検証し、不足があればエラーを報告します。
# ローカルで検証
./gradlew publishToMavenLocal -Prelease.forceVersion=1.0.0 --info
Configuration Cacheエラー
gradle-maven-publish-pluginはConfiguration Cacheと互換性がありません。
# 正しい使用方法
./gradlew publishAndReleaseToMavenCentral --no-configuration-cache
まとめ
GitHubの個人ユーザーがMaven Centralへライブラリを公開する手順を解説しました。
ポイント:
- Central Portal: GitHubログインで名前空間が自動検証される
- gradle-maven-publish-plugin: Maven Central公開を大幅に簡素化
- axion-release-plugin: Gitタグベースの宣言的なバージョン管理
- GitHub Actions: 継続的リリースの自動化
一度環境を整えれば、./gradlew publishAndReleaseToMavenCentral のワンコマンドで公開が完了します。