Release/0.1.0 - #2
Merged
Merged
Conversation
java.lang.classfile writes a member class two ways. Where nothing
enclosing it is parameterized it is flat, Ljava/util/Map$Entry;, and
className() is the whole slash-separated name. Where something is, it is
a chain, Ljava/util/EnumMap<TK;TV;>.EntrySet;, and className() is the
simple name alone -- the rest of it lives in the outer signature, which
is the only place the enclosing type's arguments can be stated.
classDesc() answers with the whole name either way. mapSignature fed
that back into the chained form, so a rebuild emitted
Ljava/util/EnumMap<TK;TV;>.java/util/EnumMap$EntrySet;
which nothing can parse. JDK 25 accepted it in silence: ClassTypeSig.of
did not validate, and neither the verifier nor
rebuildingPreservesMembersAcrossTheJdk looks at generic signatures. JDK
26 added validateIdentifier and the build stopped. The corruption is
present on every JDK the project has run on; only the newer one says so.
mapClassTypeSig now maps the outer type first and takes the mapped whole
name back apart against it to recover the simple name. Where a mapping
moves the member out of its enclosing type no simple name relates the
two, so the flat form is emitted instead -- that costs the enclosing
type's arguments, which a name that no longer nests has nowhere to put.
Three tests, each of which fails on JDK 25 without the fix:
chainedSignatureKeepsItsSimpleName covers identity over a chain, a
three-deep chain and a chain inside a type argument;
chainedSignatureFollowsARename covers a rename that carries the member
and one that detaches it; rebuiltSignaturesAcrossTheJdkStayParseable
re-parses every class, field, method and generic-local signature in a
seventh of java.base, and catches a class signature the JDK 26 run never
reached because it failed on a generic local first.
Signed-off-by: Erik Pförtner <splatcrafter@splatgames.de>
Both were committed as mode 100644, so a fresh checkout has no execute bit on either and the shell refuses them before the script runs. The IDE plugin job in build.yml calls ./gradlew by path twice. The first call died with "Permission denied" and exit code 126, which is the shell saying it would not run the file -- nothing in the wrapper, the JDK or the Gradle setup was involved. verifyPlugin, the step after it, was blocked by the same bit. shoot.sh is not on the CI path but three documents tell an agent to run it by path, unprefixed: the docsite skill and the implementer and clarity-reviewer agents. As written those commands could not work. Recorded with git update-index --chmod=+x so the bit is in the tree rather than only in a working copy. The other scripts carrying a shebang need no change: the .devcontainer ones are invoked as bash <path>, and writerside.sh is chmod +x'd in the Dockerfile. Signed-off-by: Erik Pförtner <splatcrafter@splatgames.de>
KEYS carries the public half of the key the release pipeline signs with: Splatgames.de Software CI Release Signing <release@splatgames.de>, RSA 4096, created 2026-01-11, no expiry, fingerprint C6BE 25BF 2A46 39A6 7A49 1EBD 37B5 9B93 DC75 6EE8. No private material is in the file. SECURITY.md said the key and its fingerprint were "published with the first signed release", which the file makes untrue. Its Signing keys section now identifies the key, gives the import-and-verify commands, and keeps the two bullets about pipeline ownership and how the private half reaches the build. It also says that importing KEYS and verifying against it proves only that the file and the signatures agree, since one push can replace both, and points at keyserver.ubuntu.com as a source outside this repository. That is the copy Maven Central validates against; the key is there and the fingerprint matches. keys.openpgp.org does not have it, so the text does not claim it does. The README repeats the fingerprint and the two commands under Security, because someone verifying a download reaches the README first. RELEASING.md told the releaser to add the fingerprint to SECURITY.md once the key existed. That is now done, so the instruction would have asked for it twice; it records where the key lives instead, and that rotating it means replacing all three in one commit. Signed-off-by: Erik Pförtner <splatcrafter@splatgames.de>
Three things that were stopping the build or misdescribing the project. ClassRemapper rebuilt a member of a parameterized outer type by putting the whole slash-separated name where the simple name belongs, producing a generic signature nothing can parse. JDK 25 accepted it in silence and JDK 26 rejects it, which is why the pipeline broke on a JDK bump rather than on a change to this code. Three tests cover it, each of which fails on JDK 25 without the fix. gradlew and shoot.sh were committed without an execute bit, so the IDE plugin job died at exit 126 before the wrapper ran, and three documents told an agent to run shoot.sh by a path that could not work. KEYS is published with its fingerprint in SECURITY.md and the README, which replaces the claim that the key would arrive with the first signed release. Signed-off-by: Erik Pförtner <splatcrafter@splatgames.de>
Code scanning needs GitHub Advanced Security on a private repository, so the analyze step never got past its upload: CodeQL scanned 316 files, wrote the SARIF, and then failed with "Advanced Security must be enabled for this repository to use code scanning". It failed that way on every push to main and develop, on every pull request, and weekly. Removing the workflow removes the cost and a permanently red check; the file is worth restoring if this repository ever goes public, where the same scanning is free. SECURITY.md claimed CodeQL under Automated scanning and the README carried its badge. Both are gone rather than left describing something the repository no longer runs. What is left there is what the build itself enforces on every run. The release workflow named four secrets that do not exist. The ones the repository has are CENTRAL_USERNAME, CENTRAL_TOKEN, GPG_PRIVATE_KEY and GPG_PASSPHRASE, and a secret cannot be renamed -- only deleted and recreated -- so the workflow follows the names rather than the other way round. Only the secret references moved. The environment variables the publish job sets from them are unchanged and are not free to change: MAVEN_CENTRAL_USERNAME and MAVEN_CENTRAL_TOKEN are the placeholders settings.xml resolves by name, and MAVEN_GPG_PASSPHRASE is the variable maven-gpg-plugin reads by default, which pom.xml documents at the gpg plugin. RELEASING.md now says which of the two a name belongs to. Signed-off-by: Erik Pförtner <splatcrafter@splatgames.de>
Removes the CodeQL workflow, which could never finish on a private repository: the analysis ran and the upload failed on the Advanced Security gate, on every push to a long-lived branch, every pull request and weekly. The README badge and the claim in SECURITY.md go with it, rather than being left to describe a scanner the repository no longer runs. Also points the release workflow at the four secrets this repository actually has -- CENTRAL_USERNAME, CENTRAL_TOKEN, GPG_PRIVATE_KEY, GPG_PASSPHRASE. Only the secret names moved; the environment variables the publish job sets from them are fixed by settings.xml and by maven-gpg-plugin's default, and are unchanged. Signed-off-by: Erik Pförtner <splatcrafter@splatgames.de>
The IntelliJ plugin job did not fail because the plugin is broken. The
verifier finished and said so:
Finished 1 of 1 verifications (in 78.9 s): IU-262.10315.69 against
de.splatgames.aether.weaver:0.1.0-SNAPSHOT: Compatible.
The job then died writing the report:
Exception in thread "main" java.io.IOException: No space left on device
at ...HtmlResultPrinter...PluginVerifierMain.main
The runner was out of disk. The download failures logged before that --
radler, org.jetbrains.android, PythonCore, DevKit -- were the same cause,
not a separate one. This job pulls a full IntelliJ IDEA Ultimate
distribution to compile against, another for every release
`recommended()` resolves, and then each bundled plugin the verifier walks
to; a ubuntu-latest image starts with about 14 GB free.
Four preinstalled toolchains are removed before anything downloads. The
Android SDK is roughly 9 GB on its own and nothing here compiles for
Android. Each is removed only if present, so an image that stops shipping
one of them does not fail the step, and the step prints df before and
after so the next person does not have to guess what it bought.
Nothing about the verification itself changed. `recommended()` and the
unset `untilBuild` are a deliberate pair -- the plugin claims
compatibility with every future IDE and this is what checks the claim --
and narrowing either to fit a full disk would have made the job pass by
testing less.
CodeQL comes back with the repository being public: code scanning is free
there, and the Advanced Security gate that made it fail on every run does
not apply. The workflow, the README badge and the SECURITY.md entry are
restored as they were. The Dependency Review bullet keeps the fuller
description it gained.
Signed-off-by: Erik Pförtner <splatcrafter@splatgames.de>
The IntelliJ plugin job was failing on a full runner, not on a broken plugin: the verifier reported the plugin compatible and the job then died writing its HTML report with "No space left on device". Four preinstalled toolchains are removed before the IDE downloads start, the Android SDK among them at roughly 9 GB. The verification itself is untouched -- recommended() and the unset untilBuild still check the compatibility the plugin claims. CodeQL returns now that the repository is public, where code scanning is free and the Advanced Security gate no longer applies. Workflow, README badge and SECURITY.md entry are back as they were. Signed-off-by: Erik Pförtner <splatcrafter@splatgames.de>
Six places said it was not, and it ships to the JetBrains Marketplace
beside this release. A reader who believes any of them builds a Gradle
project to get something the IDE would have installed for them.
README, IntelliJ section "not published yet; build it from ..."
README, modules table aether-weaver-ide -> "Not published"
README, project status listed among the deliberate limitations
CHANGELOG, tooling "Built from source; not published ... yet"
CHANGELOG, limitations "The IntelliJ plugin is not published"
intellij-plugin.topic tldr: "Nothing publishes it, so you build it
yourself"
Building from source stays where it is useful and is still named; it is
no longer the only way in. The Marketplace is reached by name in the
plugin browser rather than by a numeric plugin URL, which is assigned on
first upload and would be a guess today; the CHANGELOG links the vendor
page, which exists.
The modules table's column asks what you depend on, and the plugin is
not a dependency at all -- "Not published" answered a question about
Maven Central that the row was not asking. It now says what a reader
does with that row: install it in the IDE.
python3 build-config/docsite/check-docs.py passes. The --build run fails
in this container with 36 builder/INT009 "Rendering of the diagram timed
out" across 35 topics, none of them this one and no other error kind, so
it is the diagram rendering here rather than the change. docs.yml builds
in the pinned image on any push under Writerside/ and is the real check.
Signed-off-by: Erik Pförtner <splatcrafter@splatgames.de>
Step 1 listed the four files the release workflow checks and mentioned gradle.properties in passing, as "worth doing, though nothing checks it". Two files decide what the plugin ships as, and both were at 0.1.0-SNAPSHOT while the release is being cut: build.gradle.kts version = "0.1.0-SNAPSHOT" gradle.properties aetherWeaverVersion=0.1.0-SNAPSHOT The first names the archive. The second is worse: the API and the engine are implementation dependencies and are bundled into the plugin, so the plugin would ship the SNAPSHOT jars from whoever ran the build instead of the published ones. Neither is checked by anything, which is exactly why the runbook has to carry them, and the table now says what each one breaks rather than only what to set. The heading said four files and the section now covers six; it says six, and the sentence under it keeps the distinction, because the workflow still reads four and two later entries still count that way. Step 6 is the plugin release itself, which the runbook did not describe at all: wait for Central to actually serve the artefacts, since the plugin resolves them as ordinary dependencies, then buildPlugin and upload the archive to the vendor page. publishPlugin and signPlugin are registered by the Gradle plugin but neither is configured here -- no token, no certificate -- so the upload is a manual step, and the runbook says so rather than leaving a task name that looks like it would work. Signed-off-by: Erik Pförtner <splatcrafter@splatgames.de>
Six places in the README, the CHANGELOG and the IntelliJ topic said the IDE plugin was not published. It ships to the JetBrains Marketplace beside 0.1.0, so all six now say how to install it and keep building from source as the alternative rather than the only way. The runbook gains the two versions that decide what the plugin ships as -- its own `version` and the `aetherWeaverVersion` it bundles the API and engine from, both still at 0.1.0-SNAPSHOT and neither checked by anything -- and a step for the plugin release, which it did not describe at all. Signed-off-by: Erik Pförtner <splatcrafter@splatgames.de>
The root is a `pom` artefact and goes to Central with the rest of the
release, where a coordinate cannot be taken back. It read
`de.splatgames.aether.weaver:aether-weaver-parent`; it reads
`de.splatgames.aether.weaver:aether-weaver`.
Thirteen places, because the artifactId is not only declared:
pom.xml the declaration
nine module poms each names it as <parent>, and a module
whose parent no longer exists does not build
artifacts.topic "Every jar names aether-weaver-parent as its
own" is a published statement of fact
S-install.md four references in the dossier the reference
page was written from
The dossier is not checked by anything and is not published, but it is
what the next revision of that page is written against, so a stale fact
left in it is the drift the pipeline exists to prevent.
`<name>Aether Weaver (Parent)</name>` is unchanged. It still describes
what the pom is, and it is not a coordinate.
mvn -B -o clean verify passes over all ten modules, and
build-config/docsite/check-docs.py passes.
Signed-off-by: Erik Pförtner <splatcrafter@splatgames.de>
The reactor root ships to Maven Central as a pom artefact alongside the jars, and a published coordinate cannot be withdrawn. It is de.splatgames.aether.weaver:aether-weaver now, not -parent. Thirteen places: the declaration, the nine modules that name it as their parent, the reference page that states it as a fact, and the research dossier that page was written from. Signed-off-by: Erik Pförtner <splatcrafter@splatgames.de>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release v0.1.0