Skip to content

Commit e51ad20

Browse files
committed
Address carbolymer review on PR #1180
- Changelog (.changes/.../fix_haddock_links.yml): collapse the description block scalar to a single line, removing the hard wraps Herald renders verbatim (r3159565460). - derive_name_candidates (scripts/fix-haddock-links.sh): cap at two-token names. The previous loop emitted a single-token URL like cardano.cardano.intersectmbo.org as its last candidate; if that subdomain ever resolves (wildcard DNS, future deploy, catch-all), probe_site silently accepts it and rewrites every cardano-* link to the wrong site. Add an early break after the suffix strip so the heuristic never emits a URL whose subdomain is a single bare token (r3159784338). - curl retries (scripts/fix-haddock-links.sh): every probe was a single-shot attempt (5s connect, 10s max) with no retry. Worst case: Phase 3 validation downgrades a perfectly valid rewritten URL into an unclickable <span>, silently shipping a regression. Other failure modes: probe_site falling through to a wrong candidate, or the CHaP index fetch killing the whole build on a CDN hiccup. Add --retry 3 --retry-delay 2 --retry-all-errors to all five curl sites (r3159784102). - Workflow assignee 422 (.github/workflows/github-page.yml): the GitHub API rejects assignees that aren't repo collaborators with a 422. If an external contributor merges a PR that breaks the haddock- links check on master, the rolling-issue workflow step would crash there, leaving the issue or comment half-created. Wrap both addAssignees calls in try/catch and remove assignees from the issues.create payload, doing assignment as a separate best-effort call so the issue always lands (r3159784547).
1 parent 8637415 commit e51ad20

3 files changed

Lines changed: 36 additions & 23 deletions

File tree

.changes/20260428_cardano_api_fix_haddock_links.yml

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,4 @@ kind:
44
- bugfix
55
- documentation
66
description: |
7-
Fix broken cross-package Haddock links on the hosted documentation site.
8-
Links to dependency packages (cardano-ledger-*, plutus-*, cardano-base, etc.)
9-
were relative paths pointing to directories that don't exist on the site,
10-
resulting in 404s. A post-processing script now resolves each cross-package
11-
href via a name-suffix heuristic under *.cardano.intersectmbo.org plus a
12-
small fallback list of known IOG doc-site roots, and rewrites them to
13-
absolute URLs. Hrefs that don't resolve become annotated unclickable spans
14-
with tooltips. A follow-up GitHub Actions step opens or comments on a
15-
rolling tracking issue when the script reports actionable dead links on
16-
master, tagging the PR opener so the breakage lands on someone's board
17-
instead of going unnoticed.
7+
Fix broken cross-package Haddock links on the hosted documentation site. Links to dependency packages (cardano-ledger-*, plutus-*, cardano-base, etc.) were relative paths pointing to directories that don't exist on the site, resulting in 404s. A post-processing script now resolves each cross-package href via a name-suffix heuristic under *.cardano.intersectmbo.org plus a small fallback list of known IOG doc-site roots, and rewrites them to absolute URLs. Hrefs that don't resolve become annotated unclickable spans with tooltips. A follow-up GitHub Actions step opens or comments on a rolling tracking issue when the script reports actionable dead links on master, tagging the PR opener so the breakage lands on someone's board instead of going unnoticed.

.github/workflows/github-page.yml

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,19 @@ jobs:
188188
issue_number: existing.number,
189189
body: commentBody,
190190
});
191-
await github.rest.issues.addAssignees({
192-
owner: context.repo.owner,
193-
repo: context.repo.repo,
194-
issue_number: existing.number,
195-
assignees: [author],
196-
});
191+
try {
192+
await github.rest.issues.addAssignees({
193+
owner: context.repo.owner,
194+
repo: context.repo.repo,
195+
issue_number: existing.number,
196+
assignees: [author],
197+
});
198+
} catch (e) {
199+
// External contributors aren't repo collaborators, so the API
200+
// returns 422 here. Log and continue rather than crashing the
201+
// step — the comment was posted, which is the important part.
202+
console.log(`Could not assign @${author} to #${existing.number} (likely not a repo collaborator): ${e.message}`);
203+
}
197204
console.log(`Appended to existing issue #${existing.number}: ${existing.html_url}`);
198205
} else {
199206
// No open issue → create one. The body documents the fix
@@ -215,13 +222,25 @@ jobs:
215222
``,
216223
commentBody,
217224
].join('\n');
225+
// Create the issue without assignees first — passing assignees
226+
// to issues.create makes the whole call 422 for non-collaborator
227+
// authors. We assign separately so the issue always lands.
218228
const created = await github.rest.issues.create({
219229
owner: context.repo.owner,
220230
repo: context.repo.repo,
221231
title: titleText,
222232
body: issueBody,
223233
labels: [labelName],
224-
assignees: [author],
225234
});
235+
try {
236+
await github.rest.issues.addAssignees({
237+
owner: context.repo.owner,
238+
repo: context.repo.repo,
239+
issue_number: created.data.number,
240+
assignees: [author],
241+
});
242+
} catch (e) {
243+
console.log(`Could not assign @${author} to #${created.data.number} (likely not a repo collaborator): ${e.message}`);
244+
}
226245
console.log(`Opened tracking issue #${created.data.number}: ${created.data.html_url}`);
227246
}

scripts/fix-haddock-links.sh

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,15 @@ derive_name_candidates() {
165165
printf '%s\n' "https://${name}.cardano.intersectmbo.org"
166166
[[ "$name" == *-* ]] || break
167167
name="${name%-*}"
168+
[[ "$name" == *-* ]] || break
168169
done
169170
}
170171

171172
probe_site() {
172173
local code
173-
code=$(curl -sI -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 \
174+
code=$(curl -sI -o /dev/null -w "%{http_code}" \
175+
--connect-timeout 5 --max-time 10 \
176+
--retry 3 --retry-delay 2 --retry-all-errors \
174177
"${1}/${2}/doc-index.html" 2>/dev/null || echo "000")
175178
[[ "$code" == "200" || "$code" == "301" || "$code" == "302" || "$code" == "307" || "$code" == "308" ]]
176179
}
@@ -238,7 +241,8 @@ done
238241
# outage doesn't silently produce an empty index that masquerades as
239242
# "everything is non-CHaP".
240243
CHAP_PKGS_FILE=$(mktemp_tracked)
241-
if ! curl -sL --fail https://chap.intersectmbo.org/01-index.tar.gz \
244+
if ! curl -sL --fail --retry 3 --retry-delay 2 --retry-all-errors \
245+
https://chap.intersectmbo.org/01-index.tar.gz \
242246
| tar -tz | grep -oP '^[^/]+' | sort -u > "$CHAP_PKGS_FILE"; then
243247
echo "Error: failed to fetch CHaP package index from https://chap.intersectmbo.org/01-index.tar.gz" >&2
244248
exit 1
@@ -433,7 +437,7 @@ if [[ $reexport_total -gt 0 ]]; then
433437
# shellcheck disable=SC2016
434438
awk -F'\t' '{print $4}' "$REEXPORT_CANDIDATES" | sort -u | \
435439
xargs -P 16 -I{} sh -c \
436-
'code=$(curl -sI -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 "{}"); if [ "$code" = "200" ] || [ "$code" = "301" ] || [ "$code" = "302" ] || [ "$code" = "307" ] || [ "$code" = "308" ]; then echo "{}"; fi' \
440+
'code=$(curl -sI -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 --retry 3 --retry-delay 2 --retry-all-errors "{}"); if [ "$code" = "200" ] || [ "$code" = "301" ] || [ "$code" = "302" ] || [ "$code" = "307" ] || [ "$code" = "308" ]; then echo "{}"; fi' \
437441
> "$REEXPORT_VALID_FILE" 2>/dev/null
438442
fi
439443

@@ -502,7 +506,7 @@ url_count=$(wc -l < "$URLS_FILE")
502506
if [[ $url_count -gt 0 ]]; then
503507
# shellcheck disable=SC2016 # single quotes intentional: expansions evaluated by inner sh -c
504508
xargs -P 16 -I{} sh -c \
505-
'code=$(curl -sI -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 "{}"); if [ "$code" != "200" ] && [ "$code" != "301" ] && [ "$code" != "302" ] && [ "$code" != "307" ] && [ "$code" != "308" ]; then echo "{}"; fi' \
509+
'code=$(curl -sI -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 --retry 3 --retry-delay 2 --retry-all-errors "{}"); if [ "$code" != "200" ] && [ "$code" != "301" ] && [ "$code" != "302" ] && [ "$code" != "307" ] && [ "$code" != "308" ]; then echo "{}"; fi' \
506510
< "$URLS_FILE" > "$DEAD_URLS_FILE" 2>/dev/null
507511
fi
508512
dead_count=$(wc -l < "$DEAD_URLS_FILE" | tr -d ' ')
@@ -550,7 +554,7 @@ if [[ $dead_count -gt 0 ]]; then
550554
# shellcheck disable=SC2016
551555
awk -F'\t' '{print $2}' "$RESCUE_CANDIDATES" | sort -u | \
552556
xargs -P 16 -I{} sh -c \
553-
'code=$(curl -sI -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 "{}"); if [ "$code" = "200" ] || [ "$code" = "301" ] || [ "$code" = "302" ] || [ "$code" = "307" ] || [ "$code" = "308" ]; then echo "{}"; fi' \
557+
'code=$(curl -sI -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 --retry 3 --retry-delay 2 --retry-all-errors "{}"); if [ "$code" = "200" ] || [ "$code" = "301" ] || [ "$code" = "302" ] || [ "$code" = "307" ] || [ "$code" = "308" ]; then echo "{}"; fi' \
554558
> "$RESCUE_VALID_FILE" 2>/dev/null
555559
fi
556560

0 commit comments

Comments
 (0)