Skip to content

Commit 2fbf820

Browse files
committed
build: split bundled fonts into a separate artifact and slim the publication
Why: the published graph-compose artifact set was ~40 MB per release — the ~18 MB of bundled Google fonts shipped inside the main jar AND again in the -sources jar, and the -tests classifier jar was deployed too. Fonts change rarely, so re-shipping them on every engine release wasted Maven Central storage and forced an engine-only upgrade to re-download fonts. What: - New io.github.demchaav:graph-compose-fonts module (independent 1.0.0 line) carries the fonts/google/** binaries; classpath paths preserved byte-for-byte so DefaultFonts resolves them unchanged. The engine depends on it at TEST scope only, so it never propagates to consumers. - New io.github.demchaav:graph-compose-bundle (pom) aggregates engine + fonts for a one-line "batteries-included" install; tracks the engine version. - The engine release no longer attaches or deploys the -tests jar (kept as a local build aid for the benchmarks module); with the fonts gone the -sources jar is lean too. Main jar drops from ~20 MB to ~2.6 MB. - A missing fonts/google resource now fails with an actionable message naming the graph-compose-fonts dependency. - Fonts publish on their own fonts-v* tag (publish-fonts.yml); the engine v* tag deploys engine + bundle and installs fonts first for the test-scope verify. cut-release.ps1 bumps the bundle in lockstep while fonts stays independent; VersionConsistencyGuardTest enforces both. CHANGELOG, README, and docs/migration/v1.8.0-fonts.md document the consumer-facing change. Verification: ./mvnw clean verify -pl . green (1397 tests, including two new font-degradation tests and the bundle/fonts version guards); the fonts and bundle modules build and resolve; the release jar contains no fonts/google and no -tests classifier; the CvSidebarPortrait example renders (Google fonts from the fonts jar + portrait asset from the engine jar). BREAKING CHANGE: bundled Google fonts are no longer inside graph-compose. To keep them, add io.github.demchaav:graph-compose-fonts (or depend on graph-compose-bundle). The FontName API and DefaultFonts catalog are unchanged (source- and binary-compatible); standard-14 documents render with no extra dependency. See docs/migration/v1.8.0-fonts.md.
1 parent e9618ff commit 2fbf820

168 files changed

Lines changed: 848 additions & 15 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
name: Publish fonts to Maven Central
2+
3+
# Publishes the graph-compose-fonts companion artifact to Maven Central,
4+
# independently of the engine. The bundled Google fonts change rarely, so
5+
# they release on their OWN tag line (fonts-v*) — pushing an engine v* tag
6+
# never touches them, and re-publishing fonts does not require an engine
7+
# release. This mirrors publish.yml (Track D4) but targets fonts/pom.xml.
8+
#
9+
# Tagging: fonts-vX.Y.Z (e.g. fonts-v1.0.0). The fonts artifact carries its
10+
# own independent version (see fonts/pom.xml) — keep it in sync with the tag.
11+
#
12+
# Human prerequisites are identical to publish.yml (GPG key + Central token
13+
# secrets). See docs/contributing/release-process.md for the runbook.
14+
15+
on:
16+
push:
17+
tags:
18+
- 'fonts-v*'
19+
workflow_dispatch:
20+
inputs:
21+
tag:
22+
description: 'Existing fonts-v*-prefixed tag to (re-)publish'
23+
required: true
24+
type: string
25+
26+
permissions:
27+
contents: read
28+
29+
jobs:
30+
publish-fonts:
31+
name: Publish ${{ github.ref_name }} to Maven Central
32+
runs-on: ubuntu-latest
33+
# Only ship plain semver tags (fonts-vX.Y.Z) to Central; pre-release
34+
# suffixes ship nowhere from here.
35+
if: |
36+
github.event_name == 'workflow_dispatch' ||
37+
(!contains(github.ref, '-rc') && !contains(github.ref, '-alpha') && !contains(github.ref, '-beta') && !contains(github.ref, '-snapshot'))
38+
env:
39+
JAVA_TOOL_OPTIONS: -Djava.awt.headless=true
40+
41+
steps:
42+
- name: Check out repository at tag
43+
uses: actions/checkout@v6
44+
with:
45+
ref: ${{ github.event.inputs.tag || github.ref }}
46+
47+
- name: Set up Temurin JDK 17 with Central credentials and GPG key
48+
uses: actions/setup-java@v5
49+
with:
50+
distribution: temurin
51+
java-version: '17'
52+
cache: maven
53+
server-id: central
54+
server-username: CENTRAL_USERNAME
55+
server-password: CENTRAL_TOKEN
56+
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
57+
gpg-passphrase: MAVEN_GPG_PASSPHRASE
58+
59+
- name: Publish fonts to Maven Central
60+
# Activates the fonts module's release profile (sources + javadoc +
61+
# gpg sign + central-publishing) and flips gpg.skip=false. Blocks
62+
# until Sonatype's validator confirms validation.
63+
run: ./mvnw -B -ntp -f fonts/pom.xml -P release -Dgpg.skip=false deploy
64+
env:
65+
CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
66+
CENTRAL_TOKEN: ${{ secrets.CENTRAL_TOKEN }}
67+
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}

.github/workflows/publish.yml

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,42 @@ jobs:
7979
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
8080
gpg-passphrase: MAVEN_GPG_PASSPHRASE
8181

82+
- name: Install graph-compose-fonts into the local repo
83+
# The engine's visual / snapshot suite renders with the bundled
84+
# Google fonts, which now live in the separately-versioned
85+
# graph-compose-fonts artifact (engine depends on it at test
86+
# scope). Build + install it locally so the verify step below can
87+
# resolve it even before it (or this engine version) is on Central.
88+
run: ./mvnw -B -ntp -f fonts/pom.xml clean install
89+
8290
- name: Verify (full canonical suite green at tagged commit)
8391
# Re-verify the tagged commit before publishing — defence in
8492
# depth against a tag pushed from a broken branch by mistake.
8593
# The publish step below would also fail at signing/upload,
8694
# but failing here surfaces a clearer error.
8795
run: ./mvnw -B -ntp clean verify -pl .
8896

89-
- name: Publish to Maven Central
97+
- name: Publish engine to Maven Central
9098
# Activates the release profile (sources + javadoc + gpg sign +
9199
# central-publishing) and flips gpg.skip=false. The deploy
92100
# phase invokes central-publishing-maven-plugin's upload goal
93101
# which blocks until Sonatype's validator confirms validation.
102+
# The release profile also disables the tests-jar execution, so
103+
# only the main + sources + javadoc + pom artefacts are uploaded.
94104
run: ./mvnw -B -ntp -P release -DskipTests -Dgpg.skip=false deploy
95105
env:
96106
CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
97107
CENTRAL_TOKEN: ${{ secrets.CENTRAL_TOKEN }}
98108
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
109+
110+
- name: Publish bundle to Maven Central
111+
# The graph-compose-bundle convenience aggregate pins this engine
112+
# version + a compatible graph-compose-fonts version. It tracks the
113+
# engine line, so it ships on the same v* tag. pom-packaged → only a
114+
# signed .pom is uploaded; engine + fonts resolve from the local repo
115+
# (installed by the engine deploy above and the fonts step earlier).
116+
run: ./mvnw -B -ntp -f bundle/pom.xml -P release -DskipTests -Dgpg.skip=false deploy
117+
env:
118+
CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
119+
CENTRAL_TOKEN: ${{ secrets.CENTRAL_TOKEN }}
120+
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}

CHANGELOG.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,32 @@ Entries land here as they merge.
237237
node-label settings survive the toggle, `debug(none())` reliably disables
238238
everything — and disabled debug output stays byte-identical.
239239

240+
### Build & distribution
241+
242+
- **Bundled Google fonts moved to a separate, independently-versioned
243+
artifact** (`io.github.demchaav:graph-compose-fonts`). **Breaking for
244+
consumers who use the bundled families.** The ~18 MB of curated Google fonts
245+
no longer ship inside the `graph-compose` jar, so an engine upgrade never
246+
re-downloads them and the engine artifact drops from ~40 MB to a few MB. The
247+
public `FontName` constants and the `DefaultFonts` catalog are unchanged
248+
(source- and binary-compatible), and the classpath layout `fonts/google/...`
249+
is preserved byte-for-byte. To keep the bundled fonts, add
250+
`io.github.demchaav:graph-compose-fonts` (its own version line, starting at
251+
`1.0.0`) to your build, or depend on the new "batteries-included"
252+
`io.github.demchaav:graph-compose-bundle` (engine + fonts at compatible
253+
versions). With neither on the classpath, standard-14 documents render
254+
unchanged and requesting a bundled family fails fast with a message that
255+
names the missing dependency. See
256+
[docs/migration/v1.8.0-fonts.md](docs/migration/v1.8.0-fonts.md).
257+
- **Leaner Maven Central publication.** The release build no longer attaches or
258+
uploads the `-tests` classifier jar (it stays a local-only build aid for the
259+
benchmarks module), and with the fonts gone the `-sources.jar` no longer
260+
carries font binaries either. The published artifact set is now just the
261+
engine bytecode plus the small template assets.
262+
- **`graph-compose-fonts` releases on its own `fonts-v*` tag** via a dedicated
263+
publish workflow, so the font set ships only when it actually changes,
264+
independent of the engine's `v*` release cadence.
265+
240266
### Bug fixes
241267

242268
- **A stray non-drawing element no longer breaks a whole SVG icon.** A

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,25 @@ Sits between **iText** (low-level page primitives) and **JasperReports** (XML-te
6363
dependencies { implementation("io.github.demchaav:graph-compose:1.7.1") }
6464
```
6565

66+
> **Bundled fonts (from v1.8.0).** The curated Google fonts no longer ship
67+
> inside the engine jar — they live in an independently-versioned
68+
> companion artifact so an engine upgrade never re-downloads ~18 MB of
69+
> fonts. Pure-text and standard-14 documents need nothing extra; to use the
70+
> bundled families, add:
71+
>
72+
> ```xml
73+
> <dependency>
74+
> <groupId>io.github.demchaav</groupId>
75+
> <artifactId>graph-compose-fonts</artifactId>
76+
> <version>1.0.0</version>
77+
> </dependency>
78+
> ```
79+
>
80+
> Prefer a single "batteries-included" coordinate? Depend on
81+
> `io.github.demchaav:graph-compose-bundle` (same version as `graph-compose`
82+
> above) to pull the engine + fonts together. Full details and upgrade steps:
83+
> the [v1.8.0 fonts migration note](./docs/migration/v1.8.0-fonts.md).
84+
6685
> **Distribution** &mdash; Maven Central is the canonical channel from **v1.6.6** onwards
6786
> (`io.github.demchaav:graph-compose:<version>`). Hosted Javadocs auto-publish to
6887
> [javadoc.io/doc/io.github.demchaav/graph-compose](https://javadoc.io/doc/io.github.demchaav/graph-compose)

aggregator/pom.xml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,38 @@
2222
mvn -f aggregator/pom.xml versions:set -DnewVersion=X # bump all modules
2323
</description>
2424

25+
<!--
26+
Belt-and-braces: nothing aggregated here is meant to be deployed via the
27+
reactor. The published artifacts (engine, fonts, bundle) are deployed by
28+
their own targeted `-f <module>/pom.xml ... deploy` invocations in the
29+
publish workflows. This skip stops an accidental aggregator `deploy` from
30+
pushing the examples / benchmarks (which have no distributionManagement)
31+
to anywhere. The standalone engine / fonts / bundle poms do not inherit
32+
this and manage their own publication.
33+
-->
34+
<properties>
35+
<maven.deploy.skip>true</maven.deploy.skip>
36+
<!--
37+
Bundled-fonts version inherited by the examples and benchmarks
38+
modules (which render with the bundled Google families). Independent
39+
of the engine line; bump only when the font set changes.
40+
-->
41+
<graphcompose.fonts.version>1.0.0</graphcompose.fonts.version>
42+
</properties>
43+
44+
<!--
45+
Reactor build order only. `../fonts` and `../bundle` are listed so a
46+
full-reactor `install` builds them in dependency order (fonts before the
47+
engine, which depends on fonts at test scope). They are NOT children of
48+
this aggregator (no <parent> back-reference) and carry independent
49+
versions, so the lockstep `versions:set` does not rewrite them: fonts is
50+
at its own 1.0.0 line, and the bundle (== engine version) is bumped with
51+
the engine on purpose.
52+
-->
2553
<modules>
2654
<module>..</module>
55+
<module>../fonts</module>
56+
<module>../bundle</module>
2757
<module>../examples</module>
2858
<module>../benchmarks</module>
2959
</modules>

benchmarks/pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@
5454
<version>${graphcompose.version}</version>
5555
</dependency>
5656

57+
<!--
58+
Bundled Google fonts, split out of the engine jar in v1.8.0. The
59+
font-embed probes (FontEmbedProbe) and canonical benchmark fixtures
60+
render in these families, so the harness pulls the companion
61+
artifact explicitly at its own independent version.
62+
-->
63+
<dependency>
64+
<groupId>io.github.demchaav</groupId>
65+
<artifactId>graph-compose-fonts</artifactId>
66+
<version>${graphcompose.fonts.version}</version>
67+
</dependency>
68+
5769
<!--
5870
graph-compose's test-only fixtures (com.demcha.mock.*) used by
5971
CanonicalBenchmarkSupport for CV / invoice / proposal sample

bundle/pom.xml

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<!--
8+
"Batteries-included" convenience aggregate. Depending on this single
9+
artifact pulls the lean engine plus the bundled Google fonts at a
10+
compatible, pinned pair of versions — the one-line install for newcomers
11+
who want the pre-split behaviour back. Power users instead depend on
12+
graph-compose directly and pick their own graph-compose-fonts version.
13+
14+
Versioning: this module tracks the ENGINE line (its version == the engine
15+
version, bumped in lockstep), and pins a specific graph-compose-fonts
16+
version. It is standalone (no Maven parent) and pom-packaged, so Maven
17+
Central needs no sources/javadoc jars for it.
18+
-->
19+
<groupId>io.github.demchaav</groupId>
20+
<artifactId>graph-compose-bundle</artifactId>
21+
<!--
22+
Tracks the engine line. Currently 1.7.1 to match the engine version in
23+
the repo; the release-cut `versions:set` bumps engine + bundle to the
24+
release version in lockstep, while graph-compose-fonts stays on its own
25+
line. The graph-compose dependency below uses ${project.version}, so it
26+
follows automatically.
27+
-->
28+
<version>1.7.1</version>
29+
<packaging>pom</packaging>
30+
31+
<name>GraphCompose Bundle</name>
32+
<description>Batteries-included aggregate: the GraphCompose engine plus the bundled Google fonts at compatible versions.</description>
33+
<url>https://github.com/DemchaAV/GraphCompose</url>
34+
35+
<licenses>
36+
<license>
37+
<name>MIT License</name>
38+
<url>https://opensource.org/licenses/MIT</url>
39+
<distribution>repo</distribution>
40+
</license>
41+
</licenses>
42+
43+
<developers>
44+
<developer>
45+
<id>DemchaAV</id>
46+
<name>Artem Demchyshyn</name>
47+
<email>demchishynartem@gmail.com</email>
48+
<url>https://github.com/DemchaAV</url>
49+
<roles>
50+
<role>Lead Developer</role>
51+
<role>Architect</role>
52+
</roles>
53+
<timezone>UTC 0</timezone>
54+
</developer>
55+
</developers>
56+
57+
<scm>
58+
<connection>scm:git:https://github.com/DemchaAV/GraphCompose.git</connection>
59+
<developerConnection>scm:git:ssh://git@github.com/DemchaAV/GraphCompose.git</developerConnection>
60+
<url>https://github.com/DemchaAV/GraphCompose/tree/main</url>
61+
</scm>
62+
63+
<properties>
64+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
65+
66+
<!-- Pinned bundled-fonts version this bundle ships with. -->
67+
<graphcompose.fonts.version>1.0.0</graphcompose.fonts.version>
68+
69+
<maven.gpg.plugin.version>3.2.8</maven.gpg.plugin.version>
70+
<central.publishing.plugin.version>0.10.0</central.publishing.plugin.version>
71+
72+
<gpg.skip>true</gpg.skip>
73+
</properties>
74+
75+
<dependencies>
76+
<!-- The engine, at this bundle's (== engine) version. -->
77+
<dependency>
78+
<groupId>io.github.demchaav</groupId>
79+
<artifactId>graph-compose</artifactId>
80+
<version>${project.version}</version>
81+
</dependency>
82+
<!-- The bundled fonts, at the pinned independent fonts version. -->
83+
<dependency>
84+
<groupId>io.github.demchaav</groupId>
85+
<artifactId>graph-compose-fonts</artifactId>
86+
<version>${graphcompose.fonts.version}</version>
87+
</dependency>
88+
</dependencies>
89+
90+
<profiles>
91+
<!--
92+
Maven Central release. A pom-packaged artifact needs no
93+
sources/javadoc jars; it only requires a signed .pom uploaded via
94+
central-publishing. Activated with `-P release`; the publish workflow
95+
flips -Dgpg.skip=false on the engine `v*` tag (the bundle ships
96+
together with the engine it pins).
97+
-->
98+
<profile>
99+
<id>release</id>
100+
<build>
101+
<plugins>
102+
<plugin>
103+
<groupId>org.apache.maven.plugins</groupId>
104+
<artifactId>maven-gpg-plugin</artifactId>
105+
<version>${maven.gpg.plugin.version}</version>
106+
<executions>
107+
<execution>
108+
<id>sign-artifacts</id>
109+
<phase>verify</phase>
110+
<goals>
111+
<goal>sign</goal>
112+
</goals>
113+
<configuration>
114+
<skip>${gpg.skip}</skip>
115+
<gpgArguments>
116+
<arg>--pinentry-mode</arg>
117+
<arg>loopback</arg>
118+
</gpgArguments>
119+
</configuration>
120+
</execution>
121+
</executions>
122+
</plugin>
123+
<plugin>
124+
<groupId>org.sonatype.central</groupId>
125+
<artifactId>central-publishing-maven-plugin</artifactId>
126+
<version>${central.publishing.plugin.version}</version>
127+
<extensions>true</extensions>
128+
<configuration>
129+
<publishingServerId>central</publishingServerId>
130+
<autoPublish>false</autoPublish>
131+
<waitUntil>validated</waitUntil>
132+
</configuration>
133+
</plugin>
134+
</plugins>
135+
</build>
136+
</profile>
137+
</profiles>
138+
</project>

0 commit comments

Comments
 (0)