Skip to content

Update Python tools and other packaging requirement versions, then re… #97

Update Python tools and other packaging requirement versions, then re…

Update Python tools and other packaging requirement versions, then re… #97

Workflow file for this run

# For more information on GitHub Actions for Python projects, see: https://git.io/JtENw
name: pytest
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ${{ matrix.os }}
# Uncomment this line if we are running on a solitary OS
# runs-on: ubuntu-latest
strategy:
matrix:
# Uncomment this line if we are running on multiple operating systems
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
python-version: ["3.10", "3.11", "3.12"]
env:
# From https://docs.astral.sh/uv/guides/integration/github/#caching
UV_CACHE_DIR: /tmp/.uv-cache
UV_SYSTEM_PYTHON: 1
steps:
- name: Get latest Git (Win) https://github.com/actions/runner-images/issues/10843
if: startsWith(runner.os, 'Windows')
run: |
git.exe --version ;
Start-Process git.exe -Wait -ArgumentList 'update-git-for-windows -y' ;
git.exe --version ;
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
# uv pip cache dependencies to save time
- name: Restore uv cache
uses: actions/cache@v4
with:
path: /tmp/.uv-cache
key: uv-${{ runner.os }}-${{ hashFiles('requirements.txt') }}
restore-keys: |
uv-${{ runner.os }}-${{ hashFiles('requirements.txt') }}
uv-${{ runner.os }}
# - name: Use deploy key
# uses: webfactory/[email protected]
# with:
# ssh-private-key: ${{ secrets.ZZBASE_TOKEN }}
- name: Install uv
shell: bash
run: python -u -m pip install --upgrade uv=="$(python -u -c 'from pathlib import Path;print(list(set([x for x in Path("pyproject.toml").read_text(encoding="utf-8").splitlines() if "uv >= " in x]))[0].split("# ", maxsplit=1)[0].strip().split("\"")[1].removeprefix("uv >= "))')"
- name: Remove subdomain to make requirements.txt setup work in CI
run: python -c 'import fileinput; [print(line.partition("git@")[0] + "[email protected]/" + line.partition(".github.com/")[-1] if (".github.com/" in line and not line.startswith("#")) else line, end="") for line in fileinput.input(inplace=True)]' requirements.txt
- name: Print differences in git repository needed to make CI work
run: git diff
- name: Install requirements from possibly-changed requirements.txt, and package in development mode
run: uv pip install -r requirements.txt -e .
- name: Revert requirements.txt if changed
run: git checkout -- requirements.txt
- name: Run with ruff
run: python -u -m ruff check .
- name: Run with refurb to find code that can be written in a more modern way
if: startsWith(runner.os, 'Linux')
run: python -u -m refurb .
- name: Run pyright
if: startsWith(runner.os, 'Linux')
run: python -u -m pyright
- name: Install OS prerequisites
if: startsWith(runner.os, 'Linux')
run: sudo apt-get update ; sudo apt-get install ripgrep
- name: Search for existing linter ignore lines in Python
if: startsWith(runner.os, 'Linux')
run: |
rg -t py --stats "(?:(?:flake8|noqa|pylint|pyright|type): *(?:disable|ignore|noqa|[a-zA-Z]+[0-9]+)| Any|REPLACEME)" \
$(find . -type f -name "*.py" -not -path "./build/lib/*" ! -name "conf_correct.py") || true
- name: Ensure we are not increasing the number of ignore lines as a guideline
if: startsWith(runner.os, 'Linux')
run: |
if [ $(rg -t py --stats \
"(?:(?:flake8|noqa|pylint|pyright|type): *(?:disable|ignore|noqa|[a-zA-Z]+[0-9]+)| Any|REPLACEME)" \
$(find . -type f -name "*.py" -not -path "./build/lib/*" ! -name "conf_correct.py") \
| awk "/ matches/ && "\!"/ contained matches/" \
| cut -d " " -f1) -lt 5 ] ;
then exit 0 ; else exit 1 ; fi ;
- name: Run shellcheck
if: startsWith(runner.os, 'Linux')
run: rg -t sh --files | xargs shellcheck
- name: Run bashate
if: startsWith(runner.os, 'Linux')
run: rg -t sh --files | xargs bashate -i E006
- name: Generate Sphinx docs (inspect this output for Sphinx errors)
if: startsWith(runner.os, 'Linux')
run: |
( pushd docs/ > /dev/null && ./gen-sphinx-html.sh 2>&1 | rg ": (ERROR|WARNING|CRITICAL): " ; popd > /dev/null ; ) || true
- name: Reset Git repo after Sphinx documentation generation
if: startsWith(runner.os, 'Linux')
run: git clean -fd
- name: Fail if Sphinx doc generation has Sphinx errors
if: startsWith(runner.os, 'Linux')
run: |
if [ "$( pushd docs/ > /dev/null && ./gen-sphinx-html.sh 2>&1 | rg ": (ERROR|WARNING|CRITICAL): " | wc -l ; popd > /dev/null ; )" != "0" ] ; then exit 1 ; fi ;
- name: Reset Git repo a second time after Sphinx documentation generation
if: startsWith(runner.os, 'Linux')
run: git clean -fd
- name: Run tools using pytest
run: |
python -u -m pytest --cov --mypy --pylint --ruff --ruff-format --vulture
# CodeQL analysis section START
# Linux-only, enable on GitHub for public repos and private repos on Enterprise plan with Advanced Security
# IMPORTANT setup steps:
# 1) If this is a private repo NOT on a GitHub Enterprise plan with Advanced Security, disable the last CodeQL result upload step
# 2) Check ${{ secrets.CODEQL_UPLOAD_TOKEN }} has been added and updated in the GitHub settings of this repo
# 3) Check CodeQL languages for this repo are updated correctly
- name: CodeQL languages, comma-separated, for list see https://codeql.github.com/docs/codeql-cli/creating-codeql-databases/
if: startsWith(runner.os, 'Linux')
run: echo "CODEQL_LANGUAGES=python," >> "$GITHUB_ENV"
# CodeQL preprocessing checks commence
- name: Current git branch ref
if: startsWith(runner.os, 'Linux')
run: echo "$GITHUB_REF"
- name: Current git commit
if: startsWith(runner.os, 'Linux')
run: echo $(git rev-parse --verify HEAD)
- name: Current repository name
if: startsWith(runner.os, 'Linux')
run: echo "$GITHUB_REPOSITORY"
- name: Find CodeQL files on GitHub Actions runner OS
if: startsWith(runner.os, 'Linux')
run: pushd /opt/hostedtoolcache/CodeQL/ || exit ; export CODEQL_VER=( * ) ; echo CODEQL_DIR="/opt/hostedtoolcache/CodeQL/${CODEQL_VER[-1]}/x64/codeql" >> "$GITHUB_ENV" ; popd || exit ;
- name: Find CodeQL binary on GitHub Actions runner OS
if: startsWith(runner.os, 'Linux')
run: |
if [ -f $(echo "$CODEQL_DIR"/codeql) ] ;
then
echo CODEQL_BIN=$(echo "$CODEQL_DIR"/codeql) >> "$GITHUB_ENV" ;
else
exit 1 ;
fi ;
- name: Get the codeql version
if: startsWith(runner.os, 'Linux')
run: |
"$CODEQL_BIN" --version
- name: Check that the qlpacks exist for specified languages
if: startsWith(runner.os, 'Linux')
run: |
for LANG in $(echo "$CODEQL_LANGUAGES" | tr "," " ") ;
do
if ! "$CODEQL_BIN" resolve qlpacks | grep -q "$LANG-" ;
then
exit 1 ;
fi ;
done ;
- name: Check that the codeql queries exist for specified languages
if: startsWith(runner.os, 'Linux')
run: |
for LANG in $(echo "$CODEQL_LANGUAGES" | tr "," " ") ;
do
if ! ls "$CODEQL_DIR"/qlpacks/codeql/"$LANG"-queries/*.*/codeql-suites/ | grep -q "$LANG-" ;
then
exit 1 ;
fi ;
done ;
# CodeQL preprocessing checks finish
- name: Create codeql database for specified languages
if: startsWith(runner.os, 'Linux')
run: |
"$CODEQL_BIN" database create codeql-result-database/ --db-cluster --language="$CODEQL_LANGUAGES" ;
- name: Run codeql analysis on each specified languages
if: startsWith(runner.os, 'Linux')
run: |
for LANG in $(echo "$CODEQL_LANGUAGES" | tr "," " ") ;
do
"$CODEQL_BIN" database analyze codeql-result-database/"$LANG"/ --sarif-category="$LANG" --output=out-"$LANG".sarif --format=sarif-latest --threads=0 ;
done ;
- name: Upload codeql results to public GitHub repo or private repo on an enterprise plan with Advanced Security
if: startsWith(runner.os, 'Linux')
run: |
echo "$CODEQL_TOKEN" |
for SARIF in $(ls out-*.sarif) ;
do
"$CODEQL_BIN" github upload-results --commit=$(git rev-parse --verify HEAD) --ref="$GITHUB_REF" --repository="$GITHUB_REPOSITORY" --sarif="$SARIF" --github-auth-stdin ;
done ;
env:
CODEQL_TOKEN: ${{ secrets.CODEQL_UPLOAD_TOKEN }}
# We should search through grep after trying to upload, if applicable
# grep returns exit code 1 if string is not found but specified file is present
# grep returns exit code 2 if specified file is not present
- name: Look for startLine to see if any issues are found, if so, return exit code 1
if: startsWith(runner.os, 'Linux')
run: |
for OUT_FILE in $(ls out-*.sarif) ;
do
if ! (
grep --context=11 startLine "$OUT_FILE" ;
EXIT_CODE=$? ;
if [ "$EXIT_CODE" -eq 0 ] ;
then
exit 1;
fi ;
) ;
then
exit 1 ;
fi ;
done ;
# CodeQL analysis section END
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
continue-on-error: true # codecov limits number of uploads allowed for each commit
with:
env_vars: OS,PYTHON
fail_ci_if_error: true # optional (default = false)
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
- name: Minimize uv cache, --ci will only keep locally-built packages
run: uv cache prune --ci