CI: Refact and extend CI/CD workflows to leverage ansys actions #19
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: GitHub CI | |
on: | |
pull_request: | |
workflow_dispatch: | |
push: | |
tags: | |
- "*" | |
branches: | |
- main | |
env: | |
ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} | |
MAIN_PYTHON_VERSION: '3.10' | |
PACKAGE_NAME: 'PyAEDT' | |
DOCUMENTATION_CNAME: 'aedt.docs.pyansys.com' | |
MEILISEARCH_API_KEY: ${{ secrets.MEILISEARCH_API_KEY }} | |
MEILISEARCH_HOST_URL: ${{ vars.MEILISEARCH_HOST_URL }} | |
MEILISEARCH_PUBLIC_API_KEY: ${{ secrets.MEILISEARCH_PUBLIC_API_KEY }} | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
cancel-in-progress: true | |
jobs: | |
doc-style: | |
name: Documentation style check | |
runs-on: ubuntu-latest | |
steps: | |
- name: Check documentation style | |
uses: ansys/actions/doc-style@v4 | |
with: | |
token: ${{ secrets.GITHUB_TOKEN }} | |
vale-config: "doc/.vale.ini" | |
vale-version: "2.29.6" | |
smoke-tests: | |
name: Build wheelhouse with target all and perform smoke tests | |
runs-on: ${{ matrix.os }} | |
strategy: | |
fail-fast: false | |
matrix: | |
os: [ubuntu-latest, windows-latest] | |
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] | |
steps: | |
- name: Build wheelhouse and perform smoke test | |
uses: ansys/actions/build-wheelhouse@v4 | |
with: | |
library-name: ${{ env.PACKAGE_NAME }} | |
operating-system: ${{ matrix.os }} | |
python-version: ${{ matrix.python-version }} | |
target: 'all' | |
- name: Import python package | |
run: | | |
python -c "import pyaedt; from pyaedt import __version__" | |
smoke-tests-with-install-target: | |
name: Build and smoke tests (${{ matrix.os }} | Python ${{ matrix.python-version }} | Target ${{ matrix.install_target}}) | |
runs-on: ${{ matrix.os }} | |
strategy: | |
fail-fast: false | |
matrix: | |
os: [ubuntu-latest, windows-latest] | |
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] | |
install_target: ['tests', 'dotnet', 'doc', 'doc-noexamples', 'full'] | |
steps: | |
- name: "Install Git and clone project" | |
uses: actions/checkout@v4 | |
- name: Setup Python | |
uses: actions/setup-python@v4 | |
with: | |
python-version: ${{ matrix.python-version }} | |
- name: "Update pip and install the build and wheel libraries" | |
shell: bash | |
run: | | |
python -m pip install --upgrade pip build wheel | |
- name: "Install the library with specified install target" | |
shell: bash | |
run: | | |
python -m pip install .[${{ matrix.install_target }}] | |
- name: "Verify if importlib-metadata needs to be installed" | |
shell: bash | |
run: | | |
python_version="${{ matrix.python-version }}" | |
minor_python_version=$(echo "$python_version" | awk -F "." '{print $2}') | |
major_python_version=$(echo "$python_version" | awk -F "." '{print $1}') | |
if (( $(( $major_python_version == 3 )) )) && (( $(( $minor_python_version < 8 )) )); then | |
echo "needs_importlib_metadata=true" >> $GITHUB_ENV | |
elif (( $(( $major_python_version < 3 )) )); then | |
echo "needs_importlib_metadata=true" >> $GITHUB_ENV | |
else | |
echo "needs_importlib_metadata=false" >> $GITHUB_ENV | |
fi | |
- name: "Install importlib-metadata (only for Python <= 3.7)" | |
if: env.needs_importlib_metadata == 'true' | |
shell: bash | |
run: | | |
python -m pip install importlib-metadata | |
- name: "Verify pyaedt is properly installed and get its version number" | |
shell: bash | |
run: | | |
if [ ${{ env.needs_importlib_metadata }} == 'true' ]; then | |
version=$(python -c "import importlib_metadata; print(importlib_metadata.version('pyaedt'))") | |
else | |
version=$(python -c "import importlib.metadata as importlib_metadata; print(importlib_metadata.version('pyaedt'))") | |
fi | |
if [ -z "$version" ]; then | |
echo "Problem getting the library version" | |
exit 1; | |
else | |
echo "The library version is: $version"; | |
fi; | |
echo "library_version=$version" >> $GITHUB_ENV | |
doc-build: | |
name: Documentation build without examples | |
runs-on: ubuntu-latest | |
needs: [doc-style] | |
steps: | |
- name: Install Git and checkout project | |
uses: actions/checkout@v4 | |
- name: Setup Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version: ${{ env.MAIN_PYTHON_VERSION }} | |
- name: Update pip | |
run: | | |
pip install --upgrade pip | |
- name: Install pyaedt and documentation dependencies | |
run: | | |
pip install .[doc-noexamples] | |
- name: Retrieve PyAEDT version | |
id: version | |
run: | | |
echo "PYAEDT_VERSION=$(python -c 'from pyaedt import __version__; print(__version__)')" >> $GITHUB_OUTPUT | |
echo "PyAEDT version is: $(python -c "from pyaedt import __version__; print(__version__)")" | |
# TODO: Update this step once pyaedt-examples is ready | |
- name: Build documentation without examples | |
run: | | |
make -C doc clean | |
make -C doc html-noexamples | |
# Verify that sphinx generates no warnings | |
- name: Check for warnings | |
run: | | |
python doc/print_errors.py | |
- name: Upload HTML documentation without examples artifact | |
uses: actions/upload-artifact@v3 | |
with: | |
name: documentation-no-examples-html | |
path: doc/_build/html | |
retention-days: 7 | |
# # ================================================================================================= | |
# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | |
# # ================================================================================================= | |
# doc-build-with-examples: | |
# name: Documentation build with examples | |
# # if: github.event_name == 'push' && contains(github.ref, 'refs/tags') | |
# runs-on: [ self-hosted, Windows, pyaedt ] | |
# needs: [doc-style] | |
# timeout-minutes: 720 | |
# steps: | |
# - name: Install Git and checkout project | |
# uses: actions/checkout@v4 | |
# - name: Setup Python | |
# uses: actions/setup-python@v5 | |
# with: | |
# python-version: ${{ env.MAIN_PYTHON_VERSION }} | |
# - name: Create virtual environment | |
# run: | | |
# python -m venv .venv | |
# .venv\Scripts\Activate.ps1 | |
# python -m pip install pip -U | |
# python -m pip install wheel setuptools -U | |
# python -c "import sys; print(sys.executable)" | |
# - name: Install pyaedt and documentation dependencies | |
# run: | | |
# .venv\Scripts\Activate.ps1 | |
# pip install .[doc] | |
# - name: Retrieve PyAEDT version | |
# id: version | |
# run: | | |
# .venv\Scripts\Activate.ps1 | |
# echo "PYAEDT_VERSION=$(python -c 'from pyaedt import __version__; print(__version__)')" >> $GITHUB_OUTPUT | |
# echo "PyAEDT version is: $(python -c "from pyaedt import __version__; print(__version__)")" | |
# - name: Uninstall conflicting CI packages | |
# run: | | |
# .venv\Scripts\Activate.ps1 | |
# pip uninstall vtk -y | |
# - name: Install CI related dependencies | |
# run: | | |
# .venv\Scripts\Activate.ps1 | |
# pip install --extra-index-url https://wheels.vtk.org .[ci] | |
# # TODO: Update this step once pyaedt-examples is ready | |
# # NOTE: Use environment variable to keep the doctree and avoid redundant build for PDF pages | |
# - name: Build HTML documentation with examples | |
# env: | |
# SPHINXBUILD_KEEP_DOCTREEDIR: "1" | |
# run: | | |
# .venv\Scripts\Activate.ps1 | |
# .\doc\make.bat clean | |
# .\doc\make.bat html | |
# - name: Upload HTML documentation with examples artifact | |
# uses: actions/upload-artifact@v3 | |
# with: | |
# name: documentation-examples-html | |
# path: doc/_build/html | |
# retention-days: 7 | |
# # TODO: Keeping this commented as reminder of https://github.com/ansys/pyaedt/issues/4296 | |
# # # Verify that sphinx generates no warnings | |
# # - name: Check for warnings | |
# # run: | | |
# # .venv\Scripts\Activate.ps1 | |
# # python doc/print_errors.py | |
# # # Use environment variable to remove the doctree after the build of PDF pages | |
# # - name: Build PDF documentation with examples | |
# # env: | |
# # SPHINXBUILD_KEEP_DOCTREEDIR: "0" | |
# # run: | | |
# # .venv\Scripts\Activate.ps1 | |
# # .\doc\make.bat pdf | |
# # - name: Upload PDF documentation with examples artifact | |
# # uses: actions/upload-artifact@v3 | |
# # with: | |
# # name: documentation-pdf | |
# # path: doc/_build/latex/*.pdf | |
# # retention-days: 7 | |
# # ================================================================================================= | |
# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | |
# # ================================================================================================= | |
test-solvers-windows: | |
name: Testing solvers and coverage (Windows) | |
needs: [smoke-tests] | |
runs-on: [ self-hosted, Windows, pyaedt ] | |
steps: | |
- name: Install Git and checkout project | |
uses: actions/checkout@v4 | |
- name: Setup Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version: ${{ env.MAIN_PYTHON_VERSION }} | |
- name: Create virtual environment | |
run: | | |
python -m venv .venv | |
.venv\Scripts\Activate.ps1 | |
python -m pip install pip -U | |
python -m pip install wheel setuptools -U | |
python -c "import sys; print(sys.executable)" | |
- name: Install pyaedt and tests dependencies | |
run: | | |
.venv\Scripts\Activate.ps1 | |
pip install .[tests] | |
- name: Install CI dependencies (e.g. vtk-osmesa) | |
run: | | |
.venv\Scripts\Activate.ps1 | |
# Uninstall conflicting dependencies | |
pip uninstall vtk -y | |
pip install --extra-index-url https://wheels.vtk.org .[ci] | |
- name: 'Unit testing' | |
uses: nick-fields/retry@v3 | |
env: | |
PYTHONMALLOC: malloc | |
with: | |
max_attempts: 3 | |
retry_on: error | |
timeout_minutes: 40 | |
command: | | |
.venv\Scripts\Activate.ps1 | |
pytest --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest_solvers | |
- uses: codecov/codecov-action@v4 | |
with: | |
token: ${{ secrets.CODECOV_TOKEN }} | |
name: codecov-system-solver-tests | |
file: ./coverage.xml | |
flags: system,solver | |
- name: Upload pytest test results | |
uses: actions/upload-artifact@v3 | |
with: | |
name: pytest-solver-results | |
path: junit/test-results.xml | |
if: ${{ always() }} | |
# # ================================================================================================= | |
# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | |
# # ================================================================================================= | |
test-windows: | |
name: Testing and coverage (Windows) | |
needs: [smoke-tests] | |
runs-on: [ self-hosted, Windows, pyaedt ] | |
steps: | |
- name: Install Git and checkout project | |
uses: actions/checkout@v4 | |
- name: Setup Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version: ${{ env.MAIN_PYTHON_VERSION }} | |
- name: Create virtual environment | |
run: | | |
python -m venv .venv | |
.venv\Scripts\Activate.ps1 | |
python -m pip install pip -U | |
python -m pip install wheel setuptools -U | |
python -c "import sys; print(sys.executable)" | |
- name: Install pyaedt and tests dependencies | |
run: | | |
.venv\Scripts\Activate.ps1 | |
pip install .[tests] | |
- name: Install CI dependencies (e.g. vtk-osmesa) | |
run: | | |
.venv\Scripts\Activate.ps1 | |
# Uninstall conflicting dependencies | |
pip uninstall vtk -y | |
pip install --extra-index-url https://wheels.vtk.org .[ci] | |
- name: 'Unit testing' | |
uses: nick-fields/retry@v3 | |
env: | |
PYTHONMALLOC: malloc | |
with: | |
max_attempts: 3 | |
retry_on: error | |
timeout_minutes: 40 | |
command: | | |
.venv\Scripts\Activate.ps1 | |
pytest -n auto --dist loadfile --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest | |
- uses: codecov/codecov-action@v4 | |
with: | |
token: ${{ secrets.CODECOV_TOKEN }} | |
name: codecov-system-tests | |
file: ./coverage.xml | |
flags: system | |
- name: Upload pytest test results | |
uses: actions/upload-artifact@v3 | |
with: | |
name: pytest-results | |
path: junit/test-results.xml | |
if: ${{ always() }} | |
# # ================================================================================================= | |
# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | |
# # ================================================================================================= | |
test-ironpython-windows: | |
name: Testing and coverage (Windows) | |
needs: [smoke-tests] | |
runs-on: [ self-hosted, Windows, pyaedt ] | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Run Ironpython tests | |
timeout-minutes: 5 | |
run: | | |
$processA = start-process 'cmd' -ArgumentList '/c .\_unittest_ironpython\run_unittests_batchmode.cmd' -PassThru | |
$processA.WaitForExit() | |
- name: Get log content | |
run: | | |
get-content .\_unittest_ironpython\pyaedt_unit_test_ironpython.log | |
- name: Check for errors | |
run: | | |
$test_errors_failures = Select-String -Path .\_unittest_ironpython\pyaedt_unit_test_ironpython.log -Pattern "TextTestResult errors=" | |
if ($test_errors_failures -ne $null) | |
{ | |
exit 1 | |
} | |
package: | |
name: Package library | |
needs: [test-windows, test-solvers-windows, test-ironpython-windows, doc-build] | |
runs-on: ubuntu-latest | |
steps: | |
- name: Build library source and wheel artifacts | |
uses: ansys/actions/build-library@v4 | |
with: | |
library-name: ${{ env.PACKAGE_NAME }} | |
python-version: ${{ env.MAIN_PYTHON_VERSION }} | |
release: | |
name: Release project | |
if: github.event_name == 'push' && contains(github.ref, 'refs/tags') | |
needs: [package] | |
runs-on: ubuntu-latest | |
steps: | |
- name: Release to the public PyPI repository | |
uses: ansys/actions/release-pypi-public@v4 | |
with: | |
library-name: ${{ env.PACKAGE_NAME }} | |
twine-username: "__token__" | |
twine-token: ${{ secrets.PYPI_TOKEN }} | |
# TODO: Uncomment once PDF file generation is fixed in CICD | |
# - name: Release to GitHub | |
# uses: ansys/actions/release-github@v4 | |
# with: | |
# library-name: ${{ env.PACKAGE_NAME }} | |
- name: "Download all artifacts that got generated in the CI/CD" | |
uses: actions/download-artifact@v3 | |
with: | |
path: /tmp/artifacts | |
- name: "Generate a distribution folder that will contain the desired artifacts" | |
shell: bash | |
run: mkdir -p dist | |
- name: "Moving documentation artifacts to dist/documentation directory" | |
shell: bash | |
run: | | |
mkdir -p dist/documentation | |
mv /tmp/artifacts/documentation-html dist/documentation/documentation-html | |
- name: "Compressing HTML documentation" | |
uses: vimtor/[email protected] | |
with: | |
files: dist/documentation/documentation-html | |
dest: dist/documentation/documentation-html.zip | |
- name: "Move wheelhouse artifacts to dist/wheelhouse directory" | |
shell: bash | |
run: | | |
mkdir -p dist/wheelhouse | |
mv /tmp/artifacts/**/*-wheelhouse-*.zip dist/wheelhouse/ | |
- name: "Move wheel artifacts to dist/${{ env.PACKAGE_NAME }}-artifacts directory" | |
shell: bash | |
run: | | |
mv /tmp/artifacts/${{ env.PACKAGE_NAME }}-artifacts dist/${{ env.PACKAGE_NAME }}-artifacts | |
- name: "Display the structure of the 'dist/' folder" | |
shell: bash | |
run: ls -R dist/ | |
- name: "Release to GitHub" | |
uses: softprops/action-gh-release@v2 | |
with: | |
fail_on_unmatched_files: false | |
generate_release_notes: true | |
files: | | |
# Include wheel and source distribution artifacts | |
dist/${{ inputs.library-name }}-artifacts/*.whl | |
dist/${{ inputs.library-name }}-artifacts/*.tar.gz | |
# Include wheelhouse artifacts | |
dist/wheelhouse/**/*-wheelhouse-*.zip | |
# Include HTML documentation artifacts | |
dist/documentation/documentation-html.zip | |
upload-dev-doc: | |
name: Upload dev documentation | |
if: github.ref == 'refs/heads/main' | |
runs-on: ubuntu-latest | |
needs: [package] | |
steps: | |
- name: Deploy the latest documentation | |
uses: ansys/actions/doc-deploy-dev@v4 | |
with: | |
cname: ${{ env.DOCUMENTATION_CNAME }} | |
token: ${{ secrets.GITHUB_TOKEN }} | |
doc-artifact-name: 'documentation-no-examples-html' | |
doc-index-dev: | |
name: "Deploy dev index docs" | |
if: github.ref == 'refs/heads/main' | |
runs-on: ubuntu-latest | |
needs: upload-dev-doc | |
steps: | |
- name: "Deploy the latest documentation index" | |
uses: ansys/actions/doc-deploy-index@v4 | |
with: | |
cname: ${{ env.DOCUMENTATION_CNAME }}/version/dev | |
index-name: pyaedt-vdev | |
host-url: ${{ env.MEILISEARCH_HOST_URL }} | |
api-key: ${{ env.MEILISEARCH_API_KEY }} | |
python-version: ${{ env.MAIN_PYTHON_VERSION }} | |
upload-release-doc: | |
name: Upload release documentation | |
if: github.event_name == 'push' && contains(github.ref, 'refs/tags') | |
runs-on: ubuntu-latest | |
needs: [release] | |
steps: | |
- name: Deploy the stable documentation | |
uses: ansys/actions/doc-deploy-stable@v4 | |
with: | |
cname: ${{ env.DOCUMENTATION_CNAME }} | |
token: ${{ secrets.GITHUB_TOKEN }} | |
doc-artifact-name: 'documentation-examples-html' | |
doc-index-stable: | |
name: "Deploy stable docs index" | |
runs-on: ubuntu-latest | |
needs: upload-release-doc | |
steps: | |
- name: "Install Git and clone project" | |
uses: actions/checkout@v4 | |
- name: "Install the package requirements" | |
run: pip install -e . | |
- name: "Get the version to PyMeilisearch" | |
run: | | |
VERSION=$(python -c "from pyaedt import __version__; print('.'.join(__version__.split('.')[:2]))") | |
VERSION_MEILI=$(python -c "from pyaedt import __version__; print('-'.join(__version__.split('.')[:2]))") | |
echo "Calculated VERSION: $VERSION" | |
echo "Calculated VERSION_MEILI: $VERSION_MEILI" | |
echo "VERSION=$VERSION" >> $GITHUB_ENV | |
echo "VERSION_MEILI=$VERSION_MEILI" >> $GITHUB_ENV | |
- name: "Deploy the latest documentation index" | |
uses: ansys/actions/doc-deploy-index@v4 | |
with: | |
cname: ${{ env.DOCUMENTATION_CNAME }}/version/${{ env.VERSION }} | |
index-name: pyaedt-v${{ env.VERSION_MEILI }} | |
host-url: ${{ env.MEILISEARCH_HOST_URL }} | |
api-key: ${{ env.MEILISEARCH_API_KEY }} | |
python-version: ${{ env.MAIN_PYTHON_VERSION }} | |