7. Deployment View
The system has no server side of its own. It is a build-time tool: it runs wherever Maven runs and its only runtime dependency is a reachable Confluence Cloud instance.
Infrastructure Level 1
┌─────────────────────────────────────────┐
│ Build environment (developer or CI) │
│ │
│ JDK 21 Maven ≥ 3.9.2 Node 24 (*) │
│ │
│ ┌───────────────┐ ┌───────────────┐ │
│ │ Antora build │──►│ Maven plugin │ │
│ │ (site → HTML) │ │ atlassian: │ │
│ └───────────────┘ │ publish │ │
│ └───────┬───────┘ │
└──────────────────────────────┼──────────┘
│ HTTPS
▼
┌──────────────────────────┐
│ Confluence Cloud │
│ *.atlassian.net/wiki │
└──────────────────────────┘
(*) only in the module that generates the Antora site
| Element | Explanation |
|---|---|
JDK 21 |
Required by the compiled bytecode of all three artifacts. |
Maven ≥ 3.9.2 |
Runs the plugin. The floor is inherited from the release tooling, see 2. Architecture Constraints. |
Node 24 / Antora 3.1 |
Only needed where the site is generated. Installed into the build by
|
Confluence Cloud |
The target. Reached over HTTPS with the credentials of the configured account; the account’s permissions define what the tool may do. |
Deployment of the Artifacts
Three artifacts are published to Maven Central under the group
io.github.huber-and.atlassian. Three GitHub Actions workflows drive the deployments:
| Workflow | Trigger | Result |
|---|---|---|
|
Push and pull request on |
Builds and tests, then deploys a |
|
A GitHub release is created |
Builds with |
|
Push on |
Builds this documentation with Antora and deploys it to GitHub Pages. |
|
Push on |
Builds all modules and publishes this documentation to the Confluence space. |
The version is assembled from ${revision}${changelist} (CI friendly versions). A release build
overrides both from the Git tag name, so the tag is the version — there is no version string to
forget in a POM.
Signing and upload run through central-publishing-maven-plugin; distributionManagement is
deliberately absent, since the plugin routes both snapshots and releases.
Deployment of the Documentation
The documentation goes to two places, from one source.
To GitHub Pages
pages.yml builds the Antora site and publishes it to
GitHub Pages. This path does not involve Maven at
all — it needs no JDK, only Node and Antora — and it uses playbook.yml.
Two settings in that playbook are load-bearing rather than decorative:
worktrees: false-
Makes Antora read the commit instead of the working tree. Without it, Antora ignores
edit_urland emits afile://link into the CI runner’s file system on every page. It also means Pages shows the state ofmain, not of a dirty checkout. site.url-
Must carry the repository path segment (
https://huber-and.github.io/atlassian-tools), otherwise sitemap, canonical and 404 URLs point at the domain root. Setting it is also what makes Antora emitsitemap.xmland404.htmlin the first place.
| GitHub Pages has to be enabled once in the repository settings with GitHub Actions as the source. Until then, the deploy job fails with "Pages site not found" — the workflow is correct, the repository is not yet configured. |
To Confluence
The same source, published by the system itself. The result is public — the Architecture space — which makes the Antora site and the Confluence pages directly comparable:
mvn -pl architecture-docs clean compile atlassian:publish
compile runs Antora, which writes the site to target/docs/docs/main; atlassian:publish
picks it up and pushes it into the configured space. Both steps live in the same POM, so the
published state can never be newer or older than the built site.
In CI the same two steps run in confluence.yml. The build step installs into the local
repository rather than merely packaging, because the publish runs as a separate Maven invocation
and can only resolve the plugin from there. It skips everything that exists only for publishing to
Maven Central — signing, sources and javadoc. Skipping the signature is not optional: the GPG
plugin is bound to the verify phase of the default build, so a plain install fails in CI with
no default secret key. The signing key belongs to the artifact release workflows and is
deliberately absent here.
The credentials follow one constraint that shapes the whole workflow: username and password
have no CLI property, so they cannot be passed as -D
arguments — see 8. Cross-cutting Concepts. setup-java therefore writes a settings.xml containing
a <server id="confluence"> entry whose values come from the environment, and the build points
serverId at that entry. The connection URL is kept as a repository secret as well — not because
it is confidential (a Confluence cloud id is served unauthenticated from
/_edge/tenant_info) but to keep all three connection values in one place.
|
Which URL form works depends on the token type, not on the account type:
Service accounts can only create scoped tokens, so for them the gateway form is the only option —
which is why the The cloud id is not confidential; read it from Basic authentication keeps working: the account e-mail as the user and the token as the password.
A Scoped tokens also need the right scopes. Beyond reading spaces and reading and writing pages,
this publisher needs attachment access, content-property access for its content hash, and — if
|
The workflow also triggers on changes to wiki-publisher, wiki-client and the Maven plugin, not
just on documentation changes: a change to the publisher changes the result in Confluence even
when the source stays the same. Because unchanged pages are skipped by their content hash, such a
run is cheap — and it doubles as a continuous integration test of the publisher against a real
Confluence instance, which is the gap listed as D1 in 11. Risks and Technical Debt.
<mapper>
<spaceKey>AT</spaceKey>
<root>Architecture</root>
<path>${project.basedir}/target/docs/docs/main</path>
</mapper>
The path points into target, which means a clean build always publishes a freshly
generated site. Publishing a stale site is only possible by skipping compile on purpose.
|
Credentials are not part of this configuration. serverId names a <server> entry in
settings.xml, and the plugin decrypts its password through Maven’s own mechanism — see
8. Cross-cutting Concepts.