From 02ad9f09a0e906785fa833c68de56484f7ee1c45 Mon Sep 17 00:00:00 2001 From: Gregory Oschwald Date: Thu, 4 Jun 2026 19:36:07 +0000 Subject: [PATCH 1/2] Add lychee link checker config and CI workflow Adds a lychee configuration and a Links GitHub Actions workflow so that stale or redirecting links are caught automatically going forward. The checker runs on push, pull request, and weekly to catch external link rot. max_redirects is 0 so links that have moved are surfaced and can be updated to their canonical destination. The config is tuned for this Node/TypeScript repo: it scans Markdown, TypeScript sources, and package.json, and excludes generated output (node_modules, dist, build, coverage, docs) and the changelog. Part of STF-557. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/links.yml | 32 +++++++++++++++++++ .gitignore | 2 ++ lychee.toml | 62 +++++++++++++++++++++++++++++++++++++ mise.lock | 28 +++++++++++++++++ mise.toml | 5 +++ 5 files changed, 129 insertions(+) create mode 100644 .github/workflows/links.yml create mode 100644 lychee.toml diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml new file mode 100644 index 00000000..5e3255ba --- /dev/null +++ b/.github/workflows/links.yml @@ -0,0 +1,32 @@ +name: Links + +on: + push: + pull_request: + schedule: + - cron: "0 13 * * 1" # weekly, to catch external link rot without a commit + workflow_dispatch: + +permissions: + contents: read + +jobs: + linkChecker: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Setup mise + uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8 # v3.6.1 + with: + install: false + + # Install only lychee (not the repo's full toolchain) and run the check. + - name: Check links + env: + MISE_AUTO_INSTALL: "false" + run: | + mise install lychee + mise run check-links diff --git a/.gitignore b/.gitignore index 3876da99..64d73cda 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,5 @@ local # Claude config .claude + +.lycheecache diff --git a/lychee.toml b/lychee.toml new file mode 100644 index 00000000..c6070224 --- /dev/null +++ b/lychee.toml @@ -0,0 +1,62 @@ +# Lychee link checker configuration +# https://lychee.cli.rs/#/usage/config +# +# Run locally with: +# lychee './**/*.md' './src/**/*.ts' './package.json' + +# Include URL fragments in checks +include_fragments = true + +# Don't allow any redirects, so links that have moved are surfaced and updated +# to their canonical destination. +max_redirects = 0 + +# Accept these HTTP status codes +# 100-103: Informational responses +# 200-299: Success responses +# 403: Forbidden (some sites use this for rate limiting) +# 429: Too Many Requests +# 500-599: Server errors (temporary issues shouldn't fail CI) +# 999: LinkedIn's custom status code +accept = ["100..=103", "200..=299", "403", "429", "500..=599", "999"] + +# Exclude URL patterns from checking (treated as regular expressions) +exclude = [ + '^file://', + # Live / auth-gated endpoints that appear as string literals or require login + '^https://geoip\.maxmind\.com', + '^https://geolite\.info', + '^https://minfraud\.maxmind\.com', + '^https://sandbox\.maxmind\.com', + '^https://updates\.maxmind\.com', + '^https://www\.maxmind\.com/en/accounts/', + 'https://www\.maxmind\.com/en/account/login', + # package.json repository.url uses the canonical npm git clone URL + # (https://github.com/maxmind/GeoIP2-node.git); the ".git" form 301s to the + # web UI but is the correct packaging metadata, so it is not a "link" to fix. + '^https://github\.com/maxmind/GeoIP2-node\.git$', + # Placeholders / local + '^https?://example\.(com|org|net)', + '^http://localhost', + '127\.0\.0\.1', +] + +# Exclude file paths from getting checked (treated as regular expressions) +exclude_path = [ + '(^|/)node_modules/', + '(^|/)dist/', + '(^|/)build/', + '(^|/)coverage/', + # docs/ contains generated TypeDoc HTML (gitignored) + '(^|/)docs/', + '(^|/)\.git/', + # Changelog: historical entries are preserved as-is, not rewritten + '(^|/)CHANGELOG\.md$', +] + +# Cache results for 1 day to speed up repeated checks +cache = true +max_cache_age = "1d" + +# Skip missing input files instead of erroring +skip_missing = true diff --git a/mise.lock b/mise.lock index de597f28..f6e8c7f0 100644 --- a/mise.lock +++ b/mise.lock @@ -1,5 +1,33 @@ # @generated - this file is auto-generated by `mise lock` https://mise.jdx.dev/dev-tools/mise-lock.html +[[tools.lychee]] +version = "0.23.0" +backend = "aqua:lycheeverse/lychee" + +[tools.lychee."platforms.linux-arm64"] +checksum = "sha256:97eb93b02a7d78a752fc33e5b0983439ccaadbf3db952b68a0a4401acd92e6e0" +url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.23.0/lychee-aarch64-unknown-linux-gnu.tar.gz" + +[tools.lychee."platforms.linux-arm64-musl"] +checksum = "sha256:97eb93b02a7d78a752fc33e5b0983439ccaadbf3db952b68a0a4401acd92e6e0" +url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.23.0/lychee-aarch64-unknown-linux-gnu.tar.gz" + +[tools.lychee."platforms.linux-x64"] +checksum = "sha256:5538440d2c69a45a0a09983271e5dee0c2fe7137d8035d25b2632e10a66a090a" +url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.23.0/lychee-x86_64-unknown-linux-musl.tar.gz" + +[tools.lychee."platforms.linux-x64-musl"] +checksum = "sha256:5538440d2c69a45a0a09983271e5dee0c2fe7137d8035d25b2632e10a66a090a" +url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.23.0/lychee-x86_64-unknown-linux-musl.tar.gz" + +[tools.lychee."platforms.macos-arm64"] +checksum = "sha256:4c8034900e11083b68ac6f6582c377ff1f704e268991999e09d717973e493e7f" +url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.23.0/lychee-arm64-macos.dmg" + +[tools.lychee."platforms.windows-x64"] +checksum = "sha256:0fda7ff0a60c0250939fc25361c2d4e6e7853c31c996733fdd5a1dd760bcb824" +url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.23.0/lychee-x86_64-windows.exe" + [[tools.node]] version = "26.1.0" backend = "core:node" diff --git a/mise.toml b/mise.toml index 48e0bb7b..55928a7a 100644 --- a/mise.toml +++ b/mise.toml @@ -8,6 +8,7 @@ disable_backends = [ [tools] node = "latest" +lychee = "latest" [hooks] enter = "mise install --quiet --locked" @@ -15,3 +16,7 @@ enter = "mise install --quiet --locked" [[watch_files]] patterns = ["mise.toml", "mise.lock"] run = "mise install --quiet --locked" + +[tasks.check-links] +description = "Check links with lychee" +run = "lychee --no-progress './**/*.md' './src/**/*.ts' './package.json'" From b1147ca34451421ffedb01af7c1b33d3dc5fefeb Mon Sep 17 00:00:00 2001 From: Gregory Oschwald Date: Thu, 4 Jun 2026 19:36:07 +0000 Subject: [PATCH 2/2] Update stale and redirecting links Validated all links with lychee and updated those that redirected elsewhere to their canonical destinations: - dev.maxmind.com/geoip/docs/web-services -> .../web-services/ (trailing slash) - dev.maxmind.com/geoip/docs/databases -> .../databases/ (trailing slash) - support.maxmind.com/hc/en-us/requests/new -> support.maxmind.com/knowledge-base/submit-a-support-request - npmjs.com/package/@maxmind/geoip2-node -> www.npmjs.com/package/@maxmind/geoip2-node The package.json repository.url (github.com/...GeoIP2-node.git) 301s to the web UI but is the canonical npm git clone URL, so it is left unchanged and excluded in lychee.toml instead. Historical CHANGELOG.md entries are intentionally left unchanged. Part of STF-557. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/ISSUE_TEMPLATE/question.md | 4 ++-- CLAUDE.md | 2 +- README.dev.md | 2 +- README.md | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index b9e78716..d9a8adc1 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -1,7 +1,7 @@ --- name: Question -about: 'Please use Stack Overflow for questions #geoip2-node.' +about: 'Please use Stack Overflow for questions #maxmind.' --- -For _how-to_ questions and other non-bugs, please use StackOverflow instead of Github issues. You can tag your questions with [geoip2-node](https://stackoverflow.com/questions/tagged/geoip2-node). +For _how-to_ questions and other non-bugs, please use StackOverflow instead of Github issues. You can tag your questions with [maxmind](https://stackoverflow.com/questions/tagged/maxmind). diff --git a/CLAUDE.md b/CLAUDE.md index 4a5ff47c..a31cfeba 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -336,7 +336,7 @@ Refer to the GeoIP2-php implementation for guidance on new features (especially ## Additional Resources - [API Documentation](https://maxmind.github.io/GeoIP2-node/) -- [GeoIP Web Services Docs](https://dev.maxmind.com/geoip/docs/web-services) +- [GeoIP Web Services Docs](https://dev.maxmind.com/geoip/docs/web-services/) - [MaxMind DB Format](https://maxmind.github.io/MaxMind-DB/) - [node-maxmind library](https://github.com/runk/node-maxmind) - GitHub Issues: https://github.com/maxmind/GeoIP2-node/issues diff --git a/README.dev.md b/README.dev.md index 1ce940e9..2776f773 100644 --- a/README.dev.md +++ b/README.dev.md @@ -15,7 +15,7 @@ - Commit changes and push - Create a GitHub release (which triggers the npm publish workflow) 6. Merge the release PR after the workflow succeeds. -7. Verify the release on [npm](https://npmjs.com/package/@maxmind/geoip2-node). +7. Verify the release on [npm](https://www.npmjs.com/package/@maxmind/geoip2-node). Note: Publishing is done via GitHub Actions using npm Trusted Publishing (OIDC). Manual `npm publish` is not supported. diff --git a/README.md b/README.md index 38b49c6b..0f7263d0 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ ## Description This package provides a server-side API for the [GeoIP databases and GeoLite -databases](https://dev.maxmind.com/geoip/docs/databases), and a server-side +databases](https://dev.maxmind.com/geoip/docs/databases/), and a server-side API for the [GeoIP web services and GeoLite web -services](https://dev.maxmind.com/geoip/docs/web-services). +services](https://dev.maxmind.com/geoip/docs/web-services/). **This package will not work client-side.** @@ -410,7 +410,7 @@ data set, it will be automatically incorporated into future MaxMind releases. If you are a paying MaxMind customer and you're not sure where to submit a -correction, please [contact MaxMind support for help](https://support.maxmind.com/hc/en-us/requests/new). +correction, please [contact MaxMind support for help](https://support.maxmind.com/knowledge-base/submit-a-support-request). ## Requirements @@ -432,7 +432,7 @@ Please report all issues with this code using the [GitHub issue tracker](https://github.com/maxmind/GeoIP2-node/issues) If you are having an issue with a MaxMind service that is not specific to the -client API, please contact [MaxMind support for assistance](https://support.maxmind.com/hc/en-us/requests/new). +client API, please contact [MaxMind support for assistance](https://support.maxmind.com/knowledge-base/submit-a-support-request). ## Copyright and License