fix: enable CI checks to run from devcontainer - #1136
Conversation
- Add Docker-in-Docker feature and run-megalinter.sh script so MegaLinter can be executed locally via .devcontainer/run-megalinter.sh - Update devcontainer base image to devcontainers/python:1 and remove stale Yarn apt repository that causes apt-get update failures - Pin Pygments<2.20 in requirements-docs.txt to fix mkdocs build: Pygments 2.20.0 calls html.escape() on a filename option that pymdownx can pass as None, causing AttributeError during documentation build - Accept HTTP 403/429 in lychee.toml to prevent false-positive link failures from GitHub rate-limiting and bot-protection in CI; also exclude known bot-blocking domains
| # 403 (Forbidden) and 429 (Too Many Requests) are accepted because they indicate | ||
| # the target page exists but the host blocks or throttles automated clients in | ||
| # CI. Treating them as failures produces false positives for live links. | ||
| accept = ["200..=299", "403", "429"] |
There was a problem hiding this comment.
Globally accepting 403 is risky — 403 often indicates a genuinely removed/protected resource, not just bot-blocking. Since the PR already adds per-URL excludes for the known bot-blocked domains, prefer keeping accept narrow (e.g. ["200..=299", "429"]) and continuing to handle exceptions via exclude. Otherwise real breakage on any 403-returning host will silently pass CI.
|
|
||
| # Custom request headers | ||
| header = ["name=value", "other=value"] | ||
| # header = { name = "value", other = "value" } |
There was a problem hiding this comment.
Do we really need this if it's commented out?
| -w /tmp/lint \ | ||
| -e VALIDATE_ALL_CODEBASE="${VALIDATE_ALL}" \ | ||
| -e DEFAULT_BRANCH=main \ | ||
| oxsecurity/megalinter:v8.1.0 |
There was a problem hiding this comment.
v8.1.0 is hardcoded here but .github/workflows/mega-linter.yml has its own pinned version. If they drift, the local run stops mirroring CI, defeating the purpose. Consider sourcing the version from a shared file, or at least adding a comment reminding maintainers to bump both together.
| set -euo pipefail | ||
|
|
||
| REPO_ROOT="$(git rev-parse --show-toplevel)" | ||
| VALIDATE_ALL="${VALIDATE_ALL_CODEBASE:-false}" |
There was a problem hiding this comment.
MegaLinter's VALIDATE_ALL_CODEBASE=false mode typically needs DEFAULT_WORKSPACE=/tmp/lint set (and a mounted .git) to diff against DEFAULT_BRANCH=main. Worth testing that bash .devcontainer/run-megalinter.sh (no env override) actually detects only changed files rather than silently linting everything.
| # Reports are written to ./megalinter-reports/ in the repo root. | ||
| set -euo pipefail | ||
|
|
||
| REPO_ROOT="$(git rev-parse --show-toplevel)" |
There was a problem hiding this comment.
git rev-parse --show-toplevel will error out if the script is run outside a git worktree — fine for the documented use case, but consider a friendlier error message.
|
|
||
| // Use 'postCreateCommand' to run commands after the container is created. | ||
| "postCreateCommand": "pip3 install -r requirements-docs.txt", | ||
| "postCreateCommand": "pip3 install -r requirements-docs.txt && chmod +x .devcontainer/run-megalinter.sh", |
There was a problem hiding this comment.
Redundant chmod +x in postCreateCommand — the file is already committed with mode 100755. The chmod is harmless but unnecessary.
| mkdocs==1.3.* | ||
| mkdocs-material==8.2.* | ||
| pymdown-extensions>=10.0 | ||
| Pygments>=2,<2.20 |
There was a problem hiding this comment.
Pygments>=2,<2.20 — reasonable stopgap. The root cause is that mkdocs==1.3.* and mkdocs-material==8.2.* are years old (current is 1.6+/9.x); this cap is a symptom. Fine to unblock CI, but worth filing a follow-up issue to modernize the docs toolchain.
| @@ -1,6 +1,7 @@ | |||
| mkdocs==1.3.* | |||
There was a problem hiding this comment.
I think we should consider updating the dependencies in this file first in a separate PR
| FROM mcr.microsoft.com/devcontainers/python:1-${VARIANT} | ||
|
|
||
| # Remove stale Yarn apt repository that has an expired GPG key and causes apt-get update failures | ||
| RUN rm -f /etc/apt/sources.list.d/yarn.list /etc/apt/sources.list.d/yarn.list.save |
There was a problem hiding this comment.
Yarn cleanup runs rm -f before any apt-get update. If another expired repo shows up later, contributors will hit the same class of failure. Consider running apt-get update in the same layer to fail fast at build time rather than at postCreateCommand.
There was a problem hiding this comment.
Pull request overview
This PR aims to make the repository’s CI checks (notably MegaLinter and link checking) runnable from inside the devcontainer so contributors can validate changes locally before pushing.
Changes:
- Adds Docker-in-Docker support to the devcontainer (plus lockfile pinning) so Docker-based CI tooling (MegaLinter) can run inside the container.
- Introduces a local helper script to run MegaLinter similarly to CI.
- Adjusts docs/tooling dependencies and link-check configuration to reduce CI false-failures (Pygments pin; lychee acceptance/exclusions).
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
requirements-docs.txt |
Pins Pygments to avoid a documented mkdocs build crash. |
lychee.toml |
Broadens accepted HTTP statuses and expands exclusions to reduce link-check false positives in CI. |
.devcontainer/run-megalinter.sh |
Adds a local MegaLinter runner script intended to mirror the CI configuration. |
.devcontainer/Dockerfile |
Switches to the newer devcontainers Python base image and removes a stale Yarn apt repo entry. |
.devcontainer/devcontainer.json |
Adds docker-in-docker feature, migrates to customizations.vscode, and wires post-create steps for local tooling. |
.devcontainer/devcontainer-lock.json |
Pins the docker-in-docker feature version for reproducible devcontainer builds. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| docker run --rm \ | ||
| -v "${REPO_ROOT}:/tmp/lint" \ | ||
| -w /tmp/lint \ | ||
| -e VALIDATE_ALL_CODEBASE="${VALIDATE_ALL}" \ | ||
| -e DEFAULT_BRANCH=main \ | ||
| oxsecurity/megalinter:v8.1.0 |
| @@ -96,6 +100,15 @@ exclude = [ | |||
| "^https://github.com/marketplace/?$", | |||
| # Other: | |||
| "^https://opensource.org/license/", # works locally but fails with 403 on Github CI. | |||
What are you trying to address
This PR makes all CI checks runnable from the devcontainer, so contributors can validate their changes locally before pushing.
Changes:
.devcontainer/devcontainer.json— Adds thedocker-in-dockerdevcontainer feature, required to run the MegaLinter Docker image from inside the devcontainer. Also migrates settings to the currentcustomizations.vscodeschema and adds thems-azuretools.vscode-dockerextension..devcontainer/devcontainer-lock.json— New lock file pinning thedocker-in-dockerfeature tov2.17.0for reproducible builds..devcontainer/Dockerfile— Updates the base image tomcr.microsoft.com/devcontainers/python:1-${VARIANT}and removes a stale Yarn apt repository that causedapt-get updatefailures..devcontainer/run-megalinter.sh— New helper script that mirrors the MegaLinter CI step locally. Runningbash .devcontainer/run-megalinter.shscans only changed files (matchingVALIDATE_ALL_CODEBASE: falsein CI);VALIDATE_ALL_CODEBASE=true bash .devcontainer/run-megalinter.shscans everything.requirements-docs.txt— PinsPygments>=2,<2.20to avoid anAttributeErrorintroduced in Pygments 2.20.0, which caused the mkdocs build to crash whenpymdownx.highlightpassesfilename=NonetoHtmlFormatter.lychee.toml— Accepts HTTP 403 and 429 responses in addition to 2xx, preventing false-positive link-check failures on sites (including GitHub) that block automated crawlers. Also removes an invalidheadertable entry and excludes additional bot-blocking domains.Checklist