{"id":28925973,"url":"https://github.com/pronovic/gha-shared-workflows","last_synced_at":"2026-04-15T04:01:09.156Z","repository":{"id":61925656,"uuid":"552587130","full_name":"pronovic/gha-shared-workflows","owner":"pronovic","description":"Shared GitHub workflows for Ken's open source code","archived":false,"fork":false,"pushed_at":"2025-12-07T16:41:03.000Z","size":72,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-13T08:50:29.751Z","etag":null,"topics":["continuous-integration","github-actions","shared-workflows"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pronovic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-10-16T22:52:07.000Z","updated_at":"2025-12-16T00:52:43.000Z","dependencies_parsed_at":"2024-02-25T18:29:01.187Z","dependency_job_id":"5070c1e7-ad23-4805-9a56-f4387ddd8ac7","html_url":"https://github.com/pronovic/gha-shared-workflows","commit_stats":null,"previous_names":[],"tags_count":47,"template":false,"template_full_name":null,"purl":"pkg:github/pronovic/gha-shared-workflows","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pronovic%2Fgha-shared-workflows","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pronovic%2Fgha-shared-workflows/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pronovic%2Fgha-shared-workflows/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pronovic%2Fgha-shared-workflows/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pronovic","download_url":"https://codeload.github.com/pronovic/gha-shared-workflows/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pronovic%2Fgha-shared-workflows/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31825515,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T18:05:02.291Z","status":"online","status_checked_at":"2026-04-15T02:00:06.175Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["continuous-integration","github-actions","shared-workflows"],"created_at":"2025-06-22T11:11:12.854Z","updated_at":"2026-04-15T04:01:09.150Z","avatar_url":"https://github.com/pronovic.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Shared GitHub Workflows\n\nThese are shared GitHub workflows used by my open source Python repositories.  The workflows rely on my standard build process, which is implemented in the [run-script-framework](https://github.com/pronovic/run-script-framework) repository.\n\n## Previous Standards\n\nCurrently, the build process relies on the [UV](https://docs.astral.sh/uv/) build tool.  I migrated to UV starting in mid-2025. If you began using the run script framework prior to then, your repository probably relies on different standards, and the latest version of the workflows won't work for you.  Use `@v9` of the workflows instead of the latest version.\n\n## PyPI Trusted Publishers\n\nAs of this writing (in mid-2025), the recommended best practice for publishing to PyPI is to use so-called [Trusted Publishers](https://docs.pypi.org/trusted-publishers/), also discussed in the [Python Packaging User Guide](https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/) and in this [postmortem of the Ultralytics supply chain attack](https://blog.pypi.org/posts/2024-12-11-ultralytics-attack-analysis/).  The Trusted Publishers mechanism allows the publishing process to use short-lived identity tokens, which are more secure than maintaining a long-lived PyPI API key in your GitHub repository secrets.\n\nGitHub Actions is a supported publisher.  Unfortunately, as discussed on the [Troubleshooting](https://docs.pypi.org/trusted-publishers/troubleshooting/) page and detailed in [pypi/warehouse issue #11096](https://github.com/pypi/warehouse/issues/11096), the trusted publishing mechanism does not yet support reusable GitHub Actions.  Starting with `@v7` of the release workflow, I do rely on the official [PyPI Publish](https://github.com/pypa/gh-action-pypi-publish) shared action to publish artifacts.  However, there's no way to support Trusted Publishing with full attestations for the time being.\n\n## uv-build-and-test\n\nThis workflow implements the standard build and test process for my Python libraries and utilities.\n\nThe following input parameters are accepted:\n\n|Input|Type|Required|Default|Description|\n|-----|----|--------|-------|-----------|\n|`matrix-os-version`|String|Yes||JSON array as a string, a list of operating systems for the matrix build|\n|`matrix-python-version`|String|Yes||JSON array as a string, a list of Python versions for the matrix build|\n|`test-suite-command`|String|No|_see below_|Shell command used to execute the test suite|\n|`timeout-minutes`|Number|No|`30`|Job timeout in minutes|\n|`enable-coveralls`|Boolean|No|`false`|Whether to enable coverage reporting to coveralls.io|\n|`persist-python-version`|String|No|_none_|Which matrix Python version to persist artifacts for, if any|\n\n\u003e **Note:** the version of UV is controlled by `pyproject.toml`.  Set `required-version` in the `[tool.uv]` section.\n\nIn order to run the release workflow (discussed below), you must set `persist-python-version` to persist build artifacts from at _exactly one_ matrix build.  Normally, I do this for the oldest supported Python version on the Linux platform, which is what the example below shows.\n\nStarting with `v2` of the shared workflow, the default test suite command is:\n\n```\n./run suite\n```\n\nIf you need a different command, and it's more complicated than a single line like this, you should extract a script to somewhere in the repository and invoke that script in the `test-suite-command`.  However, in any repo that follows the standard `run` script convention, it's best just to adjust the `suite` task to do what you need.\n\n\u003e _Note:_ The matrix versions are passed in as JSON strings because GitHub Actions does not support workflow inputs of type array.  See [this discussion](https://github.com/community/community/discussions/11692?sort=top#discussioncomment-3541856).\n\n## release\n\nThis workflow implements the standard release process for my Python libraries and utilities.  It is designed to be triggered by pushing a new tag to GitHub, as shown in the example workflow below.  It uses the [GH Release](https://github.com/marketplace/actions/gh-release) action to create a new GitHub release, and can optionally publish to PyPI via the official [PyPI Publish](https://github.com/pypa/gh-action-pypi-publish) action.\n\nThe workflow relies on build artifacts published by the build process.  In your build workflow (discussed above), you must set `persist-python-version` to persist build artifacts from at _exactly one_ matrix build.  Normally, I do this for the oldest supported Python version on the Linux platform, which is what the example below shows.\n\nThe following input parameters are accepted:\n\n|Input|Type|Required|Default|Description|\n|-----|----|--------|-------|-----------|\n|`timeout-minutes`|Number|No|`30`|Job timeout in minutes|\n|`publish-pypi`|Boolean|No|`false`|Whether to publish artifacts to PyPI|\n\n## Example Workflow\n\n```yaml\n# On GHA, the Linux runners are *much* faster and more reliable, so we only run the full matrix build there\nname: Test Suite\non:\n  push:\n    branches:\n      - main\n    tags:\n      - \"v*\"\n  pull_request:\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\njobs:\n  linux-build-and-test:\n    name: \"Linux\"\n    uses: pronovic/gha-shared-workflows/.github/workflows/uv-build-and-test.yml@v10\n    secrets: inherit\n    with:\n      matrix-os-version: \"[ 'ubuntu-latest' ]\"\n      matrix-python-version: \"[ '3.10', '3.11', '3.12', '3.13' ]\"  # run Linux tests on all supported Python versions\n      enable-coveralls: true  # only report to coveralls.io for tests that run on Linux\n      persist-python-version: \"3.10\"  # persist artifacts for the oldest supported Python version\n  macos-build-and-test:\n    name: \"MacOS\"\n    uses: pronovic/gha-shared-workflows/.github/workflows/uv-build-and-test.yml@v10\n    secrets: inherit\n    with:\n      matrix-os-version: \"[ 'macos-latest' ]\"\n      matrix-python-version: \"[ '3.13' ]\"  # only run MacOS tests on latest Python\n  windows-build-and-test:\n    name: \"Windows\"\n    uses: pronovic/gha-shared-workflows/.github/workflows/uv-build-and-test.yml@v10\n    secrets: inherit\n    with:\n      matrix-os-version: \"[ 'windows-latest' ]\"\n      matrix-python-version: \"[ '3.13' ]\"  # only run Windows tests on latest Python\n  release:\n    name: \"Release\"\n    if: github.ref_type == 'tag'\n    uses: pronovic/gha-shared-workflows/.github/workflows/release.yml@v10\n    needs: [ linux-build-and-test, macos-build-and-test, windows-build-and-test ]\n    secrets: inherit\n    with:\n      publish-pypi: true\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpronovic%2Fgha-shared-workflows","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpronovic%2Fgha-shared-workflows","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpronovic%2Fgha-shared-workflows/lists"}