-
Notifications
You must be signed in to change notification settings - Fork 66.9k
Expand file tree
/
Copy pathlint-report.ts
More file actions
160 lines (132 loc) · 5.18 KB
/
lint-report.ts
File metadata and controls
160 lines (132 loc) · 5.18 KB
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
152
153
154
155
156
157
158
159
160
import { program } from 'commander'
import fs from 'fs'
import coreLib from '@actions/core'
import github from '@/workflows/github'
import { getEnvInputs } from '@/workflows/get-env-inputs'
import { createReportIssue, linkReports } from '@/workflows/issue-report'
import { getAllRuleNames } from '@/content-linter/lib/helpers/rule-utils'
// GitHub issue body size limit is ~65k characters, so we'll use 60k as a safe limit
const MAX_ISSUE_BODY_SIZE = 60000
// If the number of warnings exceeds this number, print a warning so we can give them attention
const MAX_WARNINGS_BEFORE_ALERT = 20
/**
* Config that only applies to automated weekly reports.
*/
export const reportingConfig = {
// Include only rules with these severities in reports
includeSeverities: ['error', 'warning'],
// Include these rules regardless of severity in reports
includeRules: ['expired-content'],
}
interface LintFlaw {
severity: string
ruleNames: string[]
errorDetail?: string
}
/**
* Determines if a lint result should be included in the automated report
*/
function shouldIncludeInReport(flaw: LintFlaw): boolean {
const allRuleNames = getAllRuleNames(flaw)
// Check if severity should be included
if (reportingConfig.includeSeverities.includes(flaw.severity)) {
return true
}
// Check if any rule name is in the include list that overrides severity
const hasIncludedRule = allRuleNames.some((ruleName: string) =>
reportingConfig.includeRules.includes(ruleName),
)
if (hasIncludedRule) {
return true
}
return false
}
// [start-readme]
//
// This script runs once a week via a scheduled GitHub Action to lint
// the entire content and data directories based on our
// markdownlint.js rules.
//
// If errors or warnings are found, it will open up a new issue in the
// docs-content repo with the label "broken content markdown report".
//
// The Content FR will go through the issue and update the content and
// data files accordingly.
//
// [end-readme]
program
.description(
'Opens an issue for Content FR with the errors and warnings from the weekly content/data linter.',
)
.option(
'-p, --path <path>',
'provide a path to the errors and warnings output json file that will be in the issue body',
)
.parse(process.argv)
const { path } = program.opts()
main()
async function main() {
const lintResults = fs.readFileSync(`${path}`, 'utf8')
const core = coreLib
const { REPORT_REPOSITORY, REPORT_AUTHOR, REPORT_LABEL } = process.env
const octokit = github()
// `GITHUB_TOKEN` is optional. If you need the token to post a comment
// or open an issue report, you might get cryptic error messages from Octokit.
getEnvInputs(['GITHUB_TOKEN'])
core.info(`Creating issue for configured lint rules...`)
const parsedResults = JSON.parse(lintResults)
// Keep track of warnings so we can print an alert when they exceed a manageable number
let totalWarnings = 0
// Filter results based on reporting configuration
const filteredResults: Record<string, LintFlaw[]> = {}
for (const [file, flaws] of Object.entries(parsedResults)) {
const filteredFlaws = (flaws as LintFlaw[]).filter((flaw) => shouldIncludeInReport(flaw))
// Only include files that have remaining flaws after filtering
if (filteredFlaws.length > 0) {
totalWarnings += filteredFlaws.filter((flaw) => flaw.severity === 'warning').length
filteredResults[file] = filteredFlaws
}
}
const totalFiles = Object.keys(filteredResults).length
const showTooManyWarningsAlert = totalWarnings > MAX_WARNINGS_BEFORE_ALERT
const tooManyWarningsAlertText = showTooManyWarningsAlert
? `**Alert**: ${totalWarnings} warning-level issues have been found. These must be addressed ASAP so they do not continue to accumulate.\n\n`
: ''
let reportBody = `${tooManyWarningsAlertText}The following files have markdown lint issues that require attention:\n\n`
let filesIncluded = 0
let truncated = false
for (const [file, flaws] of Object.entries(filteredResults)) {
const fileEntry = `File: \`${file}\`:\n\`\`\`json\n${JSON.stringify(flaws, null, 2)}\n\`\`\`\n`
// Check if adding this file would exceed the size limit
if (reportBody.length + fileEntry.length > MAX_ISSUE_BODY_SIZE) {
truncated = true
break
}
reportBody += fileEntry
filesIncluded++
}
// Add truncation notice if needed
if (truncated) {
const remaining = totalFiles - filesIncluded
reportBody += `\n---\n\n⚠️ **Output truncated**: Showing ${filesIncluded} of ${totalFiles} files with lint issues. ${remaining} additional files have been omitted to stay within GitHub's issue size limits.\n`
reportBody += `\nTo see all results, run the linter locally:\n\`\`\`bash\nnpm run lint-content -- --paths content data\n\`\`\`\n`
}
const reportProps = {
core,
octokit,
reportTitle: `Content linting issues requiring attention`,
reportBody,
reportRepository: REPORT_REPOSITORY!,
reportLabel: REPORT_LABEL!,
}
const newReport = await createReportIssue(reportProps)
const linkProps = {
core,
octokit,
newReport,
reportRepository: REPORT_REPOSITORY!,
reportAuthor: REPORT_AUTHOR!,
reportLabel: REPORT_LABEL!,
}
await linkReports(linkProps)
}