1--- 2stage: none 3group: Documentation Guidelines 4info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments 5description: Learn how to contribute to GitLab Documentation. 6--- 7 8# Documentation testing 9 10GitLab documentation is stored in projects with code and treated like code. Therefore, we use 11processes similar to those used for code to maintain standards and quality of documentation. 12 13We have tests: 14 15- To lint the words and structure of the documentation. 16- To check the validity of internal links within the documentation suite. 17- To check the validity of links from UI elements, such as files in `app/views` files. 18 19For the specifics of each test run in our CI/CD pipelines, see the configuration for those tests 20in the relevant projects: 21 22- <https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/docs.gitlab-ci.yml> 23- <https://gitlab.com/gitlab-org/gitlab-runner/-/blob/main/.gitlab/ci/docs.gitlab-ci.yml> 24- <https://gitlab.com/gitlab-org/omnibus-gitlab/-/blob/master/gitlab-ci-config/gitlab-com.yml> 25- <https://gitlab.com/gitlab-org/charts/gitlab/-/blob/master/.gitlab-ci.yml> 26 27## Run tests locally 28 29Similar to [previewing your changes locally](index.md#previewing-the-changes-live), you can also 30run these tests on your local computer. This has the advantage of: 31 32- Speeding up the feedback loop. You can know of any problems with the changes in your branch 33 without waiting for a CI/CD pipeline to run. 34- Lowering costs. Running tests locally is cheaper than running tests on the cloud 35 infrastructure GitLab uses. 36 37To run tests locally, it's important to: 38 39- [Install the tools](#install-linters), and [keep them up to date](#update-linters). 40- Run [linters](#lint-checks), [documentation link tests](#documentation-link-tests), and 41 [UI link tests](#ui-link-tests) the same way they are run in CI/CD pipelines. It's important to use 42 same configuration we use in CI/CD pipelines, which can be different than the default configuration 43 of the tool. 44 45### Lint checks 46 47Lint checks are performed by the [`lint-doc.sh`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/scripts/lint-doc.sh) 48script and can be executed as follows: 49 501. Navigate to the `gitlab` directory. 511. Run: 52 53 ```shell 54 MD_DOC_PATH=path/to/my_doc.md scripts/lint-doc.sh 55 ``` 56 57Where `MD_DOC_PATH` points to the file or directory you would like to run lint checks for. 58If you omit it completely, it defaults to the `doc/` directory. 59The output should be similar to: 60 61```plaintext 62=> Linting documents at path /path/to/gitlab as <user>... 63=> Checking for cURL short options... 64=> Checking for CHANGELOG.md duplicate entries... 65=> Checking /path/to/gitlab/doc for executable permissions... 66=> Checking for new README.md files... 67=> Linting markdown style... 68=> Linting prose... 69✔ 0 errors, 0 warnings and 0 suggestions in 1 file. 70✔ Linting passed 71``` 72 73This requires you to either: 74 75- Have the [required lint tools installed](#local-linters) on your computer. 76- A working Docker installation, in which case an image with these tools pre-installed is used. 77 78### Documentation link tests 79 80To execute documentation link tests locally: 81 821. Navigate to the [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs) directory. 831. Run the following commands: 84 85 ```shell 86 # Check for broken internal links 87 bundle exec nanoc check internal_links 88 89 # Check for broken external links (might take a lot of time to complete). 90 # This test is set to be allowed to fail and is run only in the gitlab-docs project CI 91 bundle exec nanoc check internal_anchors 92 ``` 93 94### UI link tests 95 96The `ui-docs-links lint` job uses `haml-lint` to test that all documentation links from 97UI elements (`app/views` files, for example) are linking to valid pages and anchors. 98 99To run the `ui-docs-links` test locally: 100 1011. Open the `gitlab` directory in a terminal window. 1021. Run: 103 104 ```shell 105 bundle exec haml-lint -i DocumentationLinks 106 ``` 107 108If you receive an error the first time you run this test, run `bundle install`, which 109installs the dependencies for GitLab, and try again. 110 111If you don't want to install all of the dependencies to test the links, you can: 112 1131. Open the `gitlab` directory in a terminal window. 1141. Install `haml-lint`: 115 116 ```shell 117 gem install haml_lint 118 ``` 119 1201. Run: 121 122 ```shell 123 haml-lint -i DocumentationLinks 124 ``` 125 126If you manually install `haml-lint` with this process, it does not update automatically 127and you should make sure your version matches the version used by GitLab. 128 129## Local linters 130 131To help adhere to the [documentation style guidelines](styleguide/index.md), and improve the content 132added to documentation, [install documentation linters](#install-linters) and 133[integrate them with your code editor](#configure-editors). 134 135At GitLab, we mostly use: 136 137- [markdownlint](#markdownlint) 138- [Vale](#vale) 139 140### markdownlint 141 142[markdownlint](https://github.com/DavidAnson/markdownlint) checks that Markdown syntax follows 143[certain rules](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#rules), and is 144used by the `docs-lint` test. 145 146Our [Documentation Style Guide](styleguide/index.md#markdown) and 147[Markdown Guide](https://about.gitlab.com/handbook/markdown-guide/) elaborate on which choices must 148be made when selecting Markdown syntax for GitLab documentation. This tool helps catch deviations 149from those guidelines. 150 151markdownlint configuration is found in the following projects: 152 153- [`gitlab`](https://gitlab.com/gitlab-org/gitlab) 154- [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner) 155- [`omnibus-gitlab`](https://gitlab.com/gitlab-org/omnibus-gitlab) 156- [`charts`](https://gitlab.com/gitlab-org/charts/gitlab) 157- [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit) 158 159This configuration is also used in build pipelines. 160 161You can use markdownlint: 162 163- [On the command line](https://github.com/igorshubovych/markdownlint-cli#markdownlint-cli--). 164- [In a code editor](#configure-editors). 165- [In a `pre-push` hook](#configure-pre-push-hooks). 166 167### Vale 168 169[Vale](https://docs.errata.ai/vale/about/) is a grammar, style, and word usage linter for the 170English language. Vale's configuration is stored in the 171[`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.vale.ini) file located in the root 172directory of projects. 173 174Vale supports creating [custom tests](https://errata-ai.github.io/vale/styles/) that extend any of 175several types of checks, which we store in the `.linting/vale/styles/gitlab` directory in the 176documentation directory of projects. 177 178You can find Vale configuration in the following projects: 179 180- [`gitlab`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/.vale/gitlab) 181- [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner/-/tree/main/docs/.vale/gitlab) 182- [`omnibus-gitlab`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/tree/master/doc/.vale/gitlab) 183- [`charts`](https://gitlab.com/gitlab-org/charts/gitlab/-/tree/master/doc/.vale/gitlab) 184- [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/tree/master/doc/.vale/gitlab) 185 186This configuration is also used in build pipelines, where 187[error-level rules](#vale-result-types) are enforced. 188 189You can use Vale: 190 191- [On the command line](https://docs.errata.ai/vale/cli). 192- [In a code editor](#configure-editors). 193- [In a Git hook](#configure-pre-push-hooks). Vale only reports errors in the Git hook (the same 194 configuration as the CI/CD pipelines), and does not report suggestions or warnings. 195 196#### Vale result types 197 198Vale returns three types of results: `suggestion`, `warning`, and `error`: 199 200- **Suggestion**-level results are writing tips and aren't displayed in CI 201 job output. Suggestions don't break CI. See a list of 202 [suggestion-level rules](https://gitlab.com/search?utf8=✓&snippets=false&scope=&repository_ref=master&search=path%3Adoc%2F.vale%2Fgitlab+Suggestion%3A&group_id=9970&project_id=278964). 203- **Warning**-level results are [Style Guide](styleguide/index.md) violations, aren't displayed in CI 204 job output, and should contain clear explanations of how to resolve the warning. 205 Warnings may be technical debt, or can be future error-level test items 206 (after the Technical Writing team completes its cleanup). Warnings don't break CI. See a list of 207 [warning-level rules](https://gitlab.com/search?utf8=✓&snippets=false&scope=&repository_ref=master&search=path%3Adoc%2F.vale%2Fgitlab+Warning%3A&group_id=9970&project_id=278964). 208- **Error**-level results are Style Guide violations, and should contain clear explanations 209 of how to resolve the error. Errors break CI and are displayed in CI job output. See a list of 210 [error-level rules](https://gitlab.com/search?utf8=✓&snippets=false&scope=&repository_ref=master&search=path%3Adoc%2F.vale%2Fgitlab+Error%3A&group_id=9970&project_id=278964). 211 212#### Vale spelling test 213 214When Vale flags a valid word as a spelling mistake, you can fix it following these 215guidelines: 216 217| Flagged word | Guideline | 218|------------------------------------------------------|-----------| 219| jargon | Rewrite the sentence to avoid it. | 220| *correctly-capitalized* name of a product or service | Add the word to the [vale spelling exceptions list](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/spelling-exceptions.txt). | 221| name of a person | Remove the name if it's not needed, or [add the vale exception code in-line](#disable-vale-tests). | 222| a command, variable, code, or similar | Put it in backticks or a code block. For example: ``The git clone command can be used with the CI_COMMIT_BRANCH variable.`` -> ``The `git clone` command can be used with the `CI_COMMIT_BRANCH` variable.`` | 223| UI text from GitLab | Verify it correctly matches the UI, then: If it does not match the UI, update it. If it matches the UI, but the UI seems incorrect, create an issue to see if the UI needs to be fixed. If it matches the UI and seems correct, add it to the [vale spelling exceptions list](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/spelling-exceptions.txt). | 224| UI text from a third-party product | Rewrite the sentence to avoid it, or [add the vale exception code in-line](#disable-vale-tests). | 225 226#### Vale readability score 227 228In [`ReadingLevel.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/ReadingLevel.yml), 229we have implemented 230[the Flesch-Kincaid grade level test](https://readable.com/readability/flesch-reading-ease-flesch-kincaid-grade-level/) 231to determine the readability of our documentation. 232 233As a general guideline, the lower the score, the more readable the documentation. 234For example, a page that scores `12` before a set of changes, and `9` after, indicates an iterative improvement to readability. The score is not an exact science, but is meant to help indicate the 235general complexity level of the page. 236 237The readability score is calculated by using the following formula: 238 239```plaintext 240(.39 x ASL) + (11.8 x ASW) – 15.59 241``` 242 243- `ASL` is average sentence length (the number of words divided by the number of sentences). 244- `ASW` is the average number of syllables per word (the number of syllables divided by the number of words). 245- The score excludes headings, code blocks, and lists. 246 247### Install linters 248 249At a minimum, install [markdownlint](#markdownlint) and [Vale](#vale) to match the checks run in 250build pipelines: 251 2521. Install `markdownlint-cli`: 253 254 ```shell 255 yarn global add markdownlint-cli 256 ``` 257 258 We recommend installing the version of `markdownlint-cli` 259 [used (see `variables:` section)](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/.gitlab-ci.yml) when building 260 the `image:docs-lint-markdown`. 261 2621. Install [`vale`](https://github.com/errata-ai/vale/releases). For example, to install using 263 `brew` for macOS, run: 264 265 ```shell 266 brew install vale 267 ``` 268 269These tools can be [integrated with your code editor](#configure-editors). 270 271### Update linters 272 273It's important to use linter versions that are the same or newer than those run in 274CI/CD. This provides access to new features and possible bug fixes. 275 276To match the versions of `markdownlint-cli` and `vale` used in the GitLab projects, refer to the 277[versions used (see `variables:` section)](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/.gitlab-ci.yml) 278when building the `image:docs-lint-markdown` Docker image containing these tools for CI/CD. 279 280| Tool | Version | Command | Additional information | 281|--------------------|-----------|-------------------------------------------|------------------------| 282| `markdownlint-cli` | Latest | `yarn global add markdownlint-cli` | n/a | 283| `markdownlint-cli` | Specific | `yarn global add markdownlint-cli@0.23.2` | The `@` indicates a specific version, and this example updates the tool to version `0.23.2`. | 284| Vale | Latest | `brew update && brew upgrade vale` | This command is for macOS only. | 285| Vale | Specific | n/a | Not possible using `brew`, but can be [directly downloaded](https://github.com/errata-ai/vale/releases). | 286 287### Configure editors 288 289Using linters in your editor is more convenient than having to run the commands from the 290command line. 291 292To configure markdownlint in your editor, install one of the following as appropriate: 293 294- Sublime Text [`SublimeLinter-contrib-markdownlint` package](https://packagecontrol.io/packages/SublimeLinter-contrib-markdownlint). 295- Visual Studio Code [`DavidAnson.vscode-markdownlint` extension](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint). 296- Atom [`linter-node-markdownlint` package](https://atom.io/packages/linter-node-markdownlint). 297- Vim [ALE plugin](https://github.com/dense-analysis/ale). 298 299To configure Vale in your editor, install one of the following as appropriate: 300 301- Sublime Text [`SublimeLinter-contrib-vale` package](https://packagecontrol.io/packages/SublimeLinter-contrib-vale). 302- Visual Studio Code [`errata-ai.vale-server` extension](https://marketplace.visualstudio.com/items?itemName=errata-ai.vale-server). 303 You can configure the plugin to 304 [display only a subset of alerts](#show-subset-of-vale-alerts). 305 306 In the extension's settings: 307 308 <!-- vale gitlab.Spelling = NO --> 309 310 - Select the **Use CLI** checkbox. 311 - In the **Config** setting, enter an absolute 312 path to [`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.vale.ini) 313 in one of the cloned GitLab repositories on your computer. 314 315 <!-- vale gitlab.Spelling = YES --> 316 317 - In the **Path** setting, enter the absolute path to the Vale binary. In most 318 cases, `vale` should work. To find the location, run `which vale` in a terminal. 319 320- Vim [ALE plugin](https://github.com/dense-analysis/ale). 321- Emacs [Flycheck extension](https://github.com/flycheck/flycheck). 322 This requires some configuration: 323 324 - `Flycheck` supports `markdownlint-cli` out of the box, but you must point it 325 to the `.markdownlint.yml` at the base of the project directory. A `.dir-locals.el` 326 file can accomplish this: 327 328 ```lisp 329 ;; Place this code in a file called `.dir-locals.el` at the root of the gitlab project. 330 ((markdown-mode . ((flycheck-markdown-markdownlint-cli-config . ".markdownlint.yml")))) 331 332 ``` 333 334 - A minimal configuration for Flycheck to work with Vale could look like this: 335 336 ```lisp 337 (flycheck-define-checker vale 338 "A checker for prose" 339 :command ("vale" "--output" "line" "--no-wrap" 340 source) 341 :standard-input nil 342 :error-patterns 343 ((error line-start (file-name) ":" line ":" column ":" (id (one-or-more (not (any ":")))) ":" (message) line-end)) 344 :modes (markdown-mode org-mode text-mode) 345 :next-checkers ((t . markdown-markdownlint-cli)) 346 ) 347 348 (add-to-list 'flycheck-checkers 'vale) 349 ``` 350 351 In this setup the `markdownlint` checker is set as a "next" checker from the defined `vale` checker. 352 Enabling this custom Vale checker provides error linting from both Vale and markdownlint. 353 354We don't use [Vale Server](https://errata-ai.github.io/vale/#using-vale-with-a-text-editor-or-another-third-party-application). 355 356### Configure pre-push hooks 357 358Git [pre-push hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) allow Git users to: 359 360- Run tests or other processes before pushing a branch. 361- Avoid pushing a branch if failures occur with these tests. 362 363[`lefthook`](https://github.com/Arkweid/lefthook) is a Git hooks manager, making configuring, 364installing, and removing Git hooks easy. 365 366Configuration for `lefthook` is available in the [`lefthook.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lefthook.yml) 367file for the [`gitlab`](https://gitlab.com/gitlab-org/gitlab) project. 368 369To set up `lefthook` for documentation linting, see 370[Pre-push static analysis](../contributing/style_guides.md#pre-push-static-analysis-with-lefthook). 371 372### Show subset of Vale alerts 373 374You can set Visual Studio Code to display only a subset of Vale alerts when viewing files: 375 3761. Go to **Preferences > Settings > Extensions > Vale**. 3771. In **Vale CLI: Min Alert Level**, select the minimum alert level you want displayed in files. 378 379To display only a subset of Vale alerts when running Vale from the command line, use 380the `--minAlertLevel` flag, which accepts `error`, `warning`, or `suggestion`. Combine it with `--config` 381to point to the configuration file within the project, if needed: 382 383```shell 384vale --config .vale.ini --minAlertLevel error doc/**/*.md 385``` 386 387Omit the flag to display all alerts, including `suggestion` level alerts. 388 389### Disable Vale tests 390 391You can disable a specific Vale linting rule or all Vale linting rules for any portion of a 392document: 393 394- To disable a specific rule, add a `<!-- vale gitlab.rulename = NO -->` tag before the text, and a 395 `<!-- vale gitlab.rulename = YES -->` tag after the text, replacing `rulename` with the filename 396 of a test in the 397 [GitLab styles](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/.linting/vale/styles/gitlab) 398 directory. 399- To disable all Vale linting rules, add a `<!-- vale off -->` tag before the text, and a 400 `<!-- vale on -->` tag after the text. 401 402Whenever possible, exclude only the problematic rule and lines. 403 404For more information, see 405[Vale's documentation](https://docs.errata.ai/vale/scoping#markup-based-configuration). 406 407### Disable markdownlint tests 408 409To disable all markdownlint rules, add a `<!-- markdownlint-disable -->` tag before the text, and a 410`<!-- markdownlint-enable -->` tag after the text. 411 412To disable only a [specific rule](https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#rules), 413add the rule number to the tag, for example `<!-- markdownlint-disable MD044 -->` 414and `<!-- markdownlint-enable MD044 -->`. 415 416Whenever possible, exclude only the problematic lines. 417