mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-11-11 15:07:32 +00:00
Bootstrap 5.1.3, Font Awesome 6.0.0, Socket.IO 4.7.2 and Chart.js 4.4.0 are now served from static/vendor/ at the versions the CDNs served, so every page works on a LAN with no internet. Only map tiles still need it. The Content-Security-Policy drops jsDelivr and cdnjs. Every vendored package, the map stack and login fonts included, is pinned in scripts/web-vendor/package.json and its lockfile. sync.mjs copies the listed files into static/, strips the source-map comment, empties each directory it owns first, and regenerates the version table in static/vendor/README.md; it reproduces the previously vendored files byte for byte. Font Awesome ships only its woff2 fonts, which every supported browser takes before the .ttf. Dependabot watches that directory: security fixes as advisories land, grouped minor and patch releases monthly, majors one per PR. Dependabot can't regenerate the vendored files, so vendor-refresh.yml adds them to its PRs as a second commit and dispatches the tests, since a GITHUB_TOKEN push doesn't trigger them. It runs on pull_request_target, so it uses the base branch's sync.mjs, spells out its commands instead of running the PR's npm scripts, and installs with install scripts disabled. A new CI job re-runs the sync and fails if anything under static/ changes. Tests now check that no template loads a script, stylesheet or font from another host, that every vendored file a template names exists, and that the CSP allows no CDN host. In Chrome, 12 pages load with no external request, failed load or console error.
195 lines
5.7 KiB
YAML
195 lines
5.7 KiB
YAML
name: Tests
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
- master
|
|
- dev
|
|
pull_request:
|
|
branches:
|
|
- main
|
|
- master
|
|
- dev
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
lint-frontend:
|
|
name: Lint Frontend (HTMLHint + ESLint)
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
|
|
- name: Set up Node.js
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: "24"
|
|
cache: npm
|
|
|
|
- name: Install frontend lint tools
|
|
run: npm ci
|
|
|
|
- name: HTMLHint — lint HTML templates
|
|
run: npm run lint:html
|
|
|
|
- name: ESLint — lint inline JavaScript
|
|
run: npm run lint:js
|
|
|
|
vendor-sync:
|
|
name: Vendored front-end libraries match their lockfile
|
|
# On a Dependabot pull request the first commit only bumps the lockfile;
|
|
# vendor-refresh.yml adds the files and then dispatches this workflow.
|
|
if: github.event_name != 'pull_request' || github.event.pull_request.user.login != 'dependabot[bot]'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
|
|
- name: Set up Node.js
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: "24"
|
|
cache: npm
|
|
cache-dependency-path: scripts/web-vendor/package-lock.json
|
|
|
|
- name: Re-run the sync
|
|
working-directory: scripts/web-vendor
|
|
run: npm run vendor
|
|
|
|
- name: Fail if anything under static/ changed
|
|
run: |
|
|
changes="$(git status --porcelain -- modules/web_viewer/static)"
|
|
if [ -n "$changes" ]; then
|
|
echo "$changes"
|
|
echo "::error::modules/web_viewer/static doesn't match scripts/web-vendor. Run 'npm run vendor' in scripts/web-vendor and commit the result."
|
|
exit 1
|
|
fi
|
|
|
|
lint-shell:
|
|
name: Lint Shell Scripts (ShellCheck)
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
|
|
- name: Install ShellCheck
|
|
run: sudo apt-get install -y shellcheck
|
|
|
|
- name: ShellCheck — lint all .sh files
|
|
run: |
|
|
find . -name "*.sh" \
|
|
-not -path "./.git/*" \
|
|
-not -path "./node_modules/*" \
|
|
-not -path "./.venv/*" \
|
|
-not -path "./venv/*" \
|
|
-not -path "./dist/*" \
|
|
-print0 | xargs -0 shellcheck --severity=warning
|
|
|
|
lint:
|
|
name: Lint (ruff)
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v7
|
|
with:
|
|
python-version: "3.11"
|
|
cache: pip
|
|
|
|
- name: Install ruff
|
|
run: pip install "ruff==0.15.15"
|
|
|
|
- name: ruff check — fail on any lint error
|
|
# Whole tree, not just modules/ and tests/: scripts/ and the root-level
|
|
# scripts (meshcore_bot.py, validate_config.py, generate_website.py, …)
|
|
# ship to users too. Excludes come from pyproject's [tool.ruff].
|
|
run: ruff check .
|
|
|
|
- name: Log injection check — fail on new unsanitized logger calls
|
|
run: python scripts/check_log_injection.py
|
|
|
|
- name: Config validation — fail on unrecognized sections in shipped configs
|
|
run: |
|
|
set -e
|
|
for f in config.ini.example config.ini.minimal-example config.ini.quickstart config.min.ini config-pymc.ini; do
|
|
if [ -f "$f" ]; then
|
|
echo "Validating $f"
|
|
python validate_config.py --config "$f" --strict
|
|
fi
|
|
done
|
|
|
|
typecheck:
|
|
name: Type check (mypy)
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v7
|
|
with:
|
|
python-version: "3.11"
|
|
cache: pip
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
pip install --upgrade pip
|
|
pip install -e ".[test,geo]"
|
|
pip install mypy
|
|
|
|
- name: mypy — strict overrides on typed modules
|
|
run: mypy modules/ --ignore-missing-imports
|
|
|
|
package:
|
|
name: Build and smoke-test distributions
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v7
|
|
with:
|
|
python-version: "3.11"
|
|
cache: pip
|
|
|
|
- name: Build wheel and source distribution
|
|
run: |
|
|
python -m pip install --upgrade pip build twine
|
|
python -m build
|
|
python -m twine check dist/*
|
|
|
|
- name: Install and smoke-test wheel outside the source tree
|
|
run: |
|
|
python -m venv /tmp/meshcore-wheel-smoke
|
|
/tmp/meshcore-wheel-smoke/bin/pip install dist/*.whl
|
|
cd /tmp
|
|
/tmp/meshcore-wheel-smoke/bin/python "$GITHUB_WORKSPACE/scripts/smoke_test_wheel.py"
|
|
/tmp/meshcore-wheel-smoke/bin/python "$GITHUB_WORKSPACE/scripts/smoke_test_no_geo.py"
|
|
/tmp/meshcore-wheel-smoke/bin/meshcore-bot --help >/dev/null
|
|
/tmp/meshcore-wheel-smoke/bin/meshcore-viewer --help >/dev/null
|
|
|
|
test:
|
|
name: Tests (Python ${{ matrix.python-version }})
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
|
|
- name: Set up Python ${{ matrix.python-version }}
|
|
uses: actions/setup-python@v7
|
|
with:
|
|
python-version: ${{ matrix.python-version }}
|
|
cache: pip
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
pip install --upgrade pip
|
|
# `geo` (us, pycountry) is optional at runtime but drives US state and
|
|
# country normalization; without it ~27 location tests skip and the AQI
|
|
# prefix-budget behavior silently differs from a real install.
|
|
pip install -e ".[test,geo]"
|
|
|
|
- name: Run tests with coverage
|
|
run: pytest tests/ -v --tb=short
|