diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 633b98c712b..a3760e44da6 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -109,8 +109,8 @@ jobs: - name: Setup CI env uses: ./.github/actions/setup-env with: - # No Python setup is needed, the built-in Python runtime is okay. - setup_python: false + # PDM is needed to run Vale + setup_python: "true" # Node.js is needed by lint actions. install_recipe: "node-install" diff --git a/.vale/.gitignore b/.vale/.gitignore index f8cea4a9562..9658b6fb34e 100644 --- a/.vale/.gitignore +++ b/.vale/.gitignore @@ -1,3 +1,3 @@ styles/* -!styles/Vocab/ +!styles/config/ !styles/Openverse/ diff --git a/.vale/.vale.ini b/.vale/.vale.ini index f3be33fd614..5df35fa5604 100644 --- a/.vale/.vale.ini +++ b/.vale/.vale.ini @@ -1,5 +1,3 @@ -StylesPath = styles - MinAlertLevel = suggestion Vocab = Openverse # Using an explicit reference to downloads for package zips rather than the shorthand allows us to diff --git a/.vale/Dockerfile b/.vale/Dockerfile deleted file mode 100644 index 1afd8b6e0fa..00000000000 --- a/.vale/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM jdkato/vale:v2.30.0 - -WORKDIR /vale -COPY .vale.ini . - -RUN vale sync - -COPY styles styles - -ENTRYPOINT ["vale", "--config=/vale/.vale.ini"] diff --git a/.vale/README.md b/.vale/README.md index ce9441ad83b..b177777463b 100644 --- a/.vale/README.md +++ b/.vale/README.md @@ -1,9 +1,14 @@ # Openverse Vale configuration -Openverse runs Vale using Docker. This bypasses the need for contributors to -install the Vale binary on their computers. It also prevents Vale styles getting -downloaded into the repository in clear text, which is critical to avoid lists -of sensitive terms being accidentally too-easily available. +Openverse runs Vale using +[Vale's PyPI distribution](https://pypi.org/project/vale/). This allows our Vale +version to be tracked in this directory's `pyproject.toml`, meaning tools like +Renovate will be aware of and update it automatically. + +This approach to running Vale is intended specifically for running inside `ov`, +and will likely not work outside `ov`. Synced styles are kept in `ov`'s `opt` +directory, which prevents downloaded styles from appearing within the project +files on a contributor's computer. For more information about this motivation to avoid lists of sensitive terms in the Openverse monorepo, refer to the README at @@ -15,15 +20,11 @@ To run Vale with Openverse's configuration, use the just recipe: ov just .vale/run ``` -This recipe _always_ builds Vale. The Openverse Vale docker image is fast to -build, and the most expensive steps are cached. Docker will automatically reuse -the pre-existing image unless there are changes to the Vale configuration. - -Typically it is unnecessary to run Vale directly, as pre-commit automatically +Typically, it is unnecessary to run Vale directly, as pre-commit automatically runs Vale on each commit. You only need to run Vale directly when iterating on changes to Openverse's Vale configuration. -Refer to the `VALE_FILES` variable [in the justfile](./justfile) to identify -which files we currently check with Vale. A comment on the variable explains the +Refer to the `_files` recipe [in the `justfile`](./justfile) to identify which +files we currently check with Vale. A comment on the recipe explains the rationale for that choice. The list of files will ideally expand in the future to include all textual content in the repository. diff --git a/.vale/justfile b/.vale/justfile index 3a6fcd8ce0b..5fbd468cd88 100644 --- a/.vale/justfile +++ b/.vale/justfile @@ -7,22 +7,17 @@ NO_COLOR := "\\033[0m" printf "===================={{ NO_COLOR }}\n" just --list --unsorted -# Build a local version of `openverse-vale:local` for testing -build: - docker build . -t openverse-vale:local - IGNORE_FILES_PATTERN := ".pnpm|changelogs|projects/proposals|node_modules|.?venv" # This recipe generates a list of Markdown and MDX files to be processed, excluding those # matched by the IGNORE_FILES_PATTERN. Files are listed relative to the parent directory # of the current working directory. If a custom separator is specified, newlines are # replaced with this separator before outputting the file list. -@files separator="\n": +_files separator="\n": #! /usr/bin/env sh files=$( find "$PWD/.." -type f \( -name "*.md" -o -name "*.mdx" \) \ - | grep -vE "{{ IGNORE_FILES_PATTERN }}" \ - | sed "s|$PWD/../||" + | grep -vE "{{ IGNORE_FILES_PATTERN }}" ) if [ '{{ separator }}' != '\n' ]; then echo "$files" | tr '\n' '{{ separator }}' @@ -30,12 +25,18 @@ IGNORE_FILES_PATTERN := ".pnpm|changelogs|projects/proposals|node_modules|.?venv fi echo "$files" -# Run Vale configured for Openverse in Docker. -# Using Docker avoids the need for contributors to install the Vale binary. -#Configuration defaults to what is used for CI. -run: build - docker run --rm \ - -v $PWD/..:/src:rw,Z \ - --workdir=/src \ - openverse-vale:local \ - {{ "`just files`" }} +VALE_STYLES_PATH := "/opt/.local/share/vale/styles" + +@_link_openverse_styles: + mkdir -p {{ VALE_STYLES_PATH }} + [ ! -L {{ VALE_STYLES_PATH }}/config ] && ln -s "$(pwd)"/styles/config {{ VALE_STYLES_PATH }}/config || true + [ ! -L {{ VALE_STYLES_PATH }}/Openverse ] && ln -s "$(pwd)"/styles/Openverse {{ VALE_STYLES_PATH }}/Openverse || true + +# Run Vale configured for Openverse. +@run: _link_openverse_styles + # Ensure vale is available + pdm install + # Sync to make sure styles are up to date (this is fast if they are already synced) + VALE_STYLES_PATH={{ VALE_STYLES_PATH }} pdm run vale sync + # Run vale :) + VALE_STYLES_PATH={{ VALE_STYLES_PATH }} pdm run vale {{ "`just _files`" }} diff --git a/.vale/pdm.lock b/.vale/pdm.lock new file mode 100644 index 00000000000..66af9d68357 --- /dev/null +++ b/.vale/pdm.lock @@ -0,0 +1,22 @@ +# This file is @generated by PDM. +# It is not intended for manual editing. + +[metadata] +groups = ["default"] +strategy = ["inherit_metadata"] +lock_version = "4.5.0" +content_hash = "sha256:a0a9239f1729ced61ee239a99bf78fffdf4a7c52fac089012c11b3e6efbf8e41" + +[[metadata.targets]] +requires_python = "==3.12.*" + +[[package]] +name = "vale" +version = "3.7.1.0" +requires_python = ">=3.7" +summary = "Install and use Vale (grammar & style check tool) in python environments." +groups = ["default"] +files = [ + {file = "vale-3.7.1.0-py3-none-any.whl", hash = "sha256:3d311c11cf7e7621bf048f0898734634273ab15109ea2474ce4fc6f8778be6c8"}, + {file = "vale-3.7.1.0.tar.gz", hash = "sha256:67e5474da8c3d438e0bc1f470d7d63d3d0080ad992e037dd33157536621738d1"}, +] diff --git a/.vale/pyproject.toml b/.vale/pyproject.toml new file mode 100644 index 00000000000..64951919ff1 --- /dev/null +++ b/.vale/pyproject.toml @@ -0,0 +1,16 @@ +[project] +name = "openverse-vale" +version = "0.0.0" +description = "Openverse Vale configuration" +authors = [ + {name = "Openverse Contributors", email = "openverse@wordpress.org"}, +] +dependencies = [ + "vale>=3.7.1.0", +] +requires-python = "==3.12.*" +readme = "README.md" +license = {text = "MIT"} + +[tool.pdm] +distribution = false diff --git a/.vale/styles/Vocab/Openverse/accept.txt b/.vale/styles/Vocab/Openverse/accept.txt deleted file mode 100644 index 91d4a023bae..00000000000 --- a/.vale/styles/Vocab/Openverse/accept.txt +++ /dev/null @@ -1,3 +0,0 @@ -# This matches "cliche" rulesets, but we actually use this term in earnest and with clear explanation of what we mean by it -Decision-Making Process -decision-making process diff --git a/.vale/styles/config/vocabularies/Openverse/accept.txt b/.vale/styles/config/vocabularies/Openverse/accept.txt new file mode 100644 index 00000000000..66fd6e818aa --- /dev/null +++ b/.vale/styles/config/vocabularies/Openverse/accept.txt @@ -0,0 +1,2 @@ +Decision-Making Process +decision-making process diff --git a/documentation/meta/decision_making/index.md b/documentation/meta/decision_making/index.md index e5d908b76f1..974be6b6dc7 100644 --- a/documentation/meta/decision_making/index.md +++ b/documentation/meta/decision_making/index.md @@ -1,4 +1,4 @@ -# Openverse Decision-Making Process +# Openverse decision-making process This process is loosely based on the Sociocratic "consent decision-making" model, but is heavily adapted for an asynchronous context. The purpose of this