Merge pull request #11129 from backstage/rugvip/vale

vale: update to support v2, common ignore list, and self-contained config
This commit is contained in:
Patrik Oldsberg
2022-04-28 14:27:44 +02:00
committed by GitHub
19 changed files with 124 additions and 98 deletions
@@ -8,9 +8,6 @@ airbrake
Anddddd
Apdex
api
Api
apis
args
asciidoc
async
Atlassian
@@ -19,7 +16,6 @@ autoscaling
Autoscaling
autoselect
Avro
aws
backported
backporting
Bigtable
@@ -38,7 +34,6 @@ changesets
Changesets
chanwit
Chanwit
ci
CI/CD
classname
cli
@@ -127,7 +122,6 @@ hoc
horizontalpodautoscalers
Hostname
hotspots
html
http
https
Iain
@@ -314,7 +308,6 @@ templaters
Templaters
theia
thumbsup
toc
todo
tolerations
Tolerations
@@ -339,7 +332,6 @@ unregistration
untracked
upsert
upvote
url
URIs
URLs
utils
+6
View File
@@ -0,0 +1,6 @@
StylesPath = .
Vocab = Backstage
[*.md]
BasedOnStyles = Vale
Vale.Terms = NO
+11 -3
View File
@@ -12,10 +12,18 @@ jobs:
steps:
- uses: actions/checkout@v2
# Vale does not support file excludes, so we use the script to generate a list of files instead
# The action also does not allow args or a local config file to be passed in, so the files array
# also contains an "--config=.github/vale/config.ini" option
- name: generate vale args
id: generate
run: echo "::set-output name=args::$(node scripts/check-docs-quality.js --ci-args)"
- name: documentation quality check
uses: errata-ai/vale-action@v1.4.0
# Whitelist excluding ADOPTERS, CHANGELOG and OWNERS (no exclude flag exists)
uses: errata-ai/vale-action@v1.5.0
with:
files: '[".changeset", ".github", "contrib", "docs", "microsite", "packages", "plugins", "CONTRIBUTING.md", "CODE_OF_CONDUCT.md", "GOVERNANCE.md", "README.md"]'
# This also contains --config=.github/vale/config.ini ... :/
files: '${{ steps.generate.outputs.args }}'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+1 -1
View File
@@ -78,7 +78,7 @@ If you're contributing to the backend or CLI tooling, be mindful of cross-platfo
Also be sure to skim through our [ADRs](docs/architecture-decisions) to see if they cover what you're working on. In particular [ADR006: Avoid React.FC and React.SFC](docs/architecture-decisions/adr006-avoid-react-fc.md) is one to look out for.
If there are any updates in `markdown` file please make sure to run `yarn run lint:docs`. Though it is checked on `lint-staged`. It is required to install [vale](https://docs.errata.ai/vale/install) `1.4.0` separately and make sure it is accessed by global command.
If there are any updates in `markdown` file please make sure to run `yarn run lint:docs`. Though it is checked on `lint-staged`. It is required to install [vale](https://docs.errata.ai/vale/install) separately and make sure it is accessed by global command.
## Developer Certificate of Origin
+1 -1
View File
@@ -146,7 +146,7 @@ There are a few things to pay attention to, in order to make the documentation s
API documenter will not recognize arrow functions as functions, but rather as a constant that shows up in the list of exported variables. By declaring functions using the `function` keyword, they will show up in the list of functions. They will also get a much nicer documentation page for the individual function that shows information about parameters and return types.
This also extends to React components, since API documenter doesn't have any special handling of those. By always defining exported React components using the `function` keyword, we make them show up among the list of functions in the API reference, where they are then easily discoverable through the `(props)` args (which you should be sure to include!).
This also extends to React components, since API documenter doesn't have any special handling of those. By always defining exported React components using the `function` keyword, we make them show up among the list of functions in the API reference, where they are then easily discoverable through the `(props)` argument (which you should be sure to include!).
![image](https://user-images.githubusercontent.com/4984472/133120461-59d74c3e-ebd9-44f9-900d-cc30f54a3cd2.png)
@@ -64,8 +64,8 @@ if (process.env.HTTPS_PROXY) {
If your development environment is in the cloud (like with [AWS Cloud9](https://aws.amazon.com/cloud9/) or an instance of [Theia](https://theia-ide.org/)), you will need to update your configuration.
You will probably need to make some changes in `app-config.yaml` (or another config file like `app-config.local.yaml` if you've created it, see the [configuration doc](https://backstage.io/docs/conf/#supplying-configuration)).
The exact values will depend on your setup but for instance, if your public url is `https://your-public-url.com` and the port `3000` and `8080` are open:
You will probably need to make some changes in `app-config.yaml` (or another config file like `app-config.local.yaml` if you've created it, see the [configuration doc](https://backstage.io/docs/conf/#supplying-configuration)).
The exact values will depend on your setup but for instance, if your public URL is `https://your-public-url.com` and the port `3000` and `8080` are open:
```yaml
app:
+1 -1
View File
@@ -230,7 +230,7 @@ name.
### Test the new provider
You can `curl -i localhost:7007/api/auth/providerA/start` and which should
provide a `302` redirect with a `Location` header. Paste the url from that
provide a `302` redirect with a `Location` header. Paste the URL from that
header into a web browser and you should be able to trigger the authorization
flow.
+1 -1
View File
@@ -50,7 +50,7 @@ The GitHub provider is a structure with three configuration keys:
- `clientSecret`: The client secret tied to the generated client ID.
- `enterpriseInstanceUrl` (optional): The base URL for a GitHub Enterprise
instance, e.g. `https://ghe.<company>.com`. Only needed for GitHub Enterprise.
- `callbackUrl` (optional): The callback url that GitHub will use when
- `callbackUrl` (optional): The callback URL that GitHub will use when
initiating an OAuth flow, e.g.
`https://your-intermediate-service.com/handler`. Only needed if Backstage is
not the immediate receiver (e.g. one OAuth app for many backstage instances).
+1 -1
View File
@@ -161,7 +161,7 @@ $file: ./my-secret.txt
The `$include` keyword can be used to load configuration values from an external
file. It's able to load and parse data from `.json`, `.yml`, and `.yaml` files.
It's also possible to include a url fragment (`#`) to point to a value at the
It's also possible to include a URL fragment (`#`) to point to a value at the
given path in the file, using a dot-separated list of keys.
For example, the following would read `my-secret-key` from `my-secrets.json`:
+2 -2
View File
@@ -18,8 +18,8 @@ GitLab, etc.) and passes the files to the generator for next steps.
There are two kinds of preparers available -
1. Common Git Preparer - Uses `git clone` on any repository url.
2. Url Reader - Uses source code hosting provider's API to download files.
1. Common Git Preparer - Uses `git clone` on any repository URL.
2. URL Reader - Uses source code hosting provider's API to download files.
(Faster and recommended)
### TechDocs Generator
@@ -461,7 +461,7 @@ Since the new SDK doesn't use the old way authentication, we don't need the keys
The new SDK needs the OpenStack Swift connection URL for connecting the Swift.
So you need to add a new key called `openStackSwift.swiftUrl` and give the
OpenStack Swift url here. Example url should look like that:
OpenStack Swift URL here. Example URL should look like that:
`https://example.com:6780/swift/v1`
##### That's it!
+1 -4
View File
@@ -24,7 +24,7 @@ the code.
- [`.github/`](https://github.com/backstage/backstage/tree/master/.github) -
Standard GitHub folder. It contains - amongst other things - our workflow
definitions and templates. Worth noting is the
[styles](https://github.com/backstage/backstage/tree/master/.github/styles)
[vale](https://github.com/backstage/backstage/tree/master/.github/vale)
sub-folder which is used for a markdown spellchecker.
- [`.yarn/`](https://github.com/backstage/backstage/tree/master/.yarn) -
@@ -212,9 +212,6 @@ future.
common for companies to have their own npm registry, and this file makes sure
that this folder always uses the public registry.
- [`.vale.ini`](https://github.com/backstage/backstage/tree/master/.vale.ini) -
[Spell checker](https://github.com/errata-ai/vale) for Markdown files.
- [`.yarnrc`](https://github.com/backstage/backstage/tree/master/.yarnrc) -
Enforces "our" version of Yarn.
+2 -2
View File
@@ -34,9 +34,9 @@ a structure with up to six elements:
- `baseUrl` (optional): Needed if the Gerrit instance is not reachable at
the base of the `host` option (e.g. `https://gerrit.company.com`) set the
address here. This is the address that you would open in a browser.
- `cloneUrl` (optional): The base url for HTTP clones. Will default to `baseUrl` if
- `cloneUrl` (optional): The base URL for HTTP clones. Will default to `baseUrl` if
not set. The address used to clone a repo is the `cloneUrl` plus the repo name.
- `gitilesBaseUrl` (optional): This is needed for creating a valid user-friendly url
- `gitilesBaseUrl` (optional): This is needed for creating a valid user-friendly URL
that can be used for browsing the content of the provider. If not set a default
value will be created in the same way as the "baseUrl" option. There is no
requirement to have Gitiles for the Backstage Gerrit integration but without it
@@ -48,7 +48,7 @@ you can check [this documentation page][google gcs docs].
To use this integration to import entities from a GCS bucket go to the Google
console and browse the file you would like to import. Then copy the
`Authenticated URL` and paste it into the text box in the `register component`
form. This url should look like
form. This URL should look like
`https://storage.cloud.google.com/<bucket>/<path>/catalog-info.yaml`.
[google gcs docs]: https://cloud.google.com/docs/authentication/production#auth-cloud-implicit-nodejs
@@ -52,7 +52,7 @@ calling `${backend-url}/api/proxy/<your-proxy-uri>`. The reason why
`backend-url` is referenced is because the backstage backend creates and runs
the proxy. Backstage is structured in such a way that you could run the
backstage frontend independently of the backend. So when calling your API you
need to prepend the backend url to your http call.
need to prepend the backend URL to your http call.
The recommended pattern for calling out to services is to wrap your calls in a
[Utility API](../api/utility-apis.md). This section describes the steps to wrap
+1 -1
View File
@@ -156,7 +156,7 @@ The Swagger UI package by expects to have a route to `/oauth2-redirect.html` whi
the redirect callback for the OAuth2 Authorization Code flow, however, this file is not installed
by this plugin.
Grab a copy of [oauth2-redirect.html](https://github.com/swagger-api/swagger-ui/blob/master/dist/oauth2-redirect.html)
Grab a copy of [`oauth2-redirect.html`](https://github.com/swagger-api/swagger-ui/blob/master/dist/oauth2-redirect.html)
and put it in the `app/public/` directory in order to enable Swagger UI to complete this redirection.
This also may require you to adjust `Content Security Policy` header settings of your Backstage application, so that the script in `oauth2-redirect.html` can be executed. Since the script is static we can add the hash of it directly to our CSP policy, which we do by adding the following to the `csp` section of the app configuration:
+1 -1
View File
@@ -35,7 +35,7 @@ export class CostInsightsClient extends CostInsightsApi {
### Custom Setup
Default properties such as the title, subtitle and instructions page url can be overridden - even default UI such as chart itself. Additionally, alerts can be extended to support actions such as snoozing or dismissing.
Default properties such as the title, subtitle and instructions page URL can be overridden - even default UI such as chart itself. Additionally, alerts can be extended to support actions such as snoozing or dismissing.
![project-growth-alert-custom](../assets/project-growth-alert-custom.png)
@@ -16,7 +16,7 @@ This can be used to run the kubernetes plugin locally against a mock service.
## Steps
1. Start minikube
2. Get the Kubernetes master base url `kubectl cluster-info`
2. Get the Kubernetes master base URL `kubectl cluster-info`
3. Apply manifests `kubectl apply -f dice-roller-manifests.yaml`
4. Get service account token (see below)
5. Start Backstage UI and backend
+89 -66
View File
@@ -13,81 +13,104 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const { execSync, spawnSync } = require('child_process');
// eslint-disable-next-line import/no-extraneous-dependencies
const commandExists = require('command-exists');
const { spawnSync } = require('child_process');
const { resolve: resolvePath, join: joinPath } = require('path');
const fs = require('fs').promises;
const inheritStdIo = {
stdio: 'inherit',
};
const IGNORED = [
/^ADOPTERS\.md$/,
/^OWNERS\.md$/,
/^.*[/\\]CHANGELOG\.md$/,
/^.*[/\\]api-report\.md$/,
/^docs[/\\]releases[/\\].*-changelog\.md$/,
];
const LINT_SKIPPED_MESSAGE =
'Skipping documentation quality check (vale not found). Install vale linter (https://docs.errata.ai/vale/install) to enable.\n';
const LINT_ERROR_MESSAGE = `Language linter (vale) generated errors. Please check the errors and review any markdown files that you changed.
Possibly update .github/styles/vocab.txt to add new valid words.\n`;
const VALE_NOT_FOUND_MESSAGE = `Language linter (vale) was not found. Please install vale linter (https://docs.errata.ai/vale/install).\n`;
const rootDir = resolvePath(__dirname, '..');
// Note: Make sure the script is run as `node check-docs-quality.js [FILES]` instead of `./check-docs-quality.js [FILES]`
// If the script receives arguments (file paths), the script is run exclusively on them. (e.g. when run via pre-commit hook)
const getFilesToLint = () => {
// Files have been provided as arguments
if (process.argv.length > 2) {
return process.argv.slice(2);
}
// Manual listing to avoid dependency install for listing files in CI
async function listFiles(dir = '') {
const files = await fs.readdir(dir || rootDir);
const paths = await Promise.all(
files
.filter(file => file !== 'node_modules')
.map(async file => {
const path = joinPath(dir, file);
let command = `git ls-files | ./node_modules/.bin/shx grep ".md"`;
if (process.platform === 'win32') {
command = `git ls-files | .\\node_modules\\.bin\\shx grep ".md"`;
}
if (IGNORED.some(pattern => pattern.test(path))) {
return [];
}
if ((await fs.stat(path)).isDirectory()) {
return listFiles(path);
}
if (!path.endsWith('.md')) {
return [];
}
return path;
}),
);
return paths.flat();
}
// Note this ignore list only applies locally, CI runs `.github/workflows/docs-quality-checker.yml`
const ignored = ['', 'ADOPTERS.md', 'OWNERS.md'];
return execSync(command, {
stdio: ['ignore', 'pipe', 'inherit'],
})
.toString()
.split('\n')
.filter(el => !ignored.includes(el));
};
// Proceed with the script only if Vale linter is installed. Limit the friction and surprises caused by the script.
// On CI, we want to ensure vale linter is run.
commandExists('vale')
.catch(() => {
// Proceed with the script only if Vale linter is installed. Limit the friction and surprises
// caused by the script. In CI, we want to ensure vale linter is run.
async function exitIfMissingVale() {
try {
await require('command-exists')('vale');
} catch (e) {
if (process.env.CI) {
console.log(VALE_NOT_FOUND_MESSAGE);
console.log(
`Language linter (vale) was not found. Please install vale linter (https://docs.errata.ai/vale/install).\n`,
);
process.exit(1);
}
console.log(LINT_SKIPPED_MESSAGE);
console.log(`Language linter (vale) generated errors. Please check the errors and review any markdown files that you changed.
Possibly update .github/vale/Vocab/Backstage/accept.txt to add new valid words.\n`);
process.exit(0);
})
.then(() => {
const filesToLint = getFilesToLint();
}
}
if (process.platform === 'win32') {
// Windows
try {
const output = spawnSync('vale', filesToLint, inheritStdIo);
async function runVale(files) {
const result = spawnSync(
'vale',
['--config', resolvePath(rootDir, '.github/vale/config.ini'), ...files],
{
stdio: 'inherit',
},
);
// If the command does not succeed
if (output.status !== 0) {
// If it contains system level error. In this case vale does not exist.
if (output.error) {
console.log(LINT_ERROR_MESSAGE);
}
process.exit(1);
}
} catch (e) {
console.log(e.message);
process.exit(1);
}
} else {
// Unix
const output = spawnSync('vale', filesToLint, inheritStdIo);
if (output.status !== 0) {
console.log(LINT_ERROR_MESSAGE);
process.exit(1);
}
if (result.status !== 0) {
// TODO(Rugvip): This logic was here before but seems a bit odd, could use some verification on windows.
// If it contains system level error. In this case vale does not exist.
if (process.platform !== 'win32' || result.error) {
console.log(`Language linter (vale) generated errors. Please check the errors and review any markdown files that you changed.
Possibly update .github/vale/Vocab/Backstage/accept.txt to add new valid words.\n`);
}
});
return false;
}
return true;
}
async function main() {
const files = await listFiles();
if (process.argv.includes('--ci-args')) {
process.stdout.write(
// Workaround for not being able to pass arguments to the vale action
JSON.stringify(['--config=.github/vale/config.ini', ...files]),
);
return;
}
await exitIfMissingVale();
const success = await runVale(files);
if (!success) {
process.exit(2);
}
}
main().catch(error => {
console.error(error);
process.exit(1);
});