Skip to content

Update documentation #8

Update documentation

Update documentation #8

Workflow file for this run

# SPDX-License-Identifier: Apache-2.0
name: TestSuite
env:
LATEST_PYTHON_VERSION: '3.13'
on:
push:
branches: [ develop, main ]
pull_request:
branches: [ develop, main ]
workflow_dispatch:
jobs:
test-chiltepin-amd64:
runs-on: ubuntu2204-16c-64g-600ssd
timeout-minutes: 360
strategy:
fail-fast: false
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13']
permissions:
packages: write
contents: read
pull-requests: write
steps:
-
name: Checkout repository
uses: actions/checkout@v4
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
logout: false
-
name: Clean up any existing containers from previous runs
run: |
# Stop and remove any containers from previous runs
cd docker
docker compose -f docker-compose.yml down --remove-orphans --volumes || true
-
name: Prune pre-loaded GHA docker images
run: |
docker images
docker image prune -a -f
docker images
-
name: Start Slurm cluster containers
run: |
cd docker
export DOCKER_CLIENT_TIMEOUT=600
export COMPOSE_HTTP_TIMEOUT=600
docker compose version
docker compose -f docker-compose.yml config
docker images
docker ps -a
docker compose -f docker-compose.yml up -d
-
name: Install Python ${{ matrix.python-version }} on all nodes
run: |
# Install on frontend
docker exec frontend bash -c "sudo apt-get update && sudo apt-get install -y software-properties-common"
docker exec frontend bash -c "sudo add-apt-repository -y ppa:deadsnakes/ppa"
docker exec frontend bash -c "sudo apt-get update && sudo apt-get install -y python${{ matrix.python-version }} python${{ matrix.python-version }}-venv python${{ matrix.python-version }}-dev"
# Install on all compute nodes
for node in node1 node2 node3 node4 node5; do
docker exec $node bash -c "sudo apt-get update && sudo apt-get install -y software-properties-common"
docker exec $node bash -c "sudo add-apt-repository -y ppa:deadsnakes/ppa"
docker exec $node bash -c "sudo apt-get update && sudo apt-get install -y python${{ matrix.python-version }} python${{ matrix.python-version }}-venv python${{ matrix.python-version }}-dev"
done
-
name: Copy test files to work directory
run: |
docker exec frontend bash -l -c "mkdir -p work; cd work ; cp -r ../chiltepin/* ."
-
name: Install chiltepin package
run: |
docker exec frontend bash -l -c "cd work ; module use /opt/spack-stack/envs/unified-env/install/modulefiles/Core ; module load stack-gcc; module load stack-openmpi ; python${{ matrix.python-version }} -m venv .venv-py${{ matrix.python-version }}"
docker exec frontend bash -l -c "cd work ; source .venv-py${{ matrix.python-version }}/bin/activate ; pip install -e .[test]"
-
name: Run test suite with coverage
id: pytest
env:
GLOBUS_COMPUTE_CLIENT_ID: ${{ secrets.GC_CLIENT_ID }}
GLOBUS_COMPUTE_CLIENT_SECRET: ${{ secrets.GC_CLIENT_SECRET }}
run: |
docker exec -e GLOBUS_COMPUTE_CLIENT_ID="$GLOBUS_COMPUTE_CLIENT_ID" -e GLOBUS_COMPUTE_CLIENT_SECRET="$GLOBUS_COMPUTE_CLIENT_SECRET" frontend bash -l -c "cd work; source .venv-py${{ matrix.python-version }}/bin/activate; pytest -s -v --assert=plain --cov=src/chiltepin --cov-report=term-missing --cov-report=markdown:coverage.md --cov-report=xml --cov-report=html --cov-fail-under=0 --config=tests/configs/docker.yaml"
-
name: Copy coverage reports from container
if: always()
run: |
docker cp frontend:/home/admin/work/coverage.md ./coverage.md || true
docker cp frontend:/home/admin/work/coverage.xml ./coverage.xml || true
docker cp frontend:/home/admin/work/htmlcov ./htmlcov || true
-
name: Upload coverage reports
id: upload-coverage
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-report-py${{ matrix.python-version }}
path: |
coverage.md
coverage.xml
htmlcov/
retention-days: 30
-
name: Debug session
if: failure()
uses: mxschmitt/action-tmate@v3
timeout-minutes: 60
with:
limit-access-to-actor: true
-
name: Shut down Slurm cluster containers
if: always()
run: |
cd docker
export DOCKER_CLIENT_TIMEOUT=600
export COMPOSE_HTTP_TIMEOUT=600
docker compose -f docker-compose.yml down --remove-orphans --volumes
test-chiltepin-arm64:
runs-on: LinuxARM64-16core-64G-600Gb
timeout-minutes: 360
permissions:
packages: write
contents: read
pull-requests: write
steps:
-
# ARM runners do not have Docker installed
name: Install Docker
run: |
# Uninstall incompatible packages
for pkg in docker.io containerd runc; do sudo apt-get remove $pkg; done
# Add Docker's official GPG key:
sudo apt-get update -y
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update -y
# Install docker packages
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Allow runner use to run docker without sudo
sudo usermod -aG docker $USER
sudo apt-get install acl
sudo setfacl --modify user:$USER:rw /var/run/docker.sock
-
name: Test Docker Installation
run: docker run hello-world
-
name: Checkout repository
uses: actions/checkout@v4
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
logout: false
-
name: Clean up any existing containers from previous runs
run: |
# Stop and remove any containers from previous runs
cd docker
docker compose -f docker-compose.yml down --remove-orphans --volumes || true
-
name: Prune pre-loaded GHA docker images
run: |
docker images
docker image prune -a -f
docker images
-
name: Start Slurm cluster containers
run: |
cd docker
export DOCKER_CLIENT_TIMEOUT=600
export COMPOSE_HTTP_TIMEOUT=600
docker compose version
docker compose -f docker-compose.yml config
docker images
docker ps -a
docker compose -f docker-compose.yml up -d
-
name: Install Python ${{ env.LATEST_PYTHON_VERSION }} on all nodes
run: |
# Install on frontend
docker exec frontend bash -c "sudo apt-get update && sudo apt-get install -y software-properties-common"
docker exec frontend bash -c "sudo add-apt-repository -y ppa:deadsnakes/ppa"
docker exec frontend bash -c "sudo apt-get update && sudo apt-get install -y python${{ env.LATEST_PYTHON_VERSION }} python${{ env.LATEST_PYTHON_VERSION }}-venv python${{ env.LATEST_PYTHON_VERSION }}-dev"
# Install on all compute nodes
for node in node1 node2 node3 node4 node5; do
docker exec $node bash -c "sudo apt-get update && sudo apt-get install -y software-properties-common"
docker exec $node bash -c "sudo add-apt-repository -y ppa:deadsnakes/ppa"
docker exec $node bash -c "sudo apt-get update && sudo apt-get install -y python${{ env.LATEST_PYTHON_VERSION }} python${{ env.LATEST_PYTHON_VERSION }}-venv python${{ env.LATEST_PYTHON_VERSION }}-dev"
done
-
name: Copy test files to work directory
run: |
docker exec frontend bash -l -c "mkdir -p work; cd work ; cp -r ../chiltepin/* ."
-
name: Install chiltepin package
run: |
docker exec frontend bash -l -c "cd work ; module use /opt/spack-stack/envs/unified-env/install/modulefiles/Core ; module load stack-gcc; module load stack-openmpi ; python${{ env.LATEST_PYTHON_VERSION }} -m venv .venv-py${{ env.LATEST_PYTHON_VERSION }}"
docker exec frontend bash -l -c "cd work ; source .venv-py${{ env.LATEST_PYTHON_VERSION }}/bin/activate ; pip install -e .[test]"
-
name: Run test suite
env:
GLOBUS_COMPUTE_CLIENT_ID: ${{ secrets.GC_CLIENT_ID }}
GLOBUS_COMPUTE_CLIENT_SECRET: ${{ secrets.GC_CLIENT_SECRET }}
run: |
docker exec -e GLOBUS_COMPUTE_CLIENT_ID="$GLOBUS_COMPUTE_CLIENT_ID" -e GLOBUS_COMPUTE_CLIENT_SECRET="$GLOBUS_COMPUTE_CLIENT_SECRET" frontend bash -l -c "cd work; source .venv-py${{ env.LATEST_PYTHON_VERSION }}/bin/activate; pytest -s -v --assert=plain --config=tests/configs/docker.yaml"
-
name: Debug session
if: ${{ failure() }}
uses: mxschmitt/action-tmate@v3
timeout-minutes: 60
with:
limit-access-to-actor: true
-
name: Shut down Slurm cluster containers
if: always()
run: |
cd docker
export DOCKER_CLIENT_TIMEOUT=600
export COMPOSE_HTTP_TIMEOUT=600
docker compose -f docker-compose.yml down --remove-orphans --volumes
coverage-check:
name: Coverage Check
runs-on: ubuntu-latest
needs: [test-chiltepin-amd64]
if: always()
permissions:
pull-requests: write
contents: read
steps:
-
name: Checkout repository
uses: actions/checkout@v4
-
name: Download coverage report
uses: actions/download-artifact@v4
with:
name: coverage-report-py${{ env.LATEST_PYTHON_VERSION }}
path: ./coverage
continue-on-error: true
-
name: Check coverage threshold
id: coverage
run: |
# Extract threshold from pyproject.toml
THRESHOLD=$(grep -A 5 '\[tool.coverage.report\]' pyproject.toml | grep 'fail_under' | grep -oP '\d+(\.\d+)?' | head -1)
THRESHOLD=${THRESHOLD:-80.0} # Default to 80.0 if not found
# Extract coverage percentage from XML
if [ -f ./coverage/coverage.xml ]; then
line_rate=$(grep -oP 'line-rate="\K[0-9.]+' ./coverage/coverage.xml | head -1)
coverage=$(echo "$line_rate * 100" | bc -l | xargs printf "%.2f")
echo "Coverage: ${coverage}% | Threshold: ${THRESHOLD}%"
# Determine pass/fail
if (( $(echo "$coverage >= $THRESHOLD" | bc -l) )); then
STATUS="✅ **PASS**"
RESULT="success"
echo "✅ Coverage ${coverage}% meets threshold ${THRESHOLD}%"
else
STATUS="❌ **FAIL**"
RESULT="failure"
echo "❌ Coverage ${coverage}% is below threshold ${THRESHOLD}%"
fi
else
STATUS="⚠️ **UNKNOWN**"
coverage="N/A"
RESULT="failure"
echo "⚠️ Coverage report not found"
fi
# Save outputs
echo "coverage=$coverage" >> $GITHUB_OUTPUT
echo "threshold=$THRESHOLD" >> $GITHUB_OUTPUT
echo "status=$STATUS" >> $GITHUB_OUTPUT
echo "result=$RESULT" >> $GITHUB_OUTPUT
# Build PR comment
echo "COVERAGE_REPORT<<EOF" >> $GITHUB_OUTPUT
echo "## 📊 Test Coverage Report" >> $GITHUB_OUTPUT
echo "" >> $GITHUB_OUTPUT
echo "**Status:** $STATUS (Coverage: ${coverage}% | Threshold: ${THRESHOLD}%)" >> $GITHUB_OUTPUT
echo "" >> $GITHUB_OUTPUT
if [ -f ./coverage/coverage.md ]; then
cat ./coverage/coverage.md >> $GITHUB_OUTPUT
else
echo "❌ Coverage report not available" >> $GITHUB_OUTPUT
fi
echo "" >> $GITHUB_OUTPUT
echo "---" >> $GITHUB_OUTPUT
echo "*Coverage report generated by pytest-cov. Full HTML report available in workflow artifacts.*" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
-
name: Post coverage comment to PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: process.env.COVERAGE_REPORT
});
env:
COVERAGE_REPORT: ${{ steps.coverage.outputs.COVERAGE_REPORT }}
-
name: Fail if coverage below threshold
if: steps.coverage.outputs.result == 'failure'
run: |
echo "❌ Coverage check failed: ${{ steps.coverage.outputs.coverage }}% < ${{ steps.coverage.outputs.threshold }}%"
exit 1