From d9ea21d50e0acd5da4b33056c8ccdc06dc5255d5 Mon Sep 17 00:00:00 2001 From: Sebastiaan Huber <mail@sphuber.net> Date: Sun, 3 Sep 2023 22:11:49 +0200 Subject: [PATCH] Devops: Add continuous-deployment workflow --- .github/workflows/cd.yml | 103 ++++++++++++++++++++++ .github/workflows/validate_release_tag.py | 36 ++++++++ 2 files changed, 139 insertions(+) create mode 100644 .github/workflows/cd.yml create mode 100644 .github/workflows/validate_release_tag.py diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 0000000..046bfda --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,103 @@ +name: cd + +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+*' + +jobs: + + validate-release-tag: + + if: github.repository == 'aiidateam/aiida-pseudo' + runs-on: ubuntu-latest + + steps: + - name: Checkout source + uses: actions/checkout@v2 + + - name: Install Python 3.9 + uses: actions/setup-python@v4 + with: + python-version: '3.9' + + - 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: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.9' + cache: 'pip' + cache-dependency-path: pyproject.toml + + - name: Install Python package and dependencies + run: 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.7', '3.8', '3.9'] + + services: + postgres: + image: postgres:12 + rabbitmq: + image: rabbitmq:latest + ports: + - 5672:5672 + + steps: + - uses: actions/checkout@v2 + + - name: Install Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' + cache-dependency-path: pyproject.toml + + - name: Install Python package and dependencies + run: pip install -e .[tests] + + - 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: Install Python 3.9 + uses: actions/setup-python@v4 + with: + python-version: '3.9' + + - 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 }} diff --git a/.github/workflows/validate_release_tag.py b/.github/workflows/validate_release_tag.py new file mode 100644 index 0000000..a3f69f6 --- /dev/null +++ b/.github/workflows/validate_release_tag.py @@ -0,0 +1,36 @@ +# -*- 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() + TAG_PREFIX = 'refs/tags/v' + assert args.GITHUB_REF.startswith(TAG_PREFIX), f'GITHUB_REF should start with "{TAG_PREFIX}": {args.GITHUB_REF}' + tag_version = args.GITHUB_REF.removeprefix(TAG_PREFIX) + package_version = get_version_from_module(Path('aiida_pseudo/__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