Skip to content

feat(maven): publish both artifacts to maven central - #630

Merged
andiwand merged 1 commit into
mainfrom
feat/maven-central
Jul 30, 2026
Merged

feat(maven): publish both artifacts to maven central#630
andiwand merged 1 commit into
mainfrom
feat/maven-central

Conversation

@andiwand

@andiwand andiwand commented Jul 28, 2026

Copy link
Copy Markdown
Member

Stacked on #629.

GitHub Packages demands read:packages even to read a public artifact. f-droid builds from source with no credentials at all, so it cannot resolve either artifact from there — and being consumable by droid, which f-droid builds, is the whole reason the AAR exists. #629 says this needs Maven Central "first, which is a separate piece of work — the app.opendocument namespace has to be verified, and every artifact signed." Half of that turned out to be already done.

app.opendocument is not a new namespace

The org has published android AARs to Maven Central before, under exactly this group:

artifact latest published
app.opendocument:pdf2htmlex-android 0.18.26 2024-08-25
app.opendocument:wvware-android 1.2.11 2024-08-26

Both are on repo1.maven.org today, and droid consumed them as ordinary mavenCentral() dependencies before they were archived. So this is a new artifact under an established name. What is genuinely outstanding is credentials, not verification — see below.

What this changes

The AAR goes through com.vanniktech.maven.publish. Sonatype ships no official gradle plugin for the Central Portal, and OSSRH — which pdf2htmlEX-Android and wvware-android deployed to — is gone, so their gradle-nexus/publish-plugin + s01.oss.sonatype.org setup cannot simply be copied. vanniktech is what android libraries have settled on. It renames the publication releasemaven, so the workflow now asks for the name-independent publishAllPublicationsToGitHubPackagesRepository.

The jar keeps its hand-written pom and gains a central profile. central-publishing-maven-plugin takes over the deploy lifecycle wholesale, so one mvn deploy cannot serve both destinations; the default stays GitHub Packages and -Pcentral is the Central path. maven.yml splits publishing into its own job so the secrets sit behind an environment, the shape android.yml already has.

Both keep publishing to GitHub Packages. Nothing that reads it today breaks.

Central asks for more than GitHub Packages does, and both artifacts now supply it:

  • sources and javadoc jars — the jar already had them, the AAR now does;
  • a POM carrying developersneither had one, so neither would have been accepted as it stood;
  • a PGP signature over every file.

Signing is conditional on a key being configured. Unconditional (signAllPublications() on its own) fails publishToMavenLocal with "no configured signatory", which would mean nobody could publish locally or to GitHub Packages without a private key on hand — a steep price for two destinations that never check one. The portal rejects an unsigned upload, so the release path stays guarded.

Both publishes upload a deployment and stop. Releasing is a deliberate click in the portal UI: Central never forgets a version, and that click is the last point at which a bad artifact can be dropped rather than lived with.

Verification

Locally, against a throwaway PGP key: the AAR publishes .aar, .pom, .module, sources and javadoc jars, each with a detached .asc that verifies against the key; the POM carries name, description, url, licenses, developers and scm; the AAR still contains its assets and prebuilt ABIs. With no key set it publishes the same artifacts unsigned. mvn verify and mvn validate -Pcentral both pass, and the flattened pom keeps developers.

Not verified: an actual upload to the portal, which needs credentials this repo does not have yet.

Before this can release

The maven-central environment has to exist with four secrets:

secret what
MAVEN_CENTRAL_USERNAME / MAVEN_CENTRAL_PASSWORD Central Portal user token, generated at central.sonatype.com — not portal login credentials
SIGNING_KEY armored PGP private key
SIGNING_PASS its passphrase

The archived repos hold a working SIGNING_KEY/SIGNING_PASS pair in their own OpenDocumentAppRelease environment, so the signing key may just need copying. The Sonatype credentials do not carry over: those are OSSRH-era, and the Portal issues its own tokens. Worth confirming who holds the Portal account that owns the app.opendocument namespace, since these repos came from an outside author.

🤖 Generated with Claude Code

Base automatically changed from feat/android-aar to main July 28, 2026 19:40
GitHub Packages demands `read:packages` even to read a public artifact, so
f-droid — which builds from source with no credentials — cannot resolve
either artifact from it. That is the whole reason the AAR exists, so it
has to be somewhere credential-less. `app.opendocument` is already a live
namespace on Central (`pdf2htmlex-android`, `wvware-android`, both since
2024), so this is a new artifact under an old name.

The AAR goes through `com.vanniktech.maven.publish`; sonatype ships no
official gradle plugin for the portal and OSSRH, which the org's earlier
android libraries deployed to, is gone. The publication is renamed
`release` -> `maven` by the plugin, hence the workflow now asks for
`publishAllPublicationsToGitHubPackagesRepository`. The jar keeps its
hand-written pom and gets a `central` profile, because
`central-publishing-maven-plugin` takes over the deploy lifecycle
wholesale and the two destinations cannot be driven by one invocation.

Central asks for more than GitHub Packages: sources and javadoc jars, a
pom carrying `developers` (neither had one), and a PGP signature per
file. Signing is conditional on a key being configured — unconditional
would mean no `publishToMavenLocal` and no GitHub Packages publish
without a private key on hand, and the portal rejects an unsigned upload
anyway. Both publishes upload and stop; releasing is a click, because
Central never forgets a version.

Verified locally against a throwaway PGP key: the AAR publishes with
.aar/.pom/.module plus sources and javadoc, each with a valid detached
.asc, and still publishes unsigned when no key is set.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QqTNzXTxzfeCA2w1ErQzax
@andiwand
andiwand force-pushed the feat/maven-central branch from 2699811 to 4eea81b Compare July 30, 2026 18:21
@andiwand
andiwand merged commit 746a9dc into main Jul 30, 2026
27 checks passed
@andiwand
andiwand deleted the feat/maven-central branch July 30, 2026 21:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant