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: add Python CI #2

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
15 changes: 15 additions & 0 deletions .yamllint
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

TODO: remove before merge and add this as another PR.

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
extends: default

rules:
# Rule to enforce the use of double quotes
quoted-strings:
quote-type: double
required: false
# Additional rules can be configured as needed
line-length:
max: 120
indentation:
spaces: 2
document-start: disable
...
37 changes: 37 additions & 0 deletions actions/python/code-quality/format/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
name: Format Code
description: Checks and ensures the code is formatted according to the defined
style guidelines.

inputs:
python_version:
description: Python version to use
default: "3.12"
required: false
poetry_install_options:
description: Options for installing dependencies via poetry
required: false
default: "--only=code_quality --no-root"
poetry_export_options:
description: Options for exporting dependencies to check for hash
changes for cache invalidation
required: false
default: "--only=code_quality"
uniqueg marked this conversation as resolved.
Show resolved Hide resolved

runs:
using: composite
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up environment
uses: elixir-cloud-aai/actions/python/setup/poetry@main
with:
python_version: ${{ inputs.python_version }}
poetry_install_options: ${{ inputs.poetry_install_options }}
poetry_export_options: ${{ inputs.poetry_export_options }}

- name: Check code style
shell: bash
run: poetry run ruff format --check
...
36 changes: 36 additions & 0 deletions actions/python/code-quality/lint/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
name: Lint Code
description: Lints the code to ensure code quality and adherence to standards.

inputs:
python_version:
description: Python version to use
default: "3.12"
required: false
poetry_install_options:
description: Options for installing dependencies via poetry
required: false
default: "--only=code_quality --no-root"
poetry_export_options:
description: Options for exporting dependencies to check for hash
changes for cache invalidation
required: false
default: "--only=code_quality"

runs:
using: composite
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up environment
uses: elixir-cloud-aai/actions/python/setup/poetry@main
with:
python_version: ${{ inputs.python_version }}
poetry_install_options: ${{ inputs.poetry_install_options }}
poetry_export_options: ${{ inputs.poetry_export_options }}

- name: Check code quality
shell: bash
run: poetry run ruff check .
...
36 changes: 36 additions & 0 deletions actions/python/code-quality/spell-check/action.yaml
uniqueg marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
name: Spell Check
description: Runs a spell check on the codebase to identify spelling errors.

inputs:
python_version:
description: Python version to use
default: "3.12"
required: false
poetry_install_options:
description: Options for installing dependencies via poetry
required: false
default: "--only=code_quality --no-root"
poetry_export_options:
description: Options for exporting dependencies to check for hash
changes for cache invalidation
required: false
default: "--only=code_quality"

runs:
using: composite
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up environment
uses: elixir-cloud-aai/actions/python/setup/poetry@main
with:
python_version: ${{ inputs.python_version }}
poetry_install_options: ${{ inputs.poetry_install_options }}
poetry_export_options: ${{ inputs.poetry_export_options }}

- name: Check spellings
shell: bash
run: poetry run typos .
...
42 changes: 42 additions & 0 deletions actions/python/code-quality/type-check/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
name: Type Check
description: Runs a type check on the codebase to ensure type safety and
correctness.

inputs:
python_version:
description: Python version to use
default: "3.12"
required: false
poetry_install_options:
description: Options for installing dependencies via poetry
required: false
default: "--with=code_quality --with=types --no-root"
poetry_export_options:
description: Options for exporting dependencies to check for hash
changes for cache invalidation
required: false
default: "--with=code_quality --with=types"
file_path:
description: The path to the file or directory to type check
required: false
default: " . "


runs:
using: composite
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up environment
uses: elixir-cloud-aai/actions/python/setup/poetry@main
with:
python_version: ${{ inputs.python_version }}
poetry_install_options: ${{ inputs.poetry_install_options }}
poetry_export_options: ${{ inputs.poetry_export_options }}

- name: Check types
shell: bash
run: poetry run mypy ${{ inputs.file_path }}
...
60 changes: 60 additions & 0 deletions actions/python/code-test/integration-test/action.yaml
uniqueg marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
name: Integration Test
description: Set up environment, run integration tests, and upload coverage report.

inputs:
os:
default: ubuntu-latest
description: The operating system to use
required: false
python_version:
default: "3.12"
description: The version of Python to use
required: false
poetry_install_options:
default: "--with=test"
description: Options for installing dependencies via poetry
required: false
poetry_export_options:
default: "--with=test"
description: Options for exporting dependencies for cache invalidation
required: false
codecov_token:
description: Codecov token for uploading coverage reports
required: true
file_path:
description: The path to the file or directory to integration test
required: false
default: "tests/test_integration"

runs:
using: composite
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up environment
uses: elixir-cloud-aai/actions/python/setup/poetry@main
with:
os: ${{ inputs.os }}
python_version: ${{ inputs.python_version }}
poetry_install_options: ${{ inputs.poetry_install_options }}
poetry_export_options: ${{ inputs.poetry_export_options }}

- name: Run integration tests and generate coverage report
shell: bash
run: |
poetry run pytest \
--cov-report term \
--cov-report xml:test_integration.xml \
--cov=${{ inputs.file_path }}

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ inputs.codecov_token }}
flags: test_integration
files: ./test_integration.xml
fail_ci_if_error: true
verbose: true
...
60 changes: 60 additions & 0 deletions actions/python/code-test/unit-test/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
name: Unit Test
description: Set up environment, run unit tests, and upload coverage report.

inputs:
os:
default: ubuntu-latest
description: The operating system to use
required: false
JaeAeich marked this conversation as resolved.
Show resolved Hide resolved
python_version:
default: "3.12"
description: The version of Python to use
required: false
poetry_install_options:
default: "--with=test"
description: Options for installing dependencies via poetry
required: false
poetry_export_options:
default: "--with=test"
description: Options for exporting dependencies for cache invalidation
required: false
codecov_token:
description: Codecov token for uploading coverage reports
required: true
file_path:
description: The path to the file or directory to unit test
required: false
default: "tests/test_unit"

runs:
using: composite
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up environment
uses: elixir-cloud-aai/actions/python/setup/poetry@main
with:
os: ${{ inputs.os }}
python_version: ${{ inputs.python_version }}
poetry_install_options: ${{ inputs.poetry_install_options }}
poetry_export_options: ${{ inputs.poetry_export_options }}

- name: Run unit tests and generate coverage report
shell: bash
run: |
poetry run pytest \
--cov-report term \
--cov-report xml:test_unit.xml \
--cov=${{ inputs.file_path }}

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ inputs.codecov_token }}
flags: test_unit
files: ./test_unit.xml
fail_ci_if_error: true
verbose: true
...
92 changes: 92 additions & 0 deletions actions/python/setup/poetry/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
name: Setup Python and Poetry Action
description: Configure system, Python, Poetry and deps and cache management.

inputs:
os:
default: ubuntu-latest
description: The operating system to use
python_version:
default: "3.12"
description: The version of Python to use
poetry_version:
default: "1.8.2"
description: The version of Poetry to install
poetry_install_options:
default: ""
description: Additional options to pass to poetry install
poetry_export_options:
default: ""
description: Options to pass to poetry export for hash generation for cache
invalidation

runs:
using: composite
steps:
- uses: "actions/setup-python@v5"
id: setup-python
with:
python-version: "${{ inputs.python_version }}"

- name: Setup pipx environment Variables
id: pipx-env-setup
# pipx default home and bin dir are not writable by the cache action
# so override them here and add the bin dir to PATH for later steps.
# This also ensures the pipx cache only contains poetry
run: |
SEP="${{ !startsWith(runner.os, 'windows') && '/' || '\\' }}"
PIPX_CACHE="${{ github.workspace }}${SEP}pipx_cache"
echo "pipx-cache-path=${PIPX_CACHE}" >> $GITHUB_OUTPUT
echo "pipx-version=$(pipx --version)" >> $GITHUB_OUTPUT
echo "PIPX_HOME=${PIPX_CACHE}${SEP}home" >> $GITHUB_ENV
echo "PIPX_BIN_DIR=${PIPX_CACHE}${SEP}bin" >> $GITHUB_ENV
echo "PIPX_MAN_DIR=${PIPX_CACHE}${SEP}man" >> $GITHUB_ENV
echo "${PIPX_CACHE}${SEP}bin" >> $GITHUB_PATH
shell: bash

- name: Pipx cache
id: pipx-cache
uses: actions/cache@v4
with:
path: ${{ steps.pipx-env-setup.outputs.pipx-cache-path }}
key: ${{ runner.os }}-python-
${{ steps.setup-python.outputs.python_version }}-
pipx-${{ steps.pipx-env-setup.outputs.pipx-version }}-
poetry-${{ inputs.poetry_version }}

- name: Install poetry
if: steps.pipx-cache.outputs.cache-hit != 'true'
id: install-poetry
shell: bash
run: |
pipx install poetry \
--python "${{ steps.setup-python.outputs.python-path }}"

- name: Read poetry cache location
id: poetry-cache-location
shell: bash
run: |
echo "poetry-venv-location=$(poetry config virtualenvs.path)" \
>> $GITHUB_OUTPUT

- name: Generate hash only for required deps
run: |
poetry export ${{ inputs.poetry_export_options }} \
--format=requirements.txt --output=requirements.txt
echo "DEP_HASH=$(sha256sum requirements.txt | cut -d ' ' -f 1)" \
>> $GITHUB_ENV
shell: bash

- name: Poetry cache
uses: actions/cache@v4
with:
path: ${{ steps.poetry-cache-location.outputs.poetry-venv-location }}
key: ${{ runner.os }}-[python-
${{ steps.setup-python.outputs.python_version }}]-[
${{ env.DEP_HASH }}]-[${{ inputs.poetry_install_options }}]

- name: Poetry install
if: steps.poetry-cache.outputs.cache-hit != 'true'
shell: bash
run: poetry install ${{ inputs.poetry_install_options }} --no-interaction
...
Loading