diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 0444b5cc50..4b96b6b22b 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,8 +1,11 @@ -# See here for image contents: https://github.com/microsoft/vscode-dev-containers/blob/v0.202.3/containers/python-3/.devcontainer/base.Dockerfile -# [Choice] Python version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.9, 3.8, 3.7, 3.6, 3-bullseye, 3.9-bullseye, 3.8-bullseye, 3.7-bullseye, 3.6-bullseye, 3-buster, 3.9-buster, 3.8-buster, 3.7-buster, 3.6-buster +# See here for image contents: https://github.com/devcontainers/images/tree/main/src/python +# [Choice] Python version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.9, 3.8, 3.7, 3.6, 3-bullseye, 3.9-bullseye, 3.8-bullseye, 3.7-bullseye, 3.6-bullseye ARG VARIANT=3-bullseye -FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT} +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 # [Optional] Allow the vscode user to pip install globally w/o sudo ENV PIP_TARGET=/usr/local/pip-global diff --git a/.devcontainer/devcontainer-lock.json b/.devcontainer/devcontainer-lock.json new file mode 100644 index 0000000000..5c9909954c --- /dev/null +++ b/.devcontainer/devcontainer-lock.json @@ -0,0 +1,9 @@ +{ + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": { + "version": "2.17.0", + "resolved": "ghcr.io/devcontainers/features/docker-in-docker@sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c", + "integrity": "sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c" + } + } +} diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 1fc2fde6e9..d77676af8e 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -15,33 +15,41 @@ } }, - // Set *default* container specific settings.json values on container create. - "settings": { - "terminal.integrated.profiles.linux": { - "bash": { - "path": "/bin/bash" - } - }, - "python.defaultInterpreterPath": "/usr/local/bin/python", - "python.languageServer": "Default", - "python.linting.enabled": true, - "python.linting.pylintEnabled": true, - "python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8", - "python.formatting.blackPath": "/usr/local/py-utils/bin/black", - "python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf", - "python.linting.banditPath": "/usr/local/py-utils/bin/bandit", - "python.linting.flake8Path": "/usr/local/py-utils/bin/flake8", - "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy", - "python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle", - "python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle", - "python.linting.pylintPath": "/usr/local/py-utils/bin/pylint" + // Features to add to the dev container. + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": {} }, - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "ms-python.python", - "ms-python.vscode-pylance" - ], + "customizations": { + "vscode": { + // Set *default* container specific settings.json values on container create. + "settings": { + "terminal.integrated.profiles.linux": { + "bash": { + "path": "/bin/bash" + } + }, + "python.defaultInterpreterPath": "/usr/local/bin/python", + "python.languageServer": "Default", + "python.linting.enabled": true, + "python.linting.pylintEnabled": true, + "python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8", + "python.formatting.blackPath": "/usr/local/py-utils/bin/black", + "python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf", + "python.linting.banditPath": "/usr/local/py-utils/bin/bandit", + "python.linting.flake8Path": "/usr/local/py-utils/bin/flake8", + "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy", + "python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle", + "python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle", + "python.linting.pylintPath": "/usr/local/py-utils/bin/pylint" + }, + "extensions": [ + "ms-python.python", + "ms-python.vscode-pylance", + "ms-azuretools.vscode-docker" + ] + } + }, // Use 'forwardPorts' to make a list of ports inside the container available locally. "forwardPorts": [8000], @@ -60,12 +68,12 @@ // }, // 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", // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. "remoteUser": "vscode", "mounts": [ "source=${localEnv:HOME}${localEnv:USERPROFILE}/.ssh,target=/home/vscode/.ssh,type=bind" - ], + ] } \ No newline at end of file diff --git a/.devcontainer/run-megalinter.sh b/.devcontainer/run-megalinter.sh new file mode 100755 index 0000000000..9694f1b827 --- /dev/null +++ b/.devcontainer/run-megalinter.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# Run MegaLinter locally from the devcontainer — mirrors the CI setup in +# .github/workflows/mega-linter.yml and config in .mega-linter.yml. +# +# Usage: +# .devcontainer/run-megalinter.sh # lint only changed files +# VALIDATE_ALL_CODEBASE=true .devcontainer/run-megalinter.sh # lint everything +# +# Reports are written to ./megalinter-reports/ in the repo root. +set -euo pipefail + +REPO_ROOT="$(git rev-parse --show-toplevel)" +VALIDATE_ALL="${VALIDATE_ALL_CODEBASE:-false}" + +echo "Running MegaLinter (VALIDATE_ALL_CODEBASE=${VALIDATE_ALL})..." +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 diff --git a/lychee.toml b/lychee.toml index 2cdf5c0d5e..5e703f771b 100644 --- a/lychee.toml +++ b/lychee.toml @@ -49,7 +49,11 @@ retry_wait_time = 2 # accept = "200..=204, 429" # accept = ["200", "429"] # accept = "200, 429" -accept = ["200"] +# +# 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"] # Proceed for server connections considered insecure (invalid TLS). insecure = false @@ -61,7 +65,7 @@ require_https = false method = "get" # Custom request headers -header = ["name=value", "other=value"] +# header = { name = "value", other = "value" } # Remap URI matching pattern to different URI. remap = [] @@ -96,6 +100,15 @@ exclude = [ "^https://github.com/marketplace/?$", # Other: "^https://opensource.org/license/", # works locally but fails with 403 on Github CI. + # Sites that block automated clients (TLS handshake / bot protection) but are + # valid in a browser: + "^https://www.postman.com", + "^https://blog.insightdatascience.com", + "^https://fate.fedai.org", + # Site with an expired TLS certificate (valid content, cert not renewed): + "^https://www.techdim.com", + # Valid but intermittently slow from CI (request timeouts): + "^https://www.gnu.org", ] # Exclude these filesystem paths from getting checked. diff --git a/requirements-docs.txt b/requirements-docs.txt index 7fa7f29c0e..299dfa7973 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -1,6 +1,7 @@ mkdocs==1.3.* mkdocs-material==8.2.* pymdown-extensions>=10.0 +Pygments>=2,<2.20 markdown==3.3.* mdx_truly_sane_lists==1.2 mkdocs-git-revision-date-localized-plugin==1.0.*