From 9e4a293430c221af496bb84e79615043f031da92 Mon Sep 17 00:00:00 2001 From: Gregory Oschwald Date: Thu, 4 Jun 2026 20:40:02 +0000 Subject: [PATCH 1/2] Add lychee link checker config and CI workflow Part of STF-557. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/links.yml | 32 ++++++++++++++++++ .gitignore | 1 + lychee.toml | 67 +++++++++++++++++++++++++++++++++++++ mise.lock | 28 ++++++++++++++++ mise.toml | 5 +++ 5 files changed, 133 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 dd0e2411..effe3689 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ .claude .gh-pages .idea +.lycheecache docs/.hugo_build.lock docs/public/ .pmd diff --git a/lychee.toml b/lychee.toml new file mode 100644 index 00000000..f51c4df8 --- /dev/null +++ b/lychee.toml @@ -0,0 +1,67 @@ +# Lychee link checker configuration +# https://lychee.cli.rs/#/usage/config +# +# Run locally with: +# lychee './**/*.md' './src/**/*.java' './pom.xml' + +# 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', + # XML namespace identifiers in pom.xml (not real links) + '^http://www\.w3\.org/', + '^http://maven\.apache\.org/', + '^https://maven\.apache\.org/xsd/', + '^http://java\.sun\.com/', + '^http://schemas\.', + # Maven property placeholder in a build-time download URL (not a real link) + 'japicmp\.baselineVersion', + # dev.maxmind.com docs render anchors client-side, so lychee cannot verify + # the #schema-... fragment even though the page (a clean 200) contains it. + '^https://dev\.maxmind\.com/minfraud/api-documentation/responses/#', + # 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/', + '(^|/)target/', + '(^|/)\.git/', + # Test code and fixtures contain example URLs (e.g. www.example.com), not ours + '(^|/)src/test/', + # 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 9b150a1f..a1cae619 100644 --- a/mise.lock +++ b/mise.lock @@ -36,6 +36,34 @@ url = "https://github.com/gohugoio/hugo/releases/download/v0.161.1/hugo_0.161.1_ version = "26.0.1" backend = "core:java" +[[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.maven]] version = "3.9.15" backend = "aqua:apache/maven" diff --git a/mise.toml b/mise.toml index 4a11f83e..9ac550c4 100644 --- a/mise.toml +++ b/mise.toml @@ -9,6 +9,7 @@ disable_backends = [ [tools] hugo = "latest" java = "latest" +lychee = "latest" maven = "latest" [tasks.build-docs] @@ -19,6 +20,10 @@ run = "hugo --source docs --minify" description = "Serve the docs site locally with Hugo dev server" run = "hugo server --source docs" +[tasks.check-links] +description = "Check links with lychee" +run = "lychee --no-progress './**/*.md' './src/**/*.java' './pom.xml'" + [hooks] enter = "mise install --quiet --locked" From 7cb9a22ac74ba89099a2f3246aad47cf125daf41 Mon Sep 17 00:00:00 2001 From: Gregory Oschwald Date: Thu, 4 Jun 2026 20:43:47 +0000 Subject: [PATCH 2/2] Update stale and redirecting links * README.dev.md: http://central.sonatype.org/pages/working-with-pgp-signatures.html -> https://central.sonatype.org/publish/requirements/gpg/ * README.dev.md: the two retired issues.sonatype.org JIRA links replaced with a reference to https://central.sonatype.org/faq/what-happened-to-issues-sonatype-org/ * README.md: https://www.maxmind.com/en/support -> https://support.maxmind.com/knowledge-base * pom.xml: http://dev.maxmind.com/minfraud -> https://dev.maxmind.com/minfraud/ * pom.xml: http://www.apache.org/licenses/LICENSE-2.0.html -> https://www.apache.org/licenses/LICENSE-2.0.html * pom.xml: http://www.maxmind.com/ -> https://www.maxmind.com/en/home * CustomInputs.java: https://www.maxmind.com/en/minfraud-interactive/#/custom-rules -> https://www.maxmind.com/en/accounts/current/minfraud-interactive/custom-rules * Device.java: https://dev.maxmind.com/minfraud/track-devices?lang=en -> https://dev.maxmind.com/minfraud/track-devices/?lang=en * Warning.java: https://tools.ietf.org/html/rfc6901 -> https://datatracker.ietf.org/doc/html/rfc6901 Part of STF-557. Co-Authored-By: Claude Opus 4.8 (1M context) --- README.dev.md | 8 ++++---- README.md | 2 +- pom.xml | 6 +++--- .../java/com/maxmind/minfraud/request/CustomInputs.java | 3 ++- src/main/java/com/maxmind/minfraud/response/Device.java | 2 +- src/main/java/com/maxmind/minfraud/response/Warning.java | 7 ++++--- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/README.dev.md b/README.dev.md index 1cda7587..4de2a532 100644 --- a/README.dev.md +++ b/README.dev.md @@ -19,9 +19,9 @@ To get this access, first create a Central Portal account. You will then need access to our namespace, but we have not added anyone since switching to -Central Portal. Previously you would need to make an account on the [Sonatype -JIRA issue tracker](https://issues.sonatype.org/) and make an issue asking for -access [like so](https://issues.sonatype.org/browse/OSSRH-34414). +Central Portal. Previously you would need to make an account on the Sonatype +JIRA issue tracker and make an issue asking for access. That tracker has since +been [retired](https://central.sonatype.org/faq/what-happened-to-issues-sonatype-org/). Ensure you inform MaxMind operations about your new access. @@ -52,7 +52,7 @@ and enter `trust` and choose ultimate. Make sure the key shows up in `gpg --list-secret-keys`. Make sure you publish it to a keyserver. See -[here](http://central.sonatype.org/pages/working-with-pgp-signatures.html) +[here](https://central.sonatype.org/publish/requirements/gpg/) for more info about that and the process in general. ### gpg "inappropriate ioctl" errors diff --git a/README.md b/README.md index e6fab87a..23d47296 100644 --- a/README.md +++ b/README.md @@ -327,7 +327,7 @@ Please report all issues with this code using the If you are having an issue with the minFraud service that is not specific to the client API, please see -[our support page](https://www.maxmind.com/en/support). +[our support page](https://support.maxmind.com/knowledge-base). ## Requirements ## diff --git a/pom.xml b/pom.xml index 91d321e4..027bf243 100644 --- a/pom.xml +++ b/pom.xml @@ -7,17 +7,17 @@ 4.3.0 MaxMind minFraud API MaxMind minFraud Score, Insights, Factors and Report Transaction API - http://dev.maxmind.com/minfraud + https://dev.maxmind.com/minfraud/ Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.html + https://www.apache.org/licenses/LICENSE-2.0.html repo MaxMind, Inc. - http://www.maxmind.com/ + https://www.maxmind.com/en/home https://github.com/maxmind/minfraud-api-java diff --git a/src/main/java/com/maxmind/minfraud/request/CustomInputs.java b/src/main/java/com/maxmind/minfraud/request/CustomInputs.java index 4d72ae19..eee9ddd6 100644 --- a/src/main/java/com/maxmind/minfraud/request/CustomInputs.java +++ b/src/main/java/com/maxmind/minfraud/request/CustomInputs.java @@ -8,7 +8,8 @@ /** * Custom inputs to be used in - * Custom Rules. + * Custom + * Rules. * In order to use custom inputs, you must set them up from your account portal. */ public final class CustomInputs extends AbstractModel { diff --git a/src/main/java/com/maxmind/minfraud/response/Device.java b/src/main/java/com/maxmind/minfraud/response/Device.java index 4a78f3a0..e52bb632 100644 --- a/src/main/java/com/maxmind/minfraud/response/Device.java +++ b/src/main/java/com/maxmind/minfraud/response/Device.java @@ -21,7 +21,7 @@ * date-time. * @param localTime The date and time of the transaction at the UTC offset associated with the * device. This is an RFC 3339 date-time. - * @see Device Tracking Add-on + * @see Device Tracking Add-on */ public record Device( @JsonProperty("confidence") diff --git a/src/main/java/com/maxmind/minfraud/response/Warning.java b/src/main/java/com/maxmind/minfraud/response/Warning.java index 4aaa0fb3..5fb077b2 100644 --- a/src/main/java/com/maxmind/minfraud/response/Warning.java +++ b/src/main/java/com/maxmind/minfraud/response/Warning.java @@ -35,8 +35,8 @@ * @param inputPointer This is a JSON Pointer to the input that the warning is associated with. For * instance, if the warning was about the billing city, the value would be * "/billing/city". See - * RFC 6901 for the JSON - * Pointer spec. + * RFC 6901 for the + * JSON Pointer spec. */ public record Warning( @JsonProperty("code") @@ -99,7 +99,8 @@ public String getWarning() { * @return This is a JSON Pointer to the input that the warning is associated with. For * instance, if the warning was about the billing city, the value would be "/billing/city". * See - * RFC 6901 for the JSON Pointer spec. + * RFC 6901 for the JSON Pointer + * spec. * @deprecated Use {@link #inputPointer()} instead. This method will be removed in 5.0.0. */ @Deprecated(since = "4.0.0", forRemoval = true)