Conversation
06ff246 to
8646d34
Compare
antora 3.1.15 depends on js-yaml ~4.1, and 4.1.1 is affected by GHSA advisories on quadratic CPU use in merge keys and !!omap (Dependabot alerts #25-#28). Override it to 4.3.2, the first release with all fixes; the 4.x API is unchanged and the site builds with the same known Antora errors as before.
maximthomas
left a comment
There was a problem hiding this comment.
praise: The gate is reproducible and its baselines provably match the runner build.
ui/ui-bundle.ziphashes to the sha256 recorded inantora-playbook.yml:44(e0ac81aa…e70d), so the vendored bundle can be checked against its source..github/workflows/build.yml:86-89tells lychee's exit 2 (broken links) apart from a failure of the check itself.- The Build run on 8646d34 annotates the four known errors with workspace-relative paths and emits no "No longer found" notice, so both lists match the build on the runner.
issue (non-blocking): check.sh passes when its input is missing or malformed, and --update then empties both lists.
.github/build-baseline/check.sh:83-84
"$(antora_errors)" and "$(broken_links)" are arguments to compare, so the non-zero status of jq | sort is discarded and set -e never fires. Without build/ (or with a non-JSON line in antora.log) every known entry becomes a "no longer found" notice and the script exits 0; with --update both files are rewritten to 0 entries, exit 0. In CI the jq calls in build.yml:51 and :93 fail first, so the gate itself holds; the local --update road does not. A plain assignment does stop set -euo pipefail:
errors=$(antora_errors)
links=$(broken_links)
$update || echo "## Compared with the known problems" >> "${GITHUB_STEP_SUMMARY:-/dev/null}"
compare "Antora errors" antora-errors.txt "$errors" "file <TAB> message"
compare "broken links" broken-links.txt "$links" "page <TAB> link"issue (non-blocking): build/antora.log is appended to across local builds.
.github/workflows/build.yml:44-45
Antora's log file destination appends by default (runtime.log.destination.append: true), and output.clean removes only build/site. Re-running the documented commands locally keeps errors from earlier builds in the log: check.sh still counts an error that is already fixed, and check.sh --update writes it back into antora-errors.txt. CI starts from a fresh checkout and is not affected.
run: |
mkdir -p build
rm -f build/antora.log
npx antora antora-playbook.yml --log-format=json --log-file=build/antora.log
npm run copyApiDocsquestion (non-blocking): Should a second occurrence of a known Antora error in the same file fail the build?
.github/build-baseline/check.sh:36, :59
The key is file + message without the line number, and both lists go through sort -u. A second target of xref not found: .:chap-jee-agent-config.adoc#configure-j2ee-policy-agent in chap-jetty.adoc collapses into the known key: 0 new, exit 0, while the header says the check "fails on any new one". If collapsing is intended (a partial included from several pages repeats its errors), this needs nothing. If not, comm counts repeated lines, so plain sort keeps the key free of line numbers and still catches the repeat; run check.sh --update afterwards:
| "\(.file.path // "" | ltrimstr($root))\t\(.msg)"' "$root/build/antora.log" | LC_ALL=C sort known=$({ grep -v '^#' "$file" || true; } | LC_ALL=C sort)suggestion (non-blocking): Nothing in CI exercises the failure path of check.sh.
.github/build-baseline/check.sh:72, .github/workflows/build.yml:101
The Build run only reaches the "0 new, 0 no longer found" path; the failing path was checked once by hand. A mutant that deletes failed=true (line 72), or swaps the comm operands so that new is always empty, keeps every Build run green. The step below passes against the head's check.sh and fails against the mutant without failed=true:
- name: Self-test the baseline check
run: |
t=$(mktemp -d)
mkdir -p "$t/.github" "$t/build"
cp -r .github/build-baseline "$t/.github/"
echo '{"level":"error","msg":"self-test","file":{"path":"'"$t"'/x.adoc"}}' > "$t/build/antora.log"
echo '{"error_map":{}}' > "$t/build/lychee.json"
if GITHUB_STEP_SUMMARY=/dev/null "$t/.github/build-baseline/check.sh" > /dev/null; then
echo "check.sh passed a new Antora error" >&2
exit 1
fiPin: placed before "Compare with the known problems", it turns red as soon as a new Antora error stops failing check.sh.
suggestion (non-blocking): When Antora itself fails, the job shows no cause.
.github/workflows/build.yml:47
With --log-file, Antora's CLI logs a fatal error to the configured logger — the file, not the console — and "Report Antora messages" has no if:, so it is skipped once "Generate Site" fails. A pull request that breaks the build gets a red check with nothing in the console, the summary or the annotations. The report step already annotates fatal:
- name: Report Antora messages
if: ${{ !cancelled() && hashFiles('build/antora.log') != '' }}suggestion (non-blocking): The link check does not cover anchors.
.github/workflows/build.yml:80-85
lychee 0.24.2 checks fragments only with --include-fragments, and Antora resolves only the page part of an xref. Renaming a section id so that xref:page.adoc#old-id points nowhere gives neither an Antora error nor a broken link, and the check passes. Enabling it may add existing broken anchors to broken-links.txt (not measured):
--offline --no-progress --format json --include-fragments \issue (non-blocking): Annotation text is not escaped for workflow commands.
.github/build-baseline/check.sh:70, :76, .github/workflows/build.yml:52
The runner decodes %25, %0D and %0A in command data, so a broken link c%25d.html is annotated as c%d.html, and %0A splits the line. The comparison uses the raw strings and no current entry contains %, so only the annotation text is affected.
msg=${line//%/%25}
echo "::error title=New $title::${msg//$'\t'/ — }"In build.yml:52: \(.msg | gsub("%"; "%25") | gsub("\r"; "%0D") | gsub("\n"; "%0A")).
e80e7ce to
6264be5
Compare
|
Done in 6264be5 (the branch is rebased onto the current
Anchors: measured with |
…missing-tag error, no hooks, tar -f - - lib/versions-from-tags.js: extract the tags into build/antora-tags/<tag> instead of a random mkdtemp directory, so that the file paths Antora logs for tag content are stable and can be listed in .github/build-baseline (OpenIdentityPlatform#28); name the temp branch after the tag - fail with a hint when a tag is neither local nor on origin (e.g. a fork created before the tags were pushed) - commit in the temp repository with core.hooksPath=/dev/null, so global hooks of the developer cannot abort the build - tar -x -f -: read the archive from stdin explicitly instead of $TAPE
…missing-tag error, no hooks, tar -f - - lib/versions-from-tags.js: extract the tags into build/antora-tags/<tag> instead of a random mkdtemp directory, so that the file paths Antora logs for tag content are stable and can be listed in .github/build-baseline (OpenIdentityPlatform#28); name the temp branch after the tag - fail with a hint when a tag is neither local nor on origin (e.g. a fork created before the tags were pushed) - commit in the temp repository with core.hooksPath=/dev/null, so global hooks of the developer cannot abort the build - tar -x -f -: read the archive from stdin explicitly instead of $TAPE
…nu (#30) Fixes #22 ## Changes - **`ROOT/modules/ROOT/pages/index.adoc`** (start page): - an "API Reference (Javadoc)" link at the end of the guide list of each of the four products; - a new "API Reference (Javadoc)" section (`#api-reference`) with *Products* (OpenDJ, OpenAM, OpenIG, OpenIDM) and *Libraries*: **OpenICF** and **Commons**, whose Javadoc was reachable only by URL. The links are root-relative (`/openam/apidocs/index.html`), because the Javadoc is not an Antora page but is copied into the site by `npm run copyApiDocs`. - **`supplemental-ui/partials/header-content.hbs`**: a divider and an "API Reference (Javadoc)" entry in the Projects menu, pointing to that section. Component navigation is not changed: the product release workflows replace `<product>/modules` (`rm -rf`) on every docs upload, so an entry added there in this repository would be lost; it would have to come from the product repositories. ## Verification Local Antora build of this branch (with `copyApiDocs`): - all six targets (`openam`, `opendj`, `openidm`, `openig`, `openicf`, `commons` `/apidocs/index.html`) exist in the generated site; - the menu entry resolves from every page, e.g. `./#api-reference` on the start page and `../../#api-reference` on `openam/admin-guide/`; - `lychee --offline`: no broken link on the start page; the site total is unchanged (45, all known and tracked); - no new Antora errors; - the branch is rebased onto `master` after #27 and #35, without conflicts. In CI, a missing `<dir>/apidocs/index.html` target is caught by the lychee check of #28; a renamed `#api-reference` anchor by its `--include-fragments` run proposed in #36.
maximthomas
left a comment
There was a problem hiding this comment.
praise: The round-1 fixes land where the bugs were, and the gate fails closed.
.github/build-baseline/check.sh:84-87assigns both inputs beforecompareunderset -euo pipefail. A missing or malformedantora.logorlychee.jsonnow stops the script instead of reading as an empty build, and--updatecannot empty the lists.check.sh:36and:59sort without-uand compare withcomm, so a second occurrence of a known Antora error counts as new..github/workflows/build.yml:91separates lychee's exit 2 (broken links found) from a failure of the check itself.
issue (non-blocking): A multi-line Antora message breaks the "Errors and warnings" table in the job summary.
.github/workflows/build.yml:72
The row escapes only | in .msg; line 56 also escapes CR and LF for the annotation of the same message. With an invalid component antora.yml, Antora exits with a fatal error whose message is "antora.yml has invalid syntax; …" followed by js-yaml's blank line and source snippet (@antora/content-aggregator 3.1.15:718, js-yaml 4.3.2 exception.js). The row splits, and the blank line ends the table. This is the fatal error the step now runs to show (:51). The gate is not affected.
| "| \(.level) | \(.msg | gsub("\\|"; "\\\\|") | gsub("\r?\n|\r"; "<br>")) | \(.file.path // "" | ltrimstr($ws)) | \(.file.line // "") |"' "$log"suggestion (non-blocking): The self-test does not catch swapped comm operands, and it never runs the broken-links path.
.github/workflows/build.yml:104-115
The step copies the real baseline, feeds one new Antora error and no links, and passes if check.sh exits non-zero. Measured with mutants of check.sh:
- Swapping
comm -23andcomm -13(:60-61) keeps the self-test green, because the 4 known errors that are missing from the fixture read as "new". Against the real build, that mutant exits 0 and lets a new error or link through with only a notice. .errormapfor.error_map(:41) also keeps it green, and it turns the 42 known links into "no longer found" notices with exit 0.
The step below passes on the head and fails on both mutants and on check.sh without failed=true:
- name: Self-test the baseline check
run: |
# check.sh must fail on a new Antora error and a new broken link, and pass once they are known
t=$(mktemp -d)
mkdir -p "$t/.github/build-baseline" "$t/build"
cp .github/build-baseline/check.sh "$t/.github/build-baseline/"
: > "$t/.github/build-baseline/antora-errors.txt"
: > "$t/.github/build-baseline/broken-links.txt"
echo '{"level":"error","msg":"self-test","file":{"path":"'"$t"'/x.adoc"}}' > "$t/build/antora.log"
echo '{"error_map":{"/site/p.html":[{"url":"file:///site/q"}]}}' > "$t/build/lychee.json"
out=$(GITHUB_STEP_SUMMARY=/dev/null "$t/.github/build-baseline/check.sh" 2> /dev/null) && rc=0 || rc=$?
if [ "$rc" -ne 1 ] \
|| ! grep -qxF '::error title=New Antora errors::x.adoc — self-test' <<< "$out" \
|| ! grep -qxF '::error title=New broken links::p.html — q' <<< "$out"; then
echo "check.sh did not report the new Antora error and the new broken link (exit $rc): $out" >&2
exit 1
fi
printf 'x.adoc\tself-test\n' > "$t/.github/build-baseline/antora-errors.txt"
printf 'p.html\tq\n' > "$t/.github/build-baseline/broken-links.txt"
GITHUB_STEP_SUMMARY=/dev/null "$t/.github/build-baseline/check.sh" > /dev/nullPin: with empty known lists, the comm swap leaves new empty and the exit code 0, so the step fails. Asserting on the output catches the .errormap mutant.
suggestion (non-blocking): Six of the known broken links load on the live site. They have one .. too many, so they are not legacy paths.
.github/workflows/build.yml:84, .github/build-baseline/broken-links.txt
lychee checks the site mounted at /site. A page-relative link with one .. more than the page is deep leaves /site and resolves to file:///<component>/…. A browser stops the extra .. at the host root. These targets return HTTP 200 on doc.openidentityplatform.org:
openam/jee-users-guide/chap-apache-tomcat.htmlandchap-jetty.html→openam/admin-guide/chap-cdssoopenidm/getting-started/chap-where-to-go.htmlandopenidm/samples-guide/chap-ldap-samples.html→opendj/install-guideopenidm/samples-guide/chap-fullstack-sample.html→openam/install-guide#configure-openam-customopenidm/samples-guide/chap-workflow-samples.html→opendj/install-guide#gui-install
In the last two, the anchor is defined on another page. The gate is right to fail such a link, since it breaks under any path prefix. Only the label in the description and in OpenIdentityPlatform/OpenAM#1154 and OpenIdentityPlatform/OpenIDM#232 is wrong, and it sends maintainers after pages that load. The fix in the source is one .. less:
* Any LDAPv3-compliant directory, including link:../../opendj/install-guide[OpenDJ, window=\_blank] and Active Directory (see xref:connectors-guide:chap-ldap.adoc#chap-ldap["Generic LDAP Connector"] in the __Connectors Guide__).That is openidm/modules/getting-started/pages/chap-where-to-go.adoc:93. The openam/13, openam/13.5, docs/openam/13 and openam-*-policy-agents targets return 404 and are really broken.
nitpick (non-blocking): check.sh escapes % but not CR in annotation text. build.yml:56 escapes both, and 6264be5 says both files do.
.github/build-baseline/check.sh:70, :77
A lone CR inside an Antora error message reaches ::error and ::notice raw, and the runner cuts the annotation there. An LF cannot get there, because read splits on it first. No current entry has a CR, and the comparison is not affected.
msg=${line//%/%25}
msg=${msg//$'\r'/%0D}nitpick (non-blocking): The description says that publish.yml reports the problems, but it reports none.
.github/workflows/publish.yml:50
publish.yml runs npm run buildAll, with no --log-file, no job summary and no lychee. On publish, Antora's messages appear only as console lines in the job log, and links are not checked at all. Suggested wording:
`publish.yml` is not gated: one broken docs upload of a product must not stop the publication of the docs of all products; there Antora's messages appear only in the job log, and links are not checked.- publish.yml: install with npm ci so that package-lock.json is honoured - antora-playbook.yml: use the Antora default UI bundle kept in ui/ui-bundle.zip instead of the GitLab HEAD snapshot - build.yml: build the site for every pull request and report Antora errors/warnings and broken links (lychee --offline) in the job summary; not enforced yet because of known content errors Refs OpenIdentityPlatform#25
Node.js 20 actions are deprecated and are forced onto Node 24 with a warning. Use the current majors: checkout v7, setup-node v7, configure-pages v6, upload-pages-artifact v5, deploy-pages v5. Refs OpenIdentityPlatform#25
The known ones, which come from the product repositories, are listed in .github/build-baseline; check.sh fails on any other and reports the known ones that are gone. check.sh --update rewrites the lists. Refs OpenIdentityPlatform#25
- check.sh: fail on a missing or malformed build/antora.log or build/lychee.json instead of reading it as an empty build (and emptying the lists with --update) - check.sh: keep repeated Antora errors, so that a second occurrence of a known one fails the check - check.sh, build.yml: escape %, CR and LF in annotation text - build.yml: remove build/antora.log before the build, Antora appends - build.yml: report the Antora messages also when Antora fails - build.yml: self-test that check.sh fails on a new Antora error Anchors are not checked yet, see OpenIdentityPlatform#36. Refs OpenIdentityPlatform#25
- build.yml: keep a multi-line Antora message in one row of the summary table - build.yml: self-test check.sh with empty known lists, on a new Antora error and a new broken link, and once both are known - check.sh: escape CR in annotation text as well Refs OpenIdentityPlatform#25
The OpenAM and OpenDJ docs uploaded since fixed 2 of the 4 known Antora errors and 32 of the 42 known broken links. Rewritten with check.sh --update from a build of the current master. Refs OpenIdentityPlatform#25
4b3fbf4 to
a2c1a17
Compare
…wler (#33) Fixes #25, together with #28 — this PR does item 5, the migration to the current DocSearch; items 1–4 are #28. The front end moves now, on the existing index; the crawler stays the legacy scraper until Algolia Crawler access is set up, for which this PR prepares the configuration. ## Changes - **Front end: `@docsearch/js` 3.9.0** instead of `docsearch.js` 2 (vendored as before, `supplemental-ui/js/vendor/docsearch.min.js` and `supplemental-ui/css/vendor/docsearch.min.css`): - the header shows the DocSearch button, which opens the search modal; shortcuts `Ctrl/Cmd+K` and `/`; - same application, key and index (`doc_openidentityplatform`): the records of the legacy scraper carry the fields the v3 front end reads (`hierarchy.lvl0–6`, `content`, `type`, `url`), so no reindexing is needed; - `transformItems` drops the `#cookie-notice` anchor that the legacy scraper gives to page titles and to the text before the first section (the first id on the page, the cookie notice); - rendered only when the build has both `ALGOLIA_SEARCH_API_KEY` and `ALGOLIA_APP_ID` (the v3 client requires `appId`); otherwise the `SITE_SEARCH_PROVIDER` branch (plain search input), which is kept, or no search. 3.9.0 is the last 3.x; 4.x and 5.x add Ask AI and a side panel, which this site does not use, and are 4–5 times larger (510 KB and 619 KB of JS against 133 KB). - **`docsearch/crawler-config.js`** (new): the same crawl for the [Algolia Crawler](https://www.algolia.com/doc/tools/crawler/) — records only from the product pages, as the `start_urls` of `config.json` (the site home page is crawled for links only), the same exclusions (API docs, generated references, and the older versions of #31) and the same selectors for the hierarchy and the content. Not carried over, because none of it changes the results: the version in lvl0 and the `desc(version)` ranking (every component has `version: ~`), the `component` attribute (nothing reads it) and `min_indexed_level`. It writes a new index, `doc_openidentityplatform_v3`, so the live search is not affected while it is checked. **Not run yet**: it needs Crawler access on the Algolia application (for an open-source site, through the DocSearch program). - **`docsearch/readme.md`**: how the search is set up, and the steps to move to the Crawler. The link it held before (how the index was set up for the legacy scraper) is kept. `publish.yml` and `config.json` are unchanged: the legacy scraper keeps reindexing after every deployment. ## Verification Local build with the public search key of the site, checked in a browser (Playwright): - the DocSearch button is rendered in the header, no console errors; - `Ctrl+K` opens the modal; "session" and "replication" return results from the live index, grouped by product; page titles link to the page with no anchor, and no result URL ends with `#cookie-notice` (in the live index every page-title record does); - a build with only `ALGOLIA_SEARCH_API_KEY` has neither the button nor the DocSearch bundle; - the `pathsToMatch` pattern of `crawler-config.js`, checked with micromatch, matches `/openam` and `/openam/` but not `/`, `/openicf/…` or `/commons/…`; - rebased onto `master` (with #29); merges with #30 and #32 without conflicts (`git merge-tree`).
|
Done in c7ef1cd (the branch is rebased onto the current
The six links with one The rebase onto |
maximthomas
left a comment
There was a problem hiding this comment.
praise: The self-test closes the gap from the previous round, and it fails for the right reason.
.github/workflows/build.yml:114-117capturescheck.sh's stdout and checks the exact::errorlines withgrep -qxF, not just the exit code, so the step fails on all three mutants named last round..github/build-baseline/check.sh:70-71escapes%before CR, which is the order the runner unescapes them in.build.yml:72keeps a multi-line fatal Antora message in one summary row.- The Build run at a2c1a17 passes with the shrunk baseline and shows no "No longer found" notice.
suggestion (non-blocking): The self-test never makes check.sh print a "No longer found" notice.
.github/workflows/build.yml:104-123, .github/build-baseline/check.sh:61, :80
Pass 1 runs with empty known lists and pass 2 with known == build, so fixed is empty both times. Pass 2 also discards stdout. Three mutants keep the step green: comm -13 → comm -12 at check.sh:61, fixed=, and ::notice → ::debug at :80. Under the first one, every known entry that is still present gets announced as "no longer found", and an entry that really is stale does not. The gate stays green either way, because notices never set failed=true. This step is the pin suggested in the previous round, so the gap is the reviewer's.
printf 'x.adoc\tself-test\ny.adoc\tgone\n' > "$t/.github/build-baseline/antora-errors.txt"
out=$(GITHUB_STEP_SUMMARY=/dev/null "$t/.github/build-baseline/check.sh" 2> /dev/null) && rc=0 || rc=$?
if [ "$rc" -ne 0 ] \
|| [ "$out" != '::notice title=No longer found; remove from .github/build-baseline/antora-errors.txt::y.adoc — gone' ]; then
echo "check.sh did not report only the stale known error (exit $rc)" >&2
exit 1
fiPin: append this after build.yml:123. A stale known entry must give exactly one notice and exit 0. It passes on head and fails on all three mutants.
suggestion (non-blocking): No test feeds a CR, so the new %0D escape can be deleted without any test failing.
.github/build-baseline/check.sh:71, :79, .github/workflows/build.yml:72
The self-test's message is self-test, which has no CR or %. Deleting msg=${msg//$'\r'/%0D} at :71 and :79 keeps the step green. The code at head is correct: 50%\r becomes 50%25%0D. The pin below catches the deletion at :71. The notice copy at :79 and the <br> replacement at build.yml:72 remain untested.
echo '{"level":"error","msg":"50%\r","file":{"path":"'"$t"'/c.adoc"}}' > "$t/build/antora.log"
out=$(GITHUB_STEP_SUMMARY=/dev/null "$t/.github/build-baseline/check.sh" 2> /dev/null) && rc=0 || rc=$?
if [ "$rc" -ne 1 ] || ! grep -qxF '::error title=New Antora errors::c.adoc — 50%25%0D' <<< "$out"; then
echo "check.sh did not escape % and CR in the annotation (exit $rc)" >&2
exit 1
fiPin: append this as the last block of the step, since it replaces the Antora log. It passes on head and fails once the CR escape is deleted.
issue (non-blocking): When the self-test fails, echoing check.sh's output turns its ::error lines into PR annotations.
.github/workflows/build.yml:118
$out holds check.sh's workflow commands, and line 118 sends it to stderr. The runner parses stderr for commands too: ScriptHandler.cs:336 hands stderr to an OutputManager, and OutputManager.cs:87 calls TryProcessCommand (actions/runner). The first line of $out follows the message prefix on the same line, so it stays plain text. Every line after it becomes an annotation, for example ::error title=New broken links::p.html — q, which names a page and a link that do not exist. This only happens when the self-test is already red, so the job still fails, but the annotation points at the wrong thing. Leading spaces do not prevent it, because the runner trims them before looking for ::.
echo "check.sh did not report the new Antora error and the new broken link (exit $rc); its output:" >&2
sed 's/^/> /' <<< "$out" >&2note (non-blocking): The description no longer matches the diff.
antora-playbook.yml: "Changes" still says this PR adds the CDDL header here. BASE already hasCopyright 2024-2026 3A Systems, LLC.at line 13 (872dec2), so only.github/workflows/publish.ymlgets the header in this PR.
… Sitemap line (#38) Fixes #36 Fixes #37 **Stacked on #28.** Both issues extend the `Build` workflow and the baseline check that #28 adds, so this branch carries the commits of #28 (its current head, a2c1a17). Only the commits after it are this change; the branch will be rebased onto `master` once #28 is merged. ## #36: anchors of links - **`build.yml`**: lychee runs with `--include-fragments`. - **`.github/build-baseline/broken-links.jq`** (new): the broken links of the lychee report as `page <TAB> link`, used by both `check.sh` and the job summary. It drops a `Cannot find fragment` whose anchor is the name of the target page itself (`chap-resource-conf#chap-resource-conf`): Antora renders the page title without an id, so the browser opens the top of the page, which is where the link points anyway. lychee's regular expressions have no back references, so this is done on the JSON report, as proposed in #36. - The job summary lists and counts each page/link pair once, as `check.sh` does, and shows how many links were left out: `N checked, M broken (K more point to the top of their target page).` (K counts occurrences, as lychee's `errors` does.) - **Self-test**: with empty known lists, `check.sh` must pass a link to the top of its target page, and must exit 1 with a `New broken links` annotation on a broken anchor and on a missing page linked at its own id (`d/b.html#b` as `Cannot find file`). - **`broken-links.txt`**: 35 broken anchors are added with `check.sh --update`: the 37 listed in #36 but the two `.:chap-jee-agent-config.adoc` ones, which OpenIdentityPlatform/OpenAM#1158 has fixed on `master`. The 10 known links of #28 are unchanged. Reporting them in the product repositories is not done yet, it follows separately. ## #37: head meta tags and the robots.txt Sitemap line **`.github/build-baseline/head-meta.sh <site>`** (new), run as a new last step, also when the comparison with the known problems fails, so that one run reports both. It fails when: - `robots.txt` has no line `Sitemap: <site.url>/sitemap.xml`, `site.url` read from `antora-playbook.yml`, or `sitemap.xml` is missing; - a page carries other than exactly one each of `<meta name="description"`, `og:title`, `og:description`, `og:image`, `twitter:card`, `og:url`; `og:url` is not required on `404.html`. Redirect pages (`<meta http-equiv="refresh"`, as Antora writes them) and the API docs copied by `npm run copyApiDocs` (the same paths as the link check excludes) are skipped. Problems go to the job summary and as error annotations. A self-test step feeds the script a test site with an empty `robots.txt`, no `sitemap.xml`, a redirect page and a page without `og:image`, with `twitter:card` twice, that quotes a refresh tag, and requires exactly those four problems. ## Verification On a local build of this branch, with the commands of the workflow: - lychee with `--include-fragments`: 382 distinct broken anchors, of which 347 to the page itself and the 35 above; `check.sh`: 0 new, 0 no longer found; the job summary: 45 broken, 45 rows; - both self-test steps pass, and fail against each of 12 mutants: in `broken-links.jq` the status guard replaced by `true`, no filter, every fragment error dropped, the whole path compared, no `rtrimstr`; `check.sh` exiting on the new-entry path before the annotation; in `head-meta.sh` the tag count check deleted, `-eq 1` → `-ge 0`, a loose `http-equiv="refresh"` match, the robots.txt or the sitemap.xml check deleted, always exit 0; - `head-meta.sh build/site`: 285 pages checked, 0 problems.
|
Closing: everything in this pull request is already on The third review round is done in #40 (issue #39), from
The note on the description is correct: |
|
@maximthomas, on the third round (review 5389582272): done in #40, since this PR is already on
|
…r version (#31) Fixes #26 Publishes the last release of each previous major line as an older version; `master` stays the default version, so no URL changes. | Product | `master` (unchanged URLs) | Older version | |---|---|---| | OpenAM | `/openam/…`, shown as **16.x** | `/openam/15.2/…`, **15.2.2** (tag `OpenAM-15.2.2`) | | OpenDJ | `/opendj/…`, **5.x** | `/opendj/4.10/…`, **4.10.2** | | OpenIDM | `/openidm/…`, **7.x** | `/openidm/6.3/…`, **6.3.0** | | OpenIG | `/openig/…`, **6.x** | `/openig/5.3/…`, **5.3.2** | The version menus of the default UI (component list and the per-page version menu) show the older versions as soon as a component has more than one. ## Why an extension (`lib/versions-from-tags.js`) Listing the tags as content sources in the playbook is not enough: 1. the `antora.yml` of every tag declares `version: ~`, and Antora gives the version in `antora.yml` precedence over the version of the content source, so a tag would be merged into the unversioned component version built from `master`; 2. Antora reads **every** file under the start path of a git tree, and at a tag that includes the API docs of that time (18,672 files for `OpenAM-15.2.2`, against 330 pages): the build took 4m14s instead of 43s. The extension replaces `aggregateContent`: the branch sources are aggregated as before; for each tag source it extracts only `<product>/antora.yml` and `<product>/modules` with `git archive` into a temporary repository under `build/antora-tags/<tag>` (a fixed path, so that the errors Antora logs for tag content can be listed in the baseline of #28), aggregates it separately and sets the version from the tag name (`OpenAM-15.2.2` → version `15.2`, display `15.2.2`). The build now takes about 1m16s locally. If the tag is missing — as in the shallow `actions/checkout` of CI — the extension fetches it from `origin` (with `--depth=1` in a shallow repository), so no workflow change is needed. If the fetch fails (e.g. a fork created before the tags were pushed, or no network), the build fails with the `git fetch` command that gets the tag from the upstream, followed by git's own error. The temporary commit runs with `core.hooksPath=/dev/null`, so global git hooks of a developer cannot abort the build. ## Other changes - `<product>/antora.yml`: `display_version` of `master` (16.x, 5.x, 7.x, 6.x). - `lib/add-pdf-link.js`: the "Download PDF" link only on the latest version — the wiki PDFs are built from the current sources. - `lib/add-pdf-link.js`, `<product>/antora.yml`: CDDL header with `Copyright 2024-2026 3A Systems, LLC.` — these files had no copyright line; the playbook got the same line in #29. - Tag sources have `edit_url: false`: no "Edit this Page" on older versions. - `docsearch/config.json`: older versions (`/<product>/<major>.<minor>/`) added to `stop_urls`, so search does not mix them with the current docs. ## Verification Local builds: - the 285 `master` pages differ from the current build only by the older versions added to the version menus; the start page still links to `master`; - the canonical URL of an older page points to the same page in `master` (e.g. `…/openam/admin-guide/`); no PDF or edit link on older pages; - CI scenario: a `--depth 1` clone without tags — the extension fetched the 4 tags and the build succeeded; - rebased onto `master` with #27 and #29 merged: the only conflict, the copyright line of `antora-playbook.yml`, resolved to `master`; merges with #28 without conflicts; - a `--depth 1 --no-tags` clone whose `origin` is unreachable: the build fails with `cannot fetch tag OpenDJ-4.10.2 from the origin of …; if the tag is missing there, run git fetch …`, then git's `Couldn't connect to server`; - the OpenIG-5.3.2 copy of the known `sec-release-levels.adoc` error is logged as `build/antora-tags/OpenIG-5.3.2/openig/modules/ROOT/partials/sec-release-levels.adoc` with refname `OpenIG-5.3.2`, the same on every run; - site size with API docs: **877 MB** (GitHub Pages limit: 1 GB); - `lychee --offline`: 106 broken links instead of 45. The new ones are the same legacy ForgeRock-era links inside the frozen tags, plus 8 links from `openam/15.2` pages to `openam/15.2/apidocs` — the API docs are published for the current version only. ## Merge order with #28 #28 adds a gate that fails a pull request on an Antora error or a broken link missing from `.github/build-baseline`. This PR adds one Antora error (the OpenIG-5.3.2 copy above) and the new broken links of the older versions. Whichever of the two lands second runs `.github/build-baseline/check.sh --update` on its build and commits both lists. ## Not in this PR - When a new major line is released (e.g. OpenAM 17), the tag in the playbook and `display_version` are updated by hand. - The stray tag `${TAG_NAME}` (`0abcd92e4f`) mentioned in #26 is not deleted yet; deleting a tag on `origin` is done separately.
Fixes #25, together with #33 — this PR does items 1–4 of it: a reproducible build and a pull request check that fails on new Antora errors and broken links. Item 5, the DocSearch migration, is #33.
Changes
publish.yml:npm i antora→npm ci, so the versions inpackage-lock.jsonare used.GitHub Actions on Node 24:
checkoutv7,setup-nodev7,configure-pagesv6,upload-pages-artifactv5,deploy-pagesv5 — the Node 20 versions are deprecated and were forced onto Node 24 with a warning. The only dotfile of the site,.nojekyll, whichupload-pages-artifactv4+ leaves out, is not needed by an Actions-based Pages deployment.antora-playbook.yml: the UI bundle was taken from GitLabHEADwithsnapshot: true, so any upstream UI change reached production unreviewed. It is nowui/ui-bundle.zip, kept in the repository; the playbook records its source (antora-ui-default job 15385706035,bundle-stable) and sha256. A link to a specific GitLab job is not used because job artifacts expire.publish.yml,antora-playbook.yml: the CDDL license header,Copyright 2024-2026 3A Systems, LLC.(both files have been written by 3A Systems since 2024).build.yml(new): on every pull request tomaster(and manually) builds the site with the API docs and writes to the job summary:missing attributecounts per file; also when Antora itself fails, whose fatal error goes only to the log file;lychee --offlineover the generated HTML, API docs excluded. The anchor of a link is not checked yet: CI: check the anchors of links in the pull request build #36..github/build-baseline(new): the job fails on an Antora error or a broken link that is not in the known lists —antora-errors.txt(2 known errors) andbroken-links.txt(10 known links), all tracked in the product repositories (below). A known one that is gone is reported as a notice so that it is removed from the list. A second occurrence of a known error counts as new.check.shdoes the comparison and fails on a missing or malformed build output;check.sh --updaterewrites the lists from a build. A self-test step checks thatcheck.shfails on a new Antora error and on a new broken link, and passes once they are in the lists.publish.ymlis not gated: one broken docs upload of a product must not stop the publication of the docs of all products; there Antora's messages appear only in the job log, and links are not checked.Known problems (the baseline)
appendix-scripting.adoc..too many — they load on the site, because the browser stops at the host root, but break under any path prefixFixed in the product repositories and gone from
mastersince this PR was opened: the.:chap-jee-agent-config.adocxrefs (OpenIdentityPlatform/commons#315), the legacy ForgeRock links in OpenAM (OpenIdentityPlatform/OpenAM#1154), OpenIdentityPlatform/OpenAM#1155, theopendj/javadoclinks (OpenIdentityPlatform/OpenDJ#1129) and the 3,523missing attributewarnings of the OpenDJ reference (OpenIdentityPlatform/OpenDJ#1131).Verification
Run locally with the same commands as the workflow:
lastmodin the sitemaps;npm ciinstalls Antora 3.1.15 from the lock file;master: 2 errors, 2 other warnings, 31missing attributewarnings; lychee: 43,108 links checked, 10 broken. Without--fallback-extensions htmllychee reports ~24,000 false positives, because the site uses extensionless URLs (html_extension_style: drop);master; with a broken xref, a broken link and a stale baseline entry added on purpose it fails with two "New …" errors and one "no longer found" notice;check.shexits non-zero withoutbuild/or with a non-JSON log line, and--updatethen leaves the lists untouched; a repeated known error fails it;%and CR in an annotation are sent as%25and%0D; a multi-line Antora message stays in one row of the summary table; the self-test step passes againstcheck.shand fails against it withoutfailed=true, with thecommoperands swapped, and with.error_mapmisspelled.On GitHub, the
Buildcheck of this pull request passes with the baseline check enabled, with no "no longer found" notice, so the lists match the build on the runner.