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

ci: modernize based on poetry #717

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
12 changes: 0 additions & 12 deletions .github/ISSUE_TEMPLATE/config.yml

This file was deleted.

45 changes: 45 additions & 0 deletions .github/actions/bootstrap-poetry/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Bootstrap Poetry
description: Configure the environment with the specified Python and Poetry version.

inputs:
python-version:
description: Desired node-semver compatible Python version expression (or 'default')
default: 'default'
python-latest:
description: Use an uncached Python if a newer match is available
default: 'false'
python-prereleases:
description: Allow usage of pre-release Python versions
default: 'false'
poetry-spec:
description: pip-compatible installation specification to use for Poetry
default: 'poetry'

outputs:
python-path:
description: Path to the installed Python interpreter
value: ${{ steps.setup-python.outputs.python-path }}
python-version:
description: Version of the installed Python interpreter
value: ${{ steps.setup-python.outputs.python-version }}

runs:
using: composite
steps:
- uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5
id: setup-python
if: inputs.python-version != 'default'
with:
python-version: ${{ inputs.python-version }}
check-latest: ${{ inputs.python-latest == 'true' }}
allow-prereleases: ${{ inputs.python-prereleases == 'true' }}
update-environment: false

- run: pipx install ${{ inputs.python-version != 'default' && format('--python "{0}"', steps.setup-python.outputs.python-path) || '' }} '${{ inputs.poetry-spec }}'
shell: bash

# Enable handling long path names (+260 char) on the Windows platform
# https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation
- run: git config --system core.longpaths true
if: runner.os == 'Windows'
shell: pwsh
56 changes: 56 additions & 0 deletions .github/actions/poetry-install/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Poetry Install
description: Run `poetry install` with optional artifact and metadata caching

inputs:
args:
description: Arguments for `poetry install`
cache:
description: Enable transparent Poetry artifact and metadata caching
default: 'true'
path:
description: Path to Poetry project
default: '.'

outputs:
cache-hit:
description: Whether an exact cache hit occured
value: ${{ steps.cache.outputs.cache-hit }}

runs:
using: composite
steps:
- run: printf 'cache-dir=%s\n' "$(poetry config cache-dir)" >> $GITHUB_OUTPUT
id: poetry-config
shell: bash

# Bust the cache every 24 hours to prevent it from expanding over time.
- run: printf 'date=%s\n' "$(date -I)" >> $GITHUB_OUTPUT
id: get-date
if: inputs.cache == 'true'
shell: bash

- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4
id: cache
if: inputs.cache == 'true'
with:
path: |
${{ steps.poetry-config.outputs.cache-dir }}/artifacts
${{ steps.poetry-config.outputs.cache-dir }}/cache
key: poetry-${{ steps.get-date.outputs.date }}-${{ runner.os }}-${{ hashFiles(format('{0}/pyproject.toml', inputs.path), format('{0}/poetry.lock', inputs.path)) }}
# The cache is cross-platform, and other platforms are used to seed cache misses.
restore-keys: |
poetry-${{ steps.get-date.outputs.date }}-${{ runner.os }}-
poetry-${{ steps.get-date.outputs.date }}-
enableCrossOsArchive: true

- run: poetry install ${{ inputs.args }}
working-directory: ${{ inputs.path }}
shell: bash

- run: poetry env info
working-directory: ${{ inputs.path }}
shell: bash

- run: poetry show
working-directory: ${{ inputs.path }}
shell: bash
96 changes: 96 additions & 0 deletions .github/workflows/.tests-matrix.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Reusable workflow consumed by tests.yaml; used to share a single matrix across jobs.
on:
workflow_call:
inputs:
runner:
required: true
type: string
python-version:
required: true
type: string
run-mypy:
required: true
type: boolean
run-pytest:
required: true
type: boolean
run-pytest-poetry:
required: true
type: boolean

defaults:
run:
shell: bash

jobs:
mypy:
name: mypy
runs-on: ${{ inputs.runner }}
if: inputs.run-mypy
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4

- uses: ./.github/actions/bootstrap-poetry
id: bootstrap-poetry
with:
python-version: ${{ inputs.python-version }}

- uses: ./.github/actions/poetry-install

- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4
with:
path: .mypy_cache
key: mypy-${{ runner.os }}-py${{ steps.bootstrap-poetry.outputs.python-version }}-${{ hashFiles('pyproject.toml', 'poetry.lock') }}
restore-keys: |
mypy-${{ runner.os }}-py${{ steps.bootstrap-poetry.outputs.python-version }}-
mypy-${{ runner.os }}-

- run: poetry run mypy

pytest:
name: pytest
runs-on: ${{ inputs.runner }}
if: inputs.run-pytest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4

- uses: ./.github/actions/bootstrap-poetry
with:
python-version: ${{ inputs.python-version }}

- uses: ./.github/actions/poetry-install
with:
args: --with github-actions

- run: poetry run pytest --integration -v

- run: git diff --exit-code --stat HEAD

pytest-poetry:
name: pytest (Poetry)
runs-on: ${{ inputs.runner }}
# FIXME: make Poetry tests pass with PyPy
if: inputs.run-pytest-poetry && !startsWith(inputs.python-version, 'pypy')
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
with:
path: poetry-core

- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
with:
path: poetry
repository: python-poetry/poetry

- uses: ./poetry-core/.github/actions/bootstrap-poetry
with:
python-version: ${{ inputs.python-version }}

- uses: ./poetry-core/.github/actions/poetry-install
with:
path: ./poetry

- run: poetry add ../poetry-core
working-directory: ./poetry

- run: poetry run pytest -v
working-directory: ./poetry
76 changes: 0 additions & 76 deletions .github/workflows/downstream.yml

This file was deleted.

File renamed without changes.
102 changes: 102 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: Tests

on:
merge_group:
pull_request:
push:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

defaults:
run:
shell: bash

env:
PYTHONWARNDEFAULTENCODING: 'true'

jobs:
changes:
name: Detect changed files
runs-on: ubuntu-latest
outputs:
project: ${{ steps.changes.outputs.project }}
src: ${{ steps.changes.outputs.src }}
tests: ${{ steps.changes.outputs.tests }}
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4

- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
id: changes
with:
filters: |
workflow: &workflow
- '.github/actions/**'
- '.github/workflows/tests.yaml'
- '.github/workflows/.tests-matrix.yaml'
project: &project
- *workflow
- 'poetry.lock'
- 'pyproject.toml'
src:
- *project
- 'src/**/*.py'
tests:
- *project
- 'src/**/*.py'
- 'tests/**'

lockfile:
name: Check poetry.lock
runs-on: ubuntu-latest
if: needs.changes.outputs.project == 'true'
needs: changes
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4

- uses: ./.github/actions/bootstrap-poetry

- run: poetry check --lock

tests-matrix:
# Use this matrix with multiple jobs defined in a reusable workflow:
uses: ./.github/workflows/.tests-matrix.yaml
name: ${{ matrix.os.name }} (Python ${{ matrix.python-version }})
if: '!failure() && !cancelled()'
needs:
- lockfile
- changes
with:
runner: ${{ matrix.os.image }}
python-version: ${{ matrix.python-version }}
run-mypy: ${{ needs.changes.outputs.src == 'true' }}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
run-mypy: ${{ needs.changes.outputs.src == 'true' }}
run-mypy: ${{ needs.changes.outputs.tests == 'true' }}

See python-poetry/poetry#9317

run-pytest: ${{ needs.changes.outputs.tests == 'true' }}
run-pytest-poetry: ${{ needs.changes.outputs.src == 'true' }}
secrets: inherit
strategy:
matrix:
os:
- name: Ubuntu
image: ubuntu-22.04
- name: macOS
image: macos-13
- name: Windows
image: windows-2022
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
include:
- os: {name: Ubuntu, image: ubuntu-22.04}
python-version: pypy3.9
- os: {name: Ubuntu, image: ubuntu-22.04}
python-version: pypy3.10
fail-fast: false

status:
name: Status
runs-on: ubuntu-latest
if: '!cancelled()'
needs:
- lockfile
- tests-matrix
steps:
- run: ${{ (contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) && 'false' || 'true' }}
Loading
Loading