test: enforce valid JSON in fenced markdown code blocks (#12196)

This commit is contained in:
Nejc Habjan 2021-11-11 11:11:55 +01:00 committed by GitHub
parent f885e3e437
commit 34f13fee3e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 166 additions and 67 deletions

View file

@ -154,6 +154,7 @@ jobs:
yarn prettier yarn prettier
yarn markdown-lint yarn markdown-lint
yarn git-check yarn git-check
yarn doc-fence-check
- name: Test schema - name: Test schema
run: yarn test-schema run: yarn test-schema

View file

@ -53,11 +53,10 @@ If you add a `renovate.json` file to the root of your repository, you can use th
If you add configuration options to your `package.json` then these will override any other settings above. If you add configuration options to your `package.json` then these will override any other settings above.
```json ```json
"renovate": { {
"labels": [ "renovate": {
"upgrade", "labels": ["upgrade", "bot"]
"bot" }
]
} }
``` ```

View file

@ -128,28 +128,24 @@ You can find the Renovate team's preset configs at the "Config Presets" section
If you browse the "default" presets, you will see some that contain parameters, e.g.: If you browse the "default" presets, you will see some that contain parameters, e.g.:
```json ```json
"labels": { {
"description": "Apply labels <code>{{arg0}}</code> and <code>{{arg1}}</code> to PRs", "labels": {
"labels": [ "description": "Apply labels <code>{{arg0}}</code> and <code>{{arg1}}</code> to PRs",
"{{arg0}}", "labels": ["{{arg0}}", "{{arg1}}"]
"{{arg1}}" },
] "assignee": {
}, "description": "Assign PRs to <code>{{arg0}}</code>",
"assignee": { "assignees": ["{{arg0}}"]
"description": "Assign PRs to <code>{{arg0}}</code>", }
"assignees": [ }
"{{arg0}}"
]
},
``` ```
Here is how you would use these in your Renovate config: Here is how you would use these in your Renovate config:
```json ```json
"extends": [ {
":labels(dependencies,devops)", "extends": [":labels(dependencies,devops)", ":assignee(rarkins)"]
":assignee(rarkins)" }
]
``` ```
In short, the number of `{{argx}}` parameters in the definition is how many parameters you need to provide. In short, the number of `{{argx}}` parameters in the definition is how many parameters you need to provide.
@ -170,7 +166,9 @@ To host your preset config on GitHub:
- In other repos, reference it in an extends array like "github>owner/name", for example: - In other repos, reference it in an extends array like "github>owner/name", for example:
```json ```json
{
"extends": ["github>rarkins/renovate-config"] "extends": ["github>rarkins/renovate-config"]
}
``` ```
From then on Renovate will use the Renovate config from the preset repo's default branch. From then on Renovate will use the Renovate config from the preset repo's default branch.
@ -259,7 +257,6 @@ For example:
{ {
"name": "renovate-config-fastcore", "name": "renovate-config-fastcore",
"version": "0.0.1", "version": "0.0.1",
...
"renovate-config": { "renovate-config": {
"default": { "default": {
"extends": ["config:base", "schedule:nonOfficeHours"] "extends": ["config:base", "schedule:nonOfficeHours"]
@ -271,7 +268,9 @@ For example:
Then in each of your repositories you can add your Renovate config like: Then in each of your repositories you can add your Renovate config like:
```json ```json
{
"extends": ["fastcore"] "extends": ["fastcore"]
}
``` ```
Any repository including this config will then adopt the rules of the default `library` preset but schedule it on weeknights or weekends. Any repository including this config will then adopt the rules of the default `library` preset but schedule it on weeknights or weekends.
@ -279,5 +278,7 @@ Any repository including this config will then adopt the rules of the default `l
Note: if you prefer to publish using the namespace `@fastcore/renovate-config` then you would use the `@` prefix instead: Note: if you prefer to publish using the namespace `@fastcore/renovate-config` then you would use the `@` prefix instead:
```json ```json
{
"extends": ["@fastcore"] "extends": ["@fastcore"]
}
``` ```

View file

@ -126,11 +126,13 @@ If you wish to override Docker settings for one particular type of manager, use
For example, to disable digest updates for Docker Compose only but leave them for other managers like `Dockerfile`, you would use this: For example, to disable digest updates for Docker Compose only but leave them for other managers like `Dockerfile`, you would use this:
```json ```json
{
"docker-compose": { "docker-compose": {
"digest": { "digest": {
"enabled": false "enabled": false
} }
} }
}
``` ```
The following configuration options are applicable to Docker: The following configuration options are applicable to Docker:

View file

@ -180,12 +180,14 @@ Set the configuration option `labels` to an array of labels to use.
e.g. e.g.
```json ```json
"packageRules": [ {
{ "packageRules": [
"matchPackageNames": ["abc"], {
"assignees": ["importantreviewer"] "matchPackageNames": ["abc"],
} "assignees": ["importantreviewer"]
] }
]
}
``` ```
### Apply a rule, but only for packages starting with `abc` ### Apply a rule, but only for packages starting with `abc`
@ -193,12 +195,14 @@ e.g.
Do the same as above, but instead of using `matchPackageNames`, use `matchPackagePatterns` and a regex: Do the same as above, but instead of using `matchPackageNames`, use `matchPackagePatterns` and a regex:
```json ```json
"packageRules": [ {
{ "packageRules": [
"matchPackagePatterns": "^abc", {
"assignees": ["importantreviewer"] "matchPackagePatterns": "^abc",
} "assignees": ["importantreviewer"]
] }
]
}
``` ```
### Group all packages starting with `abc` together in one PR ### Group all packages starting with `abc` together in one PR
@ -206,12 +210,14 @@ Do the same as above, but instead of using `matchPackageNames`, use `matchPackag
As above, but apply a `groupName`: As above, but apply a `groupName`:
```json ```json
"packageRules": [ {
{ "packageRules": [
"matchPackagePatterns": "^abc", {
"groupName": ["abc packages"] "matchPackagePatterns": "^abc",
} "groupName": ["abc packages"]
] }
]
}
``` ```
### Change the default values for branch name, commit message, PR title or PR description ### Change the default values for branch name, commit message, PR title or PR description

View file

@ -46,9 +46,11 @@ You can force Renovate to use a specific version of Go by setting a constraint.
As an example, say you want Renovate to use the latest patch version of the `1.16` Go binary, you'd put this in your Renovate config: As an example, say you want Renovate to use the latest patch version of the `1.16` Go binary, you'd put this in your Renovate config:
```json ```json
{
"constraints": { "constraints": {
"go": "1.16" "go": "1.16"
} }
}
``` ```
We do not support patch level versions for the minimum `go` version. We do not support patch level versions for the minimum `go` version.

View file

@ -28,12 +28,14 @@ You may wish to take this further, for example you might want to group together
In that case you might create a config like this: In that case you might create a config like this:
```json ```json
{
"packageRules": [ "packageRules": [
{ {
"matchPackagePatterns": [ "eslint" ], "matchPackagePatterns": ["eslint"],
"groupName": "eslint" "groupName": "eslint"
} }
] ]
}
``` ```
By setting `matchPackagePatterns` to "eslint", it means that any package with ESLint anywhere in its name will be grouped into a `renovate/eslint` branch and related PR. By setting `matchPackagePatterns` to "eslint", it means that any package with ESLint anywhere in its name will be grouped into a `renovate/eslint` branch and related PR.
@ -79,25 +81,29 @@ If you think about it, updates to `eslint` rules don't exactly need to be applie
You don't want to get too far behind, so how about we update `eslint` packages only once a month? You don't want to get too far behind, so how about we update `eslint` packages only once a month?
```json ```json
{
"packageRules": [ "packageRules": [
{ {
"matchPackagePatterns": [ "eslint" ], "matchPackagePatterns": ["eslint"],
"groupName": "eslint", "groupName": "eslint",
"schedule": ["on the first day of the month"] "schedule": ["on the first day of the month"]
} }
] ]
}
``` ```
Or perhaps at least weekly: Or perhaps at least weekly:
```json ```json
{
"packageRules": [ "packageRules": [
{ {
"matchPackagePatterns": [ "eslint" ], "matchPackagePatterns": ["eslint"],
"groupName": "eslint", "groupName": "eslint",
"schedule": ["before 2am on monday"] "schedule": ["before 2am on monday"]
} }
] ]
}
``` ```
If you're wondering what is supported and not, under the hood, the schedule is parsed using [@breejs/later](https://github.com/breejs/later) using the `later.parse.text(scheduleString)` API. If you're wondering what is supported and not, under the hood, the schedule is parsed using [@breejs/later](https://github.com/breejs/later) using the `later.parse.text(scheduleString)` API.
@ -149,15 +155,17 @@ Remember our running `eslint` example?
Let's automerge it if all the linting updates pass: Let's automerge it if all the linting updates pass:
```json ```json
{
"packageRules": [ "packageRules": [
{ {
"matchPackagePatterns": [ "eslint" ], "matchPackagePatterns": ["eslint"],
"groupName": "eslint", "groupName": "eslint",
"schedule": ["before 2am on monday"], "schedule": ["before 2am on monday"],
"automerge": true, "automerge": true,
"automergeType": "branch" "automergeType": "branch"
} }
] ]
}
``` ```
Have you come up with a rule that you think others would benefit from? Have you come up with a rule that you think others would benefit from?

View file

@ -30,12 +30,14 @@ Renovate by default performs all lookups on `https://api.nuget.org/v3/index.json
Alternative feeds can be specified either [in a `NuGet.config` file](https://docs.microsoft.com/en-us/nuget/reference/nuget-config-file#package-source-sections) within your repository (Renovate will not search outside the repository) or in Renovate configuration options: Alternative feeds can be specified either [in a `NuGet.config` file](https://docs.microsoft.com/en-us/nuget/reference/nuget-config-file#package-source-sections) within your repository (Renovate will not search outside the repository) or in Renovate configuration options:
```json ```json
"nuget": { {
"registryUrls": [ "nuget": {
"https://api.nuget.org/v3/index.json", "registryUrls": [
"https://example1.com/nuget/", "https://api.nuget.org/v3/index.json",
"https://example2.com/nuget/v3/index.json" "https://example1.com/nuget/",
] "https://example2.com/nuget/v3/index.json"
]
}
} }
``` ```
@ -50,10 +52,10 @@ Renovate as a NuGet client supports both versions and will use `v2` unless the c
If you have a `v3` feed that does not match this pattern (e.g. JFrog Artifactory) you need to help Renovate by appending `#protocolVersion=3` to the registry URL: If you have a `v3` feed that does not match this pattern (e.g. JFrog Artifactory) you need to help Renovate by appending `#protocolVersion=3` to the registry URL:
```json ```json
"nuget": { {
"registryUrls": [ "nuget": {
"http://myV3feed#protocolVersion=3" "registryUrls": ["http://myV3feed#protocolVersion=3"]
] }
} }
``` ```
@ -62,14 +64,16 @@ If you have a `v3` feed that does not match this pattern (e.g. JFrog Artifactory
Credentials for authenticated/private feeds can be provided via host rules in the configuration options (file or command line parameter). Credentials for authenticated/private feeds can be provided via host rules in the configuration options (file or command line parameter).
```json ```json
"hostRules": [ {
{ "hostRules": [
"hostType": "nuget", {
"matchHost": "http://example1.com/nuget", "hostType": "nuget",
"username": "root", "matchHost": "http://example1.com/nuget",
"password": "p4$$w0rd" "username": "root",
} "password": "p4$$w0rd"
] }
]
}
``` ```
Please note that at the moment only Basic HTTP authentication (via username and password) is supported. Please note that at the moment only Basic HTTP authentication (via username and password) is supported.

View file

@ -32,9 +32,11 @@ If you have a specific file or file pattern you want the Renovate bot to find, u
e.g.: e.g.:
```json ```json
{
"pip_requirements": { "pip_requirements": {
"fileMatch": ["my/specifically-named.file", "\.requirements$"] "fileMatch": ["my/specifically-named.file", "\\.requirements$"]
} }
}
``` ```
## Alternate registries ## Alternate registries
@ -63,9 +65,11 @@ You can use the `registryUrls` array to configure alternate index URL(s).
e.g.: e.g.:
```json ```json
{
"python": { "python": {
"registryUrls": ["http://example.com/private-pypi/"] "registryUrls": ["http://example.com/private-pypi/"]
} }
}
``` ```
Note: the index-url found in the `requirements.txt` file takes precedence over a `registryUrl` configured like the above. Note: the index-url found in the `requirements.txt` file takes precedence over a `registryUrl` configured like the above.
@ -76,14 +80,18 @@ To override the URL found in `requirements.txt`, you need to configure it in `pa
The most direct way to disable all Python support in Renovate is like this: The most direct way to disable all Python support in Renovate is like this:
```json ```json
{
"python": { "python": {
"enabled": false "enabled": false
} }
}
``` ```
Alternatively, maybe you only want one package manager, such as `npm`. Alternatively, maybe you only want one package manager, such as `npm`.
In that case this would enable _only_ `npm`: In that case this would enable _only_ `npm`:
```json ```json
{
"enabledManagers": ["npm"] "enabledManagers": ["npm"]
}
``` ```

View file

@ -4,8 +4,10 @@ You can create a custom [versioning config](/configuration-options/#versioning)
For example, if you want to reference a tag like `module-v1.2.5`, a block like this would work: For example, if you want to reference a tag like `module-v1.2.5`, a block like this would work:
```json ```json
"terraform": { {
"versioning": "regex:^((?<compatibility>.*)-v|v*)(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)$" "terraform": {
"versioning": "regex:^((?<compatibility>.*)-v|v*)(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)$"
}
} }
``` ```

View file

@ -15,6 +15,7 @@
"create-json-schema": "node -r ts-node/register/transpile-only -- bin/create-json-schema.js && prettier --write \"renovate-schema.json\"", "create-json-schema": "node -r ts-node/register/transpile-only -- bin/create-json-schema.js && prettier --write \"renovate-schema.json\"",
"debug": "node --inspect-brk -r ts-node/register/transpile-only -- lib/renovate.ts", "debug": "node --inspect-brk -r ts-node/register/transpile-only -- lib/renovate.ts",
"doc-fix": "run-s markdown-lint-fix prettier-fix", "doc-fix": "run-s markdown-lint-fix prettier-fix",
"doc-fence-check": "node tools/check-fenced-code.mjs",
"eslint": "eslint --ext .js,.mjs,.ts lib/ test/ tools/ --report-unused-disable-directives", "eslint": "eslint --ext .js,.mjs,.ts lib/ test/ tools/ --report-unused-disable-directives",
"eslint-fix": "eslint --ext .js,.mjs,.ts --fix lib/ test/ tools/ --report-unused-disable-directives", "eslint-fix": "eslint --ext .js,.mjs,.ts --fix lib/ test/ tools/ --report-unused-disable-directives",
"generate": "run-s generate:*", "generate": "run-s generate:*",
@ -23,7 +24,7 @@
"jest": "cross-env NODE_ENV=test LOG_LEVEL=fatal TZ=UTC node --expose-gc node_modules/jest/bin/jest.js --logHeapUsage", "jest": "cross-env NODE_ENV=test LOG_LEVEL=fatal TZ=UTC node --expose-gc node_modules/jest/bin/jest.js --logHeapUsage",
"jest-debug": "cross-env NODE_OPTIONS=--inspect-brk yarn jest --testTimeout=100000000", "jest-debug": "cross-env NODE_OPTIONS=--inspect-brk yarn jest --testTimeout=100000000",
"jest-silent": "cross-env yarn jest --reporters jest-silent-reporter", "jest-silent": "cross-env yarn jest --reporters jest-silent-reporter",
"lint": "run-s ls-lint eslint prettier markdown-lint git-check", "lint": "run-s ls-lint eslint prettier markdown-lint git-check doc-fence-check",
"lint-fix": "run-s eslint-fix prettier-fix markdown-lint-fix", "lint-fix": "run-s eslint-fix prettier-fix markdown-lint-fix",
"ls-lint": "ls-lint", "ls-lint": "ls-lint",
"markdown-lint": "markdownlint-cli2", "markdown-lint": "markdownlint-cli2",

View file

@ -0,0 +1,65 @@
import { promisify } from 'util';
import fs from 'fs-extra';
import g from 'glob';
import MarkdownIt from 'markdown-it';
import shell from 'shelljs';
const glob = promisify(g);
const errorTitle = 'Invalid JSON in fenced code block';
const errorBody =
'Fix this manually by ensuring each block is a valid, complete JSON document.';
const markdownGlob = '{docs,lib}/**/*.md';
const markdown = new MarkdownIt('zero');
let issues = 0;
markdown.enable(['fence']);
function checkValidJson(file, token) {
const start = parseInt(token.map[0], 10) + 1;
const end = parseInt(token.map[1], 10) + 1;
try {
JSON.parse(token.content);
} catch (err) {
issues += 1;
if (process.env.CI) {
shell.echo(
`::error file=${file},line=${start},endLine=${end},title=${errorTitle}::${err.message}. ${errorBody}`
);
} else {
shell.echo(
`${errorTitle} (${file} lines ${start}-${end}): ${err.message}`
);
}
}
}
async function processFile(file) {
const text = await fs.readFile(file, 'utf8');
const tokens = markdown.parse(text, undefined);
shell.echo(`Linting ${file}...`);
tokens.forEach((token) => {
if (token.type === 'fence' && token.info === 'json') {
checkValidJson(file, token);
}
});
}
// eslint-disable-next-line @typescript-eslint/no-floating-promises
(async () => {
const files = await glob(markdownGlob);
for (const file of files) {
await processFile(file);
}
if (issues) {
shell.echo(
`${issues} issues found. ${errorBody} See above for lines affected.`
);
shell.exit(1);
}
})();