Broken weekly content linting report (#42504)
Co-authored-by: Kevin Heis <heiskr@users.noreply.github.com> Co-authored-by: Peter Bengtsson <peterbe@github.com>
This commit is contained in:
125
.github/actions-scripts/lib/issue-report.js
vendored
Normal file
125
.github/actions-scripts/lib/issue-report.js
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
export async function createReportIssue({
|
||||
core,
|
||||
octokit,
|
||||
reportTitle,
|
||||
reportBody,
|
||||
reportRepository,
|
||||
reportLabel,
|
||||
}) {
|
||||
const [owner, repo] = reportRepository.split('/')
|
||||
// Create issue
|
||||
let newReport
|
||||
try {
|
||||
const { data } = await octokit.request('POST /repos/{owner}/{repo}/issues', {
|
||||
owner,
|
||||
repo,
|
||||
title: reportTitle,
|
||||
body: reportBody,
|
||||
labels: [reportLabel],
|
||||
})
|
||||
newReport = data
|
||||
core.info(`Created new report issue at ${newReport.html_url}\n`)
|
||||
} catch (error) {
|
||||
core.error(error)
|
||||
core.setFailed('Error creating new issue')
|
||||
throw error
|
||||
}
|
||||
|
||||
return newReport
|
||||
}
|
||||
|
||||
export async function linkReports({
|
||||
core,
|
||||
octokit,
|
||||
newReport,
|
||||
reportRepository,
|
||||
reportAuthor,
|
||||
reportLabel,
|
||||
}) {
|
||||
const [owner, repo] = reportRepository.split('/')
|
||||
|
||||
core.info('Attempting to link reports...')
|
||||
// Find previous report issue
|
||||
let previousReports
|
||||
try {
|
||||
previousReports = await octokit.rest.issues.listForRepo({
|
||||
owner,
|
||||
repo,
|
||||
creator: reportAuthor,
|
||||
labels: reportLabel,
|
||||
state: 'all', // We want to get the previous report, even if it is closed
|
||||
sort: 'created',
|
||||
direction: 'desc',
|
||||
per_page: 25,
|
||||
})
|
||||
previousReports = previousReports.data
|
||||
} catch (error) {
|
||||
core.setFailed('Error listing issues for repo')
|
||||
throw error
|
||||
}
|
||||
core.info(`Found ${previousReports.length} previous reports`)
|
||||
|
||||
if (previousReports.length <= 1) {
|
||||
core.info('No previous reports to link to')
|
||||
return
|
||||
}
|
||||
|
||||
// 2nd report should be most recent previous report
|
||||
const previousReport = previousReports[1]
|
||||
|
||||
// Comment the old report link on the new report
|
||||
try {
|
||||
await octokit.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: newReport.number,
|
||||
body: `⬅️ [Previous report](${previousReport.html_url})`,
|
||||
})
|
||||
core.info(`Linked old report to new report via comment on new report, #${newReport.number}`)
|
||||
} catch (error) {
|
||||
core.setFailed(`Error commenting on newReport, #${newReport.number}`)
|
||||
throw error
|
||||
}
|
||||
|
||||
// Comment on all previous reports that are still open
|
||||
for (const previousReport of previousReports) {
|
||||
if (previousReport.state === 'closed' || previousReport.html_url === newReport.html_url) {
|
||||
continue
|
||||
}
|
||||
|
||||
// If an old report is not assigned to someone we close it
|
||||
const shouldClose = !previousReport.assignees.length
|
||||
let body = `➡️ [Newer report](${newReport.html_url})`
|
||||
if (shouldClose) {
|
||||
body += '\n\nClosing in favor of newer report since there are no assignees on this issue'
|
||||
}
|
||||
try {
|
||||
await octokit.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: previousReport.number,
|
||||
body,
|
||||
})
|
||||
core.info(
|
||||
`Linked old report to new report via comment on old report: #${previousReport.number}.`,
|
||||
)
|
||||
} catch (error) {
|
||||
core.setFailed(`Error commenting on previousReport, #${previousReport.number}`)
|
||||
throw error
|
||||
}
|
||||
if (shouldClose) {
|
||||
try {
|
||||
await octokit.rest.issues.update({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: previousReport.number,
|
||||
state: 'closed',
|
||||
})
|
||||
core.info(`Closing old report: #${previousReport.number} because it doesn't have assignees`)
|
||||
} catch (error) {
|
||||
core.setFailed(`Error closing previousReport, #${previousReport.number}`)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
69
.github/actions-scripts/post-lints.js
vendored
Normal file
69
.github/actions-scripts/post-lints.js
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { program } from 'commander'
|
||||
import fs from 'fs'
|
||||
import coreLib from '@actions/core'
|
||||
|
||||
import github from '../../script/helpers/github.js'
|
||||
import { getEnvInputs } from './lib/get-env-inputs.js'
|
||||
import { createReportIssue, linkReports } from './lib/issue-report.js'
|
||||
|
||||
// [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 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 from the weekly content/data linter.')
|
||||
.option(
|
||||
'-p, --path <path>',
|
||||
'provide a path to the errors output json file that will be in the issue body',
|
||||
)
|
||||
.parse(process.argv)
|
||||
|
||||
const { path } = program.opts()
|
||||
|
||||
main()
|
||||
async function main() {
|
||||
const errors = 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 errors...`)
|
||||
|
||||
const reportProps = {
|
||||
core,
|
||||
octokit,
|
||||
reportTitle: `Error(s) in content markdown file(s)`,
|
||||
reportBody: JSON.parse(errors),
|
||||
reportRepository: REPORT_REPOSITORY,
|
||||
reportLabel: REPORT_LABEL,
|
||||
}
|
||||
|
||||
await createReportIssue(reportProps)
|
||||
|
||||
const linkProps = {
|
||||
core,
|
||||
octokit,
|
||||
newReport: await createReportIssue(reportProps),
|
||||
reportRepository: REPORT_REPOSITORY,
|
||||
reportAuthor: REPORT_AUTHOR,
|
||||
reportLabel: REPORT_LABEL,
|
||||
}
|
||||
|
||||
await linkReports(linkProps)
|
||||
}
|
||||
40
.github/workflows/lint-entire-content-data-markdown.yml
vendored
Normal file
40
.github/workflows/lint-entire-content-data-markdown.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
name: 'Lint entire content and data markdown files'
|
||||
|
||||
# **What it does**: Lints our content markdown weekly to ensure the content matches the specified styleguide. If errors exists, it opens a PR for the Docs content team to review.
|
||||
# **Why we have it**: Extra precaution to run linter on the entire content/data directories.
|
||||
# **Who does it impact**: Docs content.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '20 16 * * 0' # Run every day at 16:20 UTC / 8:20 PST every Sunday
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
lint-entire-content-data:
|
||||
name: Lint entire content and data directories
|
||||
if: github.repository == 'github/docs-internal'
|
||||
runs-on: ubuntu-20.04-xl
|
||||
steps:
|
||||
- name: Check that gh CLI is installed
|
||||
run: gh --version
|
||||
|
||||
- name: Check out repo's default branch
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
|
||||
- name: Set up Node and dependencies
|
||||
uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- name: Run content linter
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.DOCS_BOT_PAT_WRITEORG_PROJECT }}
|
||||
REPORT_AUTHOR: docs-bot
|
||||
REPORT_LABEL: broken content markdown report
|
||||
REPORT_REPOSITORY: github/docs-content
|
||||
timeout-minutes: 10
|
||||
run: |
|
||||
node src/content-linter/scripts/markdownlint.js --errors-only --paths content data --output-file /tmp/error-lints.json
|
||||
node .github/actions-scripts/post-lints.js --path /tmp/error-lints.json
|
||||
Reference in New Issue
Block a user