odooapps/.forgejo/workflows/wheelhouse.yml
Niels Göttsch 11e7fe721c
All checks were successful
wheelhouse / wheelhouse (push) Successful in 19s
[CI] wheelhouse: add manual workflow_dispatch with force_all input
Allows triggering from the Actions tab; force_all=true builds & publishes
every addon regardless of the changed-files diff, to seed the registry on
the first run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 22:08:38 +02:00

120 lines
5.1 KiB
YAML

name: wheelhouse
# Build a wheel for every CHANGED Odoo addon (via the `whool` build backend)
# and publish them to this Forgejo instance's PyPI package registry, so the
# modules can be `pip install`ed into production deployments.
#
# Versions are computed by whool's native post-version strategy: for the 16.0
# series this is ".N", where N is the number of commits to the addon since its
# manifest version last changed. So a fresh, PEP 440-newer wheel is published
# on every push (e.g. 16.0.2.4.3 -> 16.0.2.4.3.1, .2, ...) without having to
# manually bump __manifest__.py. Bumping the manifest version drops the suffix
# and publishes the clean release (16.0.2.5.0). This requires full git history,
# hence `fetch-depth: 0`.
#
# Install example (read token recommended for private repos):
# uv pip install \
# --index-url https://<user>:<token>@git.ziemlichoptimal.de/api/packages/odoo/pypi/simple/ \
# odoo-addon-sale-order-batch
on:
push:
branches:
# All Odoo series branches: 16.0, 17.0, 18.0, ...
# Deliberately excludes 16.0-ocabot-* / feature branches.
- "*.0"
# Manual trigger (Actions tab -> "Run workflow"). Use force_all=true to
# build & publish every addon regardless of the changed-files diff -- handy
# for seeding the registry on the very first run.
workflow_dispatch:
inputs:
force_all:
description: "Build & publish ALL addons (ignore the changed-files diff)"
type: boolean
default: false
jobs:
wheelhouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# Full history is required by whool to count commits since the last
# manifest version change (the ".N" post-version strategy).
fetch-depth: 0
persist-credentials: false
- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Determine addons to build
id: changed
run: |
set -euo pipefail
force="${{ github.event.inputs.force_all || 'false' }}"
addons=""
if [ "$force" = "true" ]; then
# Forced run: build every addon, ignore the diff.
for addon in */ ; do
name="${addon%/}"
if [ -f "${addon}__manifest__.py" ] && [ -f "${addon}pyproject.toml" ]; then
addons="${addons} ${name}"
fi
done
else
before="${{ github.event.before }}"
# On the first push to a branch (or a force-push), `before` is all
# zeros / unreachable; fall back to the parent commit.
if [ -z "$before" ] || ! git cat-file -e "${before}^{commit}" 2>/dev/null ; then
before="$(git rev-parse HEAD~1 2>/dev/null || true)"
fi
if [ -n "$before" ]; then
changed_files="$(git diff --name-only "$before" HEAD)"
else
changed_files="$(git ls-files)"
fi
# Reduce to top-level addon dirs that actually changed and are addons.
for addon in */ ; do
name="${addon%/}"
if [ -f "${addon}__manifest__.py" ] && [ -f "${addon}pyproject.toml" ] \
&& echo "$changed_files" | grep -q "^${name}/" ; then
addons="${addons} ${name}"
fi
done
fi
addons="$(echo "$addons" | xargs || true)"
echo "Addons to build:${addons:- (none)}"
echo "addons=${addons}" >> "$GITHUB_OUTPUT"
- name: Build wheels for changed addons
if: steps.changed.outputs.addons != ''
run: |
set -euo pipefail
rm -rf dist && mkdir -p dist
for name in ${{ steps.changed.outputs.addons }} ; do
echo "::group::Building ${name}"
# whool reads the manifest version and appends ".N" based on git
# history (16.0 series default), so no manual version bump needed.
uv build --wheel --out-dir dist "${name}"
echo "::endgroup::"
done
echo "Built wheels:"
ls -1 dist
- name: Publish to Forgejo PyPI registry
if: steps.changed.outputs.addons != ''
env:
# The PyPI registry lives under the repo owner (here: odoo).
TWINE_REPOSITORY_URL: ${{ github.server_url }}/api/packages/${{ github.repository_owner }}/pypi
# Defaults to the pushing user; set WHEELHOUSE_USER if the token below
# belongs to a different account (e.g. a dedicated publish user).
TWINE_USERNAME: ${{ secrets.WHEELHOUSE_USER || github.actor }}
# Forgejo's automatic Actions token can write packages for the
# repo owner. Override with a dedicated PAT in the WHEELHOUSE_TOKEN
# secret if you tighten the default token permissions.
TWINE_PASSWORD: ${{ secrets.WHEELHOUSE_TOKEN || secrets.GITHUB_TOKEN }}
run: |
# --skip-existing keeps re-runs idempotent should a version collide.
uvx twine upload --non-interactive --skip-existing dist/*