Skip to content

Introduce Vale as a linter#986

Open
BoHristova wants to merge 9 commits into
gardener:masterfrom
BoHristova:vale-implementation-2026-05
Open

Introduce Vale as a linter#986
BoHristova wants to merge 9 commits into
gardener:masterfrom
BoHristova:vale-implementation-2026-05

Conversation

@BoHristova
Copy link
Copy Markdown
Contributor

@BoHristova BoHristova commented May 26, 2026

How to categorize this PR?

/kind enhancement

What this PR does / why we need it:

This PR introduces Vale as a style linter for the documentation website. This is just the initial setup. The Vale rules and dictionaries will be extended and refined over time.

The following things were added:

  • Vale configuration with 7 style rules
  • 4 dictionaries
  • GitHub Actions workflow that posts inline review comments (while the linter is being refined, PRs will remain mergeable even when the check fails)
  • Make targets

Which issue(s) this PR fixes:
Fixes #975

Special notes for your reviewer:
/cc @klocke-io @marc1404

Summary by CodeRabbit

Release Notes

  • Chores
    • Added automated documentation quality checks that run on pull requests to ensure consistent style, grammar, and spelling across markdown files.
    • Documentation style guidelines now enforce best practices for clarity, proper terminology, and inclusive language.
    • Linting errors are reported directly in pull request reviews.

Review Change Stack

Signed-off-by: Bozhidara Hristova <bozhidara.hristova@sap.com>
Signed-off-by: Bozhidara Hristova <bozhidara.hristova@sap.com>
Signed-off-by: Bozhidara Hristova <bozhidara.hristova@sap.com>
Signed-off-by: Bozhidara Hristova <bozhidara.hristova@sap.com>
Signed-off-by: Bozhidara Hristova <bozhidara.hristova@sap.com>
Use tj-actions/changed-files to scope Vale to changed files only,
avoiding scanning the entire website/ directory on every PR.

Signed-off-by: Bozhidara Hristova <bozhidara.hristova@sap.com>
Use comma separator instead of JSON to avoid escaped quote issues.

Signed-off-by: Bozhidara Hristova <bozhidara.hristova@sap.com>
Signed-off-by: Bozhidara Hristova <bozhidara.hristova@sap.com>
Signed-off-by: Bozhidara Hristova <bozhidara.hristova@sap.com>
@gardener-prow gardener-prow Bot requested review from klocke-io and marc1404 May 26, 2026 10:48
@gardener-prow gardener-prow Bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. kind/enhancement Enhancement, improvement, extension labels May 26, 2026
@netlify
Copy link
Copy Markdown

netlify Bot commented May 26, 2026

Deploy Preview for gardener-docs ready!

Name Link
🔨 Latest commit d6db282
🔍 Latest deploy log https://app.netlify.com/projects/gardener-docs/deploys/6a157a64a422420008e2a1db
😎 Deploy Preview https://deploy-preview-986--gardener-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

📝 Walkthrough

Walkthrough

This PR introduces Vale prose linting to the Gardener documentation repository. It configures Vale with a Gardener-specific style, defines seven linting rules for documentation quality, populates vocabulary lists for domain-specific and third-party terms, adds local Make targets for installation and execution, and integrates automated linting into the GitHub Actions CI pipeline.

Changes

Vale Linting System Implementation

Layer / File(s) Summary
Core Vale Configuration
[.vale.ini](https://github.com/gardener/documentation/blob/main/.vale.ini)
Configuration establishes MinAlertLevel, vocabulary paths (GardenerTerms, ThirdPartyProducts, TechJargon, General, Places), globally ignored scopes (code, tt, code block), Markdown-specific extensions to the Gardener style with token/block ignores for Jinja templates, and per-file overrides that disable checks for legal disclosure and archived content.
Local Tooling: Make Targets
Makefile
Three new targets enable Vale integration: vale-install conditionally downloads the Vale binary for the host OS/architecture into bin/, vale-run computes changed website/**/*.md files via git-diff and runs Vale (excluding legal-disclosure.md and archived paths), and vale chains both. The ci-build target is marked .PHONY and orchestrates docforge-ci, install, post-process, and build steps.
Gardener Style Rules
.vale/styles/Gardener/*.yml
Seven YAML rules compose the Gardener style: Articles warns on incorrect a/an usage before acronyms with vowel/consonant mappings; CommandPrompt errors on $ patterns in raw text; Links warns on generic anchor text ([here], [click here], [read more], [learn more]); SecondPerson warns on "the user" constructions and suggests "you" forms; Spelling extends Vale's spelling check with error-level messaging and regex filters for acronyms, camelCase, versions, and identifiers; Terms errors on incorrect capitalization for project names (Kubernetes, Gardener, OpenStack, GitHub, GitLab, vSphere); WordChoice warns on non-inclusive terminology like greylist/grey-list.
Vocabulary & Terminology Lists
.vale/styles/config/vocabularies/*/{accept,reject}.txt
Five vocabulary lists populate accepted and rejected terms: GardenerTerms/accept.txt lists Gardener-specific terms (gardenadm, etcd-druid, gardenlet, docforge, Terraformer); General/accept.txt contains 27 loanwords and place names (Leverkusen, Weyhe, homogenous, reenable); TechJargon/accept.txt enumerates 1300+ technical terms covering networking, cloud, security, and development jargon; ThirdPartyProducts/accept.txt allowlists 500+ third-party product names with case-insensitive patterns; ThirdPartyProducts/reject.txt flags incorrect capitalizations (Fluentbit→fluentbit, Metallb→metallb, Wireguard→wireguard).
GitHub Actions CI Workflow
.github/workflows/vale.yml
Workflow runs Vale linting on PR events (opened, synchronize, reopened) and manual dispatch, scoped to changes under website/**/*.md, .vale.ini, and .vale/**. It checks out the repo, computes the changed file list via shell script (excluding legal-disclosure.md and archived paths), conditionally invokes the Vale action, sets concurrency to cancel in-progress runs for the same workflow/ref, limits permissions to contents:read and pull-requests:write, and configures Vale to fail on errors with warning-level minimum alerts and GitHub PR review reporter output.

Sequence Diagram

sequenceDiagram
  participant Developer
  participant LocalMake as Make (Local)
  participant GitDiff as git diff
  participant ValeExe as Vale Binary
  participant GHWorkflow as GitHub Actions Workflow
  participant ValeAction as Vale Action
  Developer->>LocalMake: make vale
  LocalMake->>LocalMake: vale-install (check bin/vale or PATH)
  LocalMake->>GitDiff: compute changed website/**/*.md
  GitDiff-->>LocalMake: file list (excluding legal/archived)
  LocalMake->>ValeExe: vale --output=JSON changed_files
  ValeExe-->>LocalMake: linting results
  Developer->>Developer: push to PR
  GHWorkflow->>GHWorkflow: triggered (opened/synchronize/reopened)
  GHWorkflow->>GitDiff: compute changed website/**/*.md
  GitDiff-->>GHWorkflow: file list (excluding legal/archived)
  GHWorkflow->>ValeAction: run with file list
  ValeAction->>ValeExe: execute Vale with GitHub reporter
  ValeExe-->>ValeAction: linting results
  ValeAction-->>GHWorkflow: PR review comments
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

size/XL

Suggested reviewers

  • marc1404
  • klocke-io

Poem

🐰 Vale's here to check our prose so fine,
Style rules and terms all in a line,
Vocabularies grow, no typos shall pass,
GitHub Actions now guard the grass!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Introduce Vale as a linter' is concise, clear, and directly summarizes the main change in the PR.
Description check ✅ Passed The PR description addresses the required template sections: it specifies the kind (/kind enhancement), explains what was added and why, and references the linked issue (#975).
Linked Issues check ✅ Passed All coding requirements from issue #975 are met: Vale rules and vocabularies added, make targets implemented, CI workflow configured, and PR review integration via GitHub Actions enabled.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing Vale as a linter. No unrelated or out-of-scope modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gardener-prow gardener-prow Bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label May 26, 2026
@gardener-prow
Copy link
Copy Markdown

gardener-prow Bot commented May 26, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign msohn for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@gardener-prow gardener-prow Bot added the cla: yes Indicates the PR's author has signed the cla-assistant.io CLA. label May 26, 2026
@BoHristova BoHristova changed the title Vale implementation 2026 05 Introduce Vale as a linter May 26, 2026
@BoHristova BoHristova marked this pull request as ready for review May 26, 2026 11:22
@BoHristova BoHristova requested a review from a team as a code owner May 26, 2026 11:22
@gardener-prow gardener-prow Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 26, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
.vale/styles/Gardener/WordChoice.yml (1)

2-2: 💤 Low value

Consider clarifying the rule message.

The message "Prefer inclusive and modern terminology" doesn't quite fit the greylist/graylist spelling preference, which is about American vs. British English rather than inclusivity. Consider a more specific message like "Use American English spelling" or keep a generic message like "Use '%s' instead of '%s'" without the inclusivity reference.

📝 Proposed message alternatives

Option 1 - Generic:

-message: "Use '%s' instead of '%s'. Prefer inclusive and modern terminology."
+message: "Use '%s' instead of '%s'."

Option 2 - Specific to spelling:

-message: "Use '%s' instead of '%s'. Prefer inclusive and modern terminology."
+message: "Use '%s' instead of '%s'. Use American English spelling."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.vale/styles/Gardener/WordChoice.yml at line 2, Update the rule message in
the WordChoice.yml entry that currently reads "Use '%s' instead of '%s'. Prefer
inclusive and modern terminology." to a clearer, more accurate phrase about
spelling—for example "Use '%s' instead of '%s'. Use American English spelling."
or simply "Use '%s' instead of '%s'." Replace the existing message value
accordingly so the wording matches the greylist/graylist spelling preference and
remove the misleading "inclusive" wording.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/vale.yml:
- Around line 26-31: Pin mutable GitHub Action tags to immutable commit SHAs and
disable credential persistence on checkout: replace uses: actions/checkout@v4
with the actions/checkout commit SHA and add with: persist-credentials: false in
the "Checkout" step; replace uses: tj-actions/changed-files@v45 with that
action's specific commit SHA; likewise pin vale-cli/vale-action@v2.1.1 to its
immutable commit SHA; keep existing separator: "," settings unchanged.

In @.vale.ini:
- Line 4: The Vale config references a missing vocabulary:
.vale/styles/Gardener/Spelling.yml uses "Places/accept.txt" in its ignore list
but .vale.ini's Vocab omits "Places" and the Places vocabulary directory/file
doesn't exist; either add a new vocabulary directory
.vale/styles/config/vocabularies/Places with an accept.txt file and add "Places"
to the Vocab line in .vale.ini, or remove the "Places/accept.txt" entry from
.vale/styles/Gardener/Spelling.yml if that ignore is not needed. Ensure the
Vocab list includes the exact token "Places" and that the accept.txt path
matches the referenced "Places/accept.txt".

In @.vale/styles/config/vocabularies/TechJargon/accept.txt:
- Around line 874-875: The vocabulary file mixes British and American spellings
(e.g., "productisation" vs "productization" and elsewhere
"virtualise"/"virtualised" vs "virtualized"); choose one variant and update the
entries in the vocab list to the selected spelling (replace "productisation"
with "productization" if standardizing on American, or vice versa), or if you
intend to accept both, add a header comment to this file documenting that both
variants are permitted; ensure the changes reference the exact tokens shown
("productisation"/"productization" and the
"virtualise"/"virtualised"/"virtualized" group) so the spellings remain
consistent across the file.
- Line 847: Update the TechJargon accept list entry for PoC to be
case-insensitive so uppercase POC is accepted; locate the existing "PoC" token
in the TechJargon vocabulary (the current entry is "PoC") and replace it with a
case-insensitive form like "(?i)PoC" or add an additional "POC" entry so both
"PoC" and "POC" pass validation, leaving other case-sensitive tokens (e.g.,
"const", "sshd", "Visio") unchanged.

In `@Makefile`:
- Around line 207-216: The vale-run target fails after a fresh install because
it calls the bare `vale` binary even though `vale-install` puts the executable
at `bin/vale`; update the `vale-run` recipe so it prefers `bin/vale` when
present (executable) and falls back to `vale` on PATH otherwise (e.g., test for
`bin/vale` and run `./bin/vale $$CHANGED` if found, else `vale $$CHANGED`),
keeping the existing CHANGED detection and output logic intact and referencing
the `vale-run` target and the `bin/vale` location.

---

Nitpick comments:
In @.vale/styles/Gardener/WordChoice.yml:
- Line 2: Update the rule message in the WordChoice.yml entry that currently
reads "Use '%s' instead of '%s'. Prefer inclusive and modern terminology." to a
clearer, more accurate phrase about spelling—for example "Use '%s' instead of
'%s'. Use American English spelling." or simply "Use '%s' instead of '%s'."
Replace the existing message value accordingly so the wording matches the
greylist/graylist spelling preference and remove the misleading "inclusive"
wording.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: aa849863-5dc0-4ed1-b401-2c2ba27500ab

📥 Commits

Reviewing files that changed from the base of the PR and between 3eff8f9 and d6db282.

📒 Files selected for processing (15)
  • .github/workflows/vale.yml
  • .vale.ini
  • .vale/styles/Gardener/Articles.yml
  • .vale/styles/Gardener/CommandPrompt.yml
  • .vale/styles/Gardener/Links.yml
  • .vale/styles/Gardener/SecondPerson.yml
  • .vale/styles/Gardener/Spelling.yml
  • .vale/styles/Gardener/Terms.yml
  • .vale/styles/Gardener/WordChoice.yml
  • .vale/styles/config/vocabularies/GardenerTerms/accept.txt
  • .vale/styles/config/vocabularies/General/accept.txt
  • .vale/styles/config/vocabularies/TechJargon/accept.txt
  • .vale/styles/config/vocabularies/ThirdPartyProducts/accept.txt
  • .vale/styles/config/vocabularies/ThirdPartyProducts/reject.txt
  • Makefile

Comment on lines +26 to +31
- name: Checkout
uses: actions/checkout@v4

- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v45
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

tj-actions/changed-files security incident 2024

💡 Result:

In March 2025, the popular GitHub Action tj-actions/changed-files was the subject of a significant supply chain security incident, tracked as CVE-2025-30066 [1][2][3]. The incident involved an attacker gaining unauthorized access to the tj-actions/changed-files repository and retroactively modifying multiple version tags to point to a malicious commit (0e58ed8671d6b60d0890c21b07f8835ace038e67) [1][3][4]. This malicious code executed a Python script that scanned the memory of the GitHub Runner process to extract CI/CD secrets [1][2][5]. These secrets were then printed to the workflow logs [1][6][7]. If the repository had public workflow logs, these secrets became publicly accessible [1][3][6]. The vulnerability was active between March 14 and March 15, 2025 [1][6]. During this time, it impacted over 23,000 repositories [1][6][5]. The incident was mitigated after GitHub took down the repository briefly to remove the malicious commits and restore legitimate tags [2][7]. It is important to distinguish this 2025 incident from a separate, earlier vulnerability in the same action, CVE-2023-51664, which was disclosed in December 2023 and addressed command injection risks [8][9][7]. Organizations that utilized tj-actions/changed-files during the March 2025 compromise window were advised to rotate any secrets that were accessible to the affected CI/CD environments [2][3][5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/vale.yml"

echo "== File: $FILE =="
nl -ba "$FILE" | sed -n '1,200p'

Repository: gardener/documentation

Length of output: 166


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/vale.yml"

echo "== File: $FILE =="
cat -n "$FILE" | sed -n '1,200p'

echo
echo "== Grep for relevant inputs/actions =="
rg -n "vale|separator|uses: |persist-credentials|tj-actions/changed-files|actions/checkout" "$FILE" || true

Repository: gardener/documentation

Length of output: 1911


🌐 Web query:

tj-actions/changed-files separator input valid values documentation

💡 Result:

For the tj-actions/changed-files GitHub Action, the separator input does not have a constrained list of valid values [1][2]. Instead, it accepts any string character or sequence of characters that you wish to use as a delimiter for the action's output strings [1][2]. Key details regarding the separator input and related configurations include: - Purpose: The separator input defines the split character used for output strings generated by the action [1][2]. - Default Value: The default value for separator is a single space (" ") [1][2]. - Other Separator Inputs: The action also provides specific separator inputs for other configurations, which default to a newline character ("\n") [1][2]: - files_separator: Used to split the files input [1][2]. - files_from_source_file_separator: Used to split the files_from_source_file input [1][2]. - files_yaml_from_source_file_separator: Used to split the files_yaml_from_source_file input [1][2]. - old_new_separator: Used to split old and new filename pairs, defaulting to a comma (",") [1][2]. - old_new_files_separator: Used to split old and new renamed filename pairs, defaulting to a space (" ") [1][2]. As there is no restricted enum or list of valid values, you can provide any valid string consistent with your workflow's requirements [1][2].

Citations:


🌐 Web query:

vale-cli/vale-action separator input documentation

💡 Result:

In the vale-cli/vale-action GitHub Action, the separator input is an optional parameter used to define the delimiter character for the files input when it is provided as a character-delimited list [1][2][3]. When you provide the files input as a string of files (e.g., 'input1,input2'), the action uses the separator input to determine how to split that string into individual file or directory arguments for the Vale CLI [1][3]. Example usage from the official documentation: yaml - uses: vale-cli/vale-action@v2.1.1 with: files: 'input1,input2' separator: "," In this configuration, the action effectively runs vale input1 input2 [1][3]. If the separator input is not explicitly defined, the default behavior for the files input varies based on the format supplied (e.g., it defaults to 'all' if no value is provided, or you can provide a JSON-formatted list as an alternative to the delimited string approach) [1][3].

Citations:


🌐 Web query:

actions/checkout v4.2.2 commit SHA 11bd71901bbe5b1630ceea73d27597364c9af683

💡 Result:

The commit SHA 11bd71901bbe5b1630ceea73d27597364c9af683 corresponds to the official release of actions/checkout version 4.2.2 [1][2]. This release was prepared on October 23, 2024 [1], and included updates to url-helper.ts to leverage well-known environment variables, as well as expanded unit test coverage for isGhes [1][2]. Users frequently pin this action to specific commit SHAs like this one as a security best practice to ensure the integrity of the code being executed in CI/CD pipelines [3][4][5].

Citations:


🌐 Web query:

tj-actions/changed-files v45.0.4 commit SHA 4edd678ac3f81e2dc578756871e4d00c19191daf

💡 Result:

The commit SHA 4edd678ac3f81e2dc578756871e4d00c19191daf is a specific, valid commit referenced in various GitHub Actions workflows, including those using the tj-actions/changed-files action [1][2]. It is not, however, a release tag for the tj-actions/changed-files repository itself, which uses versioning formats such as v45.0.4 [3]. This specific commit hash appears in technical documentation and configuration files for multiple projects (e.g., Kong/sdk-portal-js, and various CI/CD templates) [1][2]. Contextual Note: The tj-actions/changed-files repository experienced a notable supply chain incident in March 2025 [4][5]. During this event, malicious commits were injected into the repository, and tags were manipulated to point to rogue commits, potentially affecting users who pinned actions to tags or branches [4]. Security researchers and community advisories emphasize that when using third-party GitHub Actions, pinning to a specific, verified commit SHA is a recommended security practice to mitigate the risk of tag-poisoning or "imposter commit" attacks [6][4][7]. Users encountering this specific hash (4edd678ac3f81e2dc578756871e4d00c19191daf) in their workflows should verify it against the source repository's official commit history to ensure its integrity before continued use.

Citations:


🌐 Web query:

tj-actions/changed-files v45.0.4 commit hash

💡 Result:

tj-actions/changed-files v45.0.4 resolves to commit 6809677b7a5911221b35d87417198c8a289e34ec [1].

Citations:


🌐 Web query:

vale-cli/vale-action v2.1.1 commit SHA

💡 Result:

The release v2.1.1 of vale-cli/vale-action (formerly errata-ai/vale-action) was published on October 15, 2024 [1][2]. The specific commit SHA associated with the v2.1.1 tag in the vale-cli/vale-action repository is 0a56e0d. Note: While public GitHub repository interfaces frequently provide the latest release and recent commit logs [1][3], specific tag SHAs can be verified directly via the Git repository metadata (e.g., using git show v2.1.1). Users are encouraged to pin GitHub Actions to specific commit SHAs (e.g., uses: vale-cli/vale-action@0a56e0d) to ensure consistency and security, especially given recent concerns regarding tag-based reference vulnerabilities in supply chains [4].

Citations:


🌐 Web query:

actions/checkout v4.2.2 commit SHA 11bd71901bbe5b1630ceea73d27597364c9af683

💡 Result:

The commit SHA 11bd71901bbe5b1630ceea73d27597364c9af683 corresponds to the release of actions/checkout version 4.2.2 [1][2]. This specific commit was authored by John Wesley Walker III on October 23, 2024, and was used to prepare the v4.2.2 release [1][2]. The changes included in this version were: * Improvements to url-helper.ts, allowing it to better leverage well-known environment variables [1][2]. * Expanded unit test coverage for the isGhes (GitHub Enterprise Server) function [1][2]. Because this SHA refers to the actual source code and bundled JavaScript for the action, it is frequently used by developers to pin workflows to a specific, immutable version of the action to ensure consistency and security [3]. Users occasionally reference this SHA directly in their workflow files, for example: uses: actions/checkout@11bd719 [4][3].

Citations:


🌐 Web query:

actions/checkout v4 commit SHA currently points to

💡 Result:

actions/checkout@v4 currently resolves to commit SHA fd084cde189b7b76ec305d52e27be545a0172823 in the actions/checkout repo [1]. Note: “v4” is a moving ref (tag/branch) and can be repointed; pinning to the full 40-character commit SHA is recommended if you need immutability.

Citations:


🌐 Web query:

tj-actions/changed-files v45 commit SHA currently points to

💡 Result:

The tag tj-actions/changed-files@v45 currently points to commit SHA 0e58ed8671d6b60d0890c21b07f8835ace038e67. [1][2] Reasoning (brief): Multiple security writeups of the incident state that the compromised commit hash is 0e58ed8671d6b60d0890c21b07f8835ace038e67, and that (at least at the time of investigation) affected tag pointers—including v45—point to that same malicious commit. [1][2] Note: The official project also has releases/tags and later security guidance indicates tags were updated after the compromise; however, the sources above explicitly identify the compromised commit SHA as the one the v45 tag pointed to during the incident window. [1][2][3]

Citations:


🌐 Web query:

vale-cli/vale-action v2.1.1 commit SHA currently points to

💡 Result:

As of May 26, 2026, the vale-cli/vale-action version v2.1.1 refers to a release in the GitHub repository. While the repository provides the tag v2.1.1, the specific commit SHA associated with this tag can be verified directly on the repository's GitHub release page [1]. To confirm the exact, immutable commit SHA currently associated with the v2.1.1 tag, you should navigate to the vale-cli/vale-action releases page and click on the "v2.1.1" tag or release. This will display the associated commit hash, which is the most authoritative way to identify the code linked to that version. It is important to note that GitHub Actions are susceptible to tag-based redirection [2]. Security best practices, particularly following recent industry incidents involving malicious tag rewrites [3][2], recommend pinning actions to an immutable commit SHA in your workflow configuration (e.g., uses: vale-cli/vale-action@<COMMIT_SHA>) rather than relying on a mutable version tag [2].

Citations:


🌐 Web query:

GHSA-mw4p-6x4p-x5m5 tj-actions changed-files fixed commit sha

💡 Result:

The security advisory GHSA-mw4p-6x4p-x5m5 pertains to a supply chain compromise of the tj-actions/changed-files GitHub Action, which occurred between March 14 and March 15, 2025 [1]. During this incident, attackers retroactively modified multiple existing version tags to point to a malicious commit with the SHA 0e58ed8671d6b60d0890c21b07f8835ace038e67 [1][2]. This malicious commit executed a Python script that extracted CI/CD secrets from the Runner Worker process memory and printed them to the GitHub Actions logs, exposing them publicly [1][2]. The vulnerability affected versions up to 45.0.7 [1]. The incident was mitigated by updating the affected tags to point to legitimate, secure commits [1]. Users are strongly advised to pin GitHub Actions to full-length, immutable commit SHAs rather than relying on mutable version tags to prevent similar supply chain attacks where tags are redirected to malicious code [2][3].

Citations:


🌐 Web query:

actions/checkout persist-credentials default value

💡 Result:

The default value for the persist-credentials input in the actions/checkout GitHub Action is true [1][2][3]. When set to true (the default), the action automatically configures the local Git repository's configuration with the authentication token or SSH key used for the checkout [1][2]. This allows subsequent steps in the same job to execute authenticated Git commands [1][3]. The token is removed during the post-job cleanup process [1][2]. If you wish to prevent this behavior—for example, to avoid the credentials being exposed to other processes or inadvertently included if the workspace is archived—you can explicitly set this input to false [1][4][5]: - uses: actions/checkout@v4 with: persist-credentials: false

Citations:


Pin GitHub Actions to commit SHAs (and disable checkout credential persistence)

  • tj-actions/changed-files@v45 is a mutable tag; it was involved in the documented compromise (malicious commit 0e58ed8671d6b60d0890c21b07f8835ace038e67), so pin it (and ideally actions/checkout@v4 and vale-cli/vale-action@v2.1.1) to immutable commit SHAs instead of version tags.
  • Add with: persist-credentials: false to the actions/checkout step (default is true).
  • separator: "," is valid for both tj-actions/changed-files and vale-cli/vale-action; no change needed there.
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 26-27: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 27-27: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 31-31: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/vale.yml around lines 26 - 31, Pin mutable GitHub Action
tags to immutable commit SHAs and disable credential persistence on checkout:
replace uses: actions/checkout@v4 with the actions/checkout commit SHA and add
with: persist-credentials: false in the "Checkout" step; replace uses:
tj-actions/changed-files@v45 with that action's specific commit SHA; likewise
pin vale-cli/vale-action@v2.1.1 to its immutable commit SHA; keep existing
separator: "," settings unchanged.

Comment thread .vale.ini
StylesPath = .vale/styles
MinAlertLevel = warning

Vocab = GardenerTerms, ThirdPartyProducts, TechJargon, General
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check if Places vocabulary file exists and is referenced in Spelling.yml

# Check if Places vocabulary directory and file exist
fd -t d "Places" .vale/styles/config/vocabularies/

# Verify reference in Spelling.yml
rg -n "Places/accept.txt" .vale/styles/Gardener/Spelling.yml

Repository: gardener/documentation

Length of output: 90


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show .vale.ini around the Vocab line
echo "=== .vale.ini ==="
nl -ba .vale.ini | sed -n '1,120p'

# Locate Vale vocab directories/files
echo
echo "=== .vale vocabularies dir listing (first 200 entries) ==="
ls -la .vale/styles/config/vocabularies/ | head -n 200

echo
echo "=== fd matches for 'Places' (case-sensitive) ==="
fd -t d "Places" .vale/styles/config/vocabularies/ || true

echo
echo "=== fd matches for 'Places' (case-insensitive) ==="
fd -it "places" -t d .vale/styles/config/vocabularies/ || true

echo
echo "=== Spelling.yml reference ==="
rg -n "Places/accept\.txt" .vale/styles/Gardener/Spelling.yml

Repository: gardener/documentation

Length of output: 145


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== .vale.ini (full) ==="
sed -n '1,200p' .vale.ini || true
echo
echo "=== .vale.ini Vocab line(s) ==="
rg -n '^\s*Vocab\s*=' .vale.ini || true

echo
echo "=== vocabularies dir exists? ==="
ls -la .vale/styles/config/vocabularies/ || true

echo
echo "=== fd matches for 'Places' (exact) ==="
fd -t d "Places" .vale/styles/config/vocabularies/ || true

echo
echo "=== fd matches for 'places' (case-insensitive) ==="
fd -it "places" -t d .vale/styles/config/vocabularies/ || true

echo
echo "=== list vocab directories (names only) ==="
ls -1 .vale/styles/config/vocabularies/ | head -n 200 || true

echo
echo "=== Spelling.yml reference ==="
rg -n "Places/accept\.txt" .vale/styles/Gardener/Spelling.yml || true

Repository: gardener/documentation

Length of output: 1519


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Find occurrences of Places/accept.txt ==="
rg -n "Places/accept\.txt" .vale || true

echo
echo "=== Find accept.txt files under .vale ==="
fd -t f "accept\.txt" .vale || true

echo
echo "=== Find any vocab directories/files mentioning Places under .vale ==="
rg -n "Places" .vale/styles/config/vocabularies .vale/styles/Gardener .vale/styles -S || true

echo
echo "=== List .vale/styles directory (top-level) ==="
ls -la .vale/styles || true

echo
echo "=== List .vale/styles/Gardener (top-level) ==="
ls -la .vale/styles/Gardener || true

echo
echo "=== Show Spelling.yml ==="
sed -n '1,160p' .vale/styles/Gardener/Spelling.yml || true

Repository: gardener/documentation

Length of output: 2507


🌐 Web query:

Vale configuration Vocaboptionspellingruleignoreentries likePlaces/accept.txt behavior when file/directory is missing

💡 Result:

Vale “Vocabularies” don’t provide any documented behavior for an accept.txt/reject.txt entry path like Places/accept.txt when that file/directory is missing; the official docs only describe that a Vocab is a folder containing accept.txt and reject.txt with one regex per line, and that comments (#) are ignored. There is no mention in the docs of a “missing file => ignore/skip silently” fallback, so you should assume Vale expects the files to exist (and you may see a config/load error if they don’t). [1][2] For the analogous spelling rule ignore: mechanism: it is defined as a relative path (from StylesPath) to a file “consisting of one word per line to ignore”; the docs likewise do not describe special handling for missing ignore files. [3] What to do if you’re trying to make the rule tolerant of missing vocab/ignore files: - Prefer ensuring the referenced Vocab folder (and its accept.txt/reject.txt) exists in all environments. - If you need optional behavior, gate it in your CI/build tooling (e.g., only run Vale with that config when the vocab files exist), because Vale’s docs don’t document a built-in “ignore missing file” switch for either Vocab or spelling ignore:. [1][3] If you want, paste your exact .vale.ini (or the relevant YAML rule) and the Vale version; I can look for code/test evidence of the exact failure mode (error vs silent skip) for missing vocab files in that release line.

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check if ignore paths exist under .vale/styles/<Name>/accept.txt ==="
for name in GardenerTerms General TechJargon ThirdPartyProducts Places; do
  p=".vale/styles/$name/accept.txt"
  if [ -f "$p" ]; then
    echo "FOUND: $p"
  else
    echo "MISSING: $p"
  fi
done

echo
echo "=== Check if accept.txt exists under .vale/styles/config/vocabularies/<Name>/accept.txt ==="
for name in GardenerTerms General TechJargon ThirdPartyProducts Places; do
  p=".vale/styles/config/vocabularies/$name/accept.txt"
  if [ -f "$p" ]; then
    echo "FOUND: $p"
  else
    echo "MISSING: $p"
  fi
done

echo
echo "=== Verify .vale.ini StylesPath and Vocab ==="
sed -n '1,10p' .vale.ini

Repository: gardener/documentation

Length of output: 1005


Add missing Places vocabulary to Vale config (or remove its reference)

.vale/styles/Gardener/Spelling.yml references Places/accept.txt in ignore (line 9), but .vale.ini’s Vocab list omits Places and there is no .vale/styles/config/vocabularies/Places/accept.txt directory/file. Add the Places vocab (with accept.txt) and include Places in Vocab, or remove the ignore entry if it’s not needed.

🔧 Proposed fix
-Vocab = GardenerTerms, ThirdPartyProducts, TechJargon, General
+Vocab = GardenerTerms, ThirdPartyProducts, TechJargon, General, Places
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Vocab = GardenerTerms, ThirdPartyProducts, TechJargon, General
Vocab = GardenerTerms, ThirdPartyProducts, TechJargon, General, Places
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.vale.ini at line 4, The Vale config references a missing vocabulary:
.vale/styles/Gardener/Spelling.yml uses "Places/accept.txt" in its ignore list
but .vale.ini's Vocab omits "Places" and the Places vocabulary directory/file
doesn't exist; either add a new vocabulary directory
.vale/styles/config/vocabularies/Places with an accept.txt file and add "Places"
to the Vocab line in .vale.ini, or remove the "Places/accept.txt" entry from
.vale/styles/Gardener/Spelling.yml if that ignore is not needed. Ensure the
Vocab list includes the exact token "Places" and that the accept.txt path
matches the referenced "Places/accept.txt".

(?i)polyfill
(?i)polyfills
(?i)posix
PoC
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for various capitalizations of these terms in markdown files

echo "=== Checking PoC variations ==="
rg -n '\bPoC\b|\bpoc\b|\bPOC\b' --glob '*.md' | head -20

echo "=== Checking const variations ==="
rg -n '\bconst\b|\bCONST\b|\bConst\b' --glob '*.md' | head -20

echo "=== Checking sshd variations ==="
rg -n '\bsshd\b|\bSSHD\b|\bSshd\b' --glob '*.md' | head -20

echo "=== Checking Visio variations ==="
rg -n '\bVisio\b|\bvisio\b|\bVISIO\b' --glob '*.md' | head -20

Repository: gardener/documentation

Length of output: 10152


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".vale/styles/config/vocabularies/TechJargon/accept.txt"

echo "== File exists? =="
ls -l "$FILE" || true

echo
echo "== Lines around 847 =="
nl -ba "$FILE" | sed -n '820,880p'

echo
echo "== Lines around 1320-1322 =="
nl -ba "$FILE" | sed -n '1300,1340p'

echo
echo "== Direct matches in accept.txt (with line numbers) =="
rg -n '\bPoC\b|\bconst\b|\bsshd\b|\bVisio\b' "$FILE" || true

echo
echo "== Show any entries containing (?i) near those terms =="
rg -n '\(\?i\)' "$FILE" | sed -n '800,900p' || true

Repository: gardener/documentation

Length of output: 276


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".vale/styles/config/vocabularies/TechJargon/accept.txt"

echo "== Lines around 847 =="
awk 'NR>=820 && NR<=880 {printf "%d:%s\n", NR, $0}' "$FILE"

echo
echo "== Lines around 1320-1322 =="
awk 'NR>=1300 && NR<=1340 {printf "%d:%s\n", NR, $0}' "$FILE"

echo
echo "== Direct matches in accept.txt (with line numbers) =="
awk 'NR>=840 && NR<=860 || NR>=1310 && NR<=1335 {if ($0 ~ /\b(PoC|const|sshd|Visio)\b/) printf "%d:%s\n", NR, $0}' "$FILE" || true

echo
echo "== Entries containing (?i) in accept.txt near the ranges =="
awk 'NR>=820 && NR<=880 && $0 ~ /\(\?i\)/ {printf "%d:%s\n", NR, $0} {next} ' "$FILE" || true
awk 'NR>=1300 && NR<=1340 && $0 ~ /\(\?i\)/ {printf "%d:%s\n", NR, $0} {next} ' "$FILE" || true

echo
echo "== Exact (?i) occurrences in the whole file (if any) =="
rg -n '\(\?i\)' "$FILE" || true

Repository: gardener/documentation

Length of output: 24952


Update case-sensitivity for PoC in TechJargon accept list.

  • In .vale/styles/config/vocabularies/TechJargon/accept.txt, line 847 is PoC without (?i), but the docs include uppercase POC (e.g., website/blog/2025/06/06-17-taking-gardener-to-the-next-level-highlights-from-the-7th-gardener-community-hackathon-in-schelklingen.md has “Proof of Concept (POC)”). Add (?i)PoC (or a separate POC entry) if uppercase should be accepted.
  • Lines 1320-1322 (const, sshd, Visio) match the capitalization used in the markdown corpus found (no CONST/SSHD/visio occurrences), so keeping them case-sensitive is consistent.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.vale/styles/config/vocabularies/TechJargon/accept.txt at line 847, Update
the TechJargon accept list entry for PoC to be case-insensitive so uppercase POC
is accepted; locate the existing "PoC" token in the TechJargon vocabulary (the
current entry is "PoC") and replace it with a case-insensitive form like
"(?i)PoC" or add an additional "POC" entry so both "PoC" and "POC" pass
validation, leaving other case-sensitive tokens (e.g., "const", "sshd", "Visio")
unchanged.

Comment on lines +874 to +875
(?i)productisation
(?i)productization
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

British and American spelling variants mixed.

Both "productisation" (British) and "productization" (American) are present in the vocabulary list. Similarly, lines 1274-1276 mix "virtualise/virtualised" (British) with "virtualized" (American). While Vale will accept both, this may allow inconsistent spelling variants in the documentation.

Consider choosing one variant per word to enforce consistency:

Suggested fix to standardize on American spellings
 (?i)proctitle
-(?i)productisation
 (?i)productization

And for lines 1274-1276:

-(?i)virtualise
-(?i)virtualised
 (?i)virtualized

Alternatively, if both variants should be supported, document this decision in the header comment to clarify it's intentional.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
(?i)productisation
(?i)productization
(?i)productization
🧰 Tools
🪛 LanguageTool

[uncategorized] ~875-~875: Do not mix variants of the same word (‘productization’ and ‘productisation’) within a single text.
Context: ...un (?i)proctitle (?i)productisation (?i)productization (?i)profiler (?i)profilers (?i)promethe...

(EN_WORD_COHERENCY)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.vale/styles/config/vocabularies/TechJargon/accept.txt around lines 874 -
875, The vocabulary file mixes British and American spellings (e.g.,
"productisation" vs "productization" and elsewhere "virtualise"/"virtualised" vs
"virtualized"); choose one variant and update the entries in the vocab list to
the selected spelling (replace "productisation" with "productization" if
standardizing on American, or vice versa), or if you intend to accept both, add
a header comment to this file documenting that both variants are permitted;
ensure the changes reference the exact tokens shown
("productisation"/"productization" and the
"virtualise"/"virtualised"/"virtualized" group) so the spellings remain
consistent across the file.

Comment thread Makefile
Comment on lines +207 to +216
.PHONY: vale-run
vale-run: ## Lint changed website markdown files with Vale
@CHANGED=$$(git diff --name-only --diff-filter=d HEAD -- 'website/**/*.md' | \
grep -v '^website/about/legal-disclosure\.md' | \
grep -v '^website/archived/'); \
if [ -n "$$CHANGED" ]; then \
vale $$CHANGED; \
else \
echo "No changed .md files to lint."; \
fi
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

vale-run won't find the binary after fresh install.

vale-install places the binary in bin/vale, but vale-run invokes bare vale. If Vale isn't already on PATH, running make vale will fail with "command not found" after a successful install.

🐛 Proposed fix: use bin/vale when available
 .PHONY: vale-run
 vale-run: ## Lint changed website markdown files with Vale
+	`@VALE_CMD`="vale"; \
+	if [ -x bin/vale ]; then VALE_CMD="./bin/vale"; fi; \
 	`@CHANGED`=$$(git diff --name-only --diff-filter=d HEAD -- 'website/**/*.md' | \
 		grep -v '^website/about/legal-disclosure\.md' | \
 		grep -v '^website/archived/'); \
 	if [ -n "$$CHANGED" ]; then \
-		vale $$CHANGED; \
+		$$VALE_CMD $$CHANGED; \
 	else \
 		echo "No changed .md files to lint."; \
 	fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.PHONY: vale-run
vale-run: ## Lint changed website markdown files with Vale
@CHANGED=$$(git diff --name-only --diff-filter=d HEAD -- 'website/**/*.md' | \
grep -v '^website/about/legal-disclosure\.md' | \
grep -v '^website/archived/'); \
if [ -n "$$CHANGED" ]; then \
vale $$CHANGED; \
else \
echo "No changed .md files to lint."; \
fi
.PHONY: vale-run
vale-run: ## Lint changed website markdown files with Vale
`@VALE_CMD`="vale"; \
if [ -x bin/vale ]; then VALE_CMD="./bin/vale"; fi; \
`@CHANGED`=$$(git diff --name-only --diff-filter=d HEAD -- 'website/**/*.md' | \
grep -v '^website/about/legal-disclosure\.md' | \
grep -v '^website/archived/'); \
if [ -n "$$CHANGED" ]; then \
$$VALE_CMD $$CHANGED; \
else \
echo "No changed .md files to lint."; \
fi
🧰 Tools
🪛 checkmake (0.3.2)

[warning] 208-208: Target body for "vale-run" exceeds allowed length of 5 lines (8).

(maxbodylength)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Makefile` around lines 207 - 216, The vale-run target fails after a fresh
install because it calls the bare `vale` binary even though `vale-install` puts
the executable at `bin/vale`; update the `vale-run` recipe so it prefers
`bin/vale` when present (executable) and falls back to `vale` on PATH otherwise
(e.g., test for `bin/vale` and run `./bin/vale $$CHANGED` if found, else `vale
$$CHANGED`), keeping the existing CHANGED detection and output logic intact and
referencing the `vale-run` target and the `bin/vale` location.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla: yes Indicates the PR's author has signed the cla-assistant.io CLA. kind/enhancement Enhancement, improvement, extension size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Vale as linter

1 participant