0001-01-01

CDK ConstructをJsii対応してみる

cdk-log-notifier という CDK Construct Library を OSS として公開しています。

GitHub では公開したのですが、こちらのライブラリが Construct Hub に載っていないのが心残りでした。Construct Hub は、AWS がホストしている CDK Construct がまとめられているサイトです。

こちらに載せてもらうためには、ライブラリを Jsii 対応する必要があります。CDK Conference 2023 に登壇するのに合わせて対応してみることにしました。

大変だったところ

参考にしたサイト

手順

package.json 書き換え

authorrepository フィールドを埋めなければならない1みたいなので埋めておきます。

--- a/package.json
+++ b/package.json
   "version": "2.0.2",
   "main": "lib/index.js",
   "license": "MIT",
   "types": "lib/index.d.ts",
+  "author": {
+    "name": "Yuki Ito"
+  },
+  "repository": {
+    "url": "https://github.com/TheDesignium/cdk-log-notifier.git",
+    "type": "git"
+  },
   "publishConfig": {
     "access": "public"
   },

次に Jsii 設定を追加します。

--- a/package.json
+++ b/package.json
   "repository": {
     "url": "https://github.com/TheDesignium/cdk-log-notifier.git",
     "type": "git"
   },
+  "jsii": {
+    "outdir": "dist",
+    "targets": {
+      "dotnet": {
+        "namespace": "TheDesignium.CDKLogNotifier",
+        "packageId": "TheDesignium.CDKLogNotifier"
+      },
+      "java": {
+        "package": "com.thedesignium.cdk_log_notifier",
+        "maven": {
+          "groupId": "com.thedesignium",
+          "artifactId": "cdk-log-notifier"
+        }
+      },
+      "python": {
+        "distName": "cdk-log-notifier",
+        "module": "cdk_log_notifier"
+      },
+      "go": {
+        "moduleName": "github.com/TheDesignium/cdk-log-notifier-go",
+        "packageName": "lognotifier"
+      }
+    }
+  },
   "publishConfig": {
     "access": "public"
   },

それぞれの言語ごとに設定項目があります。

.NET

Jsii ドキュメント

  "dotnet": {
    "namespace": "TheDesignium.CDKLogNotifier",
    "packageId": "TheDesignium.CDKLogNotifier"
  },

namespacepackageId が必須フィールドです。namespace はライブラリの namespace で、packageId は NuGet(パッケージマネージャ)上での識別子のようです。packageIdnamespace が同じであることが推奨されている2ようなので、特別理由が無い限り同じで良いと思います。

namespace は、<company>.<technology> の形式で、PascalCase が推奨されている3ので、今回は TheDesignium.CDKLogNotifier としました。

Java

Jsii ドキュメント

  "java": {
    "package": "com.thedesignium.cdklognotifier",
    "maven": {
      "groupId": "com.thedesignium.cdklognotifier",
      "artifactId": "cdk-log-notifier"
    }
  },

上記で書いたフィールドが全て必須項目です。

package は Java ライブラリのパッケージ名です。これは慣習的にドメインを逆にしたものが利用されます。記号は含まず、小文字のアルファベット&数字で構成されていることが望ましいです。4

maven.groupIdmaven.artifactId でプロジェクトが識別されます。5 groupId は Java のパッケージ名の形式にする必要があるため、慣習的にはルートパッケージのパッケージ名をそのまま入れることが多いようです。6

Python

ドキュメント

  "python": {
    "module": "cdk_log_notifier",
    "distName": "cdk-log-notifier"
  },

module は Python のモジュール名で、スタイルガイドに依れば、小英数字とアンダースコアを使用することができます7distName は PyPI でのパッケージ名になります。こちらはアンダースコアの代わりにハイフンを使うことが多いようです8

Go

ドキュメント

  "go": {
    "moduleName": "github.com/TheDesignium/cdk-log-notifier-go",
    "packageName": "lognotifier"
  }

moduleName は Go モジュールの名前です。Go は他言語のように言語特有のリポジトリではなく、GitHub 等のサイトでホストされるので、そのドメイン名で始まるモジュール名になることが多いです。GitHub であれば、実際にここに指定した名前のリポジトリを作成し push することでデプロイとなります。

packageName は Go のパッケージの名前で、小英数字のみの利用が推奨されます(一応大文字やアンダースコアも利用できます9)。

Jsii のインストール

$ npm install -D jsii jsii-pacmak

tsconfig.json の削除

tsconfig.json は Jsii が生成してくれるようになります。tsconfig.json が既にあるとエラーになるのでリネームもしくは削除しましょう。

ほんの一部ですが、一応 package.json の jsii.tsc フィールドで変更できるコンパイルオプションがあります

コンパイル

Jsii モジュールでは tsc コマンドの代わりに jsii コマンドでコンパイルを行います。

$ npx jsii

image

いろいろとエラーが出ました。

The type … is exposed in the public API of this module

lib/index.ts:16:9 - warning JSII5: The type "aws-cdk-lib.aws_logs.ILogGroup" is exposed in the public API of this module. Therefore, the module "aws-cdk-lib" must also be defined under "peerDependencies". This will be auto-corrected unless --no-fix-peer-dependencies was specified.

16   watch(logGroup: logs.ILogGroup): void;
           ~~~~~~~~~~~~~~~~~~~~~~~~

このようなエラーがいくつか出ました。端的に言えば、現在 dependencies に入れている aws-cdk-lib を peerDependencies にも入れればいいようです。

こちらに説明がありました。Jsii モジュール(Jsii 対応しているパッケージ)に依存している場合は、そのバージョンを揃えるために peerDependencies にもリストする必要があるようです(極力 Diamond Dependency Conflict を起こさないようにするというやつですね)。

Unable to locate jsii assembly for …

Error: Unable to locate jsii assembly for "change-case". If this module is not jsii-enabled, it must also be declared under bundledDependencies: Error: Expected to find .jsii file in /home/yuki/.local/src/github.com/TheDesignium/cdk-log-notifier/node_modules/change-case, but no such file found at _tryResolveAssembly (/home/yuki/.local/src/github.com/TheDesignium/cdk-log-notifier/node_modules/jsii/lib/project-info.js:259:15)

こちらに説明がありました。

Jsii 対応されていないパッケージに依存している場合は、package.json の bundledDependencies にそのパッケージをリストして NPM パッケージに同梱する必要があるようです。

上記を解消したところビルドが通るようになりました。

それぞれの言語向けにパッケージ作成

$ npx jsii-pacmak

各言語向けにソース生成&コンパイルが走ります。

ここでそれぞれの言語のコンパイルエラーが発生する場合があります。その場合はエラーが発生している(生成された)ソースコードの該当箇所を見て何が間違っているか推測することになります。

成功すると dist/ 以下にそれぞれの言語のフォルダができます。

パッケージ公開

publib という CLI を利用することで、dist 以下をまとめてパッケージリポジトリに公開することができるみたいですが、今回自分はパッケージリポジトリの利用登録から行わなければならないところも多かったので、全て手動で行ってみました。

.NET(NuGet Gallary)

NuGet にマイクロソフトアカウントでログインし、右上のプロフィールアイコンをクリックして “Upload Package” でいけます。

image

Java(Maven Central Repository)

Maven が一番戸惑いました。まず Sonatype という会社の Jira に登録します。次にそこで「新しいパッケージを登録したいですよ」という内容の Issue を作成します。

自分は下記のような感じで申請しました。

尚 GroupID を好きなドメインにしてしまうと、そのドメインの所有確認が必要です。Issue をオープンするとこんな感じで Bot からコメントが来るので、指示に従ってドメインの確認をします。

image

io.github.myusername の形式の GroupID ならリポジトリの作成だけでドメインの確認になるみたいなので、DNS レコードを作るのが面倒な場合はそちらにしましょう。

その後パッケージの公開ですが、ここだけは Java/Maven に慣れていない自分にはちょっと煩雑そうで挫折してしまい、publib-maven の力を借りることにしました。

publib-maven のドキュメント通りに進めます。まず GPG 鍵を作成します。

$ gpg --full-generate-key

下記のように環境変数を設定することで先ほどの Maven リポジトリに push することができるはずです…!

$ env MAVEN_USERNAME=acomagu MAVEN_PASSWORD=_jcowIre981j \
  MAVEN_GPG_PRIVATE_KEY_PASSPHRASE=_jcowIre981g \
  MAVEN_GPG_PRIVATE_KEY_FILE=$PWD/private.pem \
  MAVEN_STAGING_PROFILE_ID=1a67a8f9b3d174 \
  MAVEN_ENDPOINT=https://s01.oss.sonatype.org \
  npx publib-maven

エラーが出ました…

gpg: can't open '/home/yuki/.local/src/github.com/TheDesignium/cdk-log-notifier/dist/java/com/thedesignium/cdk-log-notifier/2.0.3/cdk-log-notifier-2.0.3-javadoc.jar': No such file or directory
[GNUPG:] FAILURE sign 33587281
gpg: signing failed: No such file or directory
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.728 s
[INFO] Finished at: 2023-05-27T19:49:39+09:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-gpg-plugin:3.1.0:sign-and-deploy-file (default-cli) on project standalone-pom: Exit code: 2 -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-gpg-plugin:3.1.0:sign-and-deploy-file (default-cli) on project standalone-pom: Exit code: 2
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:375)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:351)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:215)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:171)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:163)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:298)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:960)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:293)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:196)
    at jdk.internal.reflect.DirectMethodHandleAccessor.invoke (DirectMethodHandleAccessor.java:104)
    at java.lang.reflect.Method.invoke (Method.java:578)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: org.apache.maven.plugin.MojoExecutionException: Exit code: 2
    at org.apache.maven.plugins.gpg.GpgSigner.generateSignatureForFile (GpgSigner.java:176)
    at org.apache.maven.plugins.gpg.AbstractGpgSigner.generateSignatureForArtifact (AbstractGpgSigner.java:174)
    at org.apache.maven.plugins.gpg.SignAndDeployFileMojo.execute (SignAndDeployFileMojo.java:411)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:370)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:351)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:215)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:171)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:163)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:298)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:960)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:293)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:196)
    at jdk.internal.reflect.DirectMethodHandleAccessor.invoke (DirectMethodHandleAccessor.java:104)
    at java.lang.reflect.Method.invoke (Method.java:578)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
[ERROR]
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

こちらによると、$JAVA_HOME/bin/javadoc コマンドが見つからない場合のようなので、JAVA_HOME 環境変数を正しく設定してあげると解消します。

次は別のエラーが出ました。

[ERROR] Failed to execute goal org.sonatype.plugins:nexus-staging-maven-plugin:1.6.5:deploy-staged-repository (default-cli) on project standalone-pom: Execution default-cli of goal org.sonatype.plugins:nexus-staging-maven-plugin:1.6.5:deploy-staged-repository failed: An API incompatibility was encountered while executing org.sonatype.plugins:nexus-staging-maven-plugin:1.6.5:deploy-staged-repository: java.lang.ExceptionInInitializerError: null
[ERROR] -----------------------------------------------------
[ERROR] realm =    plugin>org.sonatype.plugins:nexus-staging-maven-plugin:1.6.5
[ERROR] strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy
[ERROR] urls[0] = file:/home/yuki/.m2/repository/org/sonatype/plugins/nexus-staging-maven-plugin/1.6.5/nexus-staging-maven-plugin-1.6.5.jar
[ERROR] urls[1] = file:/home/yuki/.m2/repository/org/sonatype/nexus/maven/nexus-common/1.6.5/nexus-common-1.6.5.jar
[ERROR] urls[2] = file:/home/yuki/.m2/repository/org/sonatype/plexus/plexus-sec-dispatcher/1.4/plexus-sec-dispatcher-1.4.jar
[ERROR] urls[3] = file:/home/yuki/.m2/repository/org/sonatype/plexus/plexus-cipher/1.7/plexus-cipher-1.7.jar
[ERROR] urls[4] = file:/home/yuki/.m2/repository/com/google/guava/guava/14.0.1/guava-14.0.1.jar
[ERROR] urls[5] = file:/home/yuki/.m2/repository/org/sonatype/nexus/nexus-client-core/2.9.1-02/nexus-client-core-2.9.1-02.jar
[ERROR] urls[6] = file:/home/yuki/.m2/repository/org/sonatype/nexus/plugins/nexus-restlet1x-model/2.9.1-02/nexus-restlet1x-model-2.9.1-02.jar
[ERROR] urls[7] = file:/home/yuki/.m2/repository/com/google/code/findbugs/jsr305/2.0.1/jsr305-2.0.1.jar
[ERROR] urls[8] = file:/home/yuki/.m2/repository/com/intellij/annotations/9.0.4/annotations-9.0.4.jar
[ERROR] urls[9] = file:/home/yuki/.m2/repository/commons-io/commons-io/2.4/commons-io-2.4.jar
[ERROR] urls[10] = file:/home/yuki/.m2/repository/com/thoughtworks/xstream/xstream/1.4.7/xstream-1.4.7.jar
[ERROR] urls[11] = file:/home/yuki/.m2/repository/xmlpull/xmlpull/1.1.3.1/xmlpull-1.1.3.1.jar
[ERROR] urls[12] = file:/home/yuki/.m2/repository/xpp3/xpp3_min/1.1.4c/xpp3_min-1.1.4c.jar
[ERROR] urls[13] = file:/home/yuki/.m2/repository/joda-time/joda-time/2.2/joda-time-2.2.jar
[ERROR] urls[14] = file:/home/yuki/.m2/repository/commons-lang/commons-lang/2.6/commons-lang-2.6.jar
[ERROR] urls[15] = file:/home/yuki/.m2/repository/commons-beanutils/commons-beanutils-core/1.8.3/commons-beanutils-core-1.8.3.jar
[ERROR] urls[16] = file:/home/yuki/.m2/repository/org/sonatype/sisu/siesta/siesta-client/1.7/siesta-client-1.7.jar
[ERROR] urls[17] = file:/home/yuki/.m2/repository/org/sonatype/sisu/siesta/siesta-common/1.7/siesta-common-1.7.jar
[ERROR] urls[18] = file:/home/yuki/.m2/repository/javax/ws/rs/jsr311-api/1.1.1/jsr311-api-1.1.1.jar
[ERROR] urls[19] = file:/home/yuki/.m2/repository/com/sun/jersey/jersey-core/1.17.1/jersey-core-1.17.1.jar
[ERROR] urls[20] = file:/home/yuki/.m2/repository/javax/validation/validation-api/1.1.0.Final/validation-api-1.1.0.Final.jar
[ERROR] urls[21] = file:/home/yuki/.m2/repository/com/sun/jersey/jersey-client/1.17.1/jersey-client-1.17.1.jar
[ERROR] urls[22] = file:/home/yuki/.m2/repository/com/sun/jersey/contribs/jersey-apache-client4/1.17.1/jersey-apache-client4-1.17.1.jar
[ERROR] urls[23] = file:/home/yuki/.m2/repository/org/sonatype/sisu/siesta/siesta-jackson/1.7/siesta-jackson-1.7.jar
[ERROR] urls[24] = file:/home/yuki/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.3.1/jackson-annotations-2.3.1.jar
[ERROR] urls[25] = file:/home/yuki/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.3.1/jackson-core-2.3.1.jar
[ERROR] urls[26] = file:/home/yuki/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.3.1/jackson-databind-2.3.1.jar
[ERROR] urls[27] = file:/home/yuki/.m2/repository/com/fasterxml/jackson/jaxrs/jackson-jaxrs-json-provider/2.3.1/jackson-jaxrs-json-provider-2.3.1.jar
[ERROR] urls[28] = file:/home/yuki/.m2/repository/com/faster解消る/jackson/jaxrs/jackson-jaxrs-base/2.3.1/jackson-jaxrs-base-2.3.1.jar
[ERROR] urls[29] = file:/home/yuki/.m2/repository/com/fasterxml/jackson/module/jackson-module-jaxb-annotations/2.3.1/jackson-module-jaxb-annotations-2.3.1.jar
[ERROR] urls[30] = file:/home/yuki/.m2/repository/org/apache/httpcomponents/httpclient/4.3.5/httpclient-4.3.5.jar
[ERROR] urls[31] = file:/home/yuki/.m2/repository/commons-codec/commons-codec/1.6/commons-codec-1.6.jar
[ERROR] urls[32] = file:/home/yuki/.m2/repository/org/apache/httpcomponents/httpcore/4.3.2/httpcore-4.3.2.jar
[ERROR] urls[33] = file:/home/yuki/.m2/repository/org/slf4j/jcl-over-slf4j/1.7.7/jcl-over-slf4j-1.7.7.jar
[ERROR] urls[34] = file:/home/yuki/.m2/repository/org/sonatype/spice/zapper/spice-zapper/1.3/spice-zapper-1.3.jar
[ERROR] urls[35] = file:/home/yuki/.m2/repository/org/fusesource/hawtbuf/hawtbuf-proto/1.9/hawtbuf-proto-1.9.jar
[ERROR] urls[36] = file:/home/yuki/.m2/repository/org/fusesource/hawtbuf/hawtbuf/1.9/hawtbuf-1.9.jar
[ERROR] urls[37] = file:/home/yuki/.m2/repository/org/codehaus/plexus/plexus-utils/3.0.8/plexus-utils-3.0.8.jar
[ERROR] urls[38] = file:/home/yuki/.m2/repository/org/codehaus/plexus/plexus-interpolation/1.15/plexus-interpolation-1.15.jar
[ERROR] urls[39] = file:/home/yuki/.m2/repository/ch/qos/logback/logback-core/1.1.2/logback-core-1.1.2.jar
[ERROR] urls[40] = file:/home/yuki/.m2/repository/ch/qos/logback/logback-classic/1.1.2/logback-classic-1.1.2.jar
[ERROR] Number of foreign imports: 1
[ERROR] import: Entry[import  from realm ClassRealm[maven.api, parent: null]]
[ERROR]
[ERROR] -----------------------------------------------------
[ERROR] : Unable to make field private final java.util.Comparator java.util.TreeMap.comparator accessible: module java.base does not "opens java.util" to unnamed module @31c628e7
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginContainerException
❌ Repository deployment failed

こちらの StackOverflowで、nexus-staging-maven-plugin を 1.6.13 にアップデートすると解消するという情報がありました。確かに publib では古いバージョンを指定しているようだったので、publib のソースコード(node_modules/publib/bin/publib-maven)を修正してリトライしました。

--- a/node_modules/publib/bin/publib-maven
+++ b/node_modules/publib/bin/publib-maven
@@ -199,7 +199,7 @@ deploy_central() {

     staging_output="${workdir}/deploy-output.txt"
     $mvn --settings=${mvn_settings}                                                    \
-        org.sonatype.plugins:nexus-staging-maven-plugin:1.6.5:deploy-staged-repository \
+        org.sonatype.plugins:nexus-staging-maven-plugin:1.6.13:deploy-staged-repository \
         -DrepositoryDirectory=${staging}                                               \
         -DnexusUrl=${MAVEN_ENDPOINT:-https://oss.sonatype.org}                         \
         -DserverId=${server_id}                                                        \
@@ -248,7 +248,7 @@ HERE
     # Release!
     release_output="${workdir}/release-output.txt"
     $mvn --settings ${mvn_settings} -f ${release_pom}                 \
-        org.sonatype.plugins:nexus-staging-maven-plugin:1.6.5:release \
+        org.sonatype.plugins:nexus-staging-maven-plugin:1.6.13:release \
         -DserverId=${server_id}                                       \
         -DnexusUrl=${MAVEN_ENDPOINT:-https://oss.sonatype.org}        \
         -DstagingProfileId=${MAVEN_STAGING_PROFILE_ID}                \

また別のエラーが出ました。

[ERROR] Failed to execute goal org.sonatype.plugins:nexus-staging-maven-plugin:1.6.13:release (default-cli) on project dummy: Execution default-cli of goal o
rg.sonatype.plugins:nexus-staging-maven-plugin:1.6.13:release failed: No converter available
[ERROR] ---- Debugging information ----
[ERROR] message             : No converter available
[ERROR] type                : java.util.Arrays$ArrayList
[ERROR] converter           : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
[ERROR] message[1]          : Unable to make field protected transient int java.util.AbstractList.modCount accessible: module java.base does not "opens java.
util" to unnamed module @1eaf1e62
[ERROR] -------------------------------
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginExecutionException
❌ Release failed

nuxus-staging-maven-plugin の Issue によると、MAVEN_OPTS=--illegal-access=permit の環境変数をつけるワークアラウンドがあるようです。

しかし、このオプションは OpenJDK の最新バージョンでは無視されてしまうようでした。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Deploying and closing repository...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OpenJDK 64-Bit Server VM warning: Ignoring option --illegal-access=permit; support was removed in 17.0

その下のほうのコメントに別のワークアラウンド(MAVEN_OPTS="--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.text=ALL-UNNAMED --add-opens=java.desktop/java.awt.font=ALL-UNNAMED")があったので、こちらを試します。

[INFO] Released
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  17.021 s
[INFO] Finished at: 2023-05-28T15:02:38+09:00
[INFO] ------------------------------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
✅ All Done!

やっと動きました!😭

ここまで来ると OSSRH の NEXUS Repository Manager で確認ができます。

image

普通はアップロードした後にここで Close & Release をするようですが、publib が Close & Release をやってくれています。

2、3 時間経ったあとに、search.maven.org に反映されていれば終了です!

Python(PyPI)

まず PyPI にアカウント登録します(していない場合)。

publib-pypi を使います。PyPI アカウントのユーザーネームとパスワードを環境変数で与えます。

$ env TWINE_USERNAME=xxx TWINE_PASSWORD=xxx publib-pypi

これで完了です!

Go(GitHub)

まず GitHub にリポジトリを作成しておきます。package.json の jsii.targets.go.moduleName で指定した場所にリポジトリがある必要があります。

次はほとんど Git Push するだけなのですが、リリース等もしてくれるみたいなのでせっかくなので publib-golang を使ってみたいと思います。

このとき main ブランチとして事前に何かしらのコミットが必要みたいなので、“Add a README file” 等にチェックをつけてリポジトリを作成するか、clone して空のコミットを作成してください。

$ git commit --allow-empty --allow-empty-message -m ''  # 空のコミットを作成

元のディレクトリで publib-golang を実行します。

$ env GITHUB_USE_SSH=true npx publib-golang dist/go/lognotifier

デフォルトではリポジトリの中のサブディレクトリ内に Go Module を配置するようですが、ルートに置きたいので引数にディレクトリを指定しています。

以上で Git Push がされるはずです!


  1. https://aws.github.io/jsii/user-guides/lib-author/quick-start/set-up/#adding-mandatory-metadata ↩︎

  2. https://learn.microsoft.com/en-us/nuget/create-packages/creating-a-package#choose-a-unique-package-identifier-and-setting-the-version-number ↩︎

  3. https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/names-of-namespaces ↩︎

  4. https://stackoverflow.com/a/3179221 ↩︎

  5. https://maven.apache.org/guides/mini/guide-naming-conventions.html ↩︎

  6. 参考 ↩︎

  7. https://peps.python.org/pep-0008/#package-and-module-names ↩︎

  8. https://stackoverflow.com/a/52828384 ↩︎

  9. https://go.dev/ref/spec#PackageName ↩︎