The device-types pilot failed pip-audit on pip 25.0.1 of the venv that also held bandit and pip-audit. The package now goes into a venv of its own with a current pip; its frozen set (URL installs left out) is what pip-audit checks.
208 lines
7.2 KiB
YAML
208 lines
7.2 KiB
YAML
# The CI every NAPALM driver runs (STANDARDS.md §7). A driver repo calls it from
|
|
# its own .gitea/workflows/ci.yml — see template/.gitea/workflows/ci.yml.
|
|
#
|
|
# Every job that installs builds its own venv in the workspace: jobs on one
|
|
# runner share /opt/hostedtoolcache, and two `pip install -e .` into the same
|
|
# site-packages break each other (netOrk REPOSITORY_GUIDELINES §10).
|
|
#
|
|
# upload-artifact/download-artifact stay on v3: v4 refuses to run on Gitea
|
|
# ("not currently supported on GHES").
|
|
|
|
name: driver
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
standard-ref:
|
|
description: "Version of napalm-standard to check with; keep it equal to the @ref of this workflow"
|
|
type: string
|
|
default: "main"
|
|
pre-install:
|
|
description: "pip specs installed before the package (until its dependencies are on PyPI)"
|
|
type: string
|
|
default: ""
|
|
python-versions:
|
|
description: "JSON list of the Python versions the tests run on"
|
|
type: string
|
|
default: '["3.10", "3.11", "3.12", "3.13"]'
|
|
pypi-url:
|
|
description: "Upload target; https://test.pypi.org/legacy/ for a dry run"
|
|
type: string
|
|
default: "https://upload.pypi.org/legacy/"
|
|
secrets:
|
|
PYPI_TOKEN:
|
|
required: false
|
|
|
|
env:
|
|
STANDARD: "napalm-standard @ git+https://git.netork.io/NAPALM/driver-standard.git@${{ inputs.standard-ref }}"
|
|
|
|
jobs:
|
|
standard:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.12"
|
|
- name: Install napalm-standard
|
|
run: |
|
|
python -m venv .venv
|
|
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
|
|
.venv/bin/pip install -q "$STANDARD"
|
|
- name: Conformance
|
|
run: |
|
|
if [ "$GITHUB_REF_TYPE" = "tag" ]; then
|
|
napalm-standard check --tag "$GITHUB_REF_NAME"
|
|
else
|
|
napalm-standard check
|
|
fi
|
|
- name: Quality ratchet
|
|
run: napalm-standard ratchet
|
|
|
|
lint:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.12"
|
|
- name: ruff
|
|
run: |
|
|
python -m venv .venv
|
|
.venv/bin/pip install -q ruff
|
|
.venv/bin/ruff format --check .
|
|
.venv/bin/ruff check .
|
|
|
|
types:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.12"
|
|
- name: Install
|
|
run: |
|
|
python -m venv .venv
|
|
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
|
|
.venv/bin/pip install -q "$STANDARD" mypy
|
|
if [ -n "${{ inputs.pre-install }}" ]; then .venv/bin/pip install -q ${{ inputs.pre-install }}; fi
|
|
.venv/bin/pip install -q -e ".[dev]"
|
|
- name: mypy
|
|
run: mypy "$(napalm-standard package)"
|
|
|
|
test:
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
python-version: ${{ fromJSON(inputs.python-versions) }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: ${{ matrix.python-version }}
|
|
- name: Install
|
|
run: |
|
|
python -m venv .venv
|
|
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
|
|
if [ -n "${{ inputs.pre-install }}" ]; then .venv/bin/pip install -q ${{ inputs.pre-install }}; fi
|
|
.venv/bin/pip install -q -e ".[dev]" pytest pytest-cov
|
|
- name: pytest
|
|
# --cov takes its source from [tool.coverage.run], the floor from fail_under.
|
|
run: python -m pytest -q --tb=short --cov --cov-report=term-missing
|
|
|
|
lowest:
|
|
# The floors in pyproject.toml are a promise: install exactly them and run the tests.
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.10"
|
|
- name: Install the lowest versions the package allows
|
|
run: |
|
|
python -m venv .venv
|
|
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
|
|
.venv/bin/pip install -q uv
|
|
if [ -n "${{ inputs.pre-install }}" ]; then .venv/bin/uv pip install --python .venv/bin/python -q ${{ inputs.pre-install }}; fi
|
|
.venv/bin/uv pip install --python .venv/bin/python -q --resolution lowest-direct -e ".[dev]" pytest
|
|
- name: pytest
|
|
run: python -m pytest -q --tb=short -p no:cacheprovider
|
|
|
|
security:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.12"
|
|
- name: Install
|
|
# Two venvs: the tools, and the package alone. Auditing the tools' venv
|
|
# reported the runner's own pip instead of anything the package brings.
|
|
run: |
|
|
python -m venv .tools
|
|
.tools/bin/pip install -q --upgrade pip
|
|
.tools/bin/pip install -q "$STANDARD" bandit pip-audit
|
|
python -m venv .audit
|
|
.audit/bin/pip install -q --upgrade pip
|
|
if [ -n "${{ inputs.pre-install }}" ]; then .audit/bin/pip install -q ${{ inputs.pre-install }}; fi
|
|
.audit/bin/pip install -q .
|
|
- name: bandit
|
|
run: .tools/bin/bandit -q -r "$(.tools/bin/napalm-standard package)"
|
|
- name: pip-audit
|
|
# What a user gets today from the package's ranges. Packages installed from
|
|
# a URL (the package itself, a git pre-install) are not on PyPI's index yet.
|
|
run: |
|
|
.audit/bin/pip freeze --all | grep -vE ' @ |^-e ' > audit-requirements.txt
|
|
cat audit-requirements.txt
|
|
.tools/bin/pip-audit -r audit-requirements.txt --no-deps --disable-pip --progress-spinner off
|
|
|
|
build:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.12"
|
|
- name: Build wheel and sdist
|
|
run: |
|
|
python -m venv .venv
|
|
.venv/bin/pip install -q build twine
|
|
.venv/bin/python -m build
|
|
.venv/bin/twine check --strict dist/*
|
|
- uses: actions/upload-artifact@v3
|
|
with:
|
|
name: dist
|
|
path: dist/*
|
|
|
|
publish:
|
|
# Only a release tag publishes, and only when everything above passed.
|
|
if: github.ref_type == 'tag' && startsWith(github.ref_name, 'v')
|
|
needs: [standard, lint, types, test, lowest, security, build]
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.12"
|
|
- uses: actions/download-artifact@v3
|
|
with:
|
|
name: dist
|
|
path: dist
|
|
- name: Upload to PyPI
|
|
env:
|
|
TWINE_USERNAME: __token__
|
|
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
|
|
TWINE_REPOSITORY_URL: ${{ inputs.pypi-url }}
|
|
run: |
|
|
if [ -z "$TWINE_PASSWORD" ]; then echo "no PYPI_TOKEN secret in this repo"; exit 1; fi
|
|
python -m venv .venv
|
|
.venv/bin/pip install -q twine "$STANDARD"
|
|
.venv/bin/twine upload --non-interactive dist/*
|
|
- name: Gitea release
|
|
env:
|
|
GITEA_URL: ${{ github.server_url }}
|
|
GITEA_REPOSITORY: ${{ github.repository }}
|
|
GITEA_TOKEN: ${{ github.token }}
|
|
run: .venv/bin/napalm-standard release "$GITHUB_REF_NAME"
|