better comments #64
This file contains hidden or 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
# This file is a GitHub Actions workflow configuration file that runs Pytest on pushes and pull requests to the main and dev branches. It sets up a matrix of Python versions to test against, checks out the code, installs dependencies, and runs the tests using Pytest. | |
name: pytest | |
on: | |
push: | |
branches: | |
- main | |
- dev # for now, suppress run on dev branch | |
pull_request: | |
branches: | |
- main | |
- dev # for now, suppress run on dev branch | |
jobs: | |
test: | |
# runs-on: ubuntu-latest | |
strategy: | |
matrix: | |
# os: [macos-latest, ubuntu-latest, windows-latest] # Specify the OS versions to test against | |
os: [macos-latest] # Specify the OS versions to test against | |
# python-version: ["3.9", "3.10", "3.11"] # Specify the Python versions to test against | |
python-version: ["3.11"] # Specify the Python versions to test against | |
runs-on: ${{ matrix.os }} # Use the OS from the matrix | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
- name: Set up Python ${{ matrix.python-version }} | |
uses: actions/setup-python@v3 | |
with: | |
python-version: ${{ matrix.python-version }} # Use the version from the matrix | |
- name: Install dependencies | |
run: | | |
python -m pip install --upgrade pip | |
pip install .[dev] | |
- name: Run tests with coverage | |
# Create a timestamp for the output file, and | |
# Add variables to the GitHub environment | |
# For pytest on CD/CD, us --cov=rattlesnake (instead of --cov=src/rattlesnake) | |
# because pytest gets its coverage data from the site-packages directory | |
run: | | |
TIMESTAMP=$(date +"%Y%m%d_%H%M%S_%Z") | |
pytest -v --cov=rattlesnake --cov-report=html --cov-report=xml --cov-report=term-missing | |
echo "TIMESTAMP=$TIMESTAMP" >> $GITHUB_ENV | |
- name: Confirm new environment variables | |
run: | | |
echo "TIMESTAMP=${{ env.TIMESTAMP }}" | |
# Read the pylint output and create a custom HTML report, to be saved to | |
# https://sandialabs.github.io/rattlesnake-vibration-controller/reports/coverage | |
- name: Create custom Pytest Report in HTML format (refined version) | |
run: | | |
python src/rattlesnake/cicd/report_pytest.py \ | |
--input_file coverage.xml \ | |
--output_file pytest_report.html \ | |
--timestamp ${{ env.TIMESTAMP }} \ | |
--run_id ${{ github.run_id }} \ | |
--ref_name ${{ github.ref_name }} \ | |
--github_sha ${{ github.sha }} \ | |
--github_repo ${{ github.repository }} | |
- name: Upload Pytest report artifact | |
if: github.ref == 'refs/heads/dev' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: pytest-report | |
path: pytest_report.html | |
- name: Upload htmlcov artifact | |
if: github.ref == 'refs/heads/dev' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: htmlcov-report | |
path: htmlcov/ | |
- name: Upload coverage to artifact (Ubuntu + Python 3.9 only) | |
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.9' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: coverage-report | |
path: coverage.xml | |
# retention-days: 7 | |
# --------------------------------------------------------------- | |
# Separate job for badge generation (only runs after test passes) | |
# --------------------------------------------------------------- | |
coverage-badge: | |
needs: test # Only run if test passes | |
runs-on: ubuntu-latest | |
# if: github.ref == 'refs/heads/main' # Only create badge on main branch | |
if: github.ref == 'refs/heads/dev' # Only create badge on dev branch, update to main branch later | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
- name: Set up Python 3.11 | |
uses: actions/setup-python@v3 | |
with: | |
python-version: "3.11" # Use a specific Python version for badge generation | |
- name: Install dependencies | |
run: | | |
python -m pip install --upgrade pip | |
pip install .[dev] | |
# pip install pytest-cov coverage-badge # already included in dev dependencies | |
- name: Download report artifacts | |
if: github.ref == 'refs/heads/dev' | |
uses: actions/download-artifact@v4 | |
with: | |
name: pytest-report | |
- name: Download htmlcov artifact | |
if: github.ref == 'refs/heads/dev' | |
uses: actions/download-artifact@v4 | |
with: | |
name: htmlcov-report | |
path: htmlcov | |
- name: Assemble pages directory | |
if: github.ref == 'refs/heads/dev' | |
run: | | |
# Create the directory structure | |
mkdir -p pages/reports/coverage | |
# Move the downloaded report files into place | |
mv pytest_report.html pages/reports/coverage/index.html | |
mv htmlcov pages/reports/coverage/ | |
# Create the root index page | |
cat > pages/index.html << 'EOF' | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Rattlesnake Vibration Controller - Reports</title> | |
<style> | |
body { font-family: sans-serif; margin: 40px; background-color: #f6f8fa; } | |
.container { max-width: 800px; margin: 0 auto; background-color: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } | |
h1 { color: #333; } | |
a { color: #0366d6; text-decoration: none; } | |
a:hover { text-decoration: underline; } | |
ul { list-style-type: none; padding: 0; } | |
li { background-color: #f1f1f1; margin: 10px 0; padding: 15px; border-radius: 4px; } | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<h1>Rattlesnake Vibration Controller - Reports</h1> | |
<p>This page provides links to the latest reports generated by the CI/CD pipeline.</p> | |
<ul> | |
<li><a href="reports/coverage/index.html">View Pytest Coverage Report</a></li> | |
<li><a href="reports/pylint/index.html">View Pylint Report</a></li> | |
</ul> | |
</div> | |
</body> | |
</html> | |
EOF | |
- name: Generate coverage report | |
run: pytest --cov=rattlesnake --cov-report=xml | |
- name: Calculate coverage and color | |
run: | | |
python3 -c ''' | |
import xml.etree.ElementTree as ET | |
import os | |
try: | |
tree = ET.parse("coverage.xml") | |
root = tree.getroot() | |
coverage = float(root.attrib["line-rate"]) * 100 | |
except (FileNotFoundError, KeyError, ET.ParseError): | |
coverage = 0.0 | |
print(f"Coverage: {coverage:.1f}%") | |
if coverage >= 90: | |
color = "brightgreen" | |
elif coverage >= 80: | |
color = "green" | |
elif coverage >= 70: | |
color = "yellow" | |
elif coverage >= 60: | |
color = "orange" | |
else: | |
color = "red" | |
with open(os.environ["GITHUB_ENV"], "a") as f: | |
f.write(f"COVERAGE={coverage:.1f}\n") | |
f.write(f"BADGE_COLOR={color}\n") | |
''' | |
- name: Confirm new environment variables | |
run: | | |
echo "COVERAGE=${{ env.COVERAGE}}" | |
echo "BADGE_COLOR=${{ env.BADGE_COLOR }}" | |
- name: Generate coverage badge and metadata | |
run: | | |
# Create badges directory if it doesn't exist | |
mkdir -p badges | |
# Create the badge URL that links to the latest workflow run | |
REPO_URL="${{ github.server_url }}/${{ github.repository }}" | |
WORKFLOW_URL="${REPO_URL}/actions/workflows/pytest.yml" | |
# Download badge using shields.io | |
curl -o badges/coverage.svg "https://img.shields.io/badge/coverage-${{ env.COVERAGE }}%25-${{ env.BADGE_COLOR }}.svg" | |
# Create a JSON file with badge metadata including GitHub Pages link | |
cat > badges/coverage-info.json << EOF | |
{ | |
"coverage": "${{ env.COVERAGE }}", | |
"color": "${{ env.BADGE_COLOR }}", | |
"pages_url": "https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/reports/coverage/", | |
"workflow_url": "${WORKFLOW_URL}", | |
"run_id": "${{ github.run_id }}", | |
"artifact_url": "${REPO_URL}/actions/runs/${{ github.run_id }}", | |
"timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" | |
} | |
EOF | |
- name: Deploy to GitHub Pages | |
if: github.ref == 'refs/heads/dev' | |
uses: peaceiris/actions-gh-pages@v3 | |
with: | |
github_token: ${{ secrets.GITHUB_TOKEN }} | |
publish_dir: ./pages | |
publish_branch: gh-pages | |
keep_files: true | |
commit_message: 'Deploy coverage report for ${{ github.sha }}' | |
- name: Commit badge to main repository (dev branch for now) | |
# if: github.ref == 'refs/heads/main' # Only create badge on main branch | |
if: github.ref == 'refs/heads/dev' # Only create badge on dev branch, update to main branch later | |
run: | | |
# git fetch | |
git pull # avoid race condition with pylint.yml job | |
git config --local user.email "[email protected]" | |
git config --local user.name "GitHub Action" | |
git add badges/coverage.svg badges/coverage-info.json | |
git diff --staged --quiet || git commit -m "Update coverage badge [skip ci]" | |
git push | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- name: Upload HTML coverage report as artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: coverage-html-report-${{ github.run_id }} | |
path: htmlcov/ | |
retention-days: 7 | |
- name: Upload enhanced coverage report as artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: coverage-enhanced-report-${{ github.run_id }} | |
path: coverage_enhanced_report.html | |
retention-days: 7 |