├── .github ├── FUNDING.yml └── workflows │ ├── ci.yml │ └── lint-pr.yml ├── .gitignore ├── .releaserc ├── LICENSE ├── README.md └── action.yml /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: ['https://www.buymeacoffee.com/abatilo'] 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | 8 | jobs: 9 | ci: 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] 14 | poetry-version: ["latest", "main", "1.8.4"] 15 | os: [ubuntu-22.04, macos-latest, windows-latest] 16 | runs-on: ${{ matrix.os }} 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: actions/setup-python@v5 20 | with: 21 | python-version: ${{ matrix.python-version }} 22 | - name: Run image 23 | uses: ./ 24 | with: 25 | poetry-version: ${{ matrix.poetry-version }} 26 | - name: View poetry --help 27 | run: poetry --help 28 | ci-all: 29 | runs-on: ubuntu-latest 30 | needs: [ci] 31 | steps: 32 | - run: | 33 | echo "All matrix jobs have completed successfully!" 34 | release: 35 | if: github.event_name == 'push' 36 | needs: ci-all 37 | runs-on: ubuntu-latest 38 | steps: 39 | - uses: actions/checkout@master 40 | - uses: actions/setup-node@v4 41 | with: 42 | node-version: 20.8.1 43 | - name: Generate release 44 | env: 45 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 46 | run: npx semantic-release 47 | - name: Update major tag 48 | env: 49 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 50 | run: | 51 | git tag -d v4 52 | git push --delete origin v4 53 | git push origin :refs/tags/v4 54 | git tag v4 55 | git push --tags 56 | -------------------------------------------------------------------------------- /.github/workflows/lint-pr.yml: -------------------------------------------------------------------------------- 1 | name: "Lint PR" 2 | on: 3 | pull_request: 4 | types: 5 | - opened 6 | - edited 7 | - synchronize 8 | 9 | jobs: 10 | main: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: amannn/action-semantic-pull-request@v5.4.0 14 | env: 15 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "@semantic-release/commit-analyzer", 4 | "@semantic-release/release-notes-generator", 5 | "@semantic-release/github" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Aaron 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # actions-poetry 2 | GitHub Actions for Python projects using poetry 3 | 4 | [![license](https://img.shields.io/github/license/abatilo/actions-poetry.svg)](https://github.com/abatilo/actions-poetry/blob/master/LICENSE) 5 | [![release](https://img.shields.io/github/release/abatilo/actions-poetry.svg)](https://github.com/abatilo/actions-poetry/releases/latest) 6 | [![GitHub release date](https://img.shields.io/github/release-date/abatilo/actions-poetry.svg)](https://github.com/abatilo/actions-poetry/releases) 7 | 8 | - [python-poetry/poetry: Python dependency management and packaging made easy.](https://github.com/python-poetry/poetry) 9 | 10 | ## Getting started 11 | 12 | ### Breaking changes for v3 13 | 14 | We've started installing `poetry` with `pipx` to keep the installed artifacts 15 | isolated away from any of your application dependencies. v3 will install `pipx` 16 | for you as well. 17 | 18 | ### Breaking changes for v2 19 | 20 | We've drastically simplified this GitHub Action for v2. 21 | This is no longer a Docker action that runs as its own container, 22 | it's just a simplified way for you to install poetry. 23 | This action now makes an assumption that you've already setup Python via `setup-python` or some other way. 24 | Since we're installing poetry directly to your environment, 25 | this also means that you can cache your dependencies more easily since everything is running on the host runner instead of an isolated container environment. 26 | 27 | ### Create your workflow 28 | 29 | ```yaml 30 | name: CI 31 | on: pull_request 32 | 33 | jobs: 34 | ci: 35 | strategy: 36 | fail-fast: false 37 | matrix: 38 | python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] 39 | poetry-version: ["latest", "main", "1.8.4"] 40 | os: [ubuntu-22.04, macos-latest, windows-latest] 41 | runs-on: ${{ matrix.os }} 42 | steps: 43 | - uses: actions/checkout@v4 44 | - uses: actions/setup-python@v5 45 | with: 46 | python-version: ${{ matrix.python-version }} 47 | - name: Run image 48 | uses: abatilo/actions-poetry@v3 49 | with: 50 | poetry-version: ${{ matrix.poetry-version }} 51 | - name: View poetry --help 52 | run: poetry --help 53 | ``` 54 | 55 | ### Workflow example: cache the virtual environment 56 | 57 | It is possible to combine `actions/poetry` with [actions/cache](https://github.com/actions/cache) to speed up the installation of dependencies. 58 | The recipe is: 59 | 60 | 1. to ask `poetry` to create a virtual environment inside the project: 61 | it creates a local `.venv/` folder that can be cached 62 | 2. to create a cache key that involves the contents of the `poetry.lock` file: 63 | if the contents change (meaning that dependencies have changed), then the cache needs to be invalidated and recreated 64 | 65 | For the 1st step, you either need: 66 | 67 | - to have a `poetry.toml` file 68 | (and [not `pyproject.toml`](https://github.com/python-poetry/poetry/issues/2937)) 69 | at the root of your project with these 2 settings: 70 | 71 | ```ini 72 | [virtualenvs] 73 | create = true 74 | in-project = true 75 | ``` 76 | 77 | - or to run the following commands in the github actions to create the `poetry.toml` file: 78 | 79 | ```sh 80 | poetry config virtualenvs.create true --local 81 | poetry config virtualenvs.in-project true --local 82 | ``` 83 | 84 | Here is an example of how the steps must be declared: 85 | 86 | ```yaml 87 | jobs: 88 | ci: 89 | runs-on: ubuntu-latest 90 | steps: 91 | - uses: actions/checkout@v4 92 | - name: Install Python 93 | uses: actions/setup-python@v4 94 | # see details (matrix, python-version, python-version-file, etc.) 95 | # https://github.com/actions/setup-python 96 | - name: Install poetry 97 | uses: abatilo/actions-poetry@v4 98 | - name: Setup a local virtual environment (if no poetry.toml file) 99 | run: | 100 | poetry config virtualenvs.create true --local 101 | poetry config virtualenvs.in-project true --local 102 | - uses: actions/cache@v3 103 | name: Define a cache for the virtual environment based on the dependencies lock file 104 | with: 105 | path: ./.venv 106 | key: venv-${{ hashFiles('poetry.lock') }} 107 | - name: Install the project dependencies 108 | run: poetry install 109 | - name: Run the automated tests (for example) 110 | run: poetry run pytest -v 111 | ``` 112 | 113 | ## License 114 | 115 | [MIT License - abatilo/actions-poetry] 116 | 117 | [MIT License - abatilo/actions-poetry]: https://github.com/abatilo/actions-poetry/blob/master/LICENSE 118 | 119 | ## About the author 120 | 121 | - [abatilo's homepage](https://www.aaronbatilo.dev/) 122 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: "Python Poetry Action" 2 | author: "@abatilo" 3 | description: "An action to run https://github.com/python-poetry/poetry" 4 | branding: 5 | icon: "truck" 6 | color: "gray-dark" 7 | inputs: 8 | poetry-version: 9 | description: "The version of poetry to install" 10 | required: false 11 | default: "latest" 12 | poetry-plugins: 13 | description: "The whitespace/newline-separated list of poetry plugins to install." 14 | required: false 15 | default: "" 16 | runs: 17 | using: "composite" 18 | steps: 19 | - run: | 20 | python3 -m pip install --user pipx 21 | python3 -m pipx ensurepath 22 | shell: bash 23 | - if: ${{ inputs.poetry-version == 'latest' }} 24 | run: | 25 | pipx install poetry 26 | shell: bash 27 | - if: ${{ inputs.poetry-version == 'main' }} 28 | run: | 29 | pipx install git+https://github.com/python-poetry/poetry.git@main 30 | shell: bash 31 | - if: ${{ inputs.poetry-version != 'latest' && inputs.poetry-version != 'main' }} 32 | run: | 33 | pipx install poetry==${{ inputs.poetry-version }} 34 | shell: bash 35 | - if: ${{ inputs.poetry-plugins != '' }} 36 | run: | 37 | ALL_PLUGINS=$(echo "${{ inputs.poetry-plugins }}") 38 | for PLUGIN in $ALL_PLUGINS; do 39 | poetry self add $PLUGIN 40 | done 41 | shell: bash 42 | --------------------------------------------------------------------------------