ci(release): publish the Java client to Maven Central from the core v* tag - #738
Conversation
…entral The pom and its consumers follow _version.py in lockstep, checked by check_version.py --java and a pytest gate that also runs on a manifest-only change; the release profile publishes the validated deployment itself and waits until it is on Central. Co-Authored-By: jason.han <hanhuijun@gmail.com>
publish-maven runs in the release workflow on the v* tag, beside publish-pypi and publish-npm, signing and uploading at the core version from the restricted maven-central context. Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ording Co-Authored-By: jason.han <hanhuijun@gmail.com>
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
There was a problem hiding this comment.
Devin Review found 2 new potential issues.
1 flag not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)
| emit python "$( { [[ "$service" = true ]] || matches "$python_pattern" || matches '^client/node/package\.json$'; } && echo true || echo false)" | ||
| # The client-manifest/Python version lockstep tests live in the Python suite, | ||
| # so the Node and Java manifests have to run it too. | ||
| emit python "$( { [[ "$service" = true ]] || matches "$python_pattern" || matches '^client/node/package\.json$' || matches '^client/java/pom\.xml$'; } && echo true || echo false)" |
There was a problem hiding this comment.
🟡 Editor version drift escapes CI
When only an editor's client version changes, python remains disabled and its lockstep test never runs. An editor can then build against an older published client while the Java parent names a different version.
Learn more
The Python suite contains test_every_in_repo_reference_names_the_poms_version, which checks the two editor dependencies against the Java parent. The area filter enables that suite for changes to the Java parent, but not for changes to the editor manifests themselves. If an editor selects an existing older artifact, Maven can resolve it and the editor build can pass without detecting the mismatch.
Example: The parent declares 0.9.0, and a pull request changes only the SysON dependency to published version 0.8.0. The SysON build can use 0.8.0; the Python lockstep assertion is skipped.
Recommended fix: Enable the Python area when either editor manifest changes, and add corresponding cases to ci-changed-areas-test.sh.
| emit python "$( { [[ "$service" = true ]] || matches "$python_pattern" || matches '^client/node/package\.json$' || matches '^client/java/pom\.xml$'; } && echo true || echo false)" | |
| emit python "$( { [[ "$service" = true ]] || matches "$python_pattern" || matches '^client/node/package\.json$' || matches '^client/java/pom\.xml$' || matches '^editors/cameo/pom\.xml$' || matches '^editors/syson/backend/pom\.xml$'; } && echo true || echo false)" |
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
You're right: a change to either editor's pom alone skips the Python suite, which is where the lockstep test lives. This PR was accepted as it stands, so I'm fixing it in the stacked follow-up that publishes the Rust client, which changes this same line anyway. There, editors/cameo/pom.xml and editors/syson/backend/pom.xml will also enable the Python area, with test cases for both.
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Targets
develop. It was stacked on #735, which has merged, and #739 (Rust) is stacked on this PR.What and why
The Java client is now published the way the Python and Node clients are: from the core
v*tag, in the corereleaseworkflow, at the core's version. Before this, the Java client had areleaseMaven profile but nothing in CI published it, and the docs planned a separateopensysml-java-v*tag that was never used.Version lock
client/java/pom.xmlis set to0.9.0, the version_version.pydeclares on develop (no-SNAPSHOT). Both modules'<parent><version>match it, and so do the two in-repo consumers that build the client from the checkout:editors/cameo/pom.xml(opensysml.client.version) and theopensysml-clientdependency ineditors/syson/backend/pom.xml. The editors' own project versions are unchanged. The release branch bumps all of these alongside_version.py; the release checklist inreleasing.mdnow says so.check_version.py --javareads the pom's own<version>and checks it against_version.py(same SemVer→PEP 440 translation as--node, so0.9.0-rc1↔0.9.0rc1). When a tag is given, the tag must spell the pom version exactly.-SNAPSHOTis rejected. The Node and Java checks share one helper,_client_version, and all Node messages are unchanged.--nodeand--javaare mutually exclusive.build-python-packagecalls--javanext to--node, so a pom that disagrees fails the release before anything is built.scripts/ci-changed-areas.sh: a change toclient/java/pom.xmlnow also runs the Python suite, where the lockstep tests live (same asclient/node/package.json). The test cases were updated to match;two-clientslegitimately gainspython. The editor poms get the same trigger in ci(release): publish the Rust client to crates.io from the core v* tag #739.autoPublish=true(owner decision). The central-publishing-maven-plugin profile now sets<autoPublish>true</autoPublish>and<waitUntil>published</waitUntil>. Per Sonatype's docs,waitUntildefaults tovalidatedandpublishedrequiresautoPublish. With these settings the build blocks until Central reports the deployment published, and reports any failure, so a green job means the version is on Central.publish-mavenjob (java-executor). It requiresPublish GitHub releaseandJava client tests, and sits besidepublish-pypiandpublish-npm, independent of both.java-testwas added to thereleaseworkflow (requires: *go-suite), andPublish GitHub releasenow also requires it.The credentials come from the restricted org context
Maven Central(context: ["Maven Central"]on the workflow entry; context names are matched exactly). Whoever pushes the tag must be allowed to use it, as withPyPIandnpm.Everything that can fail runs before the upload:
v<pom version>(read withmvn help:evaluate); a-SNAPSHOTversion is refused.CENTRAL_TOKEN_USERNAME,CENTRAL_TOKEN_PASSWORD,GPG_PRIVATE_KEYandGPG_PASSPHRASEmust all be non-empty. Only the missing variable's name is printed.opensysml-parentandopensysml-client. HTTP 200 → refuse, 404 → proceed, any other response → fail rather than guess.gpg --batch --importthe ASCII-armoured key, then test-sign with the passphrase via--passphrase-fd. An expired key or a wrong passphrase fails here.~/.m2/settings.xmlgets acentralserver whose credentials are${env.…}references, so the token is never written to disk.MAVEN_GPG_PASSPHRASE=… mvn -B -Prelease deploy -pl opensysml-client -am -DskipTests. Tests are skipped becausejava-testran them on this revision in the same workflow (the same split aspublish-pypi).-ambrings the parent pom, which the client's pom names, so Central needs it too. maven-gpg-plugin 3.2.7 reads the passphrase fromMAVEN_GPG_PASSPHRASE(itspassphraseEnvNamedefault since 3.2.0), and that alone works in batch mode. A comment on this step says never to run it with-X/debug output, because the settings interpolation would print the token.Pre-releases. Central has no test registry, so a pre-release tag publishes an ordinary, permanent version, which Maven orders before the release. This is documented in
releasing.md.Docs. The
releasing.mdsection "Releasing the Java client to Maven Central" is rewritten: the core tag, the lockstep version, the four variables in theMaven Centralcontext, GPG key expiry and rotation, immutability, pre-releases, the job's steps in order, and what can be rerun after a partial failure. Also updated: thereleasing.mdintro, the release checklist, the post-release Central check, the root README,client/java/README.md, the guide, the Java API reference, the roadmap and the syson design note. One changelog fragment:changes/unreleased/java-client-maven-release.added.md.How it was verified
pytest tests/test_check_version.py tests/test_version.pypasses, including 9 new Java tests; the existing tests are unchanged.bash scripts/ci-changed-areas-test.shpasses.mvn -B -f client/java/pom.xml install -Dopensysml.requireService=truepasses (297 tests, 0 failures).-DskipTests package).MAVEN_GPG_PASSPHRASE=… mvn -B -Prelease verify -pl opensysml-client -am -DskipTestssigns 4 files, andgpg --verifyreports a good signature on the client jar and on the parent pom. Nodeploywas run.gpgis present incimg/openjdk:17.0; theapt-getinstall is only a fallback.circleci config validate,python3 scripts/changelog.py check,python3 scripts/check-doc-links.py(0 broken),make docs-check,gofmt -l .,go vet ./...andgo test ./tests/hygiene/...all pass.Nothing was published.
Checklist
make testandmake lintpass locally (the affected suites above)changes/unreleased/<slug>.<section>.md, not as an edit toCHANGELOG.mdmake docs-countsrun if a gate count moved (no gate count moved)F4,K5) in the body, docs, or changelogLink to Devin session: https://nasa-jpl-demo.devinenterprise.com/sessions/50e350d0913749039440892f390a0f90
Open in Devin Desktop: https://nasa-jpl-demo.devinenterprise.com/desktop/session/50e350d0913749039440892f390a0f90?variant=devin
Requested by: @HuiJun