diff --git a/.github/build-baseline/antora-errors.txt b/.github/build-baseline/antora-errors.txt new file mode 100644 index 0000000000..87d3d7aa73 --- /dev/null +++ b/.github/build-baseline/antora-errors.txt @@ -0,0 +1,4 @@ +# Known Antora errors of the site build, one per line: file message. +# Written by .github/build-baseline/check.sh --update; the build fails on any other. +openidm/modules/integrators-guide/pages/appendix-scripting.adoc dropping cells from incomplete row detected end of table +openig/modules/ROOT/partials/sec-release-levels.adoc level 0 sections can only be used when doctype is book diff --git a/.github/build-baseline/broken-links.txt b/.github/build-baseline/broken-links.txt new file mode 100644 index 0000000000..be8fff5d60 --- /dev/null +++ b/.github/build-baseline/broken-links.txt @@ -0,0 +1,12 @@ +# Known broken links of the site build, one per line: page link. +# Written by .github/build-baseline/check.sh --update; the build fails on any other. +openidm/connectors-guide/chap-ldap.html file:///opendj/3.5/server-dev-guide#referential-integrity +openidm/getting-started/chap-where-to-go.html file:///opendj/install-guide +openidm/integrators-guide/chap-auth.html file:///openam/13.5/admin-guide#session-state-cookies +openidm/integrators-guide/chap-passwords.html file:///opendj/3.5/admin-guide/configure-ssl +openidm/integrators-guide/chap-synchronization.html file:///opendj/3.5/admin-guide#read-ecl-as-regular-user +openidm/samples-guide/chap-fullstack-sample.html file:///openam/13/admin-guide#chap-realms +openidm/samples-guide/chap-fullstack-sample.html file:///openam/13/admin-guide#realm-data-store +openidm/samples-guide/chap-fullstack-sample.html file:///openam/install-guide#configure-openam-custom +openidm/samples-guide/chap-ldap-samples.html file:///opendj/install-guide +openidm/samples-guide/chap-workflow-samples.html file:///opendj/install-guide#gui-install diff --git a/.github/build-baseline/check.sh b/.github/build-baseline/check.sh new file mode 100755 index 0000000000..b35acb913e --- /dev/null +++ b/.github/build-baseline/check.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +# +# The contents of this file are subject to the terms of the Common Development and +# Distribution License (the License). You may not use this file except in compliance with the +# License. +# +# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the +# specific language governing permission and limitations under the License. +# +# When distributing Covered Software, include this CDDL Header Notice in each file and include +# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL +# Header, with the fields enclosed by brackets [] replaced by your own identifying +# information: "Portions copyright [year] [name of copyright owner]". +# +# Copyright 2026 3A Systems, LLC. + +# Compares the Antora errors and the broken links of a site build with the known ones listed in +# this directory, and fails on any new one. The known ones come from the product repositories and +# are fixed there; a known one that is gone is reported so that it is removed from the list. +# +# Usage, from the repository root after a build that wrote build/antora.log (Antora JSON log) and +# build/lychee.json (lychee JSON report): +# .github/build-baseline/check.sh check against the known lists +# .github/build-baseline/check.sh --update rewrite the known lists from this build + +set -euo pipefail + +dir=$(cd "$(dirname "$0")" && pwd) +root=$(cd "$dir/../.." && pwd) +update=false +[ "${1:-}" = --update ] && update=true + +# file message, the file relative to the repository root +antora_errors() { + jq -r --arg root "$root/" 'select(.level == "error" or .level == "fatal") + | "\(.file.path // "" | ltrimstr($root))\t\(.msg)"' "$root/build/antora.log" | LC_ALL=C sort +} + +# page link, both relative to the site root +broken_links() { + jq -r '.error_map // {} | to_entries[] | .key as $page | .value[] + | "\($page | ltrimstr("/site/"))\t\(.url | ltrimstr("file:///site/"))"' "$root/build/lychee.json" | LC_ALL=C sort -u +} + +failed=false + +compare() { + local title=$1 file=$dir/$2 current=$3 new fixed + if $update; then + { + echo "# Known $title of the site build, one per line: $4." + echo "# Written by .github/build-baseline/check.sh --update; the build fails on any other." + printf '%s\n' "$current" | sed '/^$/d' + } > "$file" + echo "$file: $(printf '%s\n' "$current" | sed '/^$/d' | wc -l | tr -d ' ') entries" + return + fi + local known + known=$({ grep -v '^#' "$file" || true; } | LC_ALL=C sort) + new=$(LC_ALL=C comm -23 <(printf '%s\n' "$current" | sed '/^$/d') <(printf '%s\n' "$known" | sed '/^$/d')) + fixed=$(LC_ALL=C comm -13 <(printf '%s\n' "$current" | sed '/^$/d') <(printf '%s\n' "$known" | sed '/^$/d')) + { + echo "### $title" + echo + echo "$(printf '%s' "$new" | grep -c . || true) new, $(printf '%s' "$fixed" | grep -c . || true) no longer found." + echo + } >> "${GITHUB_STEP_SUMMARY:-/dev/null}" + while IFS= read -r line; do + [ -n "$line" ] || continue + msg=${line//%/%25} + msg=${msg//$'\r'/%0D} + echo "::error title=New $title::${msg//$'\t'/ — }" + echo "- new: \`${line//$'\t'/\` — \`}\`" >> "${GITHUB_STEP_SUMMARY:-/dev/null}" + failed=true + done <<< "$new" + while IFS= read -r line; do + [ -n "$line" ] || continue + msg=${line//%/%25} + msg=${msg//$'\r'/%0D} + echo "::notice title=No longer found; remove from .github/build-baseline/$2::${msg//$'\t'/ — }" + echo "- no longer found (remove from \`$2\`): \`${line//$'\t'/\` — \`}\`" >> "${GITHUB_STEP_SUMMARY:-/dev/null}" + done <<< "$fixed" + echo >> "${GITHUB_STEP_SUMMARY:-/dev/null}" +} + +# assigned first, so that a missing or malformed input stops the script (set -e) instead of +# reading as an empty build +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 message" +compare "broken links" broken-links.txt "$links" "page link" + +if $failed; then + echo "The build has new Antora errors or broken links, see above. Fix them; if they come from a" \ + "product repository, report them there and add them to .github/build-baseline." >&2 + exit 1 +fi diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000000..40cd68c6ea --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,125 @@ +# The contents of this file are subject to the terms of the Common Development and +# Distribution License (the License). You may not use this file except in compliance with the +# License. +# +# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the +# specific language governing permission and limitations under the License. +# +# When distributing Covered Software, include this CDDL Header Notice in each file and include +# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL +# Header, with the fields enclosed by brackets [] replaced by your own identifying +# information: "Portions copyright [year] [name of copyright owner]". +# +# Copyright 2026 3A Systems, LLC. + +# Builds the site for a pull request, reports Antora messages and broken links in the job summary, +# and fails on an Antora error or a broken link that is not in the known lists of +# .github/build-baseline: the content has known problems, fixed in the product repositories, which +# would otherwise fail every pull request (#25). +name: Build +on: + pull_request: + branches: [master] + workflow_dispatch: +concurrency: + group: build-${{ github.ref }} + cancel-in-progress: true +permissions: + contents: read +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v7 + - name: Install Node.js + uses: actions/setup-node@v7 + with: + node-version: '24' + cache: npm + - name: Install Antora + run: npm ci + - name: Generate Site + run: | + mkdir -p build + # Antora appends to an existing log file + rm -f build/antora.log + npx antora antora-playbook.yml --log-format=json --log-file=build/antora.log + npm run copyApiDocs + - name: Report Antora messages + # also when Antora fails: with --log-file its fatal error goes only to the log + if: ${{ !cancelled() && hashFiles('build/antora.log') != '' }} + run: | + log=build/antora.log + # annotate the errors on the pull request + jq -r --arg ws "$GITHUB_WORKSPACE/" 'select(.level == "error" or .level == "fatal") + | "::warning file=\(.file.path // "" | ltrimstr($ws)),line=\(.file.line // 1),title=Antora \(.level)::\(.msg | gsub("%"; "%25") | gsub("\r"; "%0D") | gsub("\n"; "%0A"))"' "$log" + { + echo "## Antora" + echo + echo "| Level | Messages |" + echo "|---|---|" + jq -rs 'group_by(.level)[] | "| \(.[0].level) | \(length) |"' "$log" + echo + echo "### Errors and warnings" + echo + echo "Without \`skipping reference to missing attribute\`, which are counted below." + echo + echo "| Level | Message | File | Line |" + echo "|---|---|---|---|" + jq -r --arg ws "$GITHUB_WORKSPACE/" 'select(.level != "info" and .level != "debug") + | select(.msg | startswith("skipping reference to missing attribute") | not) + | "| \(.level) | \(.msg | gsub("\\|"; "\\\\|") | gsub("\r?\n|\r"; "
")) | \(.file.path // "" | ltrimstr($ws)) | \(.file.line // "") |"' "$log" + echo + echo "### Missing attribute references" + echo + echo "| File | Count |" + echo "|---|---|" + jq -rs --arg ws "$GITHUB_WORKSPACE/" 'map(select(.msg | startswith("skipping reference to missing attribute"))) + | group_by(.file.path)[] | "| \(.[0].file.path // "" | ltrimstr($ws)) | \(length) |"' "$log" + } >> "$GITHUB_STEP_SUMMARY" + - name: Check links + run: | + rc=0 + docker run --rm -v "$PWD/build/site:/site:ro" lycheeverse/lychee:0.24.2 \ + --offline --no-progress --format json \ + --root-dir /site --fallback-extensions html --index-files index.html \ + --exclude-path '/site/(openam|opendj|openidm|openig)/apidocs' \ + --exclude-path '/site/(openicf|commons)' \ + '/site/**/*.html' > build/lychee.json || rc=$? + # 2 means broken links were found; anything else non-zero is a failure of the check itself + if [ "$rc" -ne 0 ] && [ "$rc" -ne 2 ]; then + exit "$rc" + fi + { + echo "## Links" + echo + jq -r '"\(.total) checked, \(.errors) broken."' build/lychee.json + echo + echo "| Page | Link |" + echo "|---|---|" + jq -r '.error_map // {} | to_entries[] | .key as $page | .value[] + | "| \($page | ltrimstr("/site/")) | \(.url | ltrimstr("file:///site/")) |"' build/lychee.json + } >> "$GITHUB_STEP_SUMMARY" + - 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/null + - name: Compare with the known problems + run: .github/build-baseline/check.sh diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index dc88529436..338b60b06e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,3 +1,17 @@ +# The contents of this file are subject to the terms of the Common Development and +# Distribution License (the License). You may not use this file except in compliance with the +# License. +# +# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the +# specific language governing permission and limitations under the License. +# +# When distributing Covered Software, include this CDDL Header Notice in each file and include +# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL +# Header, with the fields enclosed by brackets [] replaced by your own identifying +# information: "Portions copyright [year] [name of copyright owner]". +# +# Copyright 2024-2026 3A Systems, LLC. + name: Publish to GitHub Pages on: push: @@ -20,27 +34,27 @@ jobs: url: ${{ steps.deployment.outputs.page_url }} steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Configure Pages - uses: actions/configure-pages@v3 + uses: actions/configure-pages@v6 - name: Install Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v7 with: node-version: '24' - name: Install Antora - run: npm i antora + run: npm ci - name: Generate Site env: ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }} ALGOLIA_SEARCH_API_KEY: ${{ secrets.ALGOLIA_SEARCH_API_KEY }} run: npm run buildAll - name: Upload Artifacts - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@v5 with: path: build/site - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@v5 - name: Reindex docs id: reindex working-directory: ./docsearch diff --git a/antora-playbook.yml b/antora-playbook.yml index 87141ef60b..a6a167ca61 100644 --- a/antora-playbook.yml +++ b/antora-playbook.yml @@ -43,8 +43,11 @@ content: edit_url: https://github.com/OpenIdentityPlatform/OpenIDM/edit/master/openidm-doc/src/main/asciidoc ui: bundle: - url: https://gitlab.com/antora/antora-ui-default/-/jobs/artifacts/HEAD/raw/build/ui-bundle.zip?job=bundle-stable - snapshot: true + # Antora default UI, kept in the repository so that a UI change is reviewed like any other. + # Taken from https://gitlab.com/antora/antora-ui-default/-/jobs/15385706035 (bundle-stable, 2026-09-30), + # sha256 e0ac81aad26961a9cd3cf9bce692a598eff4a1bd2822ce73c9cdc13a15a1e70d. + # To update, download .../-/jobs/artifacts/HEAD/raw/build/ui-bundle.zip?job=bundle-stable + url: ./ui/ui-bundle.zip supplemental_files: ./supplemental-ui output: diff --git a/ui/ui-bundle.zip b/ui/ui-bundle.zip new file mode 100644 index 0000000000..4283a6ed09 Binary files /dev/null and b/ui/ui-bundle.zip differ