Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: python test, lint and policy check workflows #18

Merged
merged 20 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/lint-python.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Lint Python
on:
workflow_call:
# Because we have a uv.lock file, we can also use this workflow to lint ourselves.
pull_request:
branches:
- main
push:
branches:
- main

jobs:
files:
runs-on: ubuntu-latest
steps:
- name: Begin snap installs of common linters
id: snap-install
run: |
echo -n 'jobs="$(sudo snap install --no-wait codespell ruff shellcheck)"' >> $GITHUB_OUTPUT
- name: Check out code
uses: actions/checkout@v4
- name: Set up uv with caching
id: setup-uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true
- name: Set up linters
run: |
for job in ${{ steps.snap-install.outputs.jobs }}; do
sudo snap watch $job
done
make setup-lint
- name: Run linters
run: make -k lint
40 changes: 0 additions & 40 deletions .github/workflows/lint.yaml

This file was deleted.

25 changes: 25 additions & 0 deletions .github/workflows/policy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Check policy
on:
workflow_call:
pull_request:
branches:
- main
push:
branches:
- main

jobs:
cla:
name: Authors signed Canonical CLA
runs-on: ubuntu-latest
steps:
- name: Check if CLA signed
uses: canonical/has-signed-canonical-cla@v1
commits:
name: Conventional Commits
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: webiny/[email protected]
with:
allowed-commit-types: "build,chore,ci,docs,feat,fix,perf,refactor,style,test"
19 changes: 19 additions & 0 deletions .github/workflows/self-test-qa.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: QA self-test
on:
pull_request:

jobs:
lint-python:
uses: ./.github/workflows/lint-python.yaml
test-python:
uses: ./.github/workflows/test-python.yaml
test-python-custom:
uses: ./.github/workflows/test-python.yaml
with:
# Test on many OS's to ensure that these workflows work everywhere.
# Also ensure we can add a list of tags for self-hosted runners.
fast-test-platforms: '[["jammy", "amd64"], ["noble", "arm64"], "ubuntu-22.04", "windows-latest", "macos-latest"]'
fast-test-python-versions: '["3.14"]'
slow-test-platforms: '["ubuntu-latest"]'
slow-test-python-versions: '["3.14"]'
lowest-python-version: "3.0"
146 changes: 146 additions & 0 deletions .github/workflows/test-python.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
name: Test Python
on:
workflow_call:
inputs:
fast-test-platforms:
type: string
default: '["jammy", "noble"]'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we need to further restrict these to amd64?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can and we needn't. I added the architectures in the self-test in order to check that we could add lists of tags, but I figured here it would be a good default to simply run the tests on the first available runner regardless of architecture.

description: |
The platforms to run fast tests on, as a JSON array.
fast-test-python-versions:
type: string
default: '["3.10", "3.11", "3.12", "3.13"]'
description: |
The python versions to run fast tests on, as a JSON array.
slow-test-platforms:
type: string
default: '["jammy"]'
description: |
The platforms to run slow tests on, as a JSON array.
slow-test-python-versions:
type: string
default: '["3.10"]'
description: |
The python versions to run slow tests on, as a JSON array.
lowest-python-platform:
type: string
description: |
The platform to run the lowest python version tests on.
default: "ubuntu-20.04"
lowest-python-version:
type: string
description: |
The Python version to run when using "lowest" resolution for tests.
default: "3.10"

jobs:
fast:
name: Fast tests
strategy:
matrix:
platform: ${{ fromJson(inputs.fast-test-platforms) }}
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up uv with caching
id: setup-uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true
cache-suffix: ${{ toJSON(matrix.platform) }}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the errors in https://github.com/canonical/starflow/actions/runs/11824136927 I think the conversion back to a JSON is giving an invalid cache key.

We could try with:

Suggested change
cache-suffix: ${{ toJSON(matrix.platform) }}
cache-suffix: ${{ matrix.platform }}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The path doesn't exist because we're not actually using uv in those tests. This needs to be toJSON so it's a string - otherwise it fails when you have an array of tags (e.g. your platform is our self-hosted [noble, amd64]).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant that it looks like this is resolving to an invalid value:

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, I see. Thank you! Fixed :-)

- name: Set up tests
shell: bash
run: |
for python_version in $(echo '${{ inputs.fast-test-python-versions }}' | jq -r .[] | tr '\n' ' '); do
python_dirname=$(echo ${{ runner.temp }} | tr '\\' /)/venv_$(echo $python_version | tr . _)
make setup-tests UV_PROJECT_ENVIRONMENT="${python_dirname}"
done
- name: Run tests
shell: bash
run: |
exit_code=0
for python_version in $(echo '${{ inputs.fast-test-python-versions }}' | jq -r .[] | tr '\n' ' '); do
echo "::group::Python ${python_version}"
python_dirname=$(echo ${{ runner.temp }} | tr '\\' /)/venv_$(echo $python_version | tr . _)
if ! make test-coverage UV_PROJECT_ENVIRONMENT="${python_dirname}" PYTEST_ADDOPTS="-m 'not slow'"
then
exit_code=1
echo "::error title=TESTS FAILED::Tests failed with Python ${python_version}"
fi
echo "::endgroup::"
done
exit $exit_code
- name: Upload test coverage
uses: actions/upload-artifact@v4
with:
name: coverage-fast-${{ matrix.platform }}
overwrite: true
path: |
./coverage.xml
htmlcov/**
slow:
name: Slow tests
strategy:
matrix:
platform: ${{ fromJson(inputs.slow-test-platforms) }}
python-version: ${{ fromJson(inputs.slow-test-python-versions) }}
runs-on: ${{ matrix.platform }}
env:
PYTEST_ADDOPTS: --no-header -v -rN -m 'slow'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up uv with caching
id: setup-uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true
cache-suffix: ${{ toJSON(matrix.platform) }}
- name: Install tools
run: |
make setup-tests
- name: Run tests
run: |
make test-coverage
- name: Upload test coverage
uses: actions/upload-artifact@v4
with:
name: coverage-slow-${{ matrix.platform }}-${{ matrix.python-version }}
overwrite: true
path: |
./coverage.xml
htmlcov/**
lowest:
name: Minimum dependencies (all tests)
if: ${{ inputs.lowest-python-version }} != ''
runs-on: ${{ inputs.lowest-python-platform }}
env:
UV_PYTHON: ${{ inputs.lowest-python-version }}
UV_RESOLUTION: lowest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up uv with caching
id: setup-uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true
cache-suffix: lowest-jammy
- name: Install tools
run: |
make setup-tests
- name: Run tests
run: |
make test-coverage
- name: Upload test coverage
uses: actions/upload-artifact@v4
with:
name: coverage-lowest-py${{ inputs.lowest-python-version }}
overwrite: true
path: |
./coverage.xml
htmlcov/**
7 changes: 7 additions & 0 deletions .test-data/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 31 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# https://github.com/snapcrafters/ci/blob/main/Makefile
.PHONY: help
help:
@echo "Usage:"
Expand All @@ -14,3 +13,34 @@ lint:
format:
## format: Formats both Markdown documents and YAML documents to preferred repository style.
npx prettier --print-width=99 --write .

.PHONY: setup
setup: setup-lint
## setup: Install the necessary tools for linting and testing.

.PHONY: setup-lint
setup-lint:
## setup-lint: Install the necessary tools for linting.
ifneq ($(shell which npx),)
else ifneq ($(shell which snap),)
sudo snap install --classic --channel 22 node
else
$(error Cannot find npx. Please install it on your system.)
endif
ifneq ($(shell which shellcheck),)
else ifneq ($(shell which snap),)
sudo snap install shellcheck
else
$(error Cannot find shellcheck. Please install it on your system.)
endif

.PHONY: setup-tests
setup-tests:
echo "Installing nothing..."
echo "Installed!"

.PHONY: test-coverage
test-coverage:
$(info Simulating coverage creation)
$(info "Running tests with extra pytest options: ${PYTEST_ADDOPTS}")
@touch coverage.xml
Loading
Loading