12
.github/workflows/content-lint-markdown.yml
vendored
12
.github/workflows/content-lint-markdown.yml
vendored
@@ -40,6 +40,18 @@ jobs:
|
||||
content/**
|
||||
data/**
|
||||
|
||||
- name: Print content linter annotations if changed content/data files
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
env:
|
||||
# Make it an environment variable so that its value doesn't need to be escaped.
|
||||
# See https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
|
||||
CHANGED_FILES: |-
|
||||
${{ steps.changed-files.outputs.all_changed_files }}
|
||||
# If there are errors, using `--print-annotations` will make it
|
||||
# so it does *not* exit non-zero.
|
||||
# This is so that all warnings and errors are printed.
|
||||
run: npm run lint-content -- --print-annotations --paths $CHANGED_FILES
|
||||
|
||||
- name: Run content linter if changed content/data files
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
env:
|
||||
|
||||
12
.github/workflows/move-content.yml
vendored
12
.github/workflows/move-content.yml
vendored
@@ -11,6 +11,10 @@ on:
|
||||
- src/content-render/scripts/test-move-content.ts
|
||||
- 'src/frame/lib/**/*.js'
|
||||
- .github/workflows/move-content.yml
|
||||
# In case any of the dependencies affect the script
|
||||
- 'package*.json'
|
||||
- src/fixtures/fixtures/content/get-started/
|
||||
- src/fixtures/fixtures/content/code-security/
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -38,12 +42,12 @@ jobs:
|
||||
ROOT: src/fixtures/fixtures
|
||||
run: |
|
||||
npm run move-content -- \
|
||||
src/fixtures/fixtures/content/get-started/quickstart/hello-world.md \
|
||||
src/fixtures/fixtures/content/get-started/quickstart/hello-wurld.md
|
||||
src/fixtures/fixtures/content/get-started/start-your-journey/hello-world.md \
|
||||
src/fixtures/fixtures/content/get-started/start-your-journey/hello-wurld.md
|
||||
|
||||
npm run test-moved-content -- \
|
||||
src/fixtures/fixtures/content/get-started/quickstart/hello-world.md \
|
||||
src/fixtures/fixtures/content/get-started/quickstart/hello-wurld.md
|
||||
src/fixtures/fixtures/content/get-started/start-your-journey/hello-world.md \
|
||||
src/fixtures/fixtures/content/get-started/start-your-journey/hello-wurld.md
|
||||
|
||||
# TODO: Add tests that inspects the git log
|
||||
git log | head -n 100
|
||||
|
||||
20
.github/workflows/orphaned-assets-check.yml
vendored
20
.github/workflows/orphaned-assets-check.yml
vendored
@@ -8,6 +8,16 @@ on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '20 16 * * 1' # Run every Monday at 16:20 UTC / 8:20 PST
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/orphaned-assets-check.yml
|
||||
# In case any of the dependencies affect the script
|
||||
- 'package*.json'
|
||||
- src/assets/scripts/find-orphaned-assets.js
|
||||
- src/workflows/walk-files.js
|
||||
- src/languages/lib/languages.js
|
||||
- .github/actions/clone-translations/action.yml
|
||||
- .github/actions/node-npm-setup/action.yml
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -38,6 +48,7 @@ jobs:
|
||||
env:
|
||||
# Needed for gh
|
||||
GITHUB_TOKEN: ${{ secrets.DOCS_BOT_PAT_READPUBLICKEY }}
|
||||
DRY_RUN: ${{ github.event_name == 'pull_request'}}
|
||||
run: |
|
||||
set -e
|
||||
|
||||
@@ -53,6 +64,13 @@ jobs:
|
||||
# If nothing to commit, exit now. It's fine. No orphans.
|
||||
git status -- ':!translations*' | grep 'nothing to commit' && exit 0
|
||||
|
||||
# When run on a pull_request, we're just testing the tooling.
|
||||
# Exit before it actually pushes the possible changes.
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "Dry-run mode when run in a pull request"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Replicated from the translation pipeline PR-maker Action
|
||||
git config --global user.name "docs-bot"
|
||||
git config --global user.email "77750099+docs-bot@users.noreply.github.com"
|
||||
@@ -82,7 +100,7 @@ jobs:
|
||||
--label docs-content-fr
|
||||
|
||||
- uses: ./.github/actions/slack-alert
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
|
||||
if: ${{ failure() && github.event_name == 'schedule' }}
|
||||
with:
|
||||
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
|
||||
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
||||
|
||||
@@ -10,7 +10,6 @@ redirect_from:
|
||||
versions:
|
||||
fpt: '*'
|
||||
ghes: '*'
|
||||
ghae: '*'
|
||||
ghec: '*'
|
||||
shortTitle: Events that trigger workflows
|
||||
---
|
||||
|
||||
@@ -4,7 +4,6 @@ intro: 'When a workflow is configured to run on the `workflow_dispatch` event, y
|
||||
versions:
|
||||
fpt: '*'
|
||||
ghes: '*'
|
||||
ghae: '*'
|
||||
ghec: '*'
|
||||
shortTitle: Manually run a workflow
|
||||
redirect_from:
|
||||
|
||||
19
package-lock.json
generated
19
package-lock.json
generated
@@ -113,7 +113,7 @@
|
||||
"@typescript-eslint/parser": "6.17.0",
|
||||
"chalk": "^5.0.1",
|
||||
"change-case": "^5.0.2",
|
||||
"commander": "^11.0.0",
|
||||
"commander": "^12.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"csp-parse": "0.0.2",
|
||||
"dedent": "^1.0.1",
|
||||
@@ -5039,12 +5039,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
|
||||
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-12.0.0.tgz",
|
||||
"integrity": "sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/compute-gcd": {
|
||||
@@ -10156,6 +10156,15 @@
|
||||
"url": "https://opencollective.com/lint-staged"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/commander": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
|
||||
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/execa": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
|
||||
|
||||
@@ -334,7 +334,7 @@
|
||||
"@typescript-eslint/parser": "6.17.0",
|
||||
"chalk": "^5.0.1",
|
||||
"change-case": "^5.0.2",
|
||||
"commander": "^11.0.0",
|
||||
"commander": "^12.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"csp-parse": "0.0.2",
|
||||
"dedent": "^1.0.1",
|
||||
|
||||
45
src/content-linter/lib/helpers/print-annotations.js
Normal file
45
src/content-linter/lib/helpers/print-annotations.js
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* This function is meant to be used by the code that runs the linter,
|
||||
* but only within Actions workflows. That means, if it works, it
|
||||
* posts all the annotations as inline comments on the PR.
|
||||
*
|
||||
*/
|
||||
|
||||
export function printAnnotationResults(results, { skippableRules = [] } = {}) {
|
||||
for (const [file, flaws] of Object.entries(results)) {
|
||||
for (const flaw of flaws) {
|
||||
if (intersection(flaw.ruleNames, skippableRules)) {
|
||||
continue
|
||||
}
|
||||
|
||||
let annotation = `::${flaw.severity === 'error' ? 'error' : 'warning'} `
|
||||
const bits = [`file=${file}`]
|
||||
if (flaw.lineNumber) {
|
||||
bits.push(`line=${flaw.lineNumber}`)
|
||||
// Note: it's possible to use a endLine property
|
||||
// if you can "lump" together the same error description on
|
||||
// consecutive lines.
|
||||
// See https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message
|
||||
}
|
||||
|
||||
if (flaw.ruleDescription) {
|
||||
bits.push(`title=${flaw.ruleDescription}`)
|
||||
}
|
||||
|
||||
annotation += `${bits.join(',')}`
|
||||
|
||||
if (flaw.errorDetail) {
|
||||
annotation += `::${flaw.errorDetail}`
|
||||
}
|
||||
|
||||
// Why console.log and not `core.error()` (from @actions/core)?
|
||||
// Because, this way you can debug this more easily on you own
|
||||
// terminal.
|
||||
console.log(annotation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function intersection(arr1, arr2) {
|
||||
return arr1.some((item) => arr2.includes(item))
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import { allConfig, allRules, customRules } from '../lib/helpers/get-rules.js'
|
||||
import { customConfig, githubDocsFrontmatterConfig } from '../style/github-docs.js'
|
||||
import { defaultConfig } from '../lib/default-markdownlint-options.js'
|
||||
import { prettyPrintResults } from './pretty-print-results.js'
|
||||
import { printAnnotationResults } from '../lib/helpers/print-annotations.js'
|
||||
|
||||
program
|
||||
.description('Run GitHub Docs Markdownlint rules.')
|
||||
@@ -45,6 +46,7 @@ program
|
||||
.addOption(
|
||||
new Option('-o, --output-file <filepath>', `Outputs the errors/warnings to the filepath.`),
|
||||
)
|
||||
.option('--print-annotations', 'Print annotations for GitHub Actions check runs.', false)
|
||||
.parse(process.argv)
|
||||
|
||||
const {
|
||||
@@ -56,6 +58,7 @@ const {
|
||||
outputFile,
|
||||
verbose,
|
||||
precommit: isPrecommit,
|
||||
printAnnotations,
|
||||
} = program.opts()
|
||||
|
||||
const ALL_CONTENT_DIR = ['content', 'data']
|
||||
@@ -91,7 +94,7 @@ async function main() {
|
||||
customRules: configuredRules.data,
|
||||
})
|
||||
|
||||
// Run Markdownlint for data directory
|
||||
// Run Markdownlint for content directory (frontmatter only)
|
||||
const resultFrontmatter = await markdownlint.promises.markdownlint({
|
||||
frontMatter: null,
|
||||
files: files.content,
|
||||
@@ -154,6 +157,18 @@ async function main() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (printAnnotations) {
|
||||
printAnnotationResults(formattedResults, {
|
||||
skippableRules: [
|
||||
// As of Feb 2024, this rule is quite noisy. It's present in
|
||||
// many files and is not always a problem. And besides, when it
|
||||
// does warn, it's usually a very long one.
|
||||
'code-fence-line-length', // a.k.a. GHD030
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
const end = Date.now()
|
||||
// Ensure previous console logging is not truncated
|
||||
console.log('\n')
|
||||
@@ -214,9 +229,15 @@ async function main() {
|
||||
}
|
||||
|
||||
if (errorFileCount) {
|
||||
process.exit(1)
|
||||
if (printAnnotations) {
|
||||
console.warn('When printing annotations, the exit code is always 0')
|
||||
process.exit(0)
|
||||
} else {
|
||||
process.exit(1)
|
||||
}
|
||||
} else {
|
||||
spinner.succeed('No errors found')
|
||||
}
|
||||
spinner.succeed('No errors found')
|
||||
}
|
||||
|
||||
function pluralize(things, word, pluralForm = null) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { allVersions } from '#src/versions/lib/all-versions.js'
|
||||
import { liquid } from '#src/content-render/index.js'
|
||||
import { supported } from '#src/versions/lib/enterprise-server-releases.js'
|
||||
import shortVersionsMiddleware from '#src/versions/middleware/short-versions.js'
|
||||
|
||||
const contextualize = (req) => {
|
||||
@@ -12,14 +13,14 @@ describe('ifversion conditionals', () => {
|
||||
beforeAll(async () => {
|
||||
req.context = {
|
||||
allVersions,
|
||||
currentVersion: 'github-ae@latest',
|
||||
currentVersion: `enterprise-server@${supported[0]}`,
|
||||
}
|
||||
contextualize(req)
|
||||
})
|
||||
|
||||
test('greater than', async () => {
|
||||
const template = `
|
||||
{% ifversion ghae > 3.2 %}
|
||||
{% ifversion ghes > 3.2 %}
|
||||
FOO
|
||||
{% else %}
|
||||
BAR
|
||||
@@ -31,7 +32,7 @@ describe('ifversion conditionals', () => {
|
||||
|
||||
test('less than', async () => {
|
||||
const template = `
|
||||
{% ifversion ghae < 3.2 %}
|
||||
{% ifversion ghes < 3.2 %}
|
||||
FOO
|
||||
{% else %}
|
||||
BAR
|
||||
@@ -43,7 +44,7 @@ describe('ifversion conditionals', () => {
|
||||
|
||||
test('Equal', async () => {
|
||||
const template = `
|
||||
{% ifversion ghae %}
|
||||
{% ifversion ghes %}
|
||||
FOO
|
||||
{% else %}
|
||||
BAR
|
||||
@@ -55,7 +56,7 @@ describe('ifversion conditionals', () => {
|
||||
|
||||
test('Not', async () => {
|
||||
const template = `
|
||||
{% ifversion not ghae %}
|
||||
{% ifversion not ghes %}
|
||||
FOO
|
||||
{% else %}
|
||||
BAR
|
||||
Reference in New Issue
Block a user