Skip to content
Merged
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
33 changes: 27 additions & 6 deletions .github/workflows/build-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ jobs:
mac_os:
runs-on: macos-latest
if: github.event.inputs.mac_os == 'true'
env:
UV_SYSTEM_PYTHON: '1'

steps:
- name: Checkout code
Expand All @@ -46,10 +48,15 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
python-version: '3.12'

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Install requirements
run: pip install -r requirements-dev.txt
run: |
uv pip install typer-invoke
inv pip install requirements-dev

- name: Build app
run: inv build.app
Expand All @@ -62,6 +69,8 @@ jobs:
windows:
runs-on: windows-latest
if: github.event.inputs.windows == 'true'
env:
UV_SYSTEM_PYTHON: '1'

steps:
- name: Checkout code
Expand All @@ -70,10 +79,15 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
python-version: '3.12'

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Install requirements
run: pip install -r admin/requirements/requirements-dev.in
run: |
uv pip install typer-invoke
inv pip install requirements-dev

- name: Build app
run: inv build.app
Expand All @@ -86,6 +100,8 @@ jobs:
linux:
runs-on: ubuntu-latest
if: github.event.inputs.linux == 'true'
env:
UV_SYSTEM_PYTHON: '1'

steps:
- name: Checkout code
Expand All @@ -101,10 +117,15 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
python-version: '3.12'

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Install requirements
run: pip install -r requirements-dev.txt
run: |
uv pip install typer-invoke
inv pip install requirements-dev

- name: Build app
run: inv build.app
Expand Down
24 changes: 13 additions & 11 deletions .github/workflows/linting.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
name: Linting
# Linting tools use `pyproject.toml` and `setup.cfg` for config.
# Linting tools use `pyproject.toml` for config.

on:
- pull_request

jobs:
linting:
runs-on: ubuntu-latest
env:
UV_SYSTEM_PYTHON: '1'

steps:
- name: Checkout code
uses: actions/checkout@v5

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
python-version: '3.12'

- name: Install uv
uses: astral-sh/setup-uv@v6

- name: Install requirements
run: pip install -r admin/requirements/requirements-dev.in
run: |
uv pip install typer-invoke
inv pip install requirements-dev

- name: isort
run: isort .
- name: black
run: black .
- name: flake8
run: flake8 .
- name: mypy
run: mypy src && mypy tests
- name: Lint and type check
run: inv lint all --check
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
python-version: '3.12'

- name: Install requirements
run: pip install -r admin/requirements/requirements-dev.in
Expand Down
11 changes: 9 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ on:
jobs:
pytest:
runs-on: windows-latest
env:
UV_SYSTEM_PYTHON: '1'
strategy:
matrix:
# Min and max versions supported
python-version: ['3.10', '3.13']
python-version: ['3.12', '3.14']
name: Python ${{ matrix.python-version }}
steps:
- name: Checkout code
Expand All @@ -29,8 +31,13 @@ jobs:
python-version: ${{ matrix.python-version }}
architecture: x64

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Install requirements
run: pip install -r admin/requirements/requirements-dev.in
run: |
uv pip install typer-invoke
inv pip install requirements-dev

- name: Run tests on Linux and Mac
# Test folder(s) configured in `pyproject.toml`
Expand Down
13 changes: 4 additions & 9 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,15 @@ default_language_version:
python: python3.12
default_stages: [ push ]
repos:
- repo: https://github.com/psf/black
rev: 25.1.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.5
hooks:
- id: black
- id: ruff-check
- id: ruff-format
args: [ --check ]
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
args: [ --check-only ]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.2.0
hooks:
- id: check-added-large-files
- id: debug-statements
- id: double-quote-string-fixer
- id: end-of-file-fixer
7 changes: 6 additions & 1 deletion admin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
from pathlib import Path

PROJECT_ROOT = Path(__file__).parents[1]
SOURCE_DIR = PROJECT_ROOT / 'src'
PROJECT_NAME = PROJECT_ROOT.name
ASSETS_DIR = PROJECT_ROOT / 'assets'
PROJECT_SOURCE_DIR = PROJECT_ROOT / 'src'
"""Source code for the whole project."""
SOURCE_DIR = PROJECT_SOURCE_DIR / PROJECT_NAME
"""Source code for the this project's package."""
56 changes: 40 additions & 16 deletions admin/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@


def _update_project_version(version: str):
regex = r'''^([ _]*version[ _]*[:=] *['"])(.*)(['"].*)$'''
regex = r"""^([ _]*version[ _]*[:=] *['"])(.*)(['"].*)$"""
for file in VERSION_FILES:
_re_sub_file(file, regex, version)


def _get_project_version() -> str:
import re

pattern = re.compile('''^[ _]*version[ _]*[:=] *['"](.*)['"]''', re.MULTILINE)
pattern = re.compile("""^[ _]*version[ _]*[:=] *['"](.*)['"]""", re.MULTILINE)
versions = {}
for file in VERSION_FILES:
with open(file) as f:
Expand Down Expand Up @@ -113,22 +113,30 @@ def _get_version_from_release_name(release_name: str) -> str:
return release_name[1:]


def _get_latest_release(c) -> tuple[str, str, list[dict]]:
def _get_latest_release(dry: bool) -> tuple[str, str, list[dict]]:
"""
Retrieves the latest release from GitHub.

:return: Tuple with: release name (ex 'v1.2.3'), tag (ex '1.2.3') and list of assets uploaded.
"""
import json

release_info_json = c.run('gh release view --json name,tagName,assets').stdout.strip()
release_info_json = (
run('gh', 'release', 'view', '--json', 'name,tagName,assets', dry=dry, capture_output=True)
.stdout.decode() # type: ignore
.strip()
)
release_info = json.loads(release_info_json)
return release_info['name'], release_info['tagName'], release_info['assets']


def _get_branch():
"""Returns the current branch."""
return run(False, 'git', 'branch', '--show-current')
return (
run('git', 'branch', '--show-current', dry=False, capture_output=True)
.stdout.decode() # type: ignore
.strip()
)


def _get_default_branch():
Expand All @@ -140,12 +148,12 @@ def _get_default_branch():

def _commit(message: str, dry: bool):
# Commit
run(dry, 'git', 'add', *VERSION_FILES)
run(dry, 'git', 'commit', '-m', message)
run('git', 'add', *VERSION_FILES, dry=dry)
run('git', 'commit', '-m', message, dry=dry)

# Push current branch
branch = _get_branch()
run(dry, 'git', 'push', 'origin', branch)
run('git', 'push', 'origin', branch, dry=dry)


def _create_pr(title: str, description: str, dry: bool):
Expand All @@ -158,7 +166,6 @@ def _create_pr(title: str, description: str, dry: bool):
default_branch = _get_default_branch()
branch = _get_branch()
run(
dry,
'gh',
'pr',
'create',
Expand All @@ -170,10 +177,11 @@ def _create_pr(title: str, description: str, dry: bool):
branch,
'--base',
default_branch,
dry=dry,
)

# Merge PR after checks pass
run(dry, 'gh', 'pr', 'merge', 'branch', '--squash', '--auto')
run('gh', 'pr', 'merge', 'branch', '--squash', '--auto', dry=dry)


@app.command(name='clean')
Expand All @@ -183,6 +191,22 @@ def build_clean():
shutil.rmtree(BUILD_DIST_DIR, ignore_errors=True)


@app.command(name='publish')
def build_publish(
upload: Annotated[bool, typer.Option(help='Upload to PyPI after build.')] = True,
yes: Annotated[bool, typer.Option(help='Skip publish confirmation.')] = False,
dry: DryAnnotation = False,
):
run('uv', 'build', dry=dry)
if not upload:
return
msg = f'Publishing version `{_get_project_version()}` to PyPI. Press Y to confirm. '
if yes or input(msg).strip().lower() == 'y':
run('uv', 'publish', dry=dry)
else:
logger.info('Package not published to PyPI.')


@app.command(name='version')
def build_version(
version: Annotated[
Expand Down Expand Up @@ -213,7 +237,7 @@ def build_version(
yes: Annotated[
bool,
typer.Option(
help='Don\'t ask confirmation to create new branch if necessary.',
help="Don't ask confirmation to create new branch if necessary.",
show_default=False,
),
] = False,
Expand Down Expand Up @@ -269,28 +293,28 @@ def build_version(
if yes or input(
f'Current branch `{branch}` is the default branch, create new branch? [Y/n] '
).strip().lower() in ['', 'y', 'yes']:
run(dry, 'git', 'checkout', '-b', f'release-{v2}')
run('git', 'checkout', '-b', f'release-{v2}', dry=dry)
branch_ok = True
if not branch_ok:
logger.error(f'Cannot make changes in the default branch `{branch}`.')
raise typer.Exit(1)

# Update files to new version
_update_project_version(str(v2))
print(
logger.info(
f'New version is `{v2}`. Modified files :\n'
+ '\n'.join(f' {file.relative_to(PROJECT_ROOT)}' for file in VERSION_FILES)
)

# Commit/push/pr
if mode == 'nothing':
print('Files not committed, PR not created.')
logger.info('Files not committed, PR not created.')
if mode in ['commit', 'pr']:
print('Commit and push changes.')
logger.info('Commit and push changes.')
_commit(f'bump version to {v2}', dry)
if mode == 'pr':
pr_title = f'Release {v2}'
print(f'Create and merge PR `{pr_title}`.')
logger.info(f'Create and merge PR `{pr_title}`.')
_create_pr(pr_title, f'Preparing for release {v2}', dry)


Expand Down
Loading