Skip to content

Commit a22a5b0

Browse files
themr0cclaude
andcommitted
feat: parallel build orchestrator with filtered output and PR failure comments
Replace sequential build-ccutil.sh with a Node.js orchestrator that runs all ~32 title builds in parallel, filters output to surface errors clearly, classifies errors against an external YAML catalog with cause/fix suggestions, and produces a JSON report consumed by the PR workflow. - build-orchestrator.js: parallel builds, semaphore concurrency, error classification - error-patterns.yml: 12 error patterns (xref, include, podman, htmltest) - build-ccutil.sh: thin Bash wrapper for backward compatibility - pr.yml: continue-on-error + if: always() for rich failure PR comments - build-asciidoc.yml: add id to build step Closes: RHDHBUGS-2903 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 6608831 commit a22a5b0

6 files changed

Lines changed: 589 additions & 67 deletions

File tree

.github/workflows/build-asciidoc.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ jobs:
4646
echo "GIT_BRANCH=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_ENV
4747
4848
- name: Build guides and indexes
49+
id: build
4950
run: |
5051
echo "Building branch ${{ env.GIT_BRANCH }}"
5152
build/scripts/build-ccutil.sh -b ${{ env.GIT_BRANCH }}

.github/workflows/pr.yml

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,19 +109,25 @@ jobs:
109109
echo "GIT_BRANCH=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_ENV
110110
111111
- name: Build guides and indexes
112+
id: build
113+
continue-on-error: true
112114
run: |
113115
echo "Building PR ${{ github.event.pull_request.number }}"
114116
cp trusted-scripts/build/scripts/build-ccutil.sh pr-content/build/scripts/build-ccutil.sh
117+
cp trusted-scripts/build/scripts/build-orchestrator.js pr-content/build/scripts/build-orchestrator.js
118+
cp trusted-scripts/build/scripts/error-patterns.yml pr-content/build/scripts/error-patterns.yml
115119
cd pr-content
116120
build/scripts/build-ccutil.sh -b "pr-${{ github.event.number }}"
117121
118122
- name: Pull from origin before pushing (if possible)
123+
if: steps.build.outcome == 'success'
119124
run: |
120125
cd pr-content
121126
/usr/bin/git pull origin gh-pages || true
122127
123128
# repo must be public for this to work
124129
- name: Deploy
130+
if: steps.build.outcome == 'success'
125131
uses: peaceiris/actions-gh-pages@v4
126132
# if: github.ref == 'refs/heads/main'
127133
with:
@@ -131,14 +137,47 @@ jobs:
131137
publish_dir: ./pr-content/titles-generated
132138

133139
- name: Post or update PR comment with doc preview link
140+
if: always() && steps.build.outcome != 'skipped'
134141
uses: actions/github-script@v7
135142
with:
136143
github-token: ${{ secrets.RHDH_BOT_TOKEN }}
137144
script: |
145+
const fs = require('fs');
138146
const prNum = context.issue.number;
139147
const previewUrl = `https://redhat-developer.github.io/red-hat-developers-documentation-rhdh/pr-${prNum}/`;
140148
const now = new Date().toLocaleString('en-US', { timeZone: 'UTC' });
141-
const body = `Updated preview: ${previewUrl} @ ${now}`;
149+
const buildOutcome = '${{ steps.build.outcome }}';
150+
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
151+
152+
let body;
153+
if (buildOutcome === 'success') {
154+
body = `Updated preview: ${previewUrl} @ ${now}`;
155+
} else {
156+
let report;
157+
try {
158+
report = JSON.parse(fs.readFileSync('pr-content/build-report.json', 'utf8'));
159+
} catch { report = null; }
160+
161+
if (report) {
162+
const failed = report.results.filter(r => r.status === 'failed');
163+
const details = failed.map(r => {
164+
const errs = r.errors.map(e =>
165+
` **Error:** \`${e.line}\`\n **Cause:** ${e.cause}\n **Fix:** ${e.fix}`
166+
).join('\n\n');
167+
return `### ${r.title}\n${errs}`;
168+
}).join('\n\n');
169+
170+
body = `## :x: Build failed\n\n` +
171+
`${report.titles.passed}/${report.titles.total} titles built successfully | ` +
172+
`${report.titles.failed} failed | ${report.duration}s\n\n` +
173+
`${details}\n\n` +
174+
`[View full logs](${runUrl}) | ${now}`;
175+
} else {
176+
body = `## :x: Build failed\n\n` +
177+
`The documentation build failed before producing a report.\n` +
178+
`[View full logs](${runUrl}) | ${now}`;
179+
}
180+
}
142181
143182
const { data: comments } = await github.rest.issues.listComments({
144183
owner: context.repo.owner,
@@ -147,7 +186,8 @@ jobs:
147186
});
148187
149188
const existing = comments.find(c =>
150-
c.body.includes('preview: https://redhat-developer.github.io/')
189+
c.body.includes('preview: https://redhat-developer.github.io/') ||
190+
c.body.includes('Build failed')
151191
);
152192
153193
if (existing) {

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ linkchecker-out.html
1212
catalog-info.yaml
1313
.claude/settings.local.json
1414
.claude/settings.json.backup
15+
build-report.json

build/scripts/build-ccutil.sh

Lines changed: 5 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -7,69 +7,9 @@
77
#
88
# SPDX-License-Identifier: EPL-2.0
99
#
10-
# Utility script build html previews with referenced images
11-
# Requires: Podman - see https://podman.io
12-
# input: titles/
13-
# output: titles-generated/ and titles-generated/$BRANCH/
10+
# Wrapper for backward compatibility — delegates to Node.js build orchestrator.
11+
# Requires: Node.js, Podman
12+
# See build-orchestrator.js for the implementation.
1413

15-
# grep regex for title folders to exclude from processing below
16-
EXCLUDED_TITLES="rhdh-plugins-reference"
17-
BRANCH="main"
18-
19-
while [[ "$#" -gt 0 ]]; do
20-
case $1 in
21-
'-b') BRANCH="$2"; shift 1;;
22-
esac
23-
shift 1
24-
done
25-
26-
rm -fr titles-generated/;
27-
mkdir -p titles-generated/"${BRANCH}";
28-
echo "<html><head><title>Red Hat Developer Hub Documentation Preview - ${BRANCH}</title></head><body><ul>" > titles-generated/"${BRANCH}"/index.html;
29-
# exclude the rhdh-plugins-reference as it's embedded in the admin guide
30-
# shellcheck disable=SC2044,SC2013
31-
set -e
32-
for t in $(find titles -name master.adoc | sort -uV | grep -E -v "${EXCLUDED_TITLES}"); do
33-
d=${t%/*};
34-
dest=${d/titles/titles-generated\/${BRANCH}};
35-
rm -rf "$d/build" || true
36-
CMD="podman run --interactive --rm --tty \
37-
--volume $(pwd):/docs:Z \
38-
--workdir /docs/$d \
39-
quay.io/ivanhorvath/ccutil:amazing ccutil compile --format html-single --lang en-US --doctype article";
40-
echo -e -n "\nBuilding $t into $dest ...\n ";
41-
echo "${CMD}" | sed -r -e "s/\ +/ \\\\\n /g"
42-
$CMD
43-
rm -rfv "$dest" || true
44-
mv -f "$d/build/tmp/en-US/html-single/" "$dest"
45-
# shellcheck disable=SC2013
46-
for im in $(grep images/ "$dest/index.html" | grep -E -v 'mask-image|background|fa-icons|jupumbra' | sed -r -e "s#.+(images/[^\"]+)\".+#\1#"); do
47-
# echo " Copy $im ...";
48-
IMDIR="$dest/${im%/*}/"
49-
mkdir -p "${IMDIR}"; rsync -q "$im" "${IMDIR}";
50-
done
51-
# shellcheck disable=SC2044
52-
# for f in $(find "$dest/" -type f); do echo " $f"; done
53-
echo "<li><a href=${dest/titles-generated\/${BRANCH}/.}>${dest/titles-generated\/${BRANCH}\//}</a></li>" >> titles-generated/"${BRANCH}"/index.html;
54-
done
55-
echo "</ul></body></html>" >> titles-generated/"${BRANCH}"/index.html
56-
57-
# shellcheck disable=SC2143
58-
if [[ $BRANCH == "pr-"* ]]; then
59-
# fetch the existing https://redhat-developer.github.io/red-hat-developers-documentation-rhdh/index.html to add prs and branches
60-
curl -sSL https://redhat-developer.github.io/red-hat-developers-documentation-rhdh/pulls.html -o titles-generated/pulls.html
61-
if [[ -z $(grep "./${BRANCH}/index.html" titles-generated/pulls.html) ]]; then
62-
echo "Building root index for $BRANCH in titles-generated/pulls.html ...";
63-
echo "<li><a href=./${BRANCH}/index.html>${BRANCH}</a></li>" >> titles-generated/pulls.html
64-
fi
65-
else
66-
# fetch the existing https://redhat-developer.github.io/red-hat-developers-documentation-rhdh/index.html to add prs and branches
67-
curl -sSL https://redhat-developer.github.io/red-hat-developers-documentation-rhdh/index.html -o titles-generated/index.html
68-
if [[ -z $(grep "./${BRANCH}/index.html" titles-generated/index.html) ]]; then
69-
echo "Building root index for $BRANCH in titles-generated/index.html ...";
70-
echo "<li><a href=./${BRANCH}/index.html>${BRANCH}</a></li>" >> titles-generated/index.html
71-
fi
72-
fi
73-
74-
# Test the links with htmltest
75-
podman run --rm --tty --volume "$(pwd)":/test:Z docker.io/wjdp/htmltest:latest -c .htmltest.yml
14+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15+
exec node "${SCRIPT_DIR}/build-orchestrator.js" "$@"

0 commit comments

Comments
 (0)