GitHub Actions workflows

August 25, 2026 · View on GitHub

What exists, in which repository, and why. Procedures live elsewhere: publishing-automation.md for releases, building-docs.md for documentation.

The inventory includes the native audioif CPython release caller.

Reusable workflows (PyDevices/.github)

Callers pin a tag, not a branch, so a change here does not alter a release until the tag moves. publishing-v3 is current; earlier tags remain for retrying a release cut before the consolidation.

WorkflowPurpose
reusable-publish-release-packages.ymlThe whole release chain: resolve the tag, build, publish to TestPyPI, request MIP publication
reusable-build-pure-python-distribution.ymlsdist + wheel for a pure-Python package
reusable-build-native-and-wasm-wheels.ymlcibuildwheel: Linux, Windows, Android (PEP 738), Pyodide wasm32
reusable-build-pydevices-distributions.ymlThe pydevices and pydevices-desktop distributions, derived from lib/ and utils/
reusable-request-mip-publication.ymlDispatch into mip's serialized publication queue
reusable-synchronize-mip-package.ymlCopy a package into mip and generate its manifests
reusable-validate-pyscript-filesystem-toml.ymlCheck a *.toml filesystem map against the tree it claims to mirror

The build workflows also check this repository out for its scripts, pinned by publishing-tools-ref — which defaults to publishing-v3, so workflows and scripts always come from the same tag.

Releasing

publish-release-packages.yml in five repositories, each a ~26-line caller of reusable-publish-release-packages.yml. All they supply is what differs:

Repositorybuild-kindDistributionMIP profile
pydevicespydevices-multipydevicespydevices
palettespure-pythonpydevices-palettespalettes
pdwidgetspure-pythonpydevices-pdwidgetspdwidgets
pygraphicsnative-and-wasmpydevices-pygraphicspygraphics
audioifnative-and-wasmpydevices-audioif— none
lvgl-pythonnative-and-wasmpydevices-lvgl— none

Triggered by a published GitHub Release, or by workflow_dispatch with an exact vX.Y.Z tag to retry one.

Cross-repository release plumbing:

RepositoryWorkflowRole
lvgl-bindingstrigger-lvgl-python-release.ymlOn a bindings change, dispatch lvgl-python's sync
lvgl-bindingscheck-dispatch-token.ymlManual check that LVCPYTHON_MOD_DISPATCH_TOKEN still works
lvgl-pythonsync-and-release.ymlSync generated bindings, commit, publish a Release
mpftppublish-vsix.ymlBuild the VSIX and publish to VS Marketplace / Open VSX
android-runnerrelease_apk.ymlBuild the APK that pydevices/bin/android.py --install-apk downloads

sync-and-release.yml uses a PAT to create its own repository's Release, which looks redundant and is not: a Release created with GITHUB_TOKEN does not trigger on: release workflows, so publish-release-packages.yml would never fire and nothing would reach TestPyPI.

MIP index (mip)

WorkflowRole
process-mip-publication-request.ymlSerialized queue consumer: synchronize a package, rebuild the index, deploy
deploy-mip-index-to-pages.ymlCompile and publish the index. Triggers on the PyDevices branch, not main
validate-mip-package-index.ymlCheck index integrity
tests.yml, ruff.yml, commit-formatting.ymlInherited from micropython-lib upstream — leave them alone

Testing and validation

RepositoryWorkflowNotes
pydevicestests.ymlAlso validates board MIP installers
palettes, pdwidgetstests.ymlSparse-checkout of sibling repos onto PYTHONPATH (pdwidgets needs four)
pygraphicstests.ymlRuns the suite twice — pure Python, then the native extension via PYGRAPHICS_TEST_NATIVE=1
pydevices-examplestests.yml, manifests.ymlGallery and install-manifest freshness
pydevices, pygraphicsvalidate-pyscript-filesystem-toml.ymlStandalone callers. pdwidgets and palettes call the same reusable as a job inside tests.yml

Pages

Two repositories publish Pages, plus the portal:

RepositoryWhat it serves
PyDevices.github.ioThe portal and every repository's landing page, at /<repo>/. Serves from main, no workflow
pydevices-examplesdeploy.yml — the PyScript gallery: manifest audits and symlink replacement
mipdeploy-mip-index-to-pages.yml — the package index

Every other landing page is generated by scripts/generate_sites.py into the portal repository from data/repos_db.json. Where a page goes is the entry's page field: portal-root, portal-subdir, self, or none. There are no per-repo deploy.yml files and no gh-pages branches; thirteen of each were removed once the portal took over those paths.

A landing page is a single index.html referencing /assets/chrome/ and /assets/img/logo.svg at the portal root.

Documentation

No repository builds documentation in Actions. ReadTheDocs builds palettes, pdwidgets, and pygraphics on push via the org GitHub App. A duplicate mkdocs build used to run here too and was deleted: it passed while two of the three sites were failing to publish, because mkdocs exits 0 and RTD then fails the build on output checks mkdocs cannot see.

Maintenance

dependabot.yml watches pinned action versions in the ten repositories that have workflows, grouped into one weekly PR each. mip is excluded — its workflows come from upstream.

Conventions

  • Pin actions to a major version (actions/checkout@v4).
  • Logic shared by more than one repository belongs in a reusable-*.yml here, called at a pinned tag.
  • Path filters on push and pull_request; workflow_dispatch on anything you might need to re-run by hand.
  • A workflow that writes to another repository needs a token in secrets; GITHUB_TOKEN cannot reach across repositories, and cannot trigger another workflow even within one.