From 6f82d7e05e906951726d65633d6bcac2f00676f1 Mon Sep 17 00:00:00 2001 From: JP-Ellis Date: Wed, 13 Sep 2023 13:21:36 +1000 Subject: [PATCH] chore(ci): migrate cicd to hatch With Hatch as the new build system, the previous GitHub actions no longer work to lint, test, and publish the package. This commit makes use of pypa/cibuildwheel to build the package for multiple platforms, and then publishes the package to PyPI using the existing secrets. Signed-off-by: JP-Ellis --- .cirrus.yml | 58 +++--- .github/workflows/build.yml | 171 ++++++++++++++++++ .github/workflows/build_and_test.yml | 54 ------ .../workflows/package_and_push_to_pypi.yml | 27 --- .github/workflows/test.yml | 61 +++++++ 5 files changed, 260 insertions(+), 111 deletions(-) create mode 100644 .github/workflows/build.yml delete mode 100644 .github/workflows/build_and_test.yml delete mode 100644 .github/workflows/package_and_push_to_pypi.yml create mode 100644 .github/workflows/test.yml diff --git a/.cirrus.yml b/.cirrus.yml index 0ad7b2988..b8c4d9331 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,51 +1,49 @@ -BUILD_TEST_TASK_TEMPLATE: &BUILD_TEST_TASK_TEMPLATE +TEST_TEMPLATE: &TEST_TEMPLATE arch_check_script: - uname -am test_script: - python --version - - python -m pip install --upgrade pip - - python -m pip install -r requirements_dev.txt - - python -m flake8 - - python -m pydocstyle pact - - python -m tox -e test - # - make examples + # TODO: Fix lints before enabling + - echo hatch run lint + # TODO: Implement the examples to work in hatch + - echo hatch run example + - hatch run test -linux_arm64_task: +linux_arm64_task: env: + PATH: ${HOME}/.local/bin:${PATH} matrix: - # - IMAGE: python:3.6-slim # This works locally, with cirrus run, but fails in CI - - IMAGE: python:3.7-slim - - IMAGE: python:3.8-slim - - IMAGE: python:3.9-slim - - IMAGE: python:3.10-slim + - IMAGE: "python:3.8-slim" + - IMAGE: "python:3.9-slim" + - IMAGE: "python:3.10-slim" + - IMAGE: "python:3.11-slim" arm_container: image: $IMAGE install_script: - - apt update --yes && apt install --yes gcc make - << : *BUILD_TEST_TASK_TEMPLATE - + - apt update --yes + - apt install --yes gcc make + - python -m pip install --upgrade pip pipx + - pipx install hatch + <<: *TEST_TEMPLATE macosx_arm64_task: macos_instance: image: ghcr.io/cirruslabs/macos-ventura-base:latest env: - PATH: ${HOME}/.pyenv/shims:${PATH} + PATH: ${HOME}/.local/bin:${HOME}/.pyenv/shims:${PATH} matrix: - - PYTHON: 3.6 - - PYTHON: 3.7 - - PYTHON: 3.8 - - PYTHON: 3.9 - - PYTHON: 3.10 + - PYTHON: "3.8" + - PYTHON: "3.9" + - PYTHON: "3.10" + - PYTHON: "3.11" install_script: - # Per the pyenv homebrew recommendations. - # https://github.com/pyenv/pyenv/wiki#suggested-build-environment - # - xcode-select --install # Unnecessary on Cirrus - - brew update - # - brew install openssl readline sqlite3 xz zlib + - brew update - brew install pyenv - pyenv install ${PYTHON} - pyenv global ${PYTHON} - pyenv rehash - ## To install rosetta - # - softwareupdate --install-rosetta --agree-to-license - << : *BUILD_TEST_TASK_TEMPLATE + - python -m pip install --upgrade pip pipx + - pyenv rehash + - pipx install hatch + - pyenv rehash + <<: *TEST_TEMPLATE diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..054dfb29e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,171 @@ +name: build + +on: + push: + tags: + - v* + branches: + - master + pull_request: + branches: + - master + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref }} + cancel-in-progress: true + +env: + STABLE_PYTHON_VERSION: "3.11" + CIBW_BUILD_FRONTEND: build + CIBW_TEST_COMMAND: > + python -c + "from pact import EachLike; + assert EachLike(1).generate() == {'json_class': 'Pact::ArrayLike', 'contents': 1, 'min': 1} + " + +jobs: + build-x86_64: + name: Build wheels on ${{ matrix.os }} (x86, 64-bit) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + archs: x86_64 + - os: macos-latest + archs: x86_64 + - os: windows-latest + archs: AMD64 + + steps: + - uses: actions/checkout@v4 + with: + # Fetch all tags + fetch-depth: 0 + + - name: Create wheels + uses: pypa/cibuildwheel@v2.15.0 + env: + CIBW_ARCHS: ${{ matrix.archs }} + + - name: Upload wheels + uses: actions/upload-artifact@v3 + with: + name: wheels + path: ./wheelhouse/*.whl + if-no-files-found: error + + build-x86: + name: Build wheels on ${{ matrix.os }} (x86, 32-bit) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: windows-latest + archs: x86 + + steps: + - uses: actions/checkout@v4 + with: + # Fetch all tags + fetch-depth: 0 + + - name: Create wheels + uses: pypa/cibuildwheel@v2.15.0 + env: + CIBW_ARCHS: ${{ matrix.archs }} + + - name: Upload wheels + uses: actions/upload-artifact@v3 + with: + name: wheels + path: ./wheelhouse/*.whl + if-no-files-found: error + + build-arm64: + name: Build wheels on ${{ matrix.os }} (arm64) + runs-on: ${{ matrix.os }} + # As this requires emulation, it's not worth running on PRs + if: >- + github.event_name == 'push' && + startsWith(github.event.ref, 'refs/tags') + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + archs: aarch64 + build: "*manylinux*" + - os: macos-latest + archs: arm64 + build: "*" + + steps: + - uses: actions/checkout@v4 + with: + # Fetch all tags + fetch-depth: 0 + + - name: Set up QEMU + if: matrix.os == 'ubuntu-latest' + uses: docker/setup-qemu-action@v3 + with: + platforms: arm64 + + - name: Create wheels + uses: pypa/cibuildwheel@v2.15.0 + env: + CIBW_ARCHS: ${{ matrix.archs }} + CIBW_BUILD: ${{ matrix.build }} + + - name: Upload wheels + uses: actions/upload-artifact@v3 + with: + name: wheels + path: ./wheelhouse/*.whl + if-no-files-found: error + + check: + name: Check wheels + needs: + - build-x86_64 + - build-x86 + - build-arm64 + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: ${{ env.STABLE_PYTHON_VERSION }} + + - uses: actions/download-artifact@v3 + with: + name: wheels + path: wheelhouse + + - run: | + pipx run twine check --strict wheelhouse/* + + publish: + name: Publish wheels + if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') + needs: [check] + runs-on: ubuntu-latest + + steps: + - uses: actions/download-artifact@v3 + with: + name: artifacts + path: wheelhouse + + - name: Push build artifacts to PyPI + uses: pypa/gh-action-pypi-publish@v1.8.10 + with: + skip_existing: true + user: ${{ secrets.PYPI_USERNAME }} + password: ${{ secrets.PYPI_PASSWORD }} + packages-dir: wheelhouse diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml deleted file mode 100644 index 26e8651ed..000000000 --- a/.github/workflows/build_and_test.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Build and Test - -on: [push, pull_request] - -jobs: - build: - name: Python ${{ matrix.python-version }} on ${{ matrix.os }} - runs-on: ${{ matrix.os }} - - strategy: - # When set to true, GitHub cancels - # all in-progress jobs if any matrix job fails. - fail-fast: false - - matrix: - python-version: - - '3.7' - - '3.8' - - '3.9' - - '3.10' - - '3.11' - os: [ ubuntu-latest, windows-latest, macos-latest ] - - # These versions are no longer supported by Python team, and may - # eventually be dropped from GitHub Actions. - include: - - python-version: '3.6' - os: ubuntu-20.04 - - steps: - - name: Check out code - uses: actions/checkout@v3 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - python -m pip install -r requirements_dev.txt - - - name: Lint with flake8, pydocstyle - run: | - flake8 - pydocstyle pact - - - name: Test with pytest - run: tox -e test - - - name: Test examples - if: runner.os == 'Linux' - run: make examples diff --git a/.github/workflows/package_and_push_to_pypi.yml b/.github/workflows/package_and_push_to_pypi.yml deleted file mode 100644 index 4336ce061..000000000 --- a/.github/workflows/package_and_push_to_pypi.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Upload Python Package - -on: - release: - types: [created] - -jobs: - deploy: - environment: "Upload Python Package" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.x' - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install setuptools wheel twine - - name: Build and publish - env: - TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} - TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - run: | - python setup.py sdist - twine upload dist/* diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..6808db77a --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,61 @@ +name: test + +on: + push: + branches: + - master + pull_request: + branches: + - master + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + STABLE_PYTHON_VERSION: "3.11" + +jobs: + run: + name: >- + Python ${{ matrix.python-version }} + on ${{ matrix.os }} + + runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.experimental }} + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + python-version: ["3.8", "3.9", "3.10", "3.11"] + experimental: [false] + include: + - # Run tests against the next Python version, but no need for the full list of OSes. + os: ubuntu-latest + python-version: "3.12-dev" + experimental: true + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Hatch + run: pip install --upgrade hatch + + - # TODO: Fix lints before enabling this + name: Lint + if: matrix.python-version == env.STABLE_PYTHON_VERSION && runner.os == 'Linux' + run: echo hatch run lint + + - # TODO: Implement the examples to work in hatch + name: Examples + if: matrix.python-version == env.STABLE_PYTHON_VERSION && runner.os == 'Linux' + run: echo hatch run example + + - name: Run tests and track code coverage + run: hatch run test