diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000..d6948166f --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,34 @@ +name: Docs + +# Runs for every change, not only docs/**: module docs pull snippets from +# packages/**/*.test.ts via codeinclude, so code changes can break the docs too. +on: + push: + branches: [main] + pull_request: + branches: [main] + +concurrency: + group: "${{ github.workflow }}-${{ github.head_ref || github.sha }}" + cancel-in-progress: true + +permissions: + contents: read + +jobs: + build: + name: Build docs + runs-on: ubuntu-24.04 + steps: + - name: Code checkout + uses: actions/checkout@v7 + - name: Install Python + uses: actions/setup-python@v7 + with: + # Same Python version Netlify uses to build and deploy the docs. + python-version-file: runtime.txt + cache: pip + - name: Install dependencies + run: pip install -r requirements.txt + - name: Build docs in strict mode + run: mkdocs build --strict diff --git a/.gitignore b/.gitignore index f7f6ed140..6c5cd7fe7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,9 @@ build/ node_modules/ coverage/ +# MkDocs build output +/site/ + # Package files are copied from the root on pack packages/**/README.md packages/**/LICENSE diff --git a/AGENTS.md b/AGENTS.md index 043db2c2d..4c02fc421 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -26,6 +26,7 @@ It captures practical rules that prevent avoidable CI and PR churn. - If new types are made part of the public API, export them from the package's `index.ts` in the same PR. - If new learnings or misunderstandings are discovered, propose an `AGENTS.md` update in the same PR. - In docs Markdown, keep `` blocks tight with no blank lines between the markers and the include line, or the rendered snippet will contain blank lines between code lines. +- Codeinclude `inside_block:` selects the block after the first line that contains `` anywhere, so a marker whose name also appears earlier in the file (for example inside another marker's name) silently includes the wrong block. The `Docs` workflow runs `mkdocs build --strict`, which fails when a marker or included file is missing but cannot catch this. - Tests should verify observable behavior changes, not only internal/config state. - Example: for a security option, assert a real secure/insecure behavior difference. - When adding a regression test for a bug fix, follow a red-green-refactor workflow. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ed6d3d7af..eaeeb6381 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,6 +34,7 @@ Then access the docs at [http://localhost:8000](http://localhost:8000). * Ensure that you have Python 3.11.0 or higher. * Set up a virtualenv and run `pip install -r requirements.txt` in the `testcontainers-node` root directory. * Once Python dependencies have been installed, run `mkdocs serve` to start a local auto-updating MkDocs server. +* Run `mkdocs build --strict` to check for broken links, anchors and code includes. CI runs the same build on every pull request. #### PR preview deployments diff --git a/docs/features/containers.md b/docs/features/containers.md index b05476dbf..6310b872c 100644 --- a/docs/features/containers.md +++ b/docs/features/containers.md @@ -95,7 +95,7 @@ const container = await new GenericContainer("alpine") **Not recommended.** -Bind mounts are not portable. They do not work with Docker in Docker or in cases where the Docker agent is remote. It is preferred to [copy files/directories/content into the container](../containers#with-filesdirectoriescontent) instead. +Bind mounts are not portable. They do not work with Docker in Docker or in cases where the Docker agent is remote. It is preferred to [copy files/directories/content into the container](#with-filesdirectoriescontent) instead. ```js const container = await new GenericContainer("alpine") @@ -122,7 +122,7 @@ const container = await new GenericContainer("alpine") **Not recommended.** -If a container with the same name already exists, Docker will raise a conflict. If you are specifying a name to enable container to container communication, look into creating a network and using [network aliases](../networking#network-aliases). +If a container with the same name already exists, Docker will raise a conflict. If you are specifying a name to enable container to container communication, look into creating a network and using [network aliases](networking.md#network-aliases). ```js const container = await new GenericContainer("alpine") @@ -246,7 +246,7 @@ const container = await new GenericContainer("alpine") ### With default log driver -May be necessary when the driver of your docker host does not support reading logs, and you want to use the [log output wait strategy](../wait-strategies#log-output). +May be necessary when the driver of your docker host does not support reading logs, and you want to use the [log output wait strategy](wait-strategies.md#log-output). See [log drivers](https://docs.docker.com/config/containers/logging/configure/#configure-the-logging-driver-for-a-container). diff --git a/mkdocs.yml b/mkdocs.yml index dd643c9ea..7e70bc96e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -23,7 +23,8 @@ extra_css: plugins: - search - - codeinclude + - codeinclude: + block_throw: true - markdownextradata markdown_extensions: @@ -97,3 +98,9 @@ nav: - Vault: modules/vault.md - Weaviate: modules/weaviate.md - Configuration: configuration.md + +validation: + omitted_files: warn + absolute_links: warn + unrecognized_links: warn + anchors: warn