GitHub Actions
No double quotes
Warning
Never use double quotes inside ${{ ... }
as it is simply not supported.
Tertiary
GHA has a really funky tertiary: ${{ x && 'ifTrue' || 'ifFalse' }}
This only works if <ifTrue>
isn't the empty string. If <ifTrue> == ''
then ''
is considered as false
, which then evaluates the right hand side of the ||
.
There are lots of gotchas here, and this is a great thread highlighting more of it.
Example
Expressions
Expressions official docs here.
Functions
This stores a value in an environment variable. Using the contains
function, the if-condition evaluates whether
to run the step or not.
steps:
- run: echo "POETRY_VERSION=$(poetry --version)" >> $GITHUB_ENV
shell: bash
- run: poetry config installer.modern-installation false
# workaround for bug: https://github.com/microsoft/debugpy/issues/1246
if: ${{ contains(env.POETRY_VERSION, '1.4.1') }}
shell: bash
Python specific
Pipx via actions/setup-python
When using actions/setup-python and Poetry, you can use pipx
to install Poetry outside of your project's virtual environment. The setup-python action provides pipx by default, but you might notice how it is not running under the Python version you chose.
To fix this, you can pass the --python
argument to pipx.
Example
Python package caching
The actions/setup-python action has built in caching, which you should likely use unless you have specific needs like support for dependency groups. For the latter use case, you can look to actions/cache.
actions/cache
When using actions/cache
, you can use the ${{ steps.<python setup step id>.outputs.python-version }}
as part of the cache key:
steps:
- uses: actions/setup-python@v4
id: cpython_setup
with:
python-version: "3.11"
- uses: actions/cache@v3
id: python-cache
env:
SEGMENT_DOWNLOAD_TIMEOUT_MIN: "15"
with:
path: |
~/.cache/pip
~/.cache/pypoetry
key: pip-poetry-${{ runner.os }}-${{ runner.arch }}-py-${{ steps.cpython_setup.outputs.python-version }}-${{ hashFiles('poetry.lock') }}
The cache key can be extended with e.g. Poetry's dependency groups.
Python shell
Python code can be written inline of a step, with the shell: python
directive.
See the jobs.<job_id>.steps[*].shell
docs for additional shells that are supported.
Test coverage comment in PR
Here's one way to add a PR commit about the changed files' test coverage, powered by romeovs/lcov-reporter-action.
Warning
Unfortunately, it will generate a GitHub notification for each comment posted.
Example
# .github/workflows/pr_cov_comment.yml
steps:
- name: run tests wrapped by coverage
run: coverage run -m pytest
- name: export coverage to lcov format
run: coverage lcov
- uses: romeovs/lcov-reporter-action@2a28ec3e25fb7eae9cb537e9141603486f810d1a
# The reason for using a hash rather than a version/tag, is the project
# failed in publishing this: https://github.com/romeovs/lcov-reporter-action/issues/47
with:
lcov-file: ./coverage/coverage.lcov
filter-changed-files: true
delete-old-comments: true
- name: export coverage to lcov format
run: coverage html
- name: Archive code coverage results
uses: actions/upload-artifact@v3
with:
name: code-coverage-report
path: coverage/html
Configure pytest and coverage in pyproject.toml
:
[tool.coverage.run]
omit = ["tests/migrations/*"]
source = ["src/mypkg"]
[tool.coverage.report]
exclude_lines =[
"pragma: nocover",
"if TYPE_CHECKING",
"@overload",
]
skip_covered = true
[tool.coverage.html]
directory = "coverage/html"
[tool.coverage.lcov]
output = "coverage/coverage.lcov"
[tool.pytest.ini_options]
testpaths = "tests"
addopts = "-rxXs --color=yes"