几年前出于兴趣,写了第一个 Keycloak 微信公众号关注即登录插件,后来不断扩展,又支持了微信扫码登录。接着又折腾了一个企业微信登录,再接着又如法炮制,分别搞了个钉钉登录、手机验证码登录等等。

这些除了钉钉登录是完全自建外,其他的几个其实都是基于别人的方案做了些魔改而已,并发布到了 GitHub 的包管理中心。

详见:

发布到 GitHub 的包管理中心非常简单,只需要配置如下 GitHub Actions 即可:

yaml name: Maven Package

on: release: types: [released]

workflow_run: workflows: [ Release Workflow ] branches: [ master ] types: - completed

jobs: build-and-publish:

runs-on: ubuntu-latest

steps:
  - uses: actions/checkout@v4
  - name: Set up JDK 18
    uses: actions/setup-java@v4
    with:
      java-version: 18
      distribution: adopt
      server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
      settings-path: ${{ github.workspace }} # location for the settings.xml file

  - name: Test
    run: mvn clean test

  - name: Build with Maven
    run: mvn -B package --file pom.xml

  - name: Publish to GitHub Packages Apache Maven
    run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml
    env:
      GITHUB_TOKEN: ${{ github.token }}
      

将 jar 包发布在 GitHub 包管理中心虽然方便,但是它是一个默认非公开的集中包管理中心,即使用时,需要使用令牌验证。我的这些包,都是希望公开给所有人使用的,所以我创建了一个令牌,并且公开写在 ReadMe 文件中。比如要使用微信登录插件,就先在 pom.xml 中添加我的包管理源:

xml github github repository https://maven.pkg.github.com/jeff-tian/*

然后,添加相关的依赖:

xml

    <dependency>
        <groupId>io.github.jeff-tian</groupId>
        <artifactId>keycloak-services-social-weixin</artifactId>
        <version>0.5.36</version>
    </dependency>

下载依赖时,需要配置环境变量:GH_TOKEN=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,比如:

shell GH_TOKEN=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 mvn install

这样,就可以了。虽然可以,但是却不够方便,最讨厌的一点是,GitHub 会扫描泄露的令牌,我将该令牌共享出来后,有可能会扫描到,从而 GitHub 会强制该令牌失效,导致用户又不能正常下载了。我看了 GitHub 的文档,似乎没有办法将发布到 GitHub 上的包设置为公开。

于是,我决定将这些包发布到 Maven Central,这样,使用者就什么都不用配置,便可以直接下载使用。下了决心,于是一口气就将以上4个插件全都发到 Maven Central 了,希望给大家使用带来尽可能多的方便!

同时,本文后半部分记录一下我将它们发布到 Maven Central 的过程,不得不说,比发布到 GitHub 还是多了很多工作量的,但是带来的收益肯定能够值回票价。

成为 sonatype 的用户

要将自己的 jar 包发布到 Maven Central,首先需要成为 sonatype 的用户,我使用 GitHub 登录了 sonatype,自动获得了一个认证的命名空间: io.github.jeff-tian。

1724241541738 3eb4c4f2 a050 4138 a809 7e73daa96d83

修改 pom.xml

检查 pom.xml,确保具有:

  • 认证通过的命名空间
  • 项目 URL 等元信息
  • 源代码元信息
  • 作者元信息
  • 许可证元信息
  • profile

以下两个典型的提交可以展示是如何添加以上信息的:

即做这样的改动:

xml io.github.jeff-tian keycloak-services-social-dingding 0.0.3 Keycloak Services Social DingDing Keycloak 钉钉登录插件。Keycloak Services Social DingDing https://github.com/Jeff-Tian/keycloak-services-social-dingding

<developers>
    <developer>
        <id>jeff-tian</id>
        <name>Jeff Tian</name>
        <email>jeff.tian@outlook.com</email>
        <url>https://jefftian.dev</url>
    </developer>
</developers>

<scm>
    <url>https://github.com/jeff-tian/keycloak-services-social-dingding</url>
    <connection>scm:git:git://github.com/jeff-tian/keycloak-services-social-dingding.git</connection>
    <developerConnection>scm:git:ssh://github.com/jeff-tian/keycloak-services-social-dingding.git</developerConnection>
    <tag>HEAD</tag>
</scm>

<developers>
    <developer>
        <id>jeff-tian</id>
        <name>Jeff Tian</name>
        <email>jeff.tian@outlook.com</email>
        <url>https://jefftian.dev</url>
    </developer>
</developers>

<scm>
    <url>https://github.com/jeff-tian/keycloak-services-social-dingding</url>
    <connection>scm:git:git://github.com/jeff-tian/keycloak-services-social-dingding.git</connection>
    <developerConnection>scm:git:ssh://github.com/jeff-tian/keycloak-services-social-dingding.git</developerConnection>
    <tag>HEAD</tag>
</scm>

向代码仓库添加需要的秘密值

一共需要向需要发布到 Maven Central 的代码仓库中添加 4 个秘密值,如下所示:

1724242599032 d7e3fca6 3413 498f 9203 c0af288a9b0c

让我们来一一分解。

CENTRAL_TOKEN_USERNAME 和 CENTRAL_TOKEN_PASSWORD

成为 sonatype 的用户之后,可以去申请令牌用户和令牌密码,以供在发布 jar 包环节,调用 sonatype 的 API 时进行身份认证。

这两个值是在 https://central.sonatype.com/account 页面进行申请的:

1724242791917 482e83d1 56d2 4492 8625 05af11437ee8

GPG_SIGNING_KEY

这是在 mvn deploy时进行对代码文件进行 GPG 签名时需要的秘钥,记住,必须使用如下命令将其值拷贝下来,并粘贴到 GitHub Actions 秘密值中:

shell gpg --armor export-secert-keys <你的ID>

这一步其实卡了我很久很久,详见 https://github.com/actions/setup-java/issues/675

后面我们会在 GitHub Actions 中通过 setup-java来进行 GPG 密钥导入。如果密钥值不对,这一步会报错。然而,我不小心使用了这个命令: gpg --armor --export <你的ID>来获取了 GPG 密钥值,并粘贴到了 GitHub Actions 中的秘密值中,结果是 setup-java显示成功地导入了 GPG 密钥,但是最后却在 mvn deploy对代码文件进行签名时说找不到密钥。这就让人非常困惑,特此提醒,一定要用 gpg --armor export-secret-keys,以免踩坑!

MAVEN_GPG_PASSPHRASE

这是能够打开你的 GPG 密钥的密码,你在上一步进行 gpg --armor export-secret-keys导出密钥时,就会被询问该密码。

通过 GitHub Actions 自动发布到 Maven Central

我希望达到的目标是,提交代码,自动运行测试做个检查。如果没有问题,并且版本号有更新,就自动创建发布目标。在发布目标生成后,就自动发布到 Maven Central。这么一套流程,就需要 3 个 GitHub Actions,分别创建3个文件来实现,以下直接给出源码,懒得一一解释了。也可以直接打开 https://github.com/Jeff-Tian/keycloak-services-social-dingding/tree/main/.github/workflows 查看在线源码。

maven.yml

这就在提交代码后运行自动化测试的工作流:

yaml

This workflow will build a Java project with Maven

For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven

name: Java CI with Maven

on: push: pull_request:

jobs: build:

runs-on: ubuntu-latest

steps:
  - uses: actions/checkout@v4
  - name: Set up JDK 18
    uses: actions/setup-java@v1
    with:
      java-version: 18
  - name: Test
    run: mvn clean test
  - name: Build with Maven
    run: mvn -B package --file pom.xml

  # 上传生成的文件作为 Artifact
  - name: Upload Maven package
    uses: actions/upload-artifact@v4
    with:
      name: java-artifacts
      path: target/

release.yml

这是在 GitHub 上创建出发布版本的工作流:

yaml name: Release Workflow

on: workflow_run: workflows: [ Java CI with Maven ] branches: [ main ] types: - completed

jobs: release: name: Release Process runs-on: ubuntu-latest

steps:
  - name: Checkout repository
    uses: actions/checkout@v4

  - name: Download Java CI with Maven artifacts
    uses: actions/download-artifact@v4
    with:
      name: java-artifacts
      github-token: ${{ secrets.GITHUB_TOKEN }}
      run-id: ${{ github.event.workflow_run.id }}

  - name: Set up JDK 18
    uses: actions/setup-java@v2
    with:
      distribution: adopt
      java-version: 18

  - name: Get latest tag
    id: get_latest_tag
    run: |
      git fetch --tags
      tag_commit=$(git rev-list --tags --max-count=1)
      
      if [ -z $tag_commit ]; then
        latest_tag=0.0.0
      else
        latest_tag=$(git describe --tags $tag_commit)
      fi
      
      echo ::set-output name=latest_tag::$latest_tag

  - name: Get current version from pom.xml
    id: get_current_version
    run: |
      current_version=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
      echo ::set-output name=current_version::$current_version

  - name: Check if pom.xml version has changed
    id: check_version
    run: |
      if [ ${{ steps.get_current_version.outputs.current_version }} != ${{ steps.get_latest_tag.outputs.latest_tag }} ]; then
        echo Version changed
        echo ::set-output name=version_changed::true
      else
        echo Version not changed
        echo ::set-output name=version_changed::false
      fi

  - name: Create and Push Tag
    id: push_tag
    if: steps.check_version.outputs.version_changed == true
    run: |
      git config --local user.email action@github.com
      git config --local user.name GitHub Action
      git tag -a ${{ steps.get_current_version.outputs.current_version }} -m Generated tag from GitHub Actions
      git push origin ${{ steps.get_current_version.outputs.current_version }}
      
      ls -al
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  - name: Create release
    id: create_release
    if: steps.check_version.outputs.version_changed == true
    uses: actions/create-release@v1
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    with:
      tag_name: ${{ steps.get_current_version.outputs.current_version }}
      release_name: Release ${{ steps.get_current_version.outputs.current_version }}
      draft: false
      prerelease: false

mavenpublish.yml

这是在版本创建出来后,自动向 GitHub 和 Maven Central 发布 jar 包的工作流:

yaml name: Maven Package

on: release: types: [ released ]

workflow_run: workflows: [ Release Workflow ] branches: [ main ] types: - completed

jobs: build:

runs-on: ubuntu-latest

steps:
  - uses: actions/checkout@v4
  - name: Set up JDK 18
    uses: actions/setup-java@v1
    with:
      java-version: 18
      server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
      settings-path: ${{ github.workspace }} # location for the settings.xml file


  - name: Get latest tag
    id: get_latest_tag
    run: |
      git fetch --tags
      tag_commit=$(git rev-list --tags --max-count=1)
      
      if [ -z $tag_commit ]; then
        latest_tag=0.0.0
      else
        latest_tag=$(git describe --tags $tag_commit)
      fi
      
      echo ::set-output name=latest_tag::$latest_tag


  - name: Get current version from pom.xml
    id: get_current_version
    run: |
      current_version=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
      echo ::set-output name=current_version::$current_version


  - name: Check if pom.xml version has changed
    id: check_version
    run: |
      if [ ${{ steps.get_current_version.outputs.current_version }} != ${{ steps.get_latest_tag.outputs.latest_tag }} ]; then
        echo Version changed
        echo ::set-output name=version_changed::true
      else
        echo Version not changed
        echo ::set-output name=version_changed::false
      fi

  - name: Test
    if: steps.check_version.outputs.version_changed == true
    run: mvn clean test

  - name: Build with Maven
    if: steps.check_version.outputs.version_changed == true
    run: mvn -B package --file pom.xml

  - name: Publish to GitHub Packages Apache Maven
    if: steps.check_version.outputs.version_changed == true
    run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml
    env:
      GITHUB_TOKEN: ${{ github.token }}

publish-to-maven-central: needs: [ build ] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Maven Central Repository uses: actions/setup-java@v4 with: java-version: 18 distribution: adopt server-id: central server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD gpg-private-key: ${{ secrets.GPG_SIGNING_KEY }} gpg-passphrase: MAVEN_GPG_PASSPHRASE

  - name: Set Version
    run: mvn versions:set -DnewVersion=${{ github.event.release.tag_name }}
  - name: Publish to Maven Central
    run: |
      mvn -P release --batch-mode deploy -DskipTests
    env:
      MAVEN_USERNAME: ${{ secrets.CENTRAL_TOKEN_USERNAME }}
      MAVEN_PASSWORD: ${{ secrets.CENTRAL_TOKEN_PASSWORD }}
      MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}

1724243698949 c38ba308 319c 404c aa8f 342fe8bd1142

验证

为了验证已经发布的 jar 包,我在 https://github.com/Jeff-Tian/keycloak-heroku 中删除了 GitHub repo 定义,直接在 pom.xml 中添加这几个包:

yaml

    <dependency>
        <groupId>io.github.jeff-tian</groupId>
        <artifactId>keycloak-services-social-weixin</artifactId>
        <version>0.5.36</version>
    </dependency>

    <dependency>
        <groupId>io.github.jeff-tian</groupId>
        <artifactId>keycloak-services-social-dingding</artifactId>
        <version>0.0.4</version>
    </dependency>

    <dependency>
        <groupId>io.github.jeff-tian</groupId>
        <artifactId>keycloak-services-social-wechat-work</artifactId>
        <version>22.0.6</version>
    </dependency>
    <dependency>
        <groupId>io.github.jeff-tian</groupId>
        <artifactId>keycloak-phone-provider</artifactId>
        <version>2.3.10</version>
    </dependency>
    <dependency>
        <groupId>io.github.jeff-tian</groupId>
        <artifactId>keycloak-phone-provider.resources</artifactId>
        <version>2.3.10</version>
    </dependency>
    <dependency>
        <groupId>io.github.jeff-tian</groupId>
        <artifactId>keycloak-sms-provider-dummy</artifactId>
        <version>2.3.10</version>
    </dependency>

本地 mvn install没有任何问题,部署到 keycloak.jiwai.win 之后的效果如下:

1724378169930 0a2d3777 07b1 42b9 8070 96d9c18c8caf

也可以通过 GitHub 的 Code Space 打开,然后在命令行中执行:

yaml docker compose -f docker-compose.heroku.yml up

1724378302496 7c4bfeff bc88 419d aaaf 55bb779bab19

然后就会有端口映射成功:

1724378329380 60c8d827 8ed8 4d27 b949 ee95b2898402

链接打开后如下:

1724378125087 1289561e de42 4641 97de c032d85b4106

在线体验

比如可以通过点击 https://keycloak.jiwai.win/realms/UniHeart/account 这个链接,选择不同的登录方式进行体验。

1724378454539 53a23e57 9b17 4dfa abde 975f67bf16c0