Skip to content

The documents the program writes are checked against the schema - #27

Merged
fabeat merged 5 commits into
mainfrom
feat/ooxml-gate
Nov 1, 2026
Merged

fabeat merged 5 commits into
mainfrom
feat/ooxml-gate

Conversation

@fabeat

@fabeat fabeat commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

An OOXML validation gate: the documents this program writes are checked against the schema with Microsoft's own validator — the one the Open XML SDK Productivity Tool uses.

The validator is vendored in tools/ooxml-validator rather than depended on: nothing the library ships depends on it, and the library's own suite does not need it to run.

The gate is on, and it is red today. The document the binary writes carries 25 schema errors and the deck carries none. All 25 are PHPWord's defects, and they are being fixed upstream: PHPOffice/PHPWord#2963 names them, and the five pull requests that fix them are #2964, #2965, #2966, #2968 and #2969.

Measured against the patch that carries them — the one at markdown-office/PHPWord's patches/1.4.0-to-fixes, which markdown-office/markdown-word declares and applies — the same document carries 0 errors and the gate is green. That is what this pull request is measured against, and the gate stays red until the patch reaches the library this program installs.

The test runs over what the binary writes rather than over what the library writes: the binary is what the release publishes and it is the one thing neither of the two libraries measures.

Where the .NET SDK is not on the machine, the test skips itself and says what is missing. The new ooxml job in tests.yml installs the SDK, so the gate cannot be skipped there.

The release workflow does not test the library — it builds and publishes — so the check is in the phar job, after the reproducibility check and before the artifact is uploaded. The documents are written by the archive itself, because the archive is built once and every released binary carries it.

The three red jobs have one cause. The ooxml job, the coverage job and the sonarcloud job all build the two libraries from the branches named in the repository variables MARKDOWN_WORD_REF and MARKDOWN_PRESENTATION_REF, and both say main. main does not carry the patch yet, so the document the program writes has the 25 errors the unpatched PHPWord gives it — and the two jobs that run the suite fail on it, the sonarcloud job among them because it runs the suite to produce the reports the analysis reads.

So this pull request is merged after the two libraries'. markdown-word's #49 and markdown-presentation's #43 carry the patch, and main carries it the moment they are merged. The run that follows is green.

The release notes are under a heading the release job can read. The changelog's ## [Unreleased] is now ## [0.1.3] - 2026-10-31, with the link reference beside the others — v0.1.2 is already cut and published, and the gate is not in it. The release job reads the newest released heading out of the changelog and refuses a tag that disagrees with it, so a tag cut before this would have failed.

Microsoft's own validator — the one the Open XML SDK Productivity Tool
uses — is the reader of the format this suite writes. It is vendored here
rather than depended on: nothing the library ships depends on it, and the
library's own suite does not need it to run.

The build output is ignored. A .NET program writes its build beside its
sources, and what it writes is a function of the machine that built it.
A .docx and a .pptx are Office Open XML, and a document that breaks the
schema is a document that is not what it claims to be. Word opens it
because Word is lenient where the schema is not, and nothing else in the
suite could see it: the two libraries are measured by their own suites,
and neither of them looks at what it wrote.

So the check runs over what the binary writes. The binary is what the
release publishes, and it is the one thing the two libraries do not
measure.

The test skips itself where the .NET SDK is not, and says what is missing
— the SDK is not on every machine, and a test that fails where it cannot
run says nothing about the code. A machine with the runtime but no SDK is
a different case and says so.

The third test asks the validator about a document with an error in it.
The gate is worth nothing if it cannot fail, and a validator that answered
"no errors" about every document would pass the two tests above.
The test skips itself where the SDK is not, so the job that runs the suite
runs it and learns nothing from it. A job of its own installs the SDK, so
the gate cannot be skipped there.

The release workflow does not test the library: it builds and publishes.
So the check belongs in the job that builds the archive, after the
reproducibility check and before the artifact is uploaded. The documents
are written by the archive itself, because the archive is built once and
every released binary carries it — so this is the document a user of the
release gets.

The status of the validator is read rather than the step's own: a failure
inside a command substitution is swallowed by the `echo` around it, so the
answer is taken here.
@sonarqubecloud

sonarqubecloud Bot commented Nov 1, 2026

Copy link
Copy Markdown

@fabeat
fabeat merged commit 8a0d377 into main Nov 1, 2026
12 of 15 checks passed
@fabeat
fabeat deleted the feat/ooxml-gate branch November 1, 2026 19:50
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