From 9337f38dc6b03fe2eadabdc8d135195c1bd83abf Mon Sep 17 00:00:00 2001 From: Marc LeBlanc <7050295+marcleblanc2@users.noreply.github.com> Date: Thu, 24 Sep 2026 21:44:09 -0600 Subject: [PATCH 1/7] ci/hostnames: Add example hostnames PR check Advisory check that flags placeholder hostnames on lines a PR adds that are not the recommended *.example.com ones, and suggests the replacement as a one-click review comment. dev/example-hostnames.json maps each recommended hostname to the placeholders #1932 replaced with it; bare fake company domains match as a hostname tail so the subdomain carries over. Amp-Thread-ID: https://ampcode.com/threads/T-01a0d69d-e558-73b8-99b1-e238a0588c49 Co-authored-by: Amp --- .github/workflows/check-hostnames.yml | 95 ++++++++ AGENTS.md | 19 +- cspell.json | 1 + dev/TODO.md | 11 + dev/check-hostnames.mjs | 322 ++++++++++++++++++++++++++ dev/example-hostnames.json | 73 ++++++ 6 files changed, 516 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/check-hostnames.yml create mode 100644 dev/check-hostnames.mjs create mode 100644 dev/example-hostnames.json diff --git a/.github/workflows/check-hostnames.yml b/.github/workflows/check-hostnames.yml new file mode 100644 index 000000000..c5cadb1a6 --- /dev/null +++ b/.github/workflows/check-hostnames.yml @@ -0,0 +1,95 @@ +name: Example hostnames + +# Reports placeholder hostnames on lines added by a pull request that are not +# the recommended ones (dev/example-hostnames.json), as a summary comment plus +# an inline suggested change on each flagged line. Advisory: never fails the PR. + +on: + pull_request: + +# A new push supersedes the run for the previous one +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: write + +jobs: + check-hostnames: + name: Example hostnames (advisory) + runs-on: ubuntu-latest + steps: + - name: Check out pull request head + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: Find placeholder hostnames added by this PR + id: check + env: + BASE_SHA: ${{ github.event.pull_request.base.sha }} + # File links in the report open the file on the PR branch + LINK_BASE: ${{ github.event.pull_request.head.repo.html_url }}/blob/${{ github.event.pull_request.head.ref }} + # The script exits 1 both with findings and when it crashes. It writes + # its output in one go at the end, so a crash leaves it empty. The + # comment step reports a crash instead of posting the empty report. + run: | + git diff -U0 "$(git merge-base "$BASE_SHA" HEAD)" HEAD -- docs > "$RUNNER_TEMP/changes.diff" + if node dev/check-hostnames.mjs --format markdown \ + --diff "$RUNNER_TEMP/changes.diff" \ + --review "$RUNNER_TEMP/review.json" \ + --link-base "$LINK_BASE" > "$RUNNER_TEMP/report.md"; then + echo "result=clean" >> "$GITHUB_OUTPUT" + elif [ -s "$RUNNER_TEMP/report.md" ]; then + echo "result=found" >> "$GITHUB_OUTPUT" + else + echo "::warning::check-hostnames crashed, so this PR was not checked" + echo "result=crashed" >> "$GITHUB_OUTPUT" + fi + cat "$RUNNER_TEMP/report.md" + + - name: Comment on the pull request + # Fork PRs get a read-only token; the report is still in the job log + if: github.event.pull_request.head.repo.full_name == github.repository + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} + RESULT: ${{ steps.check.outputs.result }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run: | + marker='' + existing_comment=$(gh api "repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" \ + --paginate --jq ".[] | select(.body | startswith(\"$marker\")) | .id" | head -n 1) + + # Comment when there is something to report, or an earlier report to resolve + case "$RESULT" in + found) + { echo "$marker"; cat "$RUNNER_TEMP/report.md"; } > "$RUNNER_TEMP/comment.md" ;; + crashed) + printf '%s\n### ⚠️ The example hostnames check could not run on this revision\n\nThis is a problem with the check, not with this PR; see the [job log](%s).\n' \ + "$marker" "$RUN_URL" > "$RUNNER_TEMP/comment.md" ;; + *) + [ -n "$existing_comment" ] || exit 0 + { echo "$marker"; cat "$RUNNER_TEMP/report.md"; } > "$RUNNER_TEMP/comment.md" ;; + esac + + if [ -n "$existing_comment" ]; then + gh api --method PATCH "repos/$GITHUB_REPOSITORY/issues/comments/$existing_comment" \ + --field body=@"$RUNNER_TEMP/comment.md" + else + gh pr comment "$PR_NUMBER" --body-file "$RUNNER_TEMP/comment.md" + fi + + - name: Suggest fixes as review comments + # One suggested change per flagged line, kept in sync with the + # findings; see dev/sync-review-comments.sh + if: >- + github.event.pull_request.head.repo.full_name == github.repository + && contains(fromJSON('["clean", "found"]'), steps.check.outputs.result) + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: dev/sync-review-comments.sh '`, + ...[...replacements].map( + ([placeholder, recommended]) => + `Placeholder: \`${placeholder}\`, use \`${recommended}\`` + ), + // A four-backtick fence so lines containing ``` cannot break out + '````suggestion', + fixed, + '````' + ]; + comments.push({path: file, line, side: 'RIGHT', body: body.join('\n')}); + } + return {event: 'COMMENT', body: '', comments}; +} + +const FORMATTERS = { + text: formatText, + json: findings => JSON.stringify(findings, null, '\t') + '\n', + markdown: formatMarkdown +}; + +function main() { + const format = FORMATTERS[FORMAT]; + if (!format) { + throw new Error( + `Unknown --format "${FORMAT}"; use text, json, or markdown` + ); + } + const {findings, fixedLines} = findPlaceholders(); + if (REVIEW_FILE) { + fs.writeFileSync( + REVIEW_FILE, + JSON.stringify(reviewRequest(findings, fixedLines), null, '\t') + + '\n' + ); + } + process.stdout.write(format(findings)); + process.exit(findings.length === 0 ? 0 : 1); +} + +main(); diff --git a/dev/example-hostnames.json b/dev/example-hostnames.json new file mode 100644 index 000000000..0f25a31c9 --- /dev/null +++ b/dev/example-hostnames.json @@ -0,0 +1,73 @@ +{ + "$comment": "Recommended placeholder hostname → placeholders the docs used instead; read by dev/check-hostnames.mjs, see its header for how entries match", + "sourcegraph.example.com": [ + "your-sourcegraph-instance.com", + "your_sourcegraph_instance.com", + "example-sourcegraph.com", + "example.sourcegraph.com", + "test.sourcegraph.com", + "myinstance.sourcegraph.com", + "yourinstance.sourcegraph.com", + "yourdomain.sourcegraph.com", + "sourcegraph.test:3443", + "sourcegraph.test", + "src.acme.com", + "cse-k8s.sgdev.org", + "domain.example.com", + "YOUR-SOURCEGRAPH-INSTANCE", + "", + "", + "", + "$HOSTNAME_OR_IP" + ], + "https://sourcegraph.example.com": [ + "", + "", + "", + "$your_sourcegraph_url", + "YOUR_SOURCEGRAPH_URL", + "$SOURCEGRAPH_BASE_URL", + "${YOUR_URL}" + ], + "bitbucket.example.com": [ + "my-bitbucket.example.com", + "bitbucketserver.example.com", + "your-bbs-instance.example.com", + "[your-bitbucket-hostname]" + ], + "github.example.com": [ + "github-enterprise.example.com", + "", + "nonexistenturl.com" + ], + "gitlab.example.com": ["my-gitlab.example.com", "$GITLAB_HOSTNAME"], + "phabricator.example.com": ["my-phabricator.example.com"], + "gerrit.example.com": ["example.gerrit.com"], + "smtp.example.com": ["smtp-server.example.com"], + "registry.example.com": [ + "myregistry.example.com", + "myregistry.company.com", + "your.private.registry.com", + "my.company" + ], + "registry2.example.com": ["myregistry2.example.com"], + "oauth.example.com": ["your-app.com"], + "example.openai.azure.com": ["acme-test.openai.azure.com"], + "example.okta.com": [".okta.com"], + "example.onelogin.com": ["mycompany.onelogin.com"], + "example.sourcegraphcloud.com": ["acme.sourcegraphcloud.com"], + "example.com": [ + "mycompany.com", + "mycompany.org", + "yourcompany.com", + "company.com", + "company.io", + "company.net", + "internal.corp", + "acme.com", + "your-domain.com", + "yourdomain.com", + "your_instance_name.com", + "sgdev.org" + ] +} From e62f72f5bc1b81dcdebf9b8072ff3968918bbc51 Mon Sep 17 00:00:00 2001 From: Marc LeBlanc <7050295+marcleblanc2@users.noreply.github.com> Date: Fri, 2 Oct 2026 12:31:48 -0600 Subject: [PATCH 2/7] ci/hostnames: Match glob and regex entries, run only on docs changes Mapping entries can be literal text, a glob where `*` matches a run of hostname characters, or a `/regex/`. Matching ignores case, and `-`, `_`, and `.` in literal and glob entries match any of the three, so one entry covers the spelling variants the docs used. The JSON is 2-space indented with keys and lists sorted, and the duplicated literals are folded into glob and regex entries, including the patterns from #1933. The workflow runs only when a PR touches docs/ or the check itself. Amp-Thread-ID: https://ampcode.com/threads/T-01a0fdce-6d4c-708e-a1ac-c5a8f9e48a65 Co-authored-by: Amp --- .github/workflows/check-hostnames.yml | 6 ++ AGENTS.md | 6 +- dev/check-hostnames.mjs | 130 ++++++++++++++--------- dev/example-hostnames.json | 146 +++++++++++++------------- 4 files changed, 166 insertions(+), 122 deletions(-) diff --git a/.github/workflows/check-hostnames.yml b/.github/workflows/check-hostnames.yml index c5cadb1a6..ff1ff8b43 100644 --- a/.github/workflows/check-hostnames.yml +++ b/.github/workflows/check-hostnames.yml @@ -6,6 +6,12 @@ name: Example hostnames on: pull_request: + paths: + - 'docs/**' + - 'dev/check-hostnames.mjs' + - 'dev/example-hostnames.json' + - 'dev/sync-review-comments.sh' + - '.github/workflows/check-hostnames.yml' # A new push supersedes the run for the previous one concurrency: diff --git a/AGENTS.md b/AGENTS.md index f8d970314..1f784a6ff 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -46,8 +46,10 @@ meant). `.github/workflows/check-hostnames.yml` runs `dev/check-hostnames.mjs` on the lines a PR adds and comments the findings with suggested changes (advisory, never fails the PR). `dev/example-hostnames.json` maps each - recommended hostname to the placeholders seen in its place; add to it when - the check misses one. `node dev/check-hostnames.mjs` checks all of `docs/` + recommended hostname to the placeholders seen in its place, as literal text, + a `*` glob, or a `/regex/`, matched case-insensitively with `-`, `_`, and + `.` interchangeable; add to it when the check misses one, keeping keys and + lists sorted. `node dev/check-hostnames.mjs` checks all of `docs/` ### Links diff --git a/dev/check-hostnames.mjs b/dev/check-hostnames.mjs index 00309ee30..2f7e8a043 100644 --- a/dev/check-hostnames.mjs +++ b/dev/check-hostnames.mjs @@ -8,13 +8,18 @@ * comments the findings; it never fails the PR. * * dev/example-hostnames.json maps each recommended hostname to the - * placeholders seen in its place. An entry matches as a whole hostname, or as - * the tail of one: `mycompany.com` under `example.com` turns - * `prometheus.mycompany.com` into `prometheus.example.com`. The longest entry - * wins where several match. A recommended value with a scheme, like - * `https://sourcegraph.example.com`, is for placeholders that stand for a whole - * URL; the scheme is dropped where the text already has one. Auto-generated - * SCHEMA_SYNC blocks are skipped: fix those upstream. + * placeholders seen in its place. An entry is literal text, a glob where `*` + * matches any run of hostname characters other than `.`, or a regular + * expression written `/.../` (escape backslashes for JSON: `\\.`). Matching + * ignores case, and in literal and glob entries each of `-`, `_`, and `.` + * matches any of the three, so `your-domain.com` also covers + * `your_domain.com`. An entry matches as a whole hostname, or as the tail of + * one: `mycompany.com` under `example.com` turns `prometheus.mycompany.com` + * into `prometheus.example.com`. The longest entry wins where several match. A + * recommended value with a scheme, like `https://sourcegraph.example.com`, is + * for placeholders that stand for a whole URL; the scheme is dropped where the + * text already has one. Auto-generated SCHEMA_SYNC blocks are skipped: fix + * those upstream. * * Usage: node dev/check-hostnames.mjs [options] * --diff Unified diff, e.g. from `git diff -U0 origin/main`; @@ -79,40 +84,66 @@ function parseDiff(file) { return addedLines; } -// {placeholder → recommended}, and one regex matching any placeholder as a -// whole hostname or the tail of one. Alternatives are tried in order, so the -// longest placeholder wins where several match; the tail prefix is lazy, so a -// placeholder that includes the subdomain wins over one that does not. +// In a literal or glob entry, each separator matches any separator. Space is +// not one: `YOUR-SOURCEGRAPH-INSTANCE` must not match the prose "your +// Sourcegraph instance" +const SEPARATOR = '[-_.]'; + +// Regex source for one mapping entry: a `/.../` entry as written, anything +// else as literal text where `*` matches any run of hostname characters +// other than `.` +function entryPattern(entry) { + const regex = entry.match(/^\/(.+)\/$/); + if (regex) return regex[1]; + return entry + .split('*') + .map(part => + part + .replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + .replace(/\\\.|[-_]/g, SEPARATOR) + ) + .join('[\\w-]*'); +} + +// [{recommended, exact}] with `exact` matching a whole placeholder, longest +// entry first, and one regex matching any placeholder as a whole hostname or +// the tail of one. Alternatives are tried in order, so the longest entry wins +// where several match; the tail prefix is lazy, so an entry that includes the +// subdomain wins over one that does not. function loadMapping() { const mapping = JSON.parse( fs.readFileSync(path.join(ROOT_DIR, MAPPING_FILE), 'utf-8') ); - const recommendedFor = new Map(); - for (const [recommended, placeholders] of Object.entries(mapping)) { - if (recommended === '$comment') continue; - for (const placeholder of placeholders) { - recommendedFor.set(placeholder, recommended); - } - } - const alternatives = [...recommendedFor.keys()] - .sort((a, b) => b.length - a.length) - .map(placeholder => placeholder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')) - .join('|'); + const entries = Object.entries(mapping) + .filter(([recommended]) => recommended !== '$comment') + .flatMap(([recommended, placeholders]) => + placeholders.map(placeholder => ({recommended, placeholder})) + ) + .sort((a, b) => b.placeholder.length - a.placeholder.length) + .map(({recommended, placeholder}) => { + const source = entryPattern(placeholder); + return { + recommended, + source, + exact: new RegExp(`^(?:${source})$`, 'i') + }; + }); + const alternatives = entries.map(entry => `(?:${entry.source})`).join('|'); const pattern = new RegExp( - `(?(?:[\\w*-]+\\.)*?)(?${alternatives})(?![\\w-]|\\.\\w)`, + 'gi' ); - return {recommendedFor, pattern}; + return {entries, pattern}; } -const {recommendedFor, pattern} = loadMapping(); +const {entries, pattern} = loadMapping(); // The recommended text for a match: the subdomains the text had in front of // the placeholder are kept, and the scheme is left out where the text has one function replacement(prefix, placeholder, precededByScheme) { - const [, scheme = '', host] = recommendedFor - .get(placeholder) - .match(/^(\w+:\/\/)?(.*)$/); + const [, scheme = '', host] = entries + .find(entry => entry.exact.test(placeholder)) + .recommended.match(/^(\w+:\/\/)?(.*)$/); return (precededByScheme ? '' : scheme) + prefix + host; } @@ -121,26 +152,27 @@ function replacement(prefix, placeholder, precededByScheme) { // included, and `fixed` is the line with every placeholder replaced function checkLine(file, line, text) { const findings = []; - const fixed = text.replace( - pattern, - (match, prefix, placeholder, offset, whole) => { - const recommended = replacement( - prefix, - placeholder, - /:\/\/$/.test(whole.slice(0, offset)) - ); - findings.push({ - file, - line, - column: offset + 1, - placeholder: match, - recommended, - text - }); - return recommended; - } - ); - return {findings, fixed}; + let fixed = ''; + let end = 0; + for (const match of text.matchAll(pattern)) { + const {prefix, placeholder} = match.groups; + const recommended = replacement( + prefix, + placeholder, + /:\/\/$/.test(text.slice(0, match.index)) + ); + findings.push({ + file, + line, + column: match.index + 1, + placeholder: match[0], + recommended, + text + }); + fixed += text.slice(end, match.index) + recommended; + end = match.index + match[0].length; + } + return {findings, fixed: fixed + text.slice(end)}; } // Sorted relative paths of the .md and .mdx files under docs/ diff --git a/dev/example-hostnames.json b/dev/example-hostnames.json index 0f25a31c9..304ff906d 100644 --- a/dev/example-hostnames.json +++ b/dev/example-hostnames.json @@ -1,73 +1,77 @@ { - "$comment": "Recommended placeholder hostname → placeholders the docs used instead; read by dev/check-hostnames.mjs, see its header for how entries match", - "sourcegraph.example.com": [ - "your-sourcegraph-instance.com", - "your_sourcegraph_instance.com", - "example-sourcegraph.com", - "example.sourcegraph.com", - "test.sourcegraph.com", - "myinstance.sourcegraph.com", - "yourinstance.sourcegraph.com", - "yourdomain.sourcegraph.com", - "sourcegraph.test:3443", - "sourcegraph.test", - "src.acme.com", - "cse-k8s.sgdev.org", - "domain.example.com", - "YOUR-SOURCEGRAPH-INSTANCE", - "", - "", - "", - "$HOSTNAME_OR_IP" - ], - "https://sourcegraph.example.com": [ - "", - "", - "", - "$your_sourcegraph_url", - "YOUR_SOURCEGRAPH_URL", - "$SOURCEGRAPH_BASE_URL", - "${YOUR_URL}" - ], - "bitbucket.example.com": [ - "my-bitbucket.example.com", - "bitbucketserver.example.com", - "your-bbs-instance.example.com", - "[your-bitbucket-hostname]" - ], - "github.example.com": [ - "github-enterprise.example.com", - "", - "nonexistenturl.com" - ], - "gitlab.example.com": ["my-gitlab.example.com", "$GITLAB_HOSTNAME"], - "phabricator.example.com": ["my-phabricator.example.com"], - "gerrit.example.com": ["example.gerrit.com"], - "smtp.example.com": ["smtp-server.example.com"], - "registry.example.com": [ - "myregistry.example.com", - "myregistry.company.com", - "your.private.registry.com", - "my.company" - ], - "registry2.example.com": ["myregistry2.example.com"], - "oauth.example.com": ["your-app.com"], - "example.openai.azure.com": ["acme-test.openai.azure.com"], - "example.okta.com": [".okta.com"], - "example.onelogin.com": ["mycompany.onelogin.com"], - "example.sourcegraphcloud.com": ["acme.sourcegraphcloud.com"], - "example.com": [ - "mycompany.com", - "mycompany.org", - "yourcompany.com", - "company.com", - "company.io", - "company.net", - "internal.corp", - "acme.com", - "your-domain.com", - "yourdomain.com", - "your_instance_name.com", - "sgdev.org" - ] + "$comment": "Recommended placeholder hostname → placeholders the docs used instead, as literal text, a glob (`*`), or a regular expression (`/.../`); read by dev/check-hostnames.mjs, see its header for how entries match", + "bitbucket.example.com": [ + "[your-bitbucket-hostname]", + "bitbucketserver.example.com", + "my-bitbucket.example.com", + "your-bbs-instance.example.com" + ], + "example.com": [ + "/(?:my|your|our)?company\\.(?:com|io|net|org)/", + "acme.com", + "internal.corp", + "sgdev.org", + "your*domain.com", + "your_instance_name.com" + ], + "example.okta.com": [ + ".okta.com" + ], + "example.onelogin.com": [ + "mycompany.onelogin.com" + ], + "example.openai.azure.com": [ + "acme-test.openai.azure.com" + ], + "example.sourcegraphcloud.com": [ + "acme.sourcegraphcloud.com" + ], + "gerrit.example.com": [ + "example.gerrit.com" + ], + "github.example.com": [ + "", + "github-enterprise.example.com" + ], + "gitlab.example.com": [ + "$GITLAB_HOSTNAME", + "my-gitlab.example.com" + ], + "https://sourcegraph.example.com": [ + "$SOURCEGRAPH_BASE_URL", + "$your_sourcegraph_url", + "${YOUR_URL}", + "", + "", + "", + "YOUR_SOURCEGRAPH_URL" + ], + "oauth.example.com": [ + "oauth.your-app.com" + ], + "phabricator.example.com": [ + "my-phabricator.example.com" + ], + "registry.example.com": [ + "myregistry.*.com", + "your.private.registry.com" + ], + "registry2.example.com": [ + "myregistry2.example.com" + ], + "smtp.example.com": [ + "smtp-server.example.com" + ], + "sourcegraph.example.com": [ + "$HOSTNAME_OR_IP", + "/(?:example|test|my\\w*|your\\w*)[-.]sourcegraph\\.com/", + "/(?:your|my|our)[-_]?sourcegraph[-\\w]*\\.(?:com|io|net|org|dev)/", + "/sourcegraph\\.test(?::\\d+)?/", + "", + "", + "YOUR-SOURCEGRAPH-INSTANCE", + "cse-k8s.sgdev.org", + "domain.example.com", + "src.acme.com" + ] } From 64b91d260411e2ff90e9cea2fae0c574241e21a6 Mon Sep 17 00:00:00 2001 From: Marc LeBlanc <7050295+marcleblanc2@users.noreply.github.com> Date: Fri, 2 Oct 2026 13:17:58 -0600 Subject: [PATCH 3/7] ci/hostnames: Add the wrapped placeholders still on main , , , $SOURCEGRAPH_ORIGIN, [hostname], , : the spellings that docs/ still uses in prose and config samples where a hostname is meant. Amp-Thread-ID: https://ampcode.com/threads/T-01a0fdce-6d4c-708e-a1ac-c5a8f9e48a65 Co-authored-by: Amp --- dev/example-hostnames.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dev/example-hostnames.json b/dev/example-hostnames.json index 304ff906d..d70570ebe 100644 --- a/dev/example-hostnames.json +++ b/dev/example-hostnames.json @@ -8,6 +8,7 @@ ], "example.com": [ "/(?:my|your|our)?company\\.(?:com|io|net|org)/", + "", "acme.com", "internal.corp", "sgdev.org", @@ -31,6 +32,7 @@ ], "github.example.com": [ "", + "", "github-enterprise.example.com" ], "gitlab.example.com": [ @@ -39,10 +41,14 @@ ], "https://sourcegraph.example.com": [ "$SOURCEGRAPH_BASE_URL", + "$SOURCEGRAPH_ORIGIN", "$your_sourcegraph_url", "${YOUR_URL}", "", + "", "", + "", + "", "", "YOUR_SOURCEGRAPH_URL" ], @@ -70,6 +76,7 @@ "", "", "YOUR-SOURCEGRAPH-INSTANCE", + "[hostname]", "cse-k8s.sgdev.org", "domain.example.com", "src.acme.com" From 3c1e4eade5cb41287754da99d54e6b772fa64aac Mon Sep 17 00:00:00 2001 From: Marc LeBlanc <7050295+marcleblanc2@users.noreply.github.com> Date: Fri, 2 Oct 2026 13:41:44 -0600 Subject: [PATCH 4/7] ci/hostnames: Add your.jaeger.endpoint Amp-Thread-ID: https://ampcode.com/threads/T-01a0fdce-6d4c-708e-a1ac-c5a8f9e48a65 Co-authored-by: Amp --- dev/example-hostnames.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev/example-hostnames.json b/dev/example-hostnames.json index d70570ebe..804af8308 100644 --- a/dev/example-hostnames.json +++ b/dev/example-hostnames.json @@ -52,6 +52,9 @@ "", "YOUR_SOURCEGRAPH_URL" ], + "jaeger.example.com": [ + "your.jaeger.endpoint" + ], "oauth.example.com": [ "oauth.your-app.com" ], From 86c53d0479840a0c5efedfaa059b45f0ca03e478 Mon Sep 17 00:00:00 2001 From: Marc LeBlanc <7050295+marcleblanc2@users.noreply.github.com> Date: Fri, 2 Oct 2026 14:17:43 -0600 Subject: [PATCH 5/7] dev: Delete dev/TODO.md Amp-Thread-ID: https://ampcode.com/threads/T-01a0fdce-6d4c-708e-a1ac-c5a8f9e48a65 Co-authored-by: Amp --- dev/TODO.md | 81 -------------------------------------- dev/vercel-ignore-build.sh | 1 - 2 files changed, 82 deletions(-) delete mode 100644 dev/TODO.md diff --git a/dev/TODO.md b/dev/TODO.md deleted file mode 100644 index fd9abf20e..000000000 --- a/dev/TODO.md +++ /dev/null @@ -1,81 +0,0 @@ -# TODO - -One PR per task; delete a task when its PR merges. - -## Site - -- Rewrite `src/components/search/docsearch/` (vendored Algolia DocSearch) so the - React Compiler ESLint rules `react-hooks/refs`, `react-hooks/set-state-in-effect` - and `react-hooks/static-components` can go back to `error` in `eslint.config.mjs` - (31 of the 39 warnings from `pnpm run lint` are in that directory) -- Move `pnpm run dev` from webpack to Turbopack, like `pnpm run build`. The only - thing keeping it on webpack is the `next-contentlayer2` plugin, which - regenerates `.contentlayer` when an `.mdx` file changes; Turbopack has no - plugin hook for that. Needs a way to start contentlayer's watcher - (`contentlayer2 dev`) automatically when `next dev` starts, then the plugin - and the `PHASE_DEVELOPMENT_SERVER` branch in `next.config.js` can go -- Faster Vercel static generation: the 505 `/api/og` images are ~40% of the - "Generating static pages" time (locally 6.6s with them, 3.6s without). - Options: hoist the font and logo reads in `src/app/api/og/[...path]/route.tsx` - to module scope, or render one image per top-level section instead of per page -- `pnpm-lock.yaml` pins two `caniuse-lite` versions (`1.0.30001769` and - `1.0.30001810`); dedupe to the newer one so `next build` stops warning that - Browserslist data is stale. #1909 was closed unmerged - -## PR checks - -- Four scripts each parse `git diff -U0` for added lines: `addedLineRanges` - in `dev/check-spelling.mjs`, `parseDiff` in `dev/check-links.mjs` and - `dev/check-hostnames.mjs`, `addedLines` in `dev/check-redirects.mjs`. Move - one into a dependency-free `dev/diff.mjs` and import it from all four -- `check-links.yml`, `check-redirects.yml`, and `check-hostnames.yml` carry the - same "Comment on the pull request" shell step (find the marker comment, - PATCH or create it). Move it to a `dev/` script next to - `sync-review-comments.sh` - -## Docs site audit leftovers - -Findings from the crawl of all 502 pages -() -with no PR yet. Fixes with PRs: #1998–#2004. - -- Every page has the same `` - (`src/app/layout.tsx`); `generateMetadata` in `src/app/[...slug]/page.tsx` - never sets one. Derive it from the first paragraph. -- Duplicate ``s: the title is the first heading only, so 4 pages are - "How-to guides", 3 "FAQs", 3 "How-tos", … Suffix with the parent section. -- `src/app/sitemap.ts`: the last-modified time is the build time for every - page, and both `/docs` and `/docs/` are listed. -- `docs/self-hosted/postgresql-collation-version-mismatch-resolution.mdx` - renders 13 `<h1>`s; demote all but the first. -- Code-comment color in `src/styles/shades-of-purple.json` is `#B362FF` on - `#2d2b55` (3.84:1, below WCAG AA); the rest of the contrast findings landed - in #1995. -- `/admin/config/site-config#<key>` anchors (19 inbound links) do not exist: - the schema is rendered as one JSON code block with no per-key ids. Deferred - by #1925. -- `/self-hosted/observability/dashboards` is generated from the - sourcegraph/sourcegraph sync (#1971) and is a giant page; fix upstream. - -## Cloudflare (needs a Cloudflare admin) - -`sourcegraph.com/docs/docs/_next/...` 404s are bingbot following the -`docs.sourcegraph.com/<page>` **302** and resolving the page's -`/docs/_next/...` asset URLs against the old host. Verified 2026-09-25: -`docs.sourcegraph.com/<page>` → 302 `sourcegraph.com/docs/<page>`, and -`docs.sourcegraph.com/docs/<page>` → 302 `sourcegraph.com/docs/docs/<page>`. - -- Make the `docs.sourcegraph.com` redirect a 301. -- Redirect `docs.sourcegraph.com/docs/*` to `sourcegraph.com/docs/$1` without - doubling the prefix. - -## GitHub repo settings (needs an org admin) - -- Add required status checks to the `main` ruleset: the link check and the - Vercel build. Today "Broken links introduced by this PR" and "CSpell - (advisory)" can be red and the PR still merges. -- Restrict the ruleset's `allowed_merge_methods` to `squash`; it still lists - `merge` and `rebase`, so only the repo-level setting enforces squash. -- Turn off Projects (`has_projects`); Issues are already off. -- Add `CODEOWNERS` and `.github/dependabot.yml`; confirm Actions permissions - and Dependabot alerts are on (not readable without admin). diff --git a/dev/vercel-ignore-build.sh b/dev/vercel-ignore-build.sh index 6eaaef00e..ad4d791b9 100755 --- a/dev/vercel-ignore-build.sh +++ b/dev/vercel-ignore-build.sh @@ -12,7 +12,6 @@ exec git diff --quiet HEAD^ HEAD -- . \ ':(exclude)README.md' \ ':(exclude).gitignore' \ ':(exclude)cspell*' \ - ':(exclude)dev/TODO.md' \ ':(exclude)dev/check-spelling.mjs' \ ':(exclude)dev/post-spelling-review.mjs' \ ':(exclude)dev/report-vercel-build.mjs' \ From d09caac6d7a09c0808f7c9b67455a5c21dd479ee Mon Sep 17 00:00:00 2001 From: Marc <7050295+marcleblanc2@users.noreply.github.com> Date: Fri, 2 Oct 2026 14:18:22 -0600 Subject: [PATCH 6/7] Remove comment from cspell.json entry --- cspell.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cspell.json b/cspell.json index c1e20d6eb..0b4e0bf08 100644 --- a/cspell.json +++ b/cspell.json @@ -24,7 +24,7 @@ "cspell.json", "cspell-allow-list.txt", "cspell-block-list.txt", - "dev/example-hostnames.json", // placeholders the docs must not use + "dev/example-hostnames.json", "pnpm-lock.yaml", "docs/self-hosted/observability/alerts.mdx", "docs/self-hosted/observability/dashboards.mdx", From 9397c01761faa8ad5a9e502dca777e0d7cee58ce Mon Sep 17 00:00:00 2001 From: Marc <7050295+marcleblanc2@users.noreply.github.com> Date: Fri, 2 Oct 2026 15:10:45 -0600 Subject: [PATCH 7/7] Rename workflow from 'Example hostnames' to 'Check example hostnames' --- .github/workflows/check-hostnames.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-hostnames.yml b/.github/workflows/check-hostnames.yml index ff1ff8b43..636357604 100644 --- a/.github/workflows/check-hostnames.yml +++ b/.github/workflows/check-hostnames.yml @@ -1,4 +1,4 @@ -name: Example hostnames +name: Check example hostnames # Reports placeholder hostnames on lines added by a pull request that are not # the recommended ones (dev/example-hostnames.json), as a summary comment plus @@ -24,7 +24,7 @@ permissions: jobs: check-hostnames: - name: Example hostnames (advisory) + name: Check example hostnames runs-on: ubuntu-latest steps: - name: Check out pull request head