Skip to content

Commit df9fde6

Browse files
louis-preclaudeseambot
authored
ci: Add redirect target validator, fix 18 broken redirects (#1093)
* ci: Add redirect target validator and fix 18 broken redirects Add validate-redirects CI check that verifies all .gitbook.yaml redirect targets resolve to existing pages. Fix 18 broken targets caused by pages being moved or removed over time. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: Keep README.md redirect targets, update validator to handle them GitBook resolves README.md in redirect targets as directory URLs, so these don't need to be changed. Update the validator to accept foo/README.md when foo.md exists as the page file. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: Remove redundant latest/ redirect prefix and deduplicate entry Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: Replace ad-hoc YAML parser with yaml package in redirect validator Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ci: Format code * fix: Use actual file paths for redirect targets instead of README.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: Remove implicit directory/README.md resolution from redirect validator Redirect targets should always point to exact files. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: Ensure all redirect targets point to files, not bare directories Replace bare directory targets with explicit README.md paths and update the validator to reject directories. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: Remove unnecessary comments from redirect validator Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: Remove unused .md extension fallback from redirect validator Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: Remove README.md→parent.md fallback from redirect validator Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Seam Bot <seambot@getseam.com>
1 parent 3f392fe commit df9fde6

5 files changed

Lines changed: 97 additions & 18 deletions

File tree

.gitbook.yaml

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ root: ./docs/guides/
44
readme: README.md
55
summary: SUMMARY.md
66
redirects:
7-
latest/quickstart/get-api-key: latest/quickstart.md
87
quickstart/get-api-key: quickstart.md
98
quickstart/installation: quickstart.md
109
quickstart/authentication: quickstart.md
@@ -16,18 +15,18 @@ redirects:
1615
core-concepts/workspaces/personal-access-tokens: core-concepts/authentication/personal-access-tokens.md
1716
core-concepts/workspaces/client-session-tokens: core-concepts/authentication/client-session-tokens/README.md
1817
core-concepts/workspaces/client-session-tokens/implementing-client-sessions-for-device-management-in-the-backend: core-concepts/authentication/client-session-tokens/implementing-client-sessions-for-device-management-in-the-backend.md
19-
products/access-systems/user-management: capability-guides/access-systems/user-management/README.md
20-
capability-guides/access-systems/managing-credentials: capability-guides/access-systems/managing-credentials/README.md
18+
products/access-systems/user-management: capability-guides/access-systems/user-management.md
19+
capability-guides/access-systems/managing-credentials: capability-guides/access-systems/managing-credentials.md
2120
capability-guides/access-systems/assigning-credentials-to-users: capability-guides/access-systems/managing-credentials/assigning-credentials-to-users.md
2221
products/access-systems/suspending-and-unsuspending-users: capability-guides/access-systems/user-management/suspending-and-unsuspending-users.md
2322
products/seam-bridge-in-development: capability-guides/seam-bridge.md
2423
core-concepts/connect-webviews: core-concepts/connect-webviews/README.md
2524
device-guides/4suites-locks: device-and-system-integration-guides/4suites-locks/README.md
2625
device-guides/assa-abloy-visionline-access-control-system-in-development: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/README.md
27-
device-guides/assa-abloy-visionline-access-control-system-in-development/credential-types: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/credential-types.md
28-
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/visionline-credential-metadata: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/visionline-credential-metadata.md
26+
device-guides/assa-abloy-visionline-access-control-system-in-development/credential-types: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/README.md
27+
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/visionline-credential-metadata: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/README.md
2928
device-guides/assa-abloy-visionline-access-control-system-in-development/common-use-cases: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/common-use-cases.md
30-
capability-guides/access-systems/understanding-acs-differences: capability-guides/access-systems/understanding-access-control-system-differences.md
29+
capability-guides/access-systems/understanding-acs-differences: capability-guides/access-systems/README.md
3130
capability-guides/thermostats/creating-and-managing-climate-schedules: capability-guides/thermostats/creating-and-managing-thermostat-schedules.md
3231
device-guides/get-started-with-schlage-locks: device-and-system-integration-guides/schlage-locks/get-started-with-schlage-locks.md
3332
api-clients/access-codes/convert-an-unmanaged-access-code: api/access_codes/unmanaged/convert_to_managed.md
@@ -95,16 +94,16 @@ redirects:
9594
api-clients/connected-accounts/list-connected-accounts: api/connected_accounts/list.md
9695
api-clients/connected-accounts/update-a-connected-account: api/connected_accounts/update.md
9796
api-clients/connected-accounts: api/connected_accounts/README.md
98-
api-clients/devices/delete-device: api/devices/delete.md
97+
api-clients/devices/delete-device: api/devices/README.md
9998
api-clients/devices/get-device-1: api/devices/unmanaged/get.md
10099
api-clients/devices/get-device: api/devices/get.md
101100
api-clients/devices/list-device-providers: api/devices/list_device_providers.md
102101
api-clients/devices/list-devices: api/devices/list.md
103102
api-clients/devices/list-unmanaged-devices: api/devices/unmanaged/list.md
104103
api-clients/devices/update-device: api/devices/update.md
105104
api-clients/devices/update-unmanaged-device: api/devices/unmanaged/update.md
106-
api-clients/events/get-an-event: api-clients/events/get.md
107-
api-clients/events/list-events: api-clients/events/list.md
105+
api-clients/events/get-an-event: api/events/get.md
106+
api-clients/events/list-events: api/events/list.md
108107
api-clients/locks/get-lock: api/locks/get.md
109108
api-clients/locks/list-locks: api/locks/list.md
110109
api-clients/locks/lock-a-lock: api/locks/lock_door.md
@@ -114,7 +113,7 @@ redirects:
114113
api-clients/noise-sensors/list-noise-thresholds: api/noise_sensors/noise_thresholds/list.md
115114
api-clients/noise-sensors/update-noise-threshold: api/noise_sensors/noise_thresholds/update.md
116115
api-clients/noise-sensors: api/noise_sensors/README.md
117-
api-clients/thermostats/get-thermostat: api/thermostats/get.md
116+
api-clients/thermostats/get-thermostat: api/thermostats/README.md
118117
api-clients/thermostats/list-thermostats: api/thermostats/list.md
119118
api-clients/thermostats/set-fan-mode: api/thermostats/set_fan_mode.md
120119
api-clients/thermostats/set-to-cool-mode: api/thermostats/cool.md
@@ -136,7 +135,7 @@ redirects:
136135
api-clients/workspaces/get-workspace: api/workspaces/get.md
137136
api-clients/workspaces/reset-workspace: api/workspaces/reset_sandbox.md
138137
api-clients/phones/create-a-sandbox-phone: api/phones/simulate/create_sandbox_phone.md
139-
device-and-system-integration-guides/assa-abloy-credential-services-credential-manager-in-development: device-and-system-integration-guides/assa-abloy-credential-services-credential-manager/README.md
138+
device-and-system-integration-guides/assa-abloy-credential-services-credential-manager-in-development: device-and-system-integration-guides/assa-abloy-vingcard-credential-services.md
140139
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/README.md
141140
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/visionline-acs-setup-instructions: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/visionline-acs-setup-instructions/README.md
142141
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/visionline-acs-setup-instructions/developing-and-launching-your-visionline-plastic-card-encoding-app: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/visionline-acs-setup-instructions/developing-and-launching-your-visionline-plastic-card-encoding-app/README.md
@@ -183,13 +182,13 @@ redirects:
183182
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/visionline-acs-setup-instructions/developing-and-launching-your-visionline-mobile-key-app/launching-your-visionline-mobile-key-app/step-7-purchase-and-import-the-callback-and-mobile-service-options-from-assa-abloy: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/visionline-acs-setup-instructions/developing-and-launching-your-visionline-mobile-key-app/launching-your-visionline-mobile-key-app/step-7-purchase-and-import-the-callback-and-mobile-service-options-from-assa-abloy.md
184183
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/visionline-acs-setup-instructions/developing-and-launching-your-visionline-mobile-key-app/launching-your-visionline-mobile-key-app/step-8-create-a-production-workspace: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/visionline-acs-setup-instructions/developing-and-launching-your-visionline-mobile-key-app/launching-your-visionline-mobile-key-app/step-8-create-a-production-workspace.md
185184
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/visionline-acs-setup-instructions/developing-and-launching-your-visionline-mobile-key-app/launching-your-visionline-mobile-key-app/step-9-connect-your-visionline-production-account-to-seam: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/visionline-acs-setup-instructions/developing-and-launching-your-visionline-mobile-key-app/launching-your-visionline-mobile-key-app/step-9-connect-your-visionline-production-account-to-seam.md
186-
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/credential-types: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/credential-types/README.md
187-
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/credential-types/issuing-various-types-of-guest-mobile-credentials: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/credential-types/issuing-various-types-of-guest-mobile-credentials.md
188-
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/credential-types/issuing-various-types-of-guest-joiner-mobile-credentials: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/credential-types/issuing-various-types-of-guest-joiner-mobile-credentials.md
189-
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/credential-types/retrieving-guest-and-common-entrances: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/credential-types/retrieving-guest-and-common-entrances.md
190-
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/credential-types/checking-if-a-user-identity-has-a-phone-that-is-set-up-for-a-credential-manager: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/credential-types/checking-if-a-user-identity-has-a-phone-that-is-set-up-for-a-credential-manager.md
191-
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/credential-types/updating-guest-mobile-credentials: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/credential-types/updating-guest-mobile-credentials.md
192-
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/credential-types/revoking-mobile-credentials: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/credential-types/revoking-mobile-credentials.md
185+
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/credential-types: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/README.md
186+
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/credential-types/issuing-various-types-of-guest-mobile-credentials: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/README.md
187+
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/credential-types/issuing-various-types-of-guest-joiner-mobile-credentials: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/README.md
188+
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/credential-types/retrieving-guest-and-common-entrances: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/README.md
189+
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/credential-types/checking-if-a-user-identity-has-a-phone-that-is-set-up-for-a-credential-manager: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/README.md
190+
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/credential-types/updating-guest-mobile-credentials: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/README.md
191+
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/credential-types/revoking-mobile-credentials: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/README.md
193192
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/mobile-credential-related-properties: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/mobile-credential-related-properties.md
194193
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/common-use-cases: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/common-use-cases.md
195194
device-and-system-integration-guides/assa-abloy-visionline-access-control-system-in-development/special-requirements-for-android-mobile-access-sdk-development: device-and-system-integration-guides/assa-abloy-visionline-access-control-system/special-requirements-for-android-mobile-access-sdk-development.md

.github/workflows/generate.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,5 @@ jobs:
8484
run: npm run validate-links
8585
- name: Validate all pages are in SUMMARY.md
8686
run: npm run validate-orphan-pages
87+
- name: Validate redirect targets
88+
run: npm run validate-redirects

codegen/validate-redirects.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { existsSync, readFileSync, statSync } from 'node:fs'
2+
import { join } from 'node:path'
3+
4+
import YAML from 'yaml'
5+
6+
import { siteSections } from './lib/config.js'
7+
8+
const gitbookConfig = YAML.parse(readFileSync('.gitbook.yaml', 'utf-8')) as {
9+
redirects?: Record<string, string>
10+
}
11+
12+
interface Redirect {
13+
source: string
14+
target: string
15+
}
16+
17+
const redirects: Redirect[] = Object.entries(gitbookConfig.redirects ?? {}).map(
18+
([source, target]) => ({ source, target }),
19+
)
20+
21+
function pageExists(fullPath: string): boolean {
22+
return existsSync(fullPath) && statSync(fullPath).isFile()
23+
}
24+
25+
function resolveTarget(target: string): boolean {
26+
for (const section of siteSections) {
27+
if (section.urlPrefix === '') continue
28+
29+
const prefix = section.urlPrefix.replace(/^\//, '') + '/'
30+
if (target.startsWith(prefix)) {
31+
const relativePath = target.slice(prefix.length)
32+
return pageExists(join(section.root, relativePath))
33+
}
34+
}
35+
36+
const guidesSection = siteSections.find((s) => s.urlPrefix === '')
37+
if (guidesSection == null) return false
38+
39+
return pageExists(join(guidesSection.root, target))
40+
}
41+
42+
const broken: Redirect[] = redirects.filter((r) => !resolveTarget(r.target))
43+
44+
if (broken.length > 0) {
45+
// eslint-disable-next-line no-console
46+
console.error(
47+
`Found ${broken.length} redirect(s) with missing target(s) in .gitbook.yaml:\n`,
48+
)
49+
for (const { source, target } of broken) {
50+
// eslint-disable-next-line no-console
51+
console.error(` ${source}`)
52+
// eslint-disable-next-line no-console
53+
console.error(` target: ${target}\n`)
54+
}
55+
process.exit(1)
56+
} else {
57+
// eslint-disable-next-line no-console
58+
console.log('All .gitbook.yaml redirect targets are valid.')
59+
}

package-lock.json

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"validate-paths": "tsx codegen/validate-paths.ts",
2020
"validate-links": "tsx codegen/validate-links.ts",
2121
"validate-orphan-pages": "tsx codegen/validate-orphan-pages.ts",
22+
"validate-redirects": "tsx codegen/validate-redirects.ts",
2223
"typecheck": "tsc",
2324
"lint": "eslint .",
2425
"postlint": "prettier --check --ignore-path .prettierignore .",
@@ -41,6 +42,7 @@
4142
"command-exists": "^1.2.9",
4243
"execa": "^9.3.1",
4344
"prettier": "^3.0.0",
45+
"yaml": "^2.8.3",
4446
"zod": "^3.23.8"
4547
}
4648
}

0 commit comments

Comments
 (0)