Skip to content

Commit

Permalink
chore: use dynamic version field in pyproject.toml based on `hatch.…
Browse files Browse the repository at this point in the history
…build.hooks.vcs` and publish dev packages on pypi for all pushes to the main branch and all pull requests targeting the main branch
  • Loading branch information
sassanh committed Oct 4, 2024
1 parent 65838c4 commit bc5ade2
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 47 deletions.
74 changes: 32 additions & 42 deletions .github/workflows/integration_delivery.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64

- name: Install uv
uses: astral-sh/setup-uv@v3
Expand Down Expand Up @@ -109,20 +108,15 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64

- name: Install uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true
cache-suffix: ubuntu-latest

- name: Create virtualenv
run: |
uv venv --system-site-packages
- name: Lint
run: uv run --frozen poe lint
run: uvx ruff check

test:
name: Test
Expand Down Expand Up @@ -151,7 +145,6 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64

- name: Install uv
uses: astral-sh/setup-uv@v3
Expand Down Expand Up @@ -215,47 +208,42 @@ jobs:
name: Setup Python
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64

- name: Install uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true
cache-suffix: ubuntu-latest

- name: Create virtualenv
run: |
uv venv --system-site-packages
- name: Extract Version
id: extract-version
run: |
echo "VERSION=$(uv run --frozen python -c 'from importlib.metadata import version; print(version("ubo_app"))')" >> "$GITHUB_OUTPUT"
echo "VERSION=$(uv run --frozen python -c 'from importlib.metadata import version; print(version("ubo_app"))')"
echo "NAME=$(uv run --frozen python -c 'from importlib.metadata import metadata; print(metadata("ubo_app")["Name"])')" >> "$GITHUB_OUTPUT"
echo "NAME=$(uv run --frozen python -c 'from importlib.metadata import metadata; print(metadata("ubo_app")["Name"])')"
git fetch --prune --unshallow
git fetch --depth=1 origin +refs/tags/*:refs/tags/*
echo "VERSION=$(uvx hatch version)" >> "$GITHUB_OUTPUT"
echo "VERSION=$(uvx hatch version)"
echo "NAME=$(uvx hatch project metadata | jq -r .name)" >> "$GITHUB_OUTPUT"
echo "NAME=$(uvx hatch project metadata | jq -r .name)"
- name: Extract Version from CHANGELOG.md
run: |
VERSION_CHANGELOG=$(sed -n '/## Version /s/## Version //p' CHANGELOG.md | head -n 1)
echo "VERSION_CHANGELOG=$VERSION_CHANGELOG"
if [ "${{ steps.extract-version.outputs.VERSION }}" != "$VERSION_CHANGELOG" ]; then
echo "Error: Version extracted from CHANGELOG.md does not match the version in pyproject.toml"
exit 1
else
echo "Versions are consistent."
fi
- name: Extract Version from Tag
if: startsWith(github.ref, 'refs/tags/v')
run: |
VERSION_TAG=$(sed 's/^v//' <<< ${{ github.ref_name }})
echo "VERSION_TAG=$VERSION_TAG"
if [ "${{ steps.extract-version.outputs.VERSION }}" != "$VERSION_TAG" ]; then
echo "Error: Version extracted from tag does not match the version in pyproject.toml"
exit 1
FIRST_HEADER=$(sed -n '/## /s/## //p' CHANGELOG.md | head -n 1)
if [ "$FIRST_HEADER" == "Upcoming" ]; then
# Check the version coming from extract-version starts with of x.y.z.devn
if [[ "${{ steps.extract-version.outputs.VERSION }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.dev[0-9]+ ]]; then
VERSION_CHANGELOG="This is a development version."
else
echo "Error: First header in CHANGELOG.md is 'Upcoming' but the version in pyproject.toml is not a development version."
exit 1
fi
else
echo "Versions are consistent."
VERSION_CHANGELOG=$(echo $FIRST_HEADER | sed 's/Version //')
if [ "${{ steps.extract-version.outputs.VERSION }}" != "$VERSION_CHANGELOG" ]; then
echo "Error: Version extracted from CHANGELOG.md does not match the version in pyproject.toml"
exit 1
else
echo "Versions are consistent."
fi
fi
- name: Configure Sentry
Expand All @@ -270,7 +258,9 @@ jobs:
cat ubo_app/.env
- name: Build
run: uv build
run:
SETUPTOOLS_SCM_PRETEND_VERSION=${{
steps.extract-version.outputs.VERSION }} uv build

- name: Upload wheel
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -379,10 +369,11 @@ jobs:
steps.generate-image-url.outputs.dashed_suffix }}.img.gz
if-no-files-found: error

pypi-publish:
name: Publish to PyPI
publish:
name: Publish
if: >-
github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
github.event_name == 'push' && github.ref == 'refs/heads/main' ||
github.event_name == 'pull_request' && github.head_ref == 'main'
needs:
- type-check
- lint
Expand All @@ -406,11 +397,10 @@ jobs:
name: binary
path: dist

- name: Publish package distributions to PyPI
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist
verbose: true

release:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
Expand All @@ -420,7 +410,7 @@ jobs:
- lint
- test
- build
- pypi-publish
- publish
- images
runs-on: ubuntu-latest
environment:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ headless_kivy_pi_buffer.raw
scripts/packer/packer_cache/
scripts/packer/output-*

# hatch
ubo_app/_version.py

/screenshots
/snapshot.json
/snapshot.bin
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## Upcoming

- chore: migrate from poetry to uv for the sake of improving performance and dealing with conflicting sub-dependencies
- feat(core): add colors to logs based on their level to make them more readable
- chore: use dynamic version field in `pyproject.toml` based on `hatch.build.hooks.vcs` and publish dev packages on pypi for all pushes to the main branch and all pull requests targeting the main branch

## Version 0.17.1

Expand Down
16 changes: 13 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "ubo-app"
version = "0.17.1"
dynamic = ["version"]
description = "Ubo main app, running on device initialization. A platform for running other apps."
license = { text = "Apache-2.0" }
readme = "README.md"
Expand Down Expand Up @@ -42,9 +42,18 @@ dependencies = [
]

[build-system]
requires = ["hatchling"]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"

[tool.hatch.version]
source = "vcs"

[tool.hatch.build.hooks.vcs]
version-file = "ubo_app/_version.py"

[tool.hatch.version.raw-options]
local_scheme = "setup_scm_schemes:local_scheme"

[tool.uv]
dev-dependencies = [
"headless-kivy [test] >=0.9.8",
Expand Down Expand Up @@ -128,6 +137,7 @@ cmd = "scripts/deploy.sh"

[tool.ruff]
target-version = 'py311'
extend-exclude = ["setup_scm_schemes.py"]

[tool.ruff.lint]
select = ["ALL"]
Expand Down Expand Up @@ -169,7 +179,7 @@ quote-style = "single"
profile = "black"

[tool.pyright]
exclude = ["typings", "ubo_app/rpc/generated", ".venv"]
exclude = ["typings", "ubo_app/rpc/generated", ".venv", "setup_scm_schemes.py"]

[[tool.pyright.executionEnvironments]]
root = "ubo_app/services/000-audio"
Expand Down
11 changes: 11 additions & 0 deletions setup_scm_schemes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from setuptools_scm.version import get_local_node_and_date
import re


def local_scheme(version):
version.node = re.sub(
r'.',
lambda match: str(ord(match.group(0))),
version.node
)
return get_local_node_and_date(version).replace('+', '').replace('.d', '')
35 changes: 33 additions & 2 deletions ubo_app/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
import json
import logging
import logging.handlers
import os
import sys
from typing import TYPE_CHECKING, cast
from typing import TYPE_CHECKING, ClassVar, cast

if TYPE_CHECKING:
from collections.abc import Mapping
Expand Down Expand Up @@ -69,6 +70,12 @@ def get_logger(name: str) -> UboLogger:
return cast(UboLogger, logging.getLogger(name))


def supports_truecolor() -> bool:
"""Check if the terminal supports truecolor (24-bit)."""
color_term = os.environ.get('COLORTERM', '')
return color_term == 'truecolor'


logger = get_logger('ubo-app')
logger.propagate = False

Expand Down Expand Up @@ -100,9 +107,28 @@ class ExtraFormatter(logging.Formatter):
'message',
)

COLORS: ClassVar[dict[int, str]] = {
VERBOSE: '\033[38;2;100;100;100m', # Dark Gray (RGB)
logging.DEBUG: '\033[38;2;150;150;150m', # Light Gray (RGB)
logging.INFO: '\033[38;2;100;200;100m', # Green (RGB)
logging.WARNING: '\033[38;2;255;165;0m', # Orange (RGB)
logging.ERROR: '\033[38;2;255;0;0m', # Red (RGB)
logging.CRITICAL: '\033[38;2;255;0;255m', # Magenta (RGB)
}
ANSI_COLORS: ClassVar[dict[int, str]] = {
VERBOSE: '\033[90m', # Gray (ANSI)
logging.DEBUG: '\033[94m', # Blue (ANSI)
logging.INFO: '\033[92m', # Green (ANSI)
logging.WARNING: '\033[93m', # Yellow (ANSI)
logging.ERROR: '\033[91m', # Red (ANSI)
logging.CRITICAL: '\033[95m', # Magenta (ANSI)
}
RESET = '\033[0m' # Reset color

def format(self: ExtraFormatter, record: logging.LogRecord) -> str:
string = super().format(record)
extra = {k: v for k, v in record.__dict__.items() if k not in self.def_keys}

if len(extra) > 0:
string += ' - extra: ' + json.dumps(
handle_circular_references(extra),
Expand All @@ -114,7 +140,12 @@ def format(self: ExtraFormatter, record: logging.LogRecord) -> str:
if self.max_length and len(string) > self.max_length:
string = string[: self.max_length - 3] + '...'

return string
# Get the color for the log level and apply it
color = (self.COLORS if supports_truecolor() else self.ANSI_COLORS).get(
record.levelno,
self.RESET,
)
return f'{color}{string}{self.RESET}'


def add_stdout_handler(logger: UboLogger, level: int = logging.DEBUG) -> None:
Expand Down

0 comments on commit bc5ade2

Please sign in to comment.