Skip to content

Commit

Permalink
Devops: add GitHub Actions workflow for continuous deployment
Browse files Browse the repository at this point in the history
This workflow will be triggered when a new tag is pushed that matches a
semantic versioning pattern. If it is pushed to the main repository of
the `aiidateam` account, a Python script `validate_release_tag.py` is
run that will parse the `__version__` attribute of the package and
compare it to the version of the tag. If they don't match, the workflow
is aborted.

Otherwise, the pre-commit and the unit test suite is ran, and when
successfull, `flit` is used to build and publish the package to PyPI.
  • Loading branch information
sphuber committed Jan 29, 2022
1 parent 86fc363 commit ef92b8f
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 0 deletions.
122 changes: 122 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
name: Continuous Deployment

on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+*'

jobs:

validate-release-tag:

if: github.repository == 'aiidateam/aiida-quantumespresso'
runs-on: ubuntu-latest

steps:
- name: Checkout source
- uses: actions/checkout@v2

- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: '3.8'

- name: Validate the tag version against the package version
- run: python .github/workflows/validate_release_tag.py $GITHUB_REF

pre-commit:

needs: [validate-release-tag]
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Cache Python dependencies
uses: actions/cache@v1
with:
path: ~/.cache/pip
key: pip-pre-commit-${{ hashFiles('**/setup.json') }}
restore-keys:
pip-pre-commit-

- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.8'

- name: Install Python dependencies
run: |
pip install --upgrade pip setuptools wheel
pip install -e .[pre-commit,tests]
- name: Run pre-commit
run: pre-commit run --all-files || ( git status --short ; git diff ; exit 1 )

tests:

needs: [validate-release-tag]
runs-on: ubuntu-latest

strategy:
matrix:
python-version: ['3.6', '3.7', '3.8', '3.9']

services:
postgres:
image: postgres:12
rabbitmq:
image: rabbitmq:latest
ports:
- 5672:5672

steps:
- uses: actions/checkout@v2

- name: Cache Python dependencies
uses: actions/cache@v1
with:
path: ~/.cache/pip
key: pip-${{ matrix.python-version }}-tests-${{ hashFiles('**/setup.json') }}
restore-keys:
pip-${{ matrix.python-version }}-tests

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Install Python dependencies
run: |
pip install --upgrade pip setuptools wheel
pip install -e .[tests]
reentry scan
- name: Run pytest
run: pytest -sv tests


publish:

name: Publish to PyPI
needs: [pre-commit, tests]
runs-on: ubuntu-latest

steps:
- name: Checkout source
uses: actions/checkout@v2

- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: '3.8'

- name: Install flit
run: pip install flit~=3.4

- name: Build and publish
run: flit publish

env:
FLIT_USERNAME: __token__
FLIT_PASSWORD: ${{ secrets.PYPI_KEY }}
35 changes: 35 additions & 0 deletions .github/workflows/validate_release_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
"""Validate that the version in the tag label matches the version of the package."""
import argparse
import ast
from pathlib import Path


def get_version_from_module(content: str) -> str:
"""Get the ``__version__`` attribute from a module.
.. note:: This has been adapted from :mod:`setuptools.config`.
"""
try:
module = ast.parse(content)
except SyntaxError as exception:
raise IOError('Unable to parse module.') from exception

try:
return next(
ast.literal_eval(statement.value) for statement in module.body if isinstance(statement, ast.Assign)
for target in statement.targets if isinstance(target, ast.Name) and target.id == '__version__'
)
except StopIteration as exception:
raise IOError('Unable to find the `__version__` attribute in the module.') from exception


if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('GITHUB_REF', help='The GITHUB_REF environmental variable')
args = parser.parse_args()
assert args.GITHUB_REF.startswith('refs/tags/v'), f'GITHUB_REF should start with "refs/tags/v": {args.GITHUB_REF}'
tag_version = args.GITHUB_REF[11:]
package_version = get_version_from_module(Path('aiida_quantumespresso/__init__.py').read_text(encoding='utf-8'))
error_message = f'The tag version `{tag_version}` is different from the package version `{package_version}`'
assert tag_version == package_version, error_message

0 comments on commit ef92b8f

Please sign in to comment.