Python & GitHub Actions
Agenda
I ❤️ GitHub
Introduction to GitHub Actions
Using GitHub Actions for Python libraries
–//– for Python projects
–//– for JavaScript libraries
–//– for full stack projects
GitHub Actions issues (if any)
I ❤️ GitHub
My GitHub Timeline
- 2008:
Created account
- 2008 - 2012:
Open source acitivity
- 2012 - 2016:
Main work tool
- 2014 - present:
GitHub PRO member. Home of all my pet projects
Code quality assistance
Jenkins
Travis CI
Circle CI
Gitlab
Drone.io and other host based solutions
Dude, Where’s my CI?
Introduction to GitHub Actions
.github/workflows/ci.yml
name: "ci"
on: ["push"]
env:
...
jobs:
...
When to start job?
On push
On push to
master
On pull request to
master
On specific tag
Trigger every hour
Trigger for changed files
…
Where run the job?
GitHub hosted runner
Where run the job?
Virtual Machine
Linux:
ubuntu-latest
,ubuntu-1604
macOS:
macos-latest
Windows:
windows-latest
Docker Container
Job strategy
Virtual machine to use
strategy:
matrix:
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
Job strategy
Different Python version
strategy:
matrix:
python-version: ["3.6", "3.7", "3.8"]
Steps
Check out
Install Python
Install poetry
Install dependencies
Setup cache for pre-commit only on Python 3.8
Run pre-commit only on Python 3.8
Validate OpenAPI schemas only on Python 3.8
Run tests
Send report to Coveralls only on Python 3.8
Steps
Check out
Setup Python
Setup poetry
Build package
Check package
Publish package, if push to tag triggered the job
Reusable Actions
steps:
- uses: "actions/checkout@v2.0.0"
Reusable Actions
steps:
- name: "Install Python"
uses: "actions/setup-python@v1.2.0"
with:
python-version: "3.8"
Reusable Actions
steps:
- name: "Install poetry"
uses: "dschep/install-poetry-action@v1.3"
with:
version: "1.0.5"
create_virtualenvs: true
Conditionals
Run pre-commit only on Python dev version
env:
DEV_PYTHON_VERSION: "3.8"
steps:
- name: "Run pre-commit"
if: "${{ matrix.python-version == env.DEV_PYTHON_VERSION }}"
uses: "pre-commit/action@v1.0.1"
Conditionals
steps:
- name: "Publish package"
if: "${{ github.event_name == ’push’ && startsWith(github.event.ref, ’refs/tags’) }}"
uses: "pypa/gh-action-pypi-publish@v1.1.0"
with:
user: "${{ secrets.PYPI_USERNAME }}"
password: "${{ secrets.PYPI_PASSWORD }}"
Services
Definition
services:
postgres:
image: "postgres:12.2-alpine"
env:
POSTGRES_USER: "project"
POSTGRES_PASSWORD: "project"
POSTGRES_DB: "test_project"
ports:
- "5432:5432"
options: "--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5"
redis:
image: "redis:5.0.7-alpine"
Services
Usage
steps:
- name: "Run Tests"
run: "make migrate-only test-api-only"
env:
LEVEL: "test"
DB_HOST: "postgres"
DB_PORT: "${{ job.services.postgres.ports[5432] }}"
REDIS_HOST: "redis"
REDIS_PORT: "6379"
More?
Using GitHub Actions
For Python libraries
Based on Hynek article: “Python in GitHub Actions”
Run in VM
Build job to check library is working on any OS
Test library on all supported Python versions
Package job to publish on PyPI
For Python libraries
Gotchas
Pin everything
Run build & test in parallel (failed job will stop workflow)
Package job needs build & test
Cache pre-commit hooks
Provide dev Python version:
To run
pre-commit
To send
coveralls
reportetc (to run only once)
For Python libraries
Examples
For Python projects
Run in container
Provide basic Docker image to reuse
Only test & deploy jobs needed
For Python projects
playpauseandstop/docker-python
runs-on: "ubuntu-latest"
container:
image: "playpauseandstop/docker-python:3.2.0-py38"
For Python projects
Install project
- name: "Cache venv"
uses: "actions/cache@v1.1.2"
with:
path: ".venv"
key: "venv-${{ hashFiles('poetry.lock') }}"
- name: "Install"
run: "make install"
For Python projects
Run unit & integrational tests
- name: "Run Unit Tests"
run: "make test-unit-only"
- name: "Run Integrational Tests"
if: "{{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/') }}"
env:
HOBOTNICA_ROOT: "~/.hobotnica-test"
GITHUB_API_USERNAME: "${{ secrets.GITHUB_API_USERNAME }}"
GITHUB_API_TOKEN: "${{ secrets.GITHUB_API_TOKEN }}"
run: "make test-integrational-only"
For Python projects
Gotchas
Base image is good idea
Cache
.venv
as well
For JavaScript libraries
Run in VM
Same rules as for Python libraries
For JavaScript libraries
- name: "Publish package"
if: "${{ github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') }}"
run: |
set -e
tag=latest
if [ ${{ contains(github.event.ref, 'alpha') }} = true ]; then
tag=alpha
else
if [ ${{ contains(github.event.ref, 'beta') }} = true ]; then
tag=beta
else
if [ ${{ contains(github.event.ref, 'rc') }} = true ]; then
tag=rc
fi
fi
fi
set -x
npm publish --tag=${tag}
env:
NODE_AUTH_TOKEN: "${{ secrets.NPM_TOKEN }}"
For full stack projects
Run in container
Same rules as for Python project
But also provide jobs for test & deploy frontend
For full stack projects
Installing node in Python image
- name: "Install node"
run: "nodeenv -n ${{ env.NODE_VERSION }} ${HOME}/.node"
- name: "Install UI"
run: "PATH=${HOME}/.node/bin:${PATH} make install-ui"
Bonus. Deploying this slides
.github/workflows/slides.yml
name: "slides"
on:
push:
paths: "slides/**"
jobs:
slides:
runs-on: "ubuntu-latest"
steps:
- uses: "actions/checkout@v2.0.0"
Bonus. Deploying this slides
- name: "Build slides"
uses: "ammaraskar/sphinx-action@0.4"
with:
docs-folder: "./slides/"
pre-build-command: "pip install Sphinx==3.0.3 sphinx-revealjs==0.11.0"
build-command: "sphinx-build -b revealjs ./ _build/"
Bonus. Deploying this slides
- name: "Deploy slides"
if: "{{ github.event_name == 'push' && github.event.ref == 'refs/heads/master' }}"
uses: "AEnterprise/rsync-deploy@v1.0"
env:
ARGS: "-avuzPt"
DEPLOY_KEY: "${{ secrets.DEPLOY_SSH_KEY }}"
FOLDER: "./slides/_build/"
SERVER_DESTINATION: "Projects/igordavydenko/slides/_build/"
SERVER_IP: "igordavydenko.com"
SERVER_PORT: "22"
USERNAME: "playpauseandstop"
GitHub Actions issues
Why GitHub released Actions only in 2019?
Documentation is messy at times
Tough to configure from the scratch
Often problems with 3rd party reusable actions
Failed job email notifications are useless
Use GitHub Actions for great good!
That’s all, folks!
I am Igor Davydenko
- GitHub:
- Twitter:
- Telegram:
Slides
Made with sphinx-revealjs