Skip to content

GitHub CI

GitHub CI #7897

Workflow file for this run

name: GitHub CI
on:
pull_request:
workflow_dispatch:
inputs:
revn:
type: choice
options:
- 'candidate'
- '261'
- '252'
- '251'
- '242'
- '241'
description: 'The Mechanical revision number to run tests on.'
default: '252' #stable version is 252, must match $stable_container
schedule:
- cron: '00 22 * * *' # UTC time, may start 5-15 mins later than scheduled time
push:
tags:
- "*"
branches:
- main
- release/*
env:
PYMECHANICAL_PORT: 10000 # default won't work on GitHub runners
PYMECHANICAL_START_INSTANCE: false
DOCKER_PACKAGE: ghcr.io/ansys/mechanical
DOCKER_MECH_CONTAINER_NAME: mechanical
PACKAGE_NAME: ansys-mechanical-core
DOCUMENTATION_CNAME: mechanical.docs.pyansys.com
MAIN_PYTHON_VERSION: '3.12'
# DEV_REVN & its Docker image are used in scheduled or registry package runs
STABLE_REVN: '252'
DEV_REVN: '261'
LICENSE_SERVER: ${{ secrets.LICENSE_SERVER }}
ANSYSLMD_LICENSE_FILE: 1055@${{ secrets.LICENSE_SERVER }}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
update-changelog:
name: "Update CHANGELOG for new tag"
if: github.event_name == 'push' && contains(github.ref, 'refs/tags')
runs-on: ubuntu-latest
permissions:
contents: write # Needed to create changelog entries in repository
pull-requests: write # Required to create pull requests for changelog updates
steps:
- uses: ansys/actions/doc-deploy-changelog@41f86da4c9ead510db9135e428e33df9cc6f92e1 # v10.2.3
with:
token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }}
bot-user: ${{ secrets.PYANSYS_CI_BOT_USERNAME }}
bot-email: ${{ secrets.PYANSYS_CI_BOT_EMAIL }}
style:
name: Code style
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: PyAnsys code style checks
uses: ansys/actions/code-style@41f86da4c9ead510db9135e428e33df9cc6f92e1 # v10.2.3
with:
python-version: ${{ env.MAIN_PYTHON_VERSION }}
doc-style:
name: Documentation Style Check
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: PyAnsys documentation style checks
uses: ansys/actions/doc-style@41f86da4c9ead510db9135e428e33df9cc6f92e1 # v10.2.3
with:
token: ${{ secrets.GITHUB_TOKEN }}
check-vulnerabilities:
name: Check Vulnerabilities
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: PyAnsys Vulnerability check (on main)
if: github.ref == 'refs/heads/main'
uses: ansys/actions/check-vulnerabilities@41f86da4c9ead510db9135e428e33df9cc6f92e1 # v10.2.3
with:
python-version: ${{ env.MAIN_PYTHON_VERSION }}
python-package-name: ${{ env.PACKAGE_NAME }}
token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }}
- name: PyAnsys Vulnerability check (on dev mode)
if: github.ref != 'refs/heads/main'
uses: ansys/actions/check-vulnerabilities@41f86da4c9ead510db9135e428e33df9cc6f92e1 # v10.2.3
with:
python-version: ${{ env.MAIN_PYTHON_VERSION }}
python-package-name: ${{ env.PACKAGE_NAME }}
token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }}
dev-mode: true
check-actions-security:
name: "Check Actions Security"
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: ansys/actions/check-actions-security@41f86da4c9ead510db9135e428e33df9cc6f92e1 # v10.2.3
with:
generate-summary: true
token: ${{ secrets.GITHUB_TOKEN }}
auditing-level: 'high'
trust-ansys-actions: true
smoke-tests:
name: Build and Smoke tests
runs-on: ${{ matrix.os }}
needs: [style]
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.10', '3.11', '3.12', '3.13']
should-release:
- ${{ github.event_name == 'push' && contains(github.ref, 'refs/tags') }}
exclude:
- should-release: false
os: macos-latest
permissions:
contents: read
steps:
- name: Build wheelhouse and perform smoke test
uses: ansys/actions/build-wheelhouse@41f86da4c9ead510db9135e428e33df9cc6f92e1 # v10.2.3
with:
library-name: ${{ env.PACKAGE_NAME }}
operating-system: ${{ matrix.os }}
python-version: ${{ matrix.python-version }}
revn-variations:
name: Save variations of revn
runs-on: ubuntu-latest
outputs:
stable_container: ${{ steps.save-versions.outputs.stable_container }}
test_revn: '${{ steps.save-versions.outputs.test_revn }}'
test_container: ${{ steps.save-versions.outputs.test_container }}
test_docker_image_version: '${{ steps.save-versions.outputs.test_docker_image_version }}'
permissions:
contents: read
steps:
- id: save-versions
env:
GH_EVENT_NAME: ${{ github.event_name }}
REVN_INPUT: ${{ github.event.inputs.revn }}
DEV_REVN: ${{ env.DEV_REVN }}
DOCKER_PACKAGE: ${{ env.DOCKER_PACKAGE }}
STABLE_REVN: ${{ env.STABLE_REVN }}
run: |
# --- Help ----
# schedule nightly uses DEV_REVN candidate
# PRs and merges use STABLE_REVN
# Workflow dispatch can use any revision number
if [[ "${GH_EVENT_NAME}" == "schedule" ]] || [[ "${REVN_INPUT}" == "candidate" ]]; then
echo "test_revn=${DEV_REVN}" >> $GITHUB_OUTPUT
test_mech_revn=${DEV_REVN}
test_mech_image_version=${test_mech_revn:0:2}.${test_mech_revn:2}_candidate
echo "test_container=${DOCKER_PACKAGE}:$test_mech_image_version" >> $GITHUB_OUTPUT
echo "test_docker_image_version=$test_mech_image_version" >> $GITHUB_OUTPUT
else
if [[ -z "${REVN_INPUT}" ]]; then
mech_revn=${STABLE_REVN}
else
mech_revn=${REVN_INPUT}
fi
export mech_image_version=${mech_revn:0:2}.${mech_revn:2}.0
echo "test_revn=$mech_revn" >> $GITHUB_OUTPUT
echo "test_container=${DOCKER_PACKAGE}:$mech_image_version" >> $GITHUB_OUTPUT
echo "test_docker_image_version=$mech_image_version" >> $GITHUB_OUTPUT
fi
stable_mech_revn=${STABLE_REVN}
stable_mech_image_version=${mech_revn:0:2}.${mech_revn:2}.0
echo "stable_container=${DOCKER_PACKAGE}:$stable_mech_image_version" >> $GITHUB_OUTPUT
test-container-info:
name: Get SHA of test container
runs-on: public-ubuntu-latest-8-cores
needs: [revn-variations]
outputs:
sha: ${{ steps.get_sha.outputs.sha }}
strategy:
matrix:
test_container: ['${{ needs.revn-variations.outputs.test_container }}']
permissions:
packages: read # Required to pull Docker images from GitHub Container Registry
steps:
- name: Login in Github Container registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Pull, launch, and validate Mechanical service
id: get_sha
env:
MECHANICAL_IMAGE: ${{ matrix.test_container }}
run: |
# Install jq for parsing JSON
pip install jq
# Get docker info
image_info=$(docker manifest inspect -v ${MECHANICAL_IMAGE}) # --format ".Descriptor.digest"
# Get digest SHA
digest=$(echo "$image_info" | jq -r '.Descriptor.digest')
# Remove the "sha256:" prefix to get only the SHA
sha="${digest#*:}"
echo "SHA of image ${MECHANICAL_IMAGE} is $sha"
echo "sha=$sha" >> $GITHUB_OUTPUT
config-matrix:
name: Configure matrix
runs-on: ubuntu-latest
needs: [revn-variations]
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
permissions:
contents: read
steps:
- id: set-matrix
env:
GH_EVENT_NAME: ${{ github.event_name }}
TEST_DOCKER_IMAGE_VERSION: ${{ needs.revn-variations.outputs.test_docker_image_version }}
GH_REF: ${{ github.ref }}
run: |
# if a tag(release) is pushed, test all versions
if [[ "${GH_EVENT_NAME}" == "push" ]] && [[ "$GH_REF" =~ "refs/tags" ]]; then
echo "matrix={\"mechanical-version\":['24.1.0', '24.2.0', '25.1.0', '25.2.0'],\"experimental\":[false]}" >> $GITHUB_OUTPUT
else
echo "matrix={\"mechanical-version\":['${TEST_DOCKER_IMAGE_VERSION}'],\"experimental\":[false]}" >> $GITHUB_OUTPUT
fi
container-stability-check:
name: Container stability check
runs-on: ubuntu-latest
needs: [revn-variations]
outputs:
container_stable_exit: ${{ steps.check_stability.outputs.container_stable_exit }}
permissions:
contents: read
steps:
- id: check_stability
env:
TEST_DOCKER_IMAGE_VERSION: ${{ needs.revn-variations.outputs.test_docker_image_version }}
run: |
sudo apt update
sudo apt install bc -y
container_version=$(echo "${TEST_DOCKER_IMAGE_VERSION}" | grep -o -E '[0-9]+(\.[0-9]+)?' | head -n 1)
if (( $(echo "$container_version > 24.2" | bc -l) )); then
echo "container_stable_exit=true" >> $GITHUB_OUTPUT
else
echo "container_stable_exit=false" >> $GITHUB_OUTPUT
fi
remote-connect:
name: Remote connect testing and coverage - Mechanical ${{ matrix.mechanical-version }}
runs-on: public-ubuntu-latest-16-cores
needs: [style, revn-variations, config-matrix]
continue-on-error: ${{ matrix.experimental }}
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.config-matrix.outputs.matrix) }}
permissions:
contents: read
packages: read # Required to pull Docker images from GitHub Container Registry
checks: write # Needed to publish test results and status checks
steps:
- name: Login in Github Container registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Pull, launch, and validate Mechanical service
env:
MECHANICAL_IMAGE: ${{ env.DOCKER_PACKAGE }}:${{ matrix.mechanical-version }}
# ANSYS_WORKBENCH_LOGGING_CONSOLE: 0
# ANSYS_WORKBENCH_LOGGING_DIRECTORY: /log_file # workbench.log file
ANSYS_WORKBENCH_LOGGING_AUTO_FLUSH: 0 # turn off autoflush for faster performance
DOCKER_MECH_CONTAINER_NAME: ${{ env.DOCKER_MECH_CONTAINER_NAME }}
LICENSE_SERVER: ${{ env.LICENSE_SERVER }}
PYMECHANICAL_PORT: ${{ env.PYMECHANICAL_PORT }}
run: |
docker pull ${MECHANICAL_IMAGE}
echo "Run docker in detached mode"
docker run -d --name ${DOCKER_MECH_CONTAINER_NAME} -e ANSYSLMD_LICENSE_FILE=1055@${LICENSE_SERVER} -p ${PYMECHANICAL_PORT}:10000 ${MECHANICAL_IMAGE}
# Wait for Mechanical to initialize with intelligent polling
max_wait=300 # Maximum wait time in seconds
check_interval=10 # Check every 10 seconds
elapsed=0
echo "Waiting for Mechanical to initialize..."
while [ $elapsed -lt $max_wait ]; do
docker logs ${DOCKER_MECH_CONTAINER_NAME} > log.txt
if grep -q 'WB Initialize Done' log.txt 2>/dev/null; then
echo "Mechanical initialized successfully after ${elapsed} seconds"
break
fi
echo "Waiting for initialization... (${elapsed}/${max_wait}s)"
sleep $check_interval
elapsed=$((elapsed + check_interval))
done
# Final check
docker logs ${DOCKER_MECH_CONTAINER_NAME} > log.txt
if ! grep -q 'WB Initialize Done' log.txt 2>/dev/null; then
echo "ERROR: Mechanical failed to initialize within ${max_wait} seconds"
echo "=== Last 50 lines of log.txt ==="
tail -n 50 log.txt || echo "No log file found"
exit 1
fi
- name: Display info
if: github.event_name == 'schedule'
id: capture_info
env:
DOCKER_PACKAGE: ${{ env.DOCKER_PACKAGE }}
MECH_VERSION: ${{ matrix.mechanical-version }}
TEST_REVN: ${{ needs.revn-variations.outputs.test_revn }}
run: |
IMAGE_NAME=${DOCKER_PACKAGE}:${MECH_VERSION}
BUILD_DATE=$(docker run --rm --entrypoint head $IMAGE_NAME -n 1 /install/ansys_inc/v${TEST_REVN}/aisol/CommonFiles/builddate.txt)
PUSHED_AT=$(docker inspect --format='{{.Created}}' $IMAGE_NAME)
echo "docker_info=$IMAGE_NAME was pushed at: $PUSHED_AT" >> $GITHUB_OUTPUT
echo "::group::Docker Info"
echo "docker_info=$PUSHED_AT" >> $GITHUB_OUTPUT
echo "build_info=$BUILD_DATE" >> $GITHUB_OUTPUT
echo "$IMAGE_NAME pushed at $PUSHED_AT"
echo "Build date : $BUILD_DATE"
echo "::endgroup::"
- name: Testing
uses: ansys/actions/tests-pytest@41f86da4c9ead510db9135e428e33df9cc6f92e1 # v10.2.3
with:
python-version: ${{ env.MAIN_PYTHON_VERSION }}
pytest-markers: '-m remote_session_connect'
pytest-extra-args: '-s --junitxml remote_results${{ env.MAIN_PYTHON_VERSION }}.xml'
- name: Publish Test Report
uses: mikepenz/action-junit-report@e08919a3b1fb83a78393dfb775a9c37f17d8eea6 # v6.0.1
if: always()
with:
report_paths: '**/remote_results*.xml'
check_name: Remote Connect Test Report ${{ matrix.python-version }}
detailed_summary: true
include_passed: true
fail_on_failure: true
- name: Upload coverage results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: matrix.mechanical-version == needs.revn-variations.outputs.test_docker_image_version
with:
include-hidden-files: true
name: coverage-tests
path: .cov
retention-days: 7
- name: Upload coverage results (as .coverage)
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: matrix.mechanical-version == needs.revn-variations.outputs.test_docker_image_version
with:
include-hidden-files: true
name: coverage-file-tests
path: .coverage
retention-days: 7
- name: Get Mechanical container logs
if: always()
run: | # zizmor: ignore[template-injection]
docker logs ${{ env.DOCKER_MECH_CONTAINER_NAME }} > mechanical_tests_log-${{ matrix.mechanical-version }}.txt 2>&1
echo CONTAINER LOGS OUTPUT
cat mechanical_tests_log-${{ matrix.mechanical-version }}.txt
echo CPU info
lscpu
- name: Upload container logs
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: mechanical_tests_log-${{ matrix.mechanical-version }}
path: mechanical_tests_log-${{ matrix.mechanical-version }}.txt
retention-days: 7
embedding-tests:
name: Embedding testing and coverage
runs-on: public-ubuntu-latest-16-cores
timeout-minutes: 30
needs: [revn-variations, test-container-info, container-stability-check, smoke-tests]
container:
image: ${{ needs.revn-variations.outputs.test_container }} # zizmor: ignore[unpinned-images]
options: --entrypoint /bin/bash
strategy:
fail-fast: false
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13']
permissions:
contents: read
packages: read # Required to pull Docker images from GitHub Container Registry
checks: write # Needed to publish test results and status checks
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Set up Python
shell: bash
env:
MAIN_PYTHON_VERSION: ${{ env.MAIN_PYTHON_VERSION }}
run: |
apt update
apt install lsb-release xvfb git curl make -y
curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv python install python${MAIN_PYTHON_VERSION}
uv venv /env
- name: "Install packages for testing"
run: |
. /env/bin/activate
uv pip install --upgrade pip
uv pip install -e .[tests]
- name: Unit Testing and coverage
env:
ANSYS_WORKBENCH_LOGGING_CONSOLE: 0
ANSYS_WORKBENCH_LOGGING: 0
ANSYS_WORKBENCH_LOGGING_FILTER_LEVEL: 2
CONTAINER_STABLE_EXIT: ${{ needs.container-stability-check.outputs.container_stable_exit }}
MATRIX_PYTHON_VERSION: ${{ matrix.python-version }}
NUM_CORES: 1
PYTHONUNBUFFERED: 1
run: |
. /env/bin/activate
if [ "${CONTAINER_STABLE_EXIT}" = "true" ]; then
xvfb-run mechanical-env pytest -m embedding -s --junitxml test_results${MATRIX_PYTHON_VERSION}.xml
else
xvfb-run mechanical-env pytest -m embedding -s --junitxml test_results${MATRIX_PYTHON_VERSION}.xml || true
fi
- name: Upload coverage results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: env.MAIN_PYTHON_VERSION == matrix.python-version
with:
include-hidden-files: true
name: coverage-tests-embedding
path: .cov
retention-days: 7
- name: Upload coverage results (as .coverage)
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: env.MAIN_PYTHON_VERSION == matrix.python-version
with:
include-hidden-files: true
name: coverage-file-tests-embedding
path: .coverage
retention-days: 7
- name: Publish Test Report
uses: mikepenz/action-junit-report@e08919a3b1fb83a78393dfb775a9c37f17d8eea6 # v6.0.1
if: always()
with:
report_paths: '**/test_results*.xml'
check_name: Test Report ${{ matrix.python-version }}
detailed_summary: true
include_passed: true
fail_on_failure: true
embedding-scripts-tests:
name: Embedding scripts testing and coverage
runs-on: public-ubuntu-latest-16-cores
timeout-minutes: 30
needs: [smoke-tests, revn-variations, test-container-info]
container:
image: ${{ needs.revn-variations.outputs.test_container }} # zizmor: ignore[unpinned-images]
options: --entrypoint /bin/bash
strategy:
fail-fast: false
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13']
permissions:
contents: read
packages: read # Required to pull Docker images from GitHub Container Registry
checks: write # Needed to publish test results and status checks
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Set up Python
shell: bash
env:
MAIN_PYTHON_VERSION: ${{ env.MAIN_PYTHON_VERSION }}
run: |
apt update
apt install lsb-release xvfb git curl make -y
curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv python install python${MAIN_PYTHON_VERSION}
uv venv /env
- name: "Install packages for testing"
run: |
. /env/bin/activate
uv pip install --upgrade pip
uv pip install -e .[tests]
- name: Embedding scripts unit testing and coverage
env:
ANSYS_WORKBENCH_LOGGING_CONSOLE: 0
ANSYS_WORKBENCH_LOGGING: 0
ANSYS_WORKBENCH_LOGGING_FILTER_LEVEL: 2
MATRIX_PYTHON_VERSION: ${{ matrix.python-version }}
NUM_CORES: 1
PYTHONUNBUFFERED: 1
run: |
. /env/bin/activate
mechanical-env pytest -m embedding_scripts -s --junitxml test_results_embedding_scripts${MAIN_PYTHON_VERSION}.xml
pytest -m cli -s --junitxml test_results_cli_scripts${MAIN_PYTHON_VERSION}.xml
- name: Upload coverage results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: env.MAIN_PYTHON_VERSION == matrix.python-version
with:
include-hidden-files: true
name: coverage-tests-embedding-scripts
path: .cov
retention-days: 7
- name: Upload coverage results (as .coverage)
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: env.MAIN_PYTHON_VERSION == matrix.python-version
with:
include-hidden-files: true
name: coverage-file-tests-embedding-scripts
path: .coverage
retention-days: 7
- name: Publish Test Report
uses: mikepenz/action-junit-report@e08919a3b1fb83a78393dfb775a9c37f17d8eea6 # v6.0.1
if: always()
with:
report_paths: '**/test_results*.xml'
check_name: Test Report ${{ matrix.python-version }}
detailed_summary: true
include_passed: true
fail_on_failure: true
launch-tests:
name: Launch testing and coverage
runs-on: public-ubuntu-latest-16-cores
timeout-minutes: 30
container:
image: ${{ needs.revn-variations.outputs.test_container }} # zizmor: ignore[unpinned-images]
options: --entrypoint /bin/bash
needs: [ style, revn-variations, container-stability-check, test-container-info]
strategy:
fail-fast: false
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13']
permissions:
contents: read
packages: read # Required to pull Docker images from GitHub Container Registry
checks: write # Needed to publish test results and status checks
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Set up Python
shell: bash
env:
MAIN_PYTHON_VERSION: ${{ env.MAIN_PYTHON_VERSION }}
run: |
apt update
apt install lsb-release xvfb git curl make -y
curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv python install python${MAIN_PYTHON_VERSION}
uv venv /env
- name: "Install packages for testing"
run: |
. /env/bin/activate
uv pip install --upgrade pip
uv pip install -e .[tests]
- name: Set environment variable
env:
TEST_REVN: ${{ needs.revn-variations.outputs.test_revn }}
run: echo "ANSYSCL${TEST_REVN}_DIR=/install/ansys_inc/v${TEST_REVN}/licensingclient" >> $GITHUB_ENV
- name: Unit Testing and coverage
env:
ANSYS_WORKBENCH_LOGGING_CONSOLE: 0
CONTAINER_STABLE_EXIT: ${{ needs.container-stability-check.outputs.container_stable_exit }}
MATRIX_PYTHON_VERSION: ${{ matrix.python-version }}
run: |
unset PYMECHANICAL_PORT
unset PYMECHANICAL_START_INSTANCE
. /env/bin/activate
if [ "${CONTAINER_STABLE_EXIT}" = "true" ]; then
pytest -m remote_session_launch -s --junitxml launch_test_results${MATRIX_PYTHON_VERSION}.xml
else
pytest -m remote_session_launch -s --junitxml launch_test_results${MATRIX_PYTHON_VERSION}.xml || true
fi
- name: Publish Launch Test Report
uses: mikepenz/action-junit-report@e08919a3b1fb83a78393dfb775a9c37f17d8eea6 # v6.0.1
if: always()
with:
report_paths: '**/launch_test_results*.xml'
check_name: Launch Test Report ${{ matrix.python-version }}
detailed_summary: true
include_passed: true
fail_on_failure: true
- name: Upload coverage results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: env.MAIN_PYTHON_VERSION == matrix.python-version
with:
include-hidden-files: true
name: coverage-tests-remote-session-launch
path: .cov
retention-days: 7
- name: Upload coverage results (as .coverage)
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: env.MAIN_PYTHON_VERSION == matrix.python-version
with:
include-hidden-files: true
name: coverage-file-tests-remote-session-launch
path: .coverage
retention-days: 7
doc-build:
name: Documentation
runs-on: public-ubuntu-latest-16-cores
timeout-minutes: 30
container:
image: ${{ needs.revn-variations.outputs.test_container }} # zizmor: ignore[unpinned-images]
options: --entrypoint /bin/bash
needs: [style, doc-style, revn-variations, container-stability-check, test-container-info]
permissions:
contents: read
packages: read # Required to pull Docker images from GitHub Container Registry
steps:
- name: Install Git and checkout project
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Set up Python
shell: bash
env:
MAIN_PYTHON_VERSION: ${{ env.MAIN_PYTHON_VERSION }}
run: |
apt update
apt install lsb-release xvfb git curl make -y
curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv python install python${MAIN_PYTHON_VERSION}
uv venv /env
- name: Install system dependencies
env:
DEBIAN_FRONTEND: 'noninteractive'
TZ: 'Etc/UTC'
run: |
apt update
apt install make lsb-release xvfb poppler-utils -y
apt install zip pandoc libgl1-mesa-glx mesa-utils texlive-latex-extra latexmk nodejs npm graphviz -y
- name: Install gh cli
run: |
(type -p wget >/dev/null || (apt update && apt-get install wget -y)) \
&& mkdir -p -m 755 /etc/apt/keyrings \
&& wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
&& chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& apt update \
&& apt install gh -y
- name: Install quarto to build cheatsheet
run: | # zizmor: ignore[template-injection]
echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token
gh release download v1.6.43 --repo github.com/quarto-dev/quarto-cli --pattern *linux-amd64.deb
apt install ./quarto*linux-amd64.deb -y
quarto install tool tinytex --log-level warning
- name: Test quarto installation
run: quarto --version
- name: Install Python requirements
run: |
. /env/bin/activate
uv pip install --upgrade pip
uv pip install -e .[doc]
- name: Build docs
env:
NUM_CORES: 1
ANSYS_WORKBENCH_LOGGING_FILTER_LEVEL: 0
BUILD_CHEATSHEET: true
CONTAINER_STABLE_EXIT: ${{ needs.container-stability-check.outputs.container_stable_exit }}
run: |
. /env/bin/activate
apt update
apt install -y libjbig-dev
# Add the /usr/lib/x86_64-linux-gnu/ path to the LD_LIBRARY_PATH (where libjbig-dev .so files are)
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/x86_64-linux-gnu/
if [ "${CONTAINER_STABLE_EXIT}" = "true" ]; then
xvfb-run mechanical-env make -C doc html
else
xvfb-run mechanical-env make -C doc html > output.txt 2>&1 || true
cat output.txt
if grep -q "build succeeded" output.txt; then
echo "Documentation building succeeded"
else
echo "Documentation building failed"
exit 1
fi
fi
- name: Check links
run: |
. /env/bin/activate
make -C doc linkcheck
- name: Upload HTML Documentation
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: documentation-html
path: doc/_build/html
retention-days: 7
doc-deploy-pr:
name: "Deploy PR documentation"
runs-on: ubuntu-latest
needs: [doc-build]
if: always() && (needs.doc-build.result == 'success' || needs.doc-build.result == 'skipped')
permissions:
contents: write # Required to push documentation to gh-pages branch
pull-requests: write # Needed to comment on PR with documentation link
steps:
- uses: ansys/actions/doc-deploy-pr@41f86da4c9ead510db9135e428e33df9cc6f92e1 # v10.2.3
with:
cname: ${{ env.DOCUMENTATION_CNAME }}
token: ${{ secrets.GITHUB_TOKEN }}
bot-user: ${{ secrets.PYANSYS_CI_BOT_USERNAME }}
bot-email: ${{ secrets.PYANSYS_CI_BOT_EMAIL }}
maximum-pr-doc-deployments: 10
coverage:
name: Merging coverage
needs: [remote-connect, embedding-tests, embedding-scripts-tests, launch-tests]
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
with:
python-version: ${{ env.MAIN_PYTHON_VERSION }}
- name: Install coverage
run: |
rm -rf ./env
python -m pip install -U pip
pip install coverage
pip install -e .
- name: Create common coverage directory
run: mkdir cov-dir
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: coverage-file-tests-embedding
path: cov-dir/embedding
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: coverage-file-tests-embedding-scripts
path: cov-dir/embedding-scripts
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: coverage-file-tests-remote-session-launch
path: cov-dir/launch
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: coverage-file-tests
path: cov-dir/normal
- name: Display structure of downloaded files
run: ls -Ra
- name: Move files to common location
run: |
mv cov-dir/embedding/.coverage .coverage.Embedding
mv cov-dir/embedding-scripts/.coverage .coverage.EmbeddingScripts
mv cov-dir/launch/.coverage .coverage.Launch
mv cov-dir/normal/.coverage .coverage.Normal
rm -rf cov-dir
- name: Generate .coveragerc file
run: |
cat > .coveragerc << 'EOF'
# .coveragerc to control coverage.py
[run]
relative_files = True
[paths]
source =
src/ansys/mechanical
/opt/hostedtoolcache/**/ansys/mechanical
/usr/local/lib/**/ansys/mechanical
.venv/lib/**/ansys/mechanical
/env/lib/**/ansys/mechanical
EOF
- name: Run coverage merge and show results
run: |
coverage combine --keep --debug=pathmap --rcfile=.coveragerc
coverage report
coverage html -d .coverage-combined/html
coverage xml -o .coverage-combined/xml
- name: Upload combined coverage results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
include-hidden-files: true
name: combined-coverage-results
path: .coverage-combined
retention-days: 7
- name: Upload coverage to Codecov
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
files: .coverage-combined/xml
- name: Upload coverage to Codacy
uses: codacy/codacy-coverage-reporter-action@89d6c85cfafaec52c72b6c5e8b2878d33104c699 # v1.3.0
with:
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
coverage-reports: '.coverage-combined/xml'
package:
name: Package library
needs: [smoke-tests, remote-connect, embedding-tests, embedding-scripts-tests, doc-build]
runs-on: ubuntu-latest
permissions:
attestations: write # Required to generate package attestations for security
contents: read
id-token: write # Needed for OIDC authentication when generating attestations
steps:
- name: Build library source and wheel artifacts
uses: ansys/actions/build-library@41f86da4c9ead510db9135e428e33df9cc6f92e1 # v10.2.3
with:
library-name: ${{ env.PACKAGE_NAME }}
python-version: ${{ env.MAIN_PYTHON_VERSION }}
attest-provenance: true
release:
name: Release project to GitHub
if: github.event_name == 'push' && contains(github.ref, 'refs/tags')
needs: [package, update-changelog]
runs-on: ubuntu-latest
permissions:
id-token: write # Required for OIDC authentication during release
contents: write # Needed to create GitHub releases and upload assets
steps:
- name: Release to GitHub
uses: ansys/actions/release-github@41f86da4c9ead510db9135e428e33df9cc6f92e1 # v10.2.3
with:
token: ${{ secrets.GITHUB_TOKEN }}
library-name: ${{ env.PACKAGE_NAME }}
only-code: true
release-pypi:
name: Release project to PyPI
if: github.event_name == 'push' && contains(github.ref, 'refs/tags')
needs: [package, update-changelog]
runs-on: ubuntu-latest
permissions:
id-token: write # Required for PyPI trusted publisher authentication
contents: write # Needed to download release artifacts
steps:
- name: "Download the library artifacts from build-library step"
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: ${{ env.PACKAGE_NAME }}-artifacts
path: ${{ env.PACKAGE_NAME }}-artifacts
- name: "Upload artifacts to PyPI using trusted publisher"
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
with:
repository-url: "https://upload.pypi.org/legacy/"
print-hash: true
packages-dir: ${{ env.PACKAGE_NAME }}-artifacts
skip-existing: false
upload_dev_docs:
name: Upload dev documentation
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: [package]
permissions:
contents: write # Required to push documentation to gh-pages branch
steps:
- name: Deploy the latest documentation
uses: ansys/actions/doc-deploy-dev@41f86da4c9ead510db9135e428e33df9cc6f92e1 # v10.2.3
with:
cname: ${{ env.DOCUMENTATION_CNAME }}
token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }}
bot-user: ${{ secrets.PYANSYS_CI_BOT_USERNAME }}
bot-email: ${{ secrets.PYANSYS_CI_BOT_EMAIL }}
upload_docs_release:
name: Upload release documentation
if: github.event_name == 'push' && contains(github.ref, 'refs/tags')
runs-on: ubuntu-latest
needs: [release]
permissions:
contents: write # Required to push stable documentation to gh-pages branch
steps:
- name: Deploy the stable documentation
uses: ansys/actions/doc-deploy-stable@41f86da4c9ead510db9135e428e33df9cc6f92e1 # v10.2.3
with:
cname: ${{ env.DOCUMENTATION_CNAME }}
token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }}
bot-user: ${{ secrets.PYANSYS_CI_BOT_USERNAME }}
bot-email: ${{ secrets.PYANSYS_CI_BOT_EMAIL }}
get-date:
name: Get date
runs-on: ubuntu-latest
outputs:
date: ${{ steps.date.outputs.date }}
permissions:
contents: read
steps:
- name: Get current date
id: date
run: |
echo "date=$(date --iso-8601)" >> $GITHUB_OUTPUT
notify-on-failure:
name: Notify on failure
needs: [get-date, embedding-tests, embedding-scripts-tests, launch-tests, remote-connect, doc-build]
if: github.event_name == 'schedule' && (failure() || cancelled())
runs-on: ubuntu-latest
permissions:
id-token: write # Required for OIDC authentication with notification services
contents: read
steps:
- name: Microsoft Teams Notification
uses: skitionek/notify-microsoft-teams@11e40c38c3a629ae65a985b582eca4897b01e79e # v1.0.9
with:
webhook_url: ${{ secrets.MSTEAMS_WEBHOOK }}
# Message to send to Teams as a webhook notification in JSON Payload format
raw: >-
{
"type": "message",
"attachments": [
{
"contentType": "application/vnd.microsoft.card.adaptive",
"content": {
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "TextBlock",
"text": "**PyMechanical Nightly Run Failed on ${{ needs.get-date.outputs.date }}**\n\n[View details in GitHub Actions](https://github.com/ansys/pymechanical/actions/runs/${{ github.run_id }})",
"wrap": true
}
]
}
}
]
}