Skip to content

Fail atlas generation on missing, empty, or invalid inputs - #98

Merged
Aerhhh merged 3 commits into
Aerhhh:masterfrom
Miracle-Town:codex/reproducible-tooling-builds
Oct 15, 2026
Merged

Aerhhh merged 3 commits into
Aerhhh:masterfrom
Miracle-Town:codex/reproducible-tooling-builds

Conversation

@Nero978

@Nero978 Nero978 commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Atlas generation can currently report success without producing a usable atlas: missing input directories, unreadable PNGs, and inputs with nothing to pack are logged or skipped. This change makes those conditions fail the run, so build integrations receive a nonzero exit status instead of packaging incomplete or stale assets.

  • Throw IllegalStateException when there is nothing to pack, including input containing only transparent images.
  • Propagate directory and image-read failures as UncheckedIOException, consistent with existing output-write failures.
  • Handle these errors in the standalone atlas/overlay entry points.
  • Update the existing silent-success tests and cover image decoding, empty inputs, page-write failures, and coordinate-write failures. Coordinates are published only after all atlas pages have been written.

This branch incorporates the maintainer's pr-98-merge-master merge. Since #99 replaced the C# renderer with an in-process Java library and already made rendering failures fatal, the obsolete renderer-pinning flags, .NET checks, and renderer-revision tests have been removed from this PR's scope.

Validation on JDK 25:

  • ./mvnw -B -pl tooling verify: passed; 135 tests, zero failures/errors/skips, packaging and EditorConfig checks passed.
  • git diff --check upstream/master...HEAD: passed.
  • ./mvnw -B verify: generator ran 1,568 tests with 16 golden-image comparison failures and 4 skips; the reactor stopped before tooling. All 16 failures were reproduced on an unmodified copy of upstream/master (022a486) by rerunning TooltipPackFontGeneratorTest, TooltipGoldenImageTest, and ToolGoldenImageTest, with identical failed test cases and pixel assertion messages. The generator module is unchanged by this PR. These existing local failures remain unresolved.

@Nero978

Nero978 commented Oct 14, 2026

Copy link
Copy Markdown
Contributor Author

Hi, I have resolved the conflict in this PR just now. It's ready to be reviewed.
If any suggestion, please let me know. XD
@Aerhhh

PR 99 replaced the C# MinecraftRenderer with the in-process asset-renderer,
so the renderer pinning half of this branch (--renderer-commit,
--no-update-renderer, the .NET check and the ItemRenderer changes) has
nothing left to apply to and is dropped here. On master the render step
already ends the run when it fails.

What survives is the rule that an atlas build never reports success without
its output. A missing or unreadable render directory, a file that is not an
image and an input with nothing to pack now end the run, using the
UncheckedIOException convention master already has for write failures. The
tests move to the new constructors, and the two tests on master that
asserted the old silent behaviour now assert the error instead.
@Aerhhh

Aerhhh commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

Thanks for this, and sorry about the timing. I merged #99 after you opened it and that one pulled the ground out from under half of your branch, which is on me. It swapped the C# MinecraftRenderer for a Java library that renders in-process, so ItemRenderer is gone and there's no checkout left to pin or .NET to look for. Master also fails the run when rendering breaks now, which was the other thing the renderer half did.

The atlas half is still a real gap though. On master AtlasGenerator.generate() prints "No textures to pack!" and returns, and SpritesheetGenerator.loadTextures() prints and moves on when the input directory is missing or a file won't decode. So an empty render directory still ends in "Complete!" with no atlas, which is exactly what you were fixing. Write failures are already fatal there (they throw UncheckedIOException) but nobody tests them, so your AtlasWriteFailureTest earns its keep too.

If you merge master yourself, this is roughly what you'll run into. The renderer side all goes: ItemRenderer, Program.cs, the new MinecraftAssetTool flags, RendererRevisionTest, and the .NET and ItemRenderer cases in ToolingFailureTest. The throws in generate() and loadTextures() stay. I'd make the I/O ones UncheckedIOException since that's what master uses and it keeps the standalone mains' catch blocks working.

The constructors changed too, to AtlasGenerator(AtlasLayout, Path, Path) and SpritesheetGenerator(Path inputDir, ToolingPaths, AtlasLayout), so the tests need updating for that. And two tests on master assert the old silent behaviour and will go red: AtlasGeneratorPagingTest.generatingNothingWritesNoFiles and SpritesheetGeneratorTest.missingInputDirectoryWritesNothing. They should assert the error now.

I did the merge myself while working out what was still live. It's on pr-98-merge-master in this repo, your commit at the bottom with one merge commit on top, and both modules pass. Use it if it saves you time, or do the merge your own way. Either is fine by me. If I've got something wrong in there, shout.

@Nero978 Nero978 changed the title Fail incomplete asset builds and support pinned renderer commits Fail atlas generation on missing, empty, or invalid inputs Oct 15, 2026
@Nero978

Nero978 commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks for preparing the merge branch! I've incorporated it into this PR and updated the title and description to reflect the atlas-only scope.

Tooling verification passes locally: all 135 tests, packaging, and EditorConfig checks passed. The full build hit 16 golden-image comparison failures, but I reproduced the exact same failures on the latest master and documented them in the PR description.

The conflicts are resolved, and it's ready for another review. Thanks again for helping adapt this to the new renderer!

Error Report

net.aerh.imagegenerator.impl.tooltip.TooltipGoldenImageTest :: defaultTooltipRenderMatchesGolden(String)[1]
Pixel mismatch for 'bordered_legendary' at (11,10) ==> expected: <-15596782> but was: <-15136751>
org.opentest4j.AssertionFailedError: Pixel mismatch for 'bordered_legendary' at (11,10) ==> expected: <-15596782> but was: <-15136751>
	at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:601)
	at net.aerh.imagegenerator.impl.tooltip.TooltipGoldenImageTest.defaultTooltipRenderMatchesGolden(TooltipGoldenImageTest.java:87)



net.aerh.imagegenerator.impl.tooltip.TooltipGoldenImageTest :: defaultTooltipRenderMatchesGolden(String)[2]
Pixel mismatch for 'borderless_text' at (10,10) ==> expected: <-11141291> but was: <-1152990138>
org.opentest4j.AssertionFailedError: Pixel mismatch for 'borderless_text' at (10,10) ==> expected: <-11141291> but was: <-1152990138>
	at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:601)
	at net.aerh.imagegenerator.impl.tooltip.TooltipGoldenImageTest.defaultTooltipRenderMatchesGolden(TooltipGoldenImageTest.java:87)



net.aerh.imagegenerator.impl.tooltip.TooltipGoldenImageTest :: defaultTooltipRenderMatchesGolden(String)[3]
Pixel mismatch for 'centered_epic_scaled' at (31,28) ==> expected: <-15596782> but was: <-15465708>
org.opentest4j.AssertionFailedError: Pixel mismatch for 'centered_epic_scaled' at (31,28) ==> expected: <-15596782> but was: <-15465708>
	at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:601)
	at net.aerh.imagegenerator.impl.tooltip.TooltipGoldenImageTest.defaultTooltipRenderMatchesGolden(TooltipGoldenImageTest.java:87)



net.aerh.imagegenerator.impl.tooltip.TooltipPackFontGeneratorTest :: packFontTooltipMatchesGolden
pixel (10,10) ==> expected: <-5592406> but was: <-10002329>
org.opentest4j.AssertionFailedError: pixel (10,10) ==> expected: <-5592406> but was: <-10002329>
	at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:601)
	at net.aerh.imagegenerator.impl.tooltip.TooltipPackFontGeneratorTest.packFontTooltipMatchesGolden(TooltipPackFontGeneratorTest.java:105)



net.aerh.imagegenerator.tools.ToolGoldenImageTest :: vanillaRenderMatchesGolden(String)[2]
golden/tools/item pixel mismatch at (307,94): expected ff120312 but was ff1a0911
org.opentest4j.AssertionFailedError: golden/tools/item pixel mismatch at (307,94): expected ff120312 but was ff1a0911
	at org.junit.jupiter.api.Assertions.fail(Assertions.java:142)
	at net.aerh.imagegenerator.testsupport.ImageAssertions.assertPixelsEqual(ImageAssertions.java:25)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.assertMatchesGolden(ToolGoldenImageTest.java:133)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.vanillaRenderMatchesGolden(ToolGoldenImageTest.java:109)



net.aerh.imagegenerator.tools.ToolGoldenImageTest :: vanillaRenderMatchesGolden(String)[3]
golden/tools/text pixel mismatch at (25,25): expected ff55ff55 but was 8f56ff56
org.opentest4j.AssertionFailedError: golden/tools/text pixel mismatch at (25,25): expected ff55ff55 but was 8f56ff56
	at org.junit.jupiter.api.Assertions.fail(Assertions.java:142)
	at net.aerh.imagegenerator.testsupport.ImageAssertions.assertPixelsEqual(ImageAssertions.java:25)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.assertMatchesGolden(ToolGoldenImageTest.java:133)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.vanillaRenderMatchesGolden(ToolGoldenImageTest.java:109)



net.aerh.imagegenerator.tools.ToolGoldenImageTest :: vanillaRenderMatchesGolden(String)[4]
golden/tools/inventory pixel mismatch at (110,63): expected ff3f3f3f but was ff404040
org.opentest4j.AssertionFailedError: golden/tools/inventory pixel mismatch at (110,63): expected ff3f3f3f but was ff404040
	at org.junit.jupiter.api.Assertions.fail(Assertions.java:142)
	at net.aerh.imagegenerator.testsupport.ImageAssertions.assertPixelsEqual(ImageAssertions.java:25)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.assertMatchesGolden(ToolGoldenImageTest.java:133)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.vanillaRenderMatchesGolden(ToolGoldenImageTest.java:109)



net.aerh.imagegenerator.tools.ToolGoldenImageTest :: vanillaRenderMatchesGolden(String)[6]
golden/tools/powerstone pixel mismatch at (306,54): expected ff55ff55 but was ff389038
org.opentest4j.AssertionFailedError: golden/tools/powerstone pixel mismatch at (306,54): expected ff55ff55 but was ff389038
	at org.junit.jupiter.api.Assertions.fail(Assertions.java:142)
	at net.aerh.imagegenerator.testsupport.ImageAssertions.assertPixelsEqual(ImageAssertions.java:25)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.assertMatchesGolden(ToolGoldenImageTest.java:133)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.vanillaRenderMatchesGolden(ToolGoldenImageTest.java:109)



net.aerh.imagegenerator.tools.ToolGoldenImageTest :: vanillaRenderMatchesGolden(String)[7]
golden/tools/dialogue_single pixel mismatch at (25,25): expected ffffff55 but was 8fffff56
org.opentest4j.AssertionFailedError: golden/tools/dialogue_single pixel mismatch at (25,25): expected ffffff55 but was 8fffff56
	at org.junit.jupiter.api.Assertions.fail(Assertions.java:142)
	at net.aerh.imagegenerator.testsupport.ImageAssertions.assertPixelsEqual(ImageAssertions.java:25)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.assertMatchesGolden(ToolGoldenImageTest.java:133)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.vanillaRenderMatchesGolden(ToolGoldenImageTest.java:109)



net.aerh.imagegenerator.tools.ToolGoldenImageTest :: vanillaRenderMatchesGolden(String)[8]
golden/tools/dialogue_multi pixel mismatch at (25,25): expected ffffff55 but was 8fffff56
org.opentest4j.AssertionFailedError: golden/tools/dialogue_multi pixel mismatch at (25,25): expected ffffff55 but was 8fffff56
	at org.junit.jupiter.api.Assertions.fail(Assertions.java:142)
	at net.aerh.imagegenerator.testsupport.ImageAssertions.assertPixelsEqual(ImageAssertions.java:25)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.assertMatchesGolden(ToolGoldenImageTest.java:133)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.vanillaRenderMatchesGolden(ToolGoldenImageTest.java:109)



net.aerh.imagegenerator.tools.ToolGoldenImageTest :: fixturePackRenderMatchesGolden(String)[2]
golden/tools/fixture/item pixel mismatch at (321,94): expected ff112233 but was ff192731
org.opentest4j.AssertionFailedError: golden/tools/fixture/item pixel mismatch at (321,94): expected ff112233 but was ff192731
	at org.junit.jupiter.api.Assertions.fail(Assertions.java:142)
	at net.aerh.imagegenerator.testsupport.ImageAssertions.assertPixelsEqual(ImageAssertions.java:25)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.assertMatchesGolden(ToolGoldenImageTest.java:133)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.fixturePackRenderMatchesGolden(ToolGoldenImageTest.java:115)



net.aerh.imagegenerator.tools.ToolGoldenImageTest :: fixturePackRenderMatchesGolden(String)[4]
golden/tools/fixture/text pixel mismatch at (39,39): expected ff55ff55 but was ff5d8f3f
org.opentest4j.AssertionFailedError: golden/tools/fixture/text pixel mismatch at (39,39): expected ff55ff55 but was ff5d8f3f
	at org.junit.jupiter.api.Assertions.fail(Assertions.java:142)
	at net.aerh.imagegenerator.testsupport.ImageAssertions.assertPixelsEqual(ImageAssertions.java:25)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.assertMatchesGolden(ToolGoldenImageTest.java:133)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.fixturePackRenderMatchesGolden(ToolGoldenImageTest.java:115)



net.aerh.imagegenerator.tools.ToolGoldenImageTest :: fixturePackRenderMatchesGolden(String)[5]
golden/tools/fixture/inventory pixel mismatch at (110,63): expected ff3f3f3f but was ff404040
org.opentest4j.AssertionFailedError: golden/tools/fixture/inventory pixel mismatch at (110,63): expected ff3f3f3f but was ff404040
	at org.junit.jupiter.api.Assertions.fail(Assertions.java:142)
	at net.aerh.imagegenerator.testsupport.ImageAssertions.assertPixelsEqual(ImageAssertions.java:25)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.assertMatchesGolden(ToolGoldenImageTest.java:133)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.fixturePackRenderMatchesGolden(ToolGoldenImageTest.java:115)



net.aerh.imagegenerator.tools.ToolGoldenImageTest :: fixturePackRenderMatchesGolden(String)[6]
golden/tools/fixture/powerstone pixel mismatch at (320,54): expected ff55ff55 but was ff3e9d3e
org.opentest4j.AssertionFailedError: golden/tools/fixture/powerstone pixel mismatch at (320,54): expected ff55ff55 but was ff3e9d3e
	at org.junit.jupiter.api.Assertions.fail(Assertions.java:142)
	at net.aerh.imagegenerator.testsupport.ImageAssertions.assertPixelsEqual(ImageAssertions.java:25)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.assertMatchesGolden(ToolGoldenImageTest.java:133)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.fixturePackRenderMatchesGolden(ToolGoldenImageTest.java:115)



net.aerh.imagegenerator.tools.ToolGoldenImageTest :: fixturePackRenderMatchesGolden(String)[7]
golden/tools/fixture/dialogue_single pixel mismatch at (39,39): expected ffffff55 but was ff9d9d3e
org.opentest4j.AssertionFailedError: golden/tools/fixture/dialogue_single pixel mismatch at (39,39): expected ffffff55 but was ff9d9d3e
	at org.junit.jupiter.api.Assertions.fail(Assertions.java:142)
	at net.aerh.imagegenerator.testsupport.ImageAssertions.assertPixelsEqual(ImageAssertions.java:25)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.assertMatchesGolden(ToolGoldenImageTest.java:133)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.fixturePackRenderMatchesGolden(ToolGoldenImageTest.java:115)



net.aerh.imagegenerator.tools.ToolGoldenImageTest :: fixturePackRenderMatchesGolden(String)[8]
golden/tools/fixture/dialogue_multi pixel mismatch at (39,39): expected ffffff55 but was ff9d9d3e
org.opentest4j.AssertionFailedError: golden/tools/fixture/dialogue_multi pixel mismatch at (39,39): expected ffffff55 but was ff9d9d3e
	at org.junit.jupiter.api.Assertions.fail(Assertions.java:142)
	at net.aerh.imagegenerator.testsupport.ImageAssertions.assertPixelsEqual(ImageAssertions.java:25)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.assertMatchesGolden(ToolGoldenImageTest.java:133)
	at net.aerh.imagegenerator.tools.ToolGoldenImageTest.fixturePackRenderMatchesGolden(ToolGoldenImageTest.java:115)

Full Log

pr98-validation-logs.zip

@Aerhhh

Aerhhh commented Oct 15, 2026

Copy link
Copy Markdown
Owner

Will have a look at that later today!

@Aerhhh
Aerhhh merged commit b860790 into Aerhhh:master Oct 15, 2026
3 checks passed
@Aerhhh

Aerhhh commented Oct 15, 2026

Copy link
Copy Markdown
Owner

Thanks :)

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.

2 participants