{"id":15046186,"url":"https://github.com/patrick-kidger/action_update_python_project","last_synced_at":"2025-11-17T15:33:30.055Z","repository":{"id":49749479,"uuid":"466937456","full_name":"patrick-kidger/action_update_python_project","owner":"patrick-kidger","description":"Github Action to: Check version / Test / git tag / GitHub Release / Deploy to PyPI","archived":false,"fork":false,"pushed_at":"2025-03-17T18:23:44.000Z","size":22,"stargazers_count":17,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-06-09T18:49:23.081Z","etag":null,"topics":["action","actions","github-actions","pypi","python"],"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/patrick-kidger.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["patrick-kidger"]}},"created_at":"2022-03-07T04:07:19.000Z","updated_at":"2025-04-09T10:20:54.000Z","dependencies_parsed_at":"2023-01-04T12:30:17.998Z","dependency_job_id":"98b1d026-3a74-46d4-987c-389b2f1d9ec7","html_url":"https://github.com/patrick-kidger/action_update_python_project","commit_stats":{"total_commits":7,"total_committers":1,"mean_commits":7.0,"dds":0.0,"last_synced_commit":"ca4b423862984110b34ebfe1fa0bac77b5553b9b"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/patrick-kidger/action_update_python_project","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrick-kidger%2Faction_update_python_project","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrick-kidger%2Faction_update_python_project/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrick-kidger%2Faction_update_python_project/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrick-kidger%2Faction_update_python_project/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/patrick-kidger","download_url":"https://codeload.github.com/patrick-kidger/action_update_python_project/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrick-kidger%2Faction_update_python_project/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268285811,"owners_count":24225798,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-01T02:00:08.611Z","response_time":67,"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":["action","actions","github-actions","pypi","python"],"created_at":"2024-09-24T20:52:49.516Z","updated_at":"2025-11-17T15:33:30.049Z","avatar_url":"https://github.com/patrick-kidger.png","language":null,"readme":"\u003ch1 align='center'\u003eUpdate Python project:\u003cbr\u003eCheck version / Test / git tag / GitHub Release / Deploy to PyPI\u003c/h1\u003e\n\nThis is a GitHub Action to automate deployment of a new version of a Python project.\n\nThis action will:\n- Check out your code;\n- Check the version of your code against the latest version available on PyPI;\n- If your code has a newer version:\n    - It will build both an sdist and a wheel;\n    - It will run tests against both;\n    - If both pass:\n        - An annotated git tag is added;\n        - A GitHub Release is made\n        - The sdist and wheel are both uploaded to PyPI.\n\n### Usage\n\nRequires a Linux runner.\n\nAssumes that your project uses a `pyproject.toml` file; the `project.name` and `project.version` fields will be accessed. In particular the latter must not be dynamic. (You should put `__version__ = importlib.metadata.version(your_package_name)` in your top-level `__init__.py` file to get the version at runtime.)\n\nYou should go to `\u003cyour repository\u003e \u003e Settings \u003e Actions \u003e General \u003e Workflow permissions` and enable `Read and write permissions` so that releases can be made to GitHub.\n\n### Example\n\n```\nname: Release\n\non:\n  push:\n    branches:\n      - main\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Release\n        uses: patrick-kidger/action_update_python_project@v7\n        with:\n            python-version: \"3.11\"\n            test-script: |\n                cp -r ${{ github.workspace }}/test ./test\n                cp ${{ github.workspace }}/pyproject.toml ./pyproject.toml\n                uv sync --extra tests --no-install-project --inexact\n                uv run --no-sync pytest\n            pypi-token: ${{ secrets.pypi_token }}\n            github-user: your-username-here\n            github-token: ${{ github.token }}  # automatically created token\n```\n\nThis will run every time the `main` branch is updated. If the version has updated, then it will trigger things as described above.\n\n### Options\n\nThe following are mandatory arguments (for passing to `with`) that must be specified:\n\n- `python-version`: What Python version to run everything with. Must be at least 3.11. Set to `false` to skip this (and use whatever Python you already have on the system).\n- `test-script`: What test script to run. Will execute in a precreated `uv` venv, e.g. commands often look like `uv sync --foo`.\n- `pypi-token`: What password or token to use when pushing to PyPI. Set to `false` to use some other already-configured authentication mechanism, e.g. from a previous job that runs `gcloud auth`.\n- `github-user`: What GitHub user to use when authenticating the release with GitHub.\n- `github-token`: What GitHub token to use when authenticating the release with GitHub.\n\nThe following are optional arguments that come with a default value:\n\n- `pypi-user`: What username to use when pushing to PyPI. Defaults to `'__token__'`, corresponding to the use of a PyPI token.\n- `pypi-repository-url`: What PyPI repository to use. Defaults to `'https://pypi.org/'`\n- `checkout`: Whether to check out the repository. Set to `false` to disable this if you've already done this in an earlier step.\n- `allow-first-release`: Whether to allow a first release to PyPI. Defaults to `false`, to avoid accidentally pushing code publicly until you're ready. (We generally recommend pushing a first release manually when you're ready, but this flag can be useful if you're pushing to an internal PyPI repository that only your CD has authentication for.)\n\nNotes on `test-script`:\n\n- It runs in a temporary directory. Thus you will need to copy your tests over as in the example above. This is to avoid spuriously passing tests: it can happen that files have been incorrectly left out of the sdist/wheel, but are still available through the repository itself.\n- Any `\"` characters must be escaped as `\\\"`.\n- The exit code of this script is used to determine whether the tests count as having passed or not. `0` is a pass; everything else is a failure.\n- The code from your library will have been installed into a fresh virtual environment at `./.venv` using `uv pip install`. The `uv sync` command in the example above is the appropriate invocation to install the `dev` extras from copied `pyproject.toml`, *without* also overwriting the existing install, and *without* removing the existing install.\n\n### FAQ\n\n**I'm getting a random/spurious failure.**\n\nIf you call this action shortly (\u003c5 minutes?) after it triggers (and has pushed an update to PyPI) then sometimes the second invocation won't see that the updated version exists yet, so it will think that it has a new version -- and will attempt to start the update process itself. This should just be a harmless failure.\n","funding_links":["https://github.com/sponsors/patrick-kidger"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatrick-kidger%2Faction_update_python_project","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpatrick-kidger%2Faction_update_python_project","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatrick-kidger%2Faction_update_python_project/lists"}