chore(release): v1.1.0 #839
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: CI/CD | |
on: | |
push: | |
branches: | |
- main | |
tags: | |
- 'v*' | |
pull_request: | |
workflow_dispatch: | |
env: | |
PYTHON_VERSION: '3.11.9' | |
jobs: | |
dependencies: | |
name: Install Dependencies | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
name: Checkout | |
- name: System Dependencies | |
run: | | |
sudo apt-get update -y | |
sudo apt-get install -y portaudio19-dev | |
- name: Setup Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version: ${{ env.PYTHON_VERSION }} | |
- 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: Install dependencies | |
run: uv sync --frozen | |
ubo-pod-dependencies: | |
name: Install Ubo Pod Dependencies | |
runs-on: ubo-pod-pi5 | |
outputs: | |
python-version: ${{ steps.get-python-version.outputs.PYTHON_VERSION }} | |
steps: | |
- uses: actions/checkout@v4 | |
name: Checkout | |
- name: Extract Python Version | |
id: get-python-version | |
run: | | |
echo "PYTHON_VERSION=$(python --version | cut -d' ' -f2)" >> $GITHUB_OUTPUT | |
echo "PYTHON_VERSION=$(python --version | cut -d' ' -f2)" | |
- name: Install uv | |
uses: astral-sh/setup-uv@v3 | |
with: | |
enable-cache: true | |
cache-suffix: ubo-pod | |
- name: Create virtualenv | |
run: | | |
uv venv --system-site-packages | |
- name: Install dependencies | |
run: | | |
uv sync --frozen | |
type-check: | |
name: Type Check | |
needs: | |
- ubo-pod-dependencies | |
runs-on: ubo-pod-pi5 | |
steps: | |
- uses: actions/checkout@v4 | |
name: Checkout | |
- name: Install uv | |
uses: astral-sh/setup-uv@v3 | |
with: | |
enable-cache: true | |
cache-suffix: ubo-pod | |
- name: Create virtualenv | |
run: | | |
uv venv --system-site-packages | |
- name: Create stub files | |
run: | | |
uv run --frozen pyright --createstub kivy | |
- name: Type Check | |
run: | | |
uv run --frozen poe typecheck | |
lint: | |
name: Lint | |
needs: | |
- dependencies | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
name: Checkout | |
- name: Install uv | |
uses: astral-sh/setup-uv@v3 | |
with: | |
enable-cache: true | |
cache-suffix: ubuntu-latest | |
- name: Lint | |
run: uvx ruff check | |
test: | |
name: Test | |
needs: | |
- dependencies | |
- ubo-pod-dependencies | |
strategy: | |
matrix: | |
runner: ['ubo-pod', 'ubo-pod-pi5', 'ubuntu-latest'] | |
runs-on: ${{ matrix.runner }} | |
environment: | |
name: test | |
url: https://app.codecov.io/gh/${{ github.repository }}/ | |
steps: | |
- name: System Dependencies | |
if: matrix.runner == 'ubuntu-latest' | |
run: | | |
sudo apt-get update -y | |
sudo apt-get install -y libegl1 libgl1 libmtdev1 libzbar0 | |
- uses: actions/checkout@v4 | |
name: Checkout | |
- name: Setup Python | |
if: matrix.runner == 'ubuntu-latest' | |
uses: actions/setup-python@v5 | |
with: | |
python-version: ${{ env.PYTHON_VERSION }} | |
- name: Install uv | |
uses: astral-sh/setup-uv@v3 | |
with: | |
enable-cache: true | |
cache-suffix: | |
${{ startsWith(matrix.runner, 'ubo-pod') && 'ubo-pod' || | |
'ubuntu-latest' }} | |
- name: Create virtualenv | |
run: | | |
uv venv --system-site-packages | |
- name: Run Tests | |
run: | | |
uv run --frozen poe test --verbosity=2 --make-screenshots --cov-report=xml --cov-report=html --log-level=DEBUG --log-cli-level=5 -n ${{ startsWith(matrix.runner, 'ubo-pod') && '1' || 'auto' }} | |
- name: Collect Window Screenshots | |
uses: actions/upload-artifact@v4 | |
if: always() | |
with: | |
name: screenshots-${{ matrix.runner }} | |
path: tests/**/results/**/*.png | |
- name: Collect Store Snapshots | |
uses: actions/upload-artifact@v4 | |
if: always() | |
with: | |
name: snapshots-${{ matrix.runner }} | |
path: tests/**/results/**/*.jsonc | |
- name: Collect HTML Coverage Report | |
uses: actions/upload-artifact@v4 | |
with: | |
name: coverage-report-${{ matrix.runner }} | |
path: htmlcov | |
- name: Upload Coverage to Codecov | |
uses: codecov/codecov-action@v4 | |
with: | |
file: ./coverage.xml | |
flags: ${{ matrix.runner }} | |
fail_ci_if_error: false | |
token: ${{ secrets.CODECOV_TOKEN }} | |
build: | |
name: Build | |
needs: | |
- dependencies | |
runs-on: ubuntu-latest | |
outputs: | |
version: ${{ steps.extract-version.outputs.VERSION }} | |
name: ${{ steps.extract-version.outputs.NAME }} | |
steps: | |
- uses: actions/checkout@v4 | |
name: Checkout | |
with: | |
lfs: true | |
- uses: actions/setup-python@v5 | |
name: Setup Python | |
with: | |
python-version: ${{ env.PYTHON_VERSION }} | |
- name: Install uv | |
uses: astral-sh/setup-uv@v3 | |
with: | |
enable-cache: true | |
cache-suffix: ubuntu-latest | |
- name: Extract Version | |
id: extract-version | |
run: | | |
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: | | |
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 | |
VERSION_CHANGELOG=$(echo $FIRST_HEADER | sed 's/Version //') | |
if [ "${{ steps.extract-version.outputs.VERSION }}" =~ "^$VERSION_CHANGELOG\.dev[0-9]+" ]; 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 | |
run: | | |
echo "SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> ubo_app/.env | |
# conditionally set it based on whether it's a tag or not using github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') | |
if [ "${{ github.event_name }}" == "push" ] && [ "$(echo ${{ github.ref }} | grep -c 'refs/tags/v')" -eq 1 ]; then | |
echo "SENTRY_RELEASE=ubo-app@${{ steps.extract-version.outputs.VERSION }}" >> ubo_app/.env | |
else | |
echo "SENTRY_RELEASE=ubo-app@${{ github.sha }}" >> ubo_app/.env | |
fi | |
cat ubo_app/.env | |
- name: Build | |
run: | |
SETUPTOOLS_SCM_PRETEND_VERSION=${{ | |
steps.extract-version.outputs.VERSION }} uv build | |
- name: Upload wheel | |
uses: actions/upload-artifact@v4 | |
with: | |
name: wheel | |
path: dist/*.whl | |
if-no-files-found: error | |
- name: Upload binary | |
uses: actions/upload-artifact@v4 | |
with: | |
name: binary | |
path: dist/*.tar.gz | |
if-no-files-found: error | |
images: | |
name: Create Images | |
needs: | |
- type-check | |
- lint | |
- test | |
- build | |
runs-on: ubuntu-latest | |
container: | |
image: mkaczanowski/packer-builder-arm | |
volumes: | |
- /dev:/dev | |
options: --rm --privileged | |
strategy: | |
fail-fast: false | |
matrix: | |
suffix: ['lite', ''] | |
steps: | |
- run: echo Building amd64-${{ matrix.suffix }} image | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- uses: actions/download-artifact@v4 | |
with: | |
name: wheel | |
path: /build/dist | |
- uses: actions/download-artifact@v4 | |
with: | |
name: binary | |
path: /build/dist | |
- name: Generate Image URL and Checksum | |
id: generate-image-url | |
run: | | |
SUFFIX="" | |
if [ -n "${{ matrix.suffix }}" ]; then | |
SUFFIX="_${{ matrix.suffix }}" | |
fi | |
DASHED_SUFFIX=$(echo $SUFFIX | sed 's/_/-/g') | |
IMAGE_NAME="2024-07-04-raspios-bookworm-arm64${DASHED_SUFFIX}" | |
IMAGE_URL="https://downloads.raspberrypi.com/raspios${SUFFIX}_arm64/images/raspios${SUFFIX}_arm64-2024-07-04/${IMAGE_NAME}.img.xz" | |
CHECKSUM_URL="${IMAGE_URL}.sha256" | |
echo "suffix=$SUFFIX" >> "$GITHUB_OUTPUT" | |
echo "dashed_suffix=$DASHED_SUFFIX" >> "$GITHUB_OUTPUT" | |
echo "image_url=$IMAGE_URL" >> "$GITHUB_OUTPUT" | |
echo "image_name=$IMAGE_NAME" >> "$GITHUB_OUTPUT" | |
echo "image_checksum_url=$CHECKSUM_URL" >> "$GITHUB_OUTPUT" | |
IMAGE_SIZE_GB=${{ matrix.suffix == 'lite' && '4.5' || matrix.suffix == '' && '6.75' || '13' }} | |
IMAGE_SIZE=$(awk -v IMAGE_SIZE_GB=$IMAGE_SIZE_GB 'BEGIN {printf "%.0f", IMAGE_SIZE_GB * 1024 ^ 3}') | |
echo "image_size=$IMAGE_SIZE" >> "$GITHUB_OUTPUT" | |
- name: Build Artifact | |
env: | |
PKR_VAR_ubo_app_version: ${{ needs.build.outputs.version }} | |
PKR_VAR_image_url: ${{ steps.generate-image-url.outputs.image_url }} | |
PKR_VAR_image_name: ${{ steps.generate-image-url.outputs.image_name }} | |
PKR_VAR_image_checksum_url: | |
${{ steps.generate-image-url.outputs.image_checksum_url }} | |
PKR_VAR_target_image_size: | |
${{ steps.generate-image-url.outputs.image_size}} | |
run: | | |
/entrypoint.sh init scripts/packer/image.pkr.hcl | |
SETUP_QEMU=false /entrypoint.sh build scripts/packer/image.pkr.hcl | |
ls -lh | |
mv image.img /build | |
ls -lh /build | |
- name: Fill Free Space with Zeros | |
run: | | |
apt-get update | |
apt-get install -y zerofree | |
LOOP_DEV=$(losetup -f) | |
losetup -P $LOOP_DEV /build/image.img | |
zerofree -v "${LOOP_DEV}p2" | |
losetup -d $LOOP_DEV | |
- name: Compress File with Gzip | |
run: | | |
scripts/consume.sh /build/image.img | gzip -9 > /ubo_app-${{ needs.build.outputs.version }}-bookworm${{ steps.generate-image-url.outputs.dashed_suffix }}.img.gz | |
- name: Upload Image | |
uses: actions/upload-artifact@v4 | |
with: | |
name: | |
ubo_app-${{ needs.build.outputs.version }}-bookworm${{ | |
steps.generate-image-url.outputs.dashed_suffix}}-arm64.img.gz | |
path: | |
/ubo_app-${{ needs.build.outputs.version }}-bookworm${{ | |
steps.generate-image-url.outputs.dashed_suffix }}.img.gz | |
if-no-files-found: error | |
publish: | |
name: Publish | |
if: >- | |
github.event_name == 'push' && github.ref == 'refs/heads/main' || | |
github.event_name == 'pull_request' && github.event.pull_request.base.ref | |
== 'main' | |
needs: | |
- type-check | |
- lint | |
- test | |
- build | |
runs-on: ubuntu-latest | |
environment: | |
name: pypi | |
url: | |
https://pypi.org/project/${{ needs.build.outputs.name }}/${{ | |
needs.build.outputs.version }} | |
permissions: | |
id-token: write | |
steps: | |
- uses: actions/download-artifact@v4 | |
with: | |
name: wheel | |
path: dist | |
- uses: actions/download-artifact@v4 | |
with: | |
name: binary | |
path: dist | |
- name: Publish to PyPI | |
uses: pypa/gh-action-pypi-publish@release/v1 | |
with: | |
packages-dir: dist | |
release: | |
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') | |
name: Release | |
needs: | |
- type-check | |
- lint | |
- test | |
- build | |
- publish | |
- images | |
runs-on: ubuntu-latest | |
environment: | |
name: release | |
url: | |
https://github.com/${{ github.repository }}/releases/tag/v${{ | |
needs.build.outputs.version }} | |
permissions: | |
contents: write | |
steps: | |
- uses: actions/checkout@v4 | |
name: Checkout | |
- name: Procure Lite Image | |
uses: actions/download-artifact@v4 | |
with: | |
name: | |
ubo_app-${{ needs.build.outputs.version | |
}}-bookworm-lite-arm64.img.gz | |
path: artifacts | |
- name: Procure Default Image | |
uses: actions/download-artifact@v4 | |
with: | |
name: ubo_app-${{ needs.build.outputs.version }}-bookworm-arm64.img.gz | |
path: artifacts | |
- name: Procure Wheel | |
uses: actions/download-artifact@v4 | |
with: | |
name: wheel | |
path: artifacts | |
- name: Procure Binary | |
uses: actions/download-artifact@v4 | |
with: | |
name: binary | |
path: artifacts | |
- name: | |
Split Large Files into 2GB chunks in a for loop only if they are | |
bigger than 2GB | |
run: | | |
for file in artifacts/*; do | |
if [ $(stat -c%s "$file") -gt 2147000000 ]; then | |
split -b 2147000000 "$file" "$file"_ | |
rm "$file" | |
fi | |
done | |
- name: Extract Changelog | |
id: changelog | |
run: | | |
perl -0777 -ne 'while (/## Version ${{ needs.build.outputs.version }}\n(\s*\n)*(.*?)(\s*\n)*## Version \d+\.\d+\.\d+\n/sg) {print "$2\n"}' CHANGELOG.md > CURRENT_CHANGELOG.md | |
{ | |
echo "CONTENT<<EOF" | |
cat CURRENT_CHANGELOG.md | |
echo "EOF" | |
} >> "$GITHUB_OUTPUT" | |
- name: Release | |
uses: softprops/action-gh-release@v2 | |
with: | |
files: artifacts/* | |
tag_name: v${{ needs.build.outputs.version }} | |
body: | | |
PyPI package: https://pypi.org/project/${{ needs.build.outputs.name }}/${{ needs.build.outputs.version }} | |
# Changes: | |
${{ steps.changelog.outputs.CONTENT }} | |
--- | |
*Note than GitHub doesn't allow assets bigger than 2GB in a release. Due to this, the files bigger than 2GB have been split into 2GB chunks. You can join them using the following command:* | |
```bash | |
cat [[filename]]_* > [[filename]] | |
``` | |
prerelease: false | |
draft: false |