chore(ci): Improve Vale style linting:

- Run Vale in a Docker container by running ./.ci/vale/vale.sh <args>
- Define vale lint scripts in package.json. Lint added and changed files for products.
- Define error-level vale linting in the lint-staged configuration for staged files.
- Improve product-specific nomenclature checks (e.g. database vs bucket)
- Simplify vocab terms and allowed words lists.
- Fixes content errors revealed by vale.
pull/5505/head
Jason Stirnaman 2024-06-25 18:25:55 -05:00
parent 26eb724431
commit 922e48182a
29 changed files with 280 additions and 247 deletions

View File

@ -0,0 +1,11 @@
extends: substitution
message: Did you mean '%s' instead of '%s'
level: warning
ignorecase: false
# swap maps tokens in form of bad: good
# NOTE: The left-hand (bad) side can match the right-hand (good) side;
# Vale ignores alerts that match the intended form.
swap:
'cloud-serverless|clustered': cloud-dedicated
'Cloud Serverless|Clustered': Cloud Dedicated
'API token': database token

View File

@ -0,0 +1,10 @@
extends: substitution
message: Did you mean '%s' instead of '%s'
level: warning
ignorecase: false
# swap maps tokens in form of bad: good
# NOTE: The left-hand (bad) side can match the right-hand (good) side;
# Vale ignores alerts that match the intended form.
swap:
'(?i)bucket': database
'(?i)measurement': table

View File

@ -0,0 +1,14 @@
extends: substitution
message: Did you mean '%s' instead of '%s'
level: warning
ignorecase: false
# swap maps tokens in form of bad: good
# NOTE: The left-hand (bad) side can match the right-hand (good) side;
# Vale ignores alerts that match the intended form.
swap:
'cloud-dedicated|clustered': cloud-serverless
'Cloud Dedicated|Clustered': Cloud Serverless
'(?i)database token': API token
'(?i)management token': API token
'(?i)database': bucket
'(?i)table': measurement

View File

@ -0,0 +1,11 @@
extends: substitution
message: Did you mean '%s' instead of '%s'
level: warning
ignorecase: false
# swap maps tokens in form of bad: good
# NOTE: The left-hand (bad) side can match the right-hand (good) side;
# Vale ignores alerts that match the intended form.
swap:
'cloud-serverless|cloud-dedicated': clustered
'Cloud Serverless|Cloud Dedicated': Clustered
'API token': database token

View File

@ -0,0 +1,10 @@
extends: substitution
message: Did you mean '%s' instead of '%s'
level: warning
ignorecase: false
# swap maps tokens in form of bad: good
# NOTE: The left-hand (bad) side can match the right-hand (good) side;
# Vale ignores alerts that match the intended form.
swap:
'(?i)bucket': database
'(?i)measurement': table

View File

@ -1,45 +1,20 @@
extends: substitution
message: Use '%s' instead of '%s'
level: warning
ignorecase: true
ignorecase: false
# swap maps tokens in form of bad: good
# NOTE: The left-hand (bad) side can match the right-hand (good) side;
# Vale ignores alerts that match the intended form.
swap:
# NOTE: The left-hand (bad) side can match the right-hand (good) side; Vale
# will ignore any alerts that match the intended form.
"anaconda": Anaconda
"(?i)api": API
"arrow": Arrow
"authtoken": authToken
"Authtoken": AuthToken
"chronograf": Chronograf
"cli": CLI
"(?i)clockface": Clockface
"the compactor": the Compactor
"data explorer": Data Explorer
"datetime": dateTime
"dedupe": deduplicate
"(?i)executionplan": ExecutionPlan
"fieldkey": fieldKey
"fieldtype": fieldType
"flight": Flight
"(?i)flightquery": FlightQuery
"(?i)FlightSQL": Flight SQL
"/b(?i)influxdata/b": InfluxData
"/w*/b(?i)influxdb": InfluxDB
"(?i)influxql": InfluxQL
"influxer": Influxer
"the ingester": the Ingester
"(?i)iox": v3
"java[ -]?scripts?": JavaScript
"kapa": Kapacitor
"logicalplan": LogicalPlan
"the object store": the Object store
"a {{% product-name %}}": an {{% product-name %}}
"Pandas": pandas
" parquet": Parquet
"the querier": the Querier
"SQL Alchemy": SQLAlchemy
"superset": Superset
"tagkey": tagKey
"telegraf": Telegraf
"telegraph": Telegraf
'the compactor': the Compactor
'dedupe': deduplicate
'/b(?i)influxdata/b': InfluxData
'/w*/b(?i)influxdb': InfluxDB
'the ingester': the Ingester
'(?i)iox': v3
'the object store': the Object store
'a {{% product-name %}}': an {{% product-name %}}
'the querier': the Querier
'SQL Alchemy': SQLAlchemy
'telegraph': Telegraf
'(?i)vscode': VSCode

View File

@ -1,36 +1,14 @@
extends: spelling
message: "Did you really mean '%s'?"
level: error
level: warning
scope:
- ~table.header
- ~table.cell
ignore:
# Located at StylesPath/ignore1.txt
- InfluxDataDocs/Terms/influxdb.txt
- InfluxDataDocs/Terms/configuration-terms.txt
# Ignore the following words. All words are case-insensitive.
# To use case-sensitive matching, use the filters section or vocabulary Terms.
- InfluxDataDocs/Terms/ignore.txt
- InfluxDataDocs/Terms/query-functions.txt
- InfluxDataDocs/Terms/telegraf.txt
filters:
# Ignore Hugo, layout, and design words.
- 'Flexbox'
- '(?i)frontmatter'
- '(?i)shortcode(s?)'
- '(?i)tooltip(s?)'
# Ignore all words starting with 'py'.
# e.g., 'PyYAML'.
- '[pP]y.*\b'
# Ignore underscore-delimited words.
# e.g., avg_temp
- '\b\w+_\w+\b'
- '\b_\w+\b'
# Ignore SQL variables.
- '(?i)AS \w+'
# Ignore custom words
- '(?i)deduplicat(ion|e|ed|es|ing)'
- '(?i)downsampl(e|ing|ed|es)'
- 'InfluxDB-specific'
- '(?i)repartition(ed|s|ing)'
- '(?i)subcommand(s?)'
- '(?i)union(ing|ed|s)?'
- 'unsignedLong'
- 'US (East|West|Central|North|South|Northeast|Northwest|Southeast|Southwest)'
# Allow product-specific Branding.yml configurations to handle [Ss]erverless while also allowing serverless as a valid dictionary word.
- '[Ss]erverless'

View File

@ -1,12 +0,0 @@
autogen
batchBucket
batchInterval
commentPrefix
destinationBucket
destinationHost
destinationOrg
destinationToken
quoteChar
retentionRules
sourceBucket
src

View File

@ -1,126 +1,97 @@
api
apis
autogen
boolean
bundler
chronograf
clockface
flexbox
flight
frontmatter
kapacitor
telegraf
unix
args
authtoken
authz
boolean
booleans
bundler
bundlers
chronograf
cli
clockface
cloud
callout
codeblock
compactor
conda
csv
config
crypto
dashboarding
datagram
datasource
datetime
deduplicate
deserialize
downsample
dotenv
downsample
enum
executionplan
fieldkey
fieldtype
file_groups
flighquery
Grafana
groupId
fullscreen
gzip
gzipped
homogenous
hostname
hostUrl
hostURL
HostURL
implementor
implementors
influxctl
influxd
influxdata.com
influx3
ingester
ingesters
iox
kapacitor
lat
locf
logicalplan
logstash
lon
lookahead
lookbehind
metaquery
metaqueries
metaquery
middleware
namespace
noaa
npm
oauth
output_ordering
pandas
param
performant
projection
protofiles
pushdown
querier
queryable
quoteChar
rearchitect
rearchitected
redoc
remediations
repartition
retentionRules
retention_policy
retryable
rp
serializable
serializer
serverless
shortcode
signout
Splunk
SQLAlchemy
src
stderr
stdin
stdout
subcommand
subcommands
subnet
subnets
subprocessor
subprocessors
subquery
subqueries
subquery
substring
substrings
superset
svg
syntaxes
tagkey
tagKey
tagset
telegraf
telegraf's
tombstoned
tsm
tooltip
uint
uinteger
unescaped
ungroup
ungrouped
unprocessable
unix
unioned
unioning
unions
unmarshal
unmarshalled
unpackage
unprocessable
unsignedLong
upsample
upsert
urls
venv
VSCode
WALs
Webpack
xpath
XPath

View File

@ -1 +0,0 @@
[Tt]elegraf

View File

@ -55,6 +55,7 @@ swap:
fewer data: less data
file name: filename
firewalls: firewall rules
fully qualified: fully-qualified
functionality: capability|feature
Google account: Google Account
Google accounts: Google Accounts

View File

@ -1,2 +0,0 @@
cloud-dedicated
Cloud Dedicated

View File

@ -1,6 +0,0 @@
API token
bucket name
Cloud Serverless
cloud-serverless
Clustered
clustered

View File

@ -1,2 +0,0 @@
cloud-serverless
Cloud Serverless

View File

@ -1,7 +0,0 @@
Cloud Dedicated
cloud-dedicated
Clustered
clustered
database name
database token
management token

View File

@ -1 +0,0 @@
clustered

View File

@ -1,6 +0,0 @@
API token
bucket name
Cloud Dedicated
cloud-dedicated
Cloud Serverless
cloud-serverless

View File

@ -0,0 +1,77 @@
(?i)AS \w+
(InfluxQL|influxql)
(tsm|TSM)
(xpath|XPath)
APIs?
Anaconda
Apache Superset
Arrow
AuthToken
CLI
CSV
Data Explorer
Dedup
Execd
ExecutionPlan
Flight SQL
FlightQuery
GBs?
Grafana
HostURL
InfluxDB Cloud
InfluxDB OSS
InfluxDB-specific
Influxer
JavaScript
KBs?
LogicalPlan
MBs?
PBs?
Parquet
Redoc
SQLAlchemy
SQLAlchemy
Splunk
[Ss]uperset
TBs?
UI
URLs
US (East|West|Central|North|South|Northeast|Northwest|Southeast|Southwest)
Unix
WALs?
Webpack
[pP]y.*\b
\b\w+_\w+\b
\b_\w+\b
batchBucket
batchInterval
commentPrefix
destinationBucket
destinationHost
destinationOrg
destinationToken
docs-v2
fieldKey
fieldType
groupId
hostURL
hostUrl
influx3
influxctl
influxd
influxdata.com
iox
lat
locf
logicalplan
noaa|NOAA
npm|NPM
oauth|OAuth
pandas
quoteChar
retentionRules
sourceBucket
tagKey
v2
v3
venv

28
.ci/vale/vale.sh Normal file → Executable file
View File

@ -1,16 +1,20 @@
# Lint cloud-dedicated
docspath=.
contentpath=$docspath/content
#!/bin/bash
# Vale searches for a configuration file (.vale.ini) in the directory of the file being linted, and then in each of its parent directories.
# Lint cloud-dedicated
npx vale --output=line --relative --minAlertLevel=error $contentpath/influxdb/cloud-dedicated
# Run Vale to lint files for writing style and consistency
# Lint cloud-serverless
npx vale --config=$contentpath/influxdb/cloud-serverless/.vale.ini --output=line --relative --minAlertLevel=error $contentpath/influxdb/cloud-serverless
# Example usage:
# Lint clustered
npx vale --config=$contentpath/influxdb/clustered/.vale.ini --output=line --relative --minAlertLevel=error $contentpath/influxdb/clustered
# Lint all added and modified files in the cloud-dedicated directory and report suggestions, warnings, and errors.
# Lint telegraf
# npx vale --config=$docspath/.vale.ini --output=line --relative --minAlertLevel=error $contentpath/telegraf
# git diff --name-only --diff-filter=d HEAD | grep "content/influxdb/cloud-dedicated" | xargs .ci/vale/vale.sh --minAlertLevel=suggestion --config=content/influxdb/cloud-dedicated/.vale.ini
# Lint files provided as arguments
docker run \
--rm \
--label tag=influxdata-docs \
--label stage=lint \
--mount type=bind,src=$(pwd),dst=/workdir \
-w /workdir \
--entrypoint /bin/vale \
jdkato/vale:latest \
"$@"

View File

@ -27,7 +27,7 @@ function testStagedContent(paths, productPath) {
// This script first checks if there are any tests to run using `pytest --collect-only`.
// If there are tests, it runs them; otherwise, it exits with a success code.
// Whether tests pass or fail, the container is removed,
// but the CONTENT container will remain until the next run.
// but the CONTENT container and associated volume will remain until the next run.
`sh -c "docker run --rm --name ${TEST}-collector \
--env-file ${productPath}/.env.test \
--volumes-from ${CONTENT} \
@ -46,23 +46,55 @@ function testStagedContent(paths, productPath) {
];
}
// Export a lint-staged configuration object.
// Run tests and linters on staged files.
export default {
"*.{js,css}": paths => `prettier --write ${paths.join(' ')}`,
"*.{js,css}": paths => `prettier --write ${paths.join(' ')}`,
// Don't let prettier check or write Markdown files for now;
// it indents code blocks within list items, which breaks Hugo's rendering.
// "*.md": paths => `prettier --check ${paths.join(' ')}`,
"*.md": paths => `.ci/vale/vale.sh --config .vale.ini ${paths} --min|| true`,
"content/influxdb/cloud-dedicated/**/*.md":
paths => [...testStagedContent(paths, 'content/influxdb/cloud-dedicated')],
"content/influxdb/cloud-serverless/**/*.md":
paths => [...testStagedContent(paths, 'content/influxdb/cloud-serverless')],
"content/influxdb/clustered/**/*.md":
paths => [...testStagedContent(paths, 'content/influxdb/clustered')],
// "content/influxdb/cloud-serverless/**/*.md": "docker compose run -T lint --config=content/influxdb/cloud-serverless/.vale.ini --minAlertLevel=error",
"content/influxdb/api-docs/": paths =>
`.ci/vale/vale.sh --config .vale.ini --minAlertLevel error ${paths}`,
// "content/influxdb/clustered/**/*.md": "docker compose run -T lint --config=content/influxdb/clustered/.vale.ini --minAlertLevel=error",
"content/influxdb/cloud/**/*.md":
paths => [
`.ci/vale/vale.sh --config .vale.ini --minAlertLevel error ${paths}`,
...testStagedContent(paths, 'content/influxdb/cloud'),
],
// "content/influxdb/{cloud,v2,telegraf}/**/*.md": "docker compose run -T lint --config=.vale.ini --minAlertLevel=error"
"content/influxdb/cloud-dedicated/**/*.md":
paths => [
`.ci/vale/vale.sh --config content/influxdb/cloud-dedicated/.vale.ini --minAlertLevel error ${paths}`,
...testStagedContent(paths, 'content/influxdb/cloud-dedicated'),
],
"content/influxdb/cloud-serverless/**/*.md":
paths => [
`.ci/vale/vale.sh --config content/influxdb/cloud-serverless/.vale.ini --minAlertLevel error ${paths}`,
...testStagedContent(paths, 'content/influxdb/cloud-serverless'),
],
"content/influxdb/clustered/**/*.md":
paths => [
`.ci/vale/vale.sh --config content/influxdb/clustered/.vale.ini --minAlertLevel error ${paths}`,
...testStagedContent(paths, 'content/influxdb/clustered'),
],
"content/influxdb/v1/**/*.md":
paths => [
`.ci/vale/vale.sh --config .vale.ini --minAlertLevel error ${paths}`,
...testStagedContent(paths, 'content/influxdb/v1'),
],
"content/influxdb/v2/**/*.md":
paths => [
`.ci/vale/vale.sh --config .vale.ini --minAlertLevel error ${paths}`,
...testStagedContent(paths, 'content/influxdb/v2'),
],
"content/telegraf/**/*.md":
paths => [
`.ci/vale/vale.sh --config .vale.ini --minAlertLevel error ${paths}`,
...testStagedContent(paths, 'content/telegraf'),
],
}

View File

@ -1,12 +1,15 @@
StylesPath = ".ci/vale/styles"
StylesPath = .ci/vale/styles
MinAlertLevel = warning
Packages = Google, Hugo, write-good
Vocab = InfluxDataDocs
Packages = Google, write-good, Hugo
[*.md]
BasedOnStyles = Vale, InfluxDataDocs, Google, write-good
Google.Ellipses = NO
Google.Headings = NO
Google.WordList = NO
Google.WordList = NO
Vale.Spelling = NO

View File

@ -1,39 +1,7 @@
# This is a Docker Compose file for the InfluxData documentation site.
## Run documentation tests for code samples.
name: influxdata-docs
volumes:
test-content:
services:
markdownlint:
image: davidanson/markdownlint-cli2:v0.13.0
container_name: markdownlint
profiles:
- ci
- lint
volumes:
- type: bind
source: .
target: /workdir
working_dir: /workdir
build:
context: .
vale:
image: jdkato/vale:latest
container_name: vale
profiles:
- ci
- lint
volumes:
- type: bind
source: .
target: /workdir
working_dir: /workdir
entrypoint: ["/bin/vale"]
build:
context: .
dockerfile_inline: |
COPY .ci /src/.ci
COPY **/.vale.ini /src/
## Run InfluxData documentation with the hugo development server on port 1313.
## For more information about the hugomods/hugo image, see
## https://docker.hugomods.com/docs/development/docker-compose/

View File

@ -1,14 +1,15 @@
StylesPath = "../../../.ci/vale/styles"
Vocab = Cloud-Dedicated
Vocab = InfluxDataDocs
MinAlertLevel = warning
Packages = Google, Hugo, write-good
Packages = Google, write-good, Hugo
[*.md]
BasedOnStyles = Vale, InfluxDataDocs, Google, write-good
BasedOnStyles = Vale, InfluxDataDocs, Cloud-Dedicated, Google, write-good
Google.Ellipses = NO
Google.Headings = NO
Google.WordList = NO
Google.WordList = NO
Vale.Spelling = NO

View File

@ -174,9 +174,7 @@ can write data to {{% product-name %}}.
## Authorization
**{{% product-name %}} requires authentication** using
[tokens](/influxdb/cloud-dedicated/admin/tokens/).
There are two types of tokens:
one of the following [token](/influxdb/cloud-dedicated/admin/tokens/) types:
- **Database token**: A token that grants read and write access to InfluxDB
databases.

View File

@ -1,14 +1,15 @@
StylesPath = "../../../.ci/vale/styles"
Vocab = Cloud-Serverless
Vocab = InfluxDataDocs
MinAlertLevel = warning
Packages = Google, Hugo, write-good
Packages = Google, write-good, Hugo
[*.md]
BasedOnStyles = Vale, InfluxDataDocs, Google, write-good
BasedOnStyles = Vale, InfluxDataDocs, Cloud-Serverless, Google, write-good
Google.Ellipses = NO
Google.Headings = NO
Google.WordList = NO
Google.WordList = NO
Vale.Spelling = NO

View File

@ -1,14 +1,15 @@
StylesPath = "../../../.ci/vale/styles"
Vocab = Clustered
Vocab = InfluxDataDocs
MinAlertLevel = warning
Packages = Google, Hugo, write-good
Packages = Google, write-good, Hugo
[*.md]
BasedOnStyles = Vale, InfluxDataDocs, Google, write-good
BasedOnStyles = Vale, InfluxDataDocs, Clustered, Google, write-good
Google.Ellipses = NO
Google.Headings = NO
Google.WordList = NO
Google.WordList = NO
Vale.Spelling = NO

View File

@ -161,9 +161,7 @@ They use the HTTP API to write data and use InfluxDB's Flight gRPC API to query
## Authorization
**{{% product-name %}} requires authentication** using
[tokens](/influxdb/clustered/admin/tokens/).
There are two types of tokens:
one of the following [token](/influxdb/clustered/admin/tokens/) types:
- **Database token**: A token that grants read and write access to InfluxDB
databases.

View File

@ -20,9 +20,15 @@
"js-yaml": "^4.1.0"
},
"scripts": {
"lint-cloud": "git diff --name-only --diff-filter=d HEAD | grep \"content/influxdb/cloud\" | xargs .ci/vale/vale.sh --minAlertLevel=suggestion --config=.vale.ini",
"lint-clustered": "git diff --name-only --diff-filter=d HEAD | grep \"content/influxdb/clustered\" | xargs .ci/vale/vale.sh --minAlertLevel=suggestion --config=content/influxdb/clustered/.vale.ini",
"lint-dedicated": "git diff --name-only --diff-filter=d HEAD | grep \"content/influxdb/cloud-dedicated\" | xargs .ci/vale/vale.sh --minAlertLevel=suggestion --config=content/influxdb/cloud-dedicated/.vale.ini",
"lint-serverless": "git diff --name-only --diff-filter=d HEAD | grep \"content/influxdb/cloud-serverless\" | xargs .ci/vale/vale.sh --minAlertLevel=suggestion --config=content/influxdb/cloud-serverless/.vale.ini",
"lint-telegraf": "git diff --name-only --diff-filter=d HEAD | grep \"content/telegraf\" | xargs .ci/vale/vale.sh --minAlertLevel=suggestion --config=.vale.ini",
"lint-v1": "git diff --name-only --diff-filter=d HEAD | grep \"content/influxdb/v1\" | xargs .ci/vale/vale.sh --minAlertLevel=suggestion --config=.vale.ini",
"lint-v2": "git diff --name-only --diff-filter=d HEAD | grep \"content/influxdb/v2\" | xargs .ci/vale/vale.sh --minAlertLevel=suggestion --config=.vale.ini",
"prepare": "husky",
"lint-vale": ".ci/vale/vale.sh",
"lint-staged": "lint-staged --relative"
"test": "lint-staged --relative"
},
"main": "index.js",
"module": "main.js",