forked from github/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rendered-content-link-checker.js
executable file
·151 lines (140 loc) · 4.7 KB
/
rendered-content-link-checker.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/env node
// [start-readme]
//
// This script goes through all content and renders their HTML and from there
// can analyze for various flaws (e.g. broken links)
//
// [end-readme]
import fs from 'fs'
import path from 'path'
import { program, Option, InvalidArgumentError } from 'commander'
import renderedContentLinkChecker from '../.github/actions-scripts/rendered-content-link-checker.js'
import { getCoreInject, getUploadArtifactInject } from './helpers/action-injections.js'
import { allVersions } from '../lib/all-versions.js'
import github from './helpers/github.js'
const STATIC_PREFIXES = {
assets: path.resolve('assets'),
public: path.resolve(path.join('data', 'graphql')),
}
// Sanity check that these are valid paths
Object.entries(STATIC_PREFIXES).forEach(([key, value]) => {
if (!fs.existsSync(value)) {
throw new Error(`Can't find static prefix (${key}): ${value}`)
}
})
program
.description('Analyze all checked content files, render them, and check for flaws.')
.addOption(
new Option(
'-L, --level <LEVEL>',
'Level of broken link to be marked as a flaw (default: "warning")',
).choices(['all', 'warning', 'critical']),
)
.option('-f, --filter <FILTER...>', 'Search filter(s) on the paths')
.option(
'-V, --version <VERSION...>',
"Specific versions to only do (e.g. 'free-pro-team@latest')",
(version) => {
if (!(version in allVersions)) {
for (const [key, data] of Object.entries(allVersions)) {
if (version === data.miscVersionName) {
return key
}
}
throw new InvalidArgumentError(
`'${version}' is not a recognized version. (not one of ${Object.keys(allVersions)})`,
)
}
return version
},
)
.option('-v, --verbose', 'Verbose outputs')
.option(
'--create-report',
'Create a report issue in report-repository if there are flaws. (default: false)',
)
.option(
'--report-repository <REPOSITORY>',
'Repository to create issue in. (default: "github/docs-content")',
)
.option(
'--link-reports',
'If comments should be made on previous report and new report "linking" them. (default: false)',
)
.option(
'--report-author <AUTHOR>',
'Previous author of report PR for linking. (default: "docs-bot")',
)
.option(
'--report-label <LABEL>',
'Label to assign to report issue. (default: "broken link report")',
)
.option(
'--comment-on-pr <URI>',
'For debugging. Comment on a PR in form "owner/repo-name:pr_number"',
)
.option('--should-comment', 'Comments failed links on PR')
.option('--check-anchors', "Validate links that start with a '#' too")
.option('--check-images', 'Validate local images too')
.option('--check-external-links', 'Check external URLs too')
.option('--debug', "Loud about everything it's doing")
.option('--patient', 'Give external link checking longer timeouts and more retries')
.option('--random', 'Load pages in a random order (useful for debugging)')
.option('--bail', 'Exit on the first possible flaw')
.option('--verbose-url <BASE_URL>', 'Print the absolute URL if set')
.option('--fail-on-flaw', 'Throw error on link flaws (default: false)')
.option('--external-server-errors-as-warning', 'Treat server errors as warning (default: false)')
.option('--max <number>', 'integer argument (default: none)', (value) => {
const parsed = parseInt(value, 10)
if (isNaN(parsed)) {
throw new InvalidArgumentError('Not a number.')
}
return parsed
})
.option(
'--list <file>.json',
'JSON file containing an array of specific files to check (default: none)',
(filePath) => {
const resolvedPath = path.resolve(filePath)
let stats
try {
stats = fs.statSync(resolvedPath)
} catch (error) {
// Ignore
}
if (!stats || !stats.isFile()) {
throw new InvalidArgumentError('Not an existing file.')
}
return resolvedPath
},
)
.arguments('[files...]', 'Specific files to check')
.parse(process.argv)
const opts = program.opts()
const files = program.args || opts.list
const octokit = github()
if (opts.list && Array.isArray(files) && files.length > 0) {
throw new InvalidArgumentError('Cannot specify both --list and a file list.')
}
// For debugging PR comment. e.g. "github/howie-testing-ebonsignori:140"
if (opts.commentOnPr) {
const [owner, repoPRNumber] = opts.commentOnPr.split('/')
const [repo, number] = repoPRNumber.split(':')
opts.shouldComment = true
opts.actionContext = {
owner,
repo,
pull_request: {
number,
},
}
}
renderedContentLinkChecker(
getCoreInject(opts.debug),
octokit,
getUploadArtifactInject(opts.debug),
{
...opts,
files,
},
)