Skip to content

fix(rpmutils): add Dist filtering to transitive dependency resolution #1218

fix(rpmutils): add Dist filtering to transitive dependency resolution

fix(rpmutils): add Dist filtering to transitive dependency resolution #1218

name: Unit Tests and Coverage
on:
pull_request:
branches: [main]
push:
branches: [main] # Only on main to avoid duplicate runs with pull_request
workflow_dispatch:
inputs:
ref:
description: "Branch or SHA to test"
required: false
cov_threshold:
description: "Override coverage threshold (%)"
required: false
concurrency:
group: unit-tests-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: write # Needed to push threshold updates
jobs:
test:
name: Unit Tests & Coverage Gate
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
ref: ${{ inputs.ref || github.event.pull_request.head.sha || github.sha }}
- name: Setup Earthly
uses: earthly/actions/setup-earthly@v1
with:
version: "latest"
- name: Configure test parameters
id: config
env:
INPUT_COV_THRESHOLD: ${{ inputs.cov_threshold }}
run: |
# Read threshold from file, allow manual override
# Use fallback 65.0 if file is missing, empty, or unreadable
FILE_THRESHOLD=$(cat .coverage-threshold 2>/dev/null | tr -d '[:space:]')
FILE_THRESHOLD="${FILE_THRESHOLD:-65.0}"
COV_THRESHOLD="${INPUT_COV_THRESHOLD:-$FILE_THRESHOLD}"
# Validate it's a number, otherwise use fallback
if ! [[ "$COV_THRESHOLD" =~ ^[0-9]+\.?[0-9]*$ ]]; then
echo "::warning::Invalid threshold '$COV_THRESHOLD', using 65.0"
COV_THRESHOLD="65.0"
fi
echo "cov_threshold=${COV_THRESHOLD}" >> "$GITHUB_OUTPUT"
echo "build_id=${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT"
if [[ -n "${INPUT_COV_THRESHOLD}" ]]; then
echo "::notice::Coverage threshold: ${COV_THRESHOLD}% (from manual override)"
else
echo "::notice::Coverage threshold: ${COV_THRESHOLD}% (from .coverage-threshold file)"
fi
- name: Run tests with coverage
id: test
env:
COV_THRESHOLD: ${{ steps.config.outputs.cov_threshold }}
BUILD_ID: ${{ steps.config.outputs.build_id }}
run: |
earthly +test \
--COV_THRESHOLD="${COV_THRESHOLD}" \
--PRINT_TS="${BUILD_ID}" \
--FAIL_ON_NO_TESTS="false"
- name: Upload coverage artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-${{ github.run_id }}
path: |
coverage.out
coverage_report.txt
retention-days: 30
- name: Generate coverage summary
if: always()
run: |
{
echo "## 📊 Test Coverage Report"
echo ""
# Extract overall coverage
if [[ -f coverage_report.txt ]]; then
# Extract numeric values using simpler patterns
OVERALL=$(grep "Overall Coverage:" coverage_report.txt | sed 's/[^0-9.]*\([0-9.]\+\)%.*/\1/')%
THRESHOLD=$(grep "Threshold:" coverage_report.txt | sed 's/[^0-9.]*\([0-9.]\+\)%.*/\1/')%
# Get last word on the Status line (PASSED or FAILED)
STATUS=$(grep "Status:" coverage_report.txt | awk '{print $NF}')
# Status badge
if [[ "$STATUS" == "PASSED" ]]; then
echo "| Metric | Value | Status |"
echo "|--------|-------|--------|"
echo "| **Overall Coverage** | $OVERALL | ✅ PASSED |"
echo "| **Threshold** | $THRESHOLD | - |"
echo "| **Build** | #${{ github.run_id }} | - |"
else
echo "| Metric | Value | Status |"
echo "|--------|-------|--------|"
echo "| **Overall Coverage** | $OVERALL | ❌ FAILED |"
echo "| **Threshold** | $THRESHOLD | - |"
echo "| **Build** | #${{ github.run_id }} | - |"
fi
echo ""
# Failed tests section
if grep -q "Failed Tests:" coverage_report.txt; then
echo "### ❌ Failed Tests"
echo ""
sed -n '/\*\*Failed Tests:\*\*/,/^\*\*Note/p' coverage_report.txt | grep "•" | head -20
echo ""
fi
# Directory results table
if grep -q "| Directory" coverage_report.txt; then
echo "### 📁 Directory Results"
echo ""
sed -n '/| Directory/,/^$/p' coverage_report.txt | head -50
echo ""
fi
else
echo "⚠️ Coverage report not generated"
echo ""
echo "Check the workflow logs for details."
fi
} >> "$GITHUB_STEP_SUMMARY"
- name: Auto-update coverage threshold (ratchet)
if: success() && github.ref != 'refs/heads/main'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
EVENT_NAME: ${{ github.event_name }}
HEAD_REF: ${{ github.head_ref }}
REF_NAME: ${{ github.ref_name }}
run: |
set -x # Debug: show commands
# Determine branch name based on event type
if [[ "${EVENT_NAME}" == "pull_request" ]]; then
BRANCH="${HEAD_REF}"
else
# For workflow_dispatch or other events, use ref_name
BRANCH="${REF_NAME}"
fi
echo "Target branch: ${BRANCH}"
# Skip if on main branch (shouldn't happen due to condition, but safety check)
if [[ "$BRANCH" == "main" ]]; then
echo "Skipping ratchet on main branch"
exit 0
fi
# Get current coverage from report using simpler pattern
CURRENT=$(grep "Overall Coverage:" coverage_report.txt | sed 's/[^0-9.]*\([0-9.]\+\)%.*/\1/')
OLD_THRESHOLD=$(cat .coverage-threshold 2>/dev/null || echo "0")
# Validate CURRENT is a valid number before proceeding
if [[ -z "$CURRENT" ]] || ! [[ "$CURRENT" =~ ^[0-9]+\.?[0-9]*$ ]]; then
echo "::error::Failed to parse coverage value from report (got: '$CURRENT')"
exit 1
fi
echo "Current coverage: ${CURRENT}%"
echo "Current threshold: ${OLD_THRESHOLD}%"
# Calculate new threshold (0.5% buffer below actual coverage)
# Use printf to ensure consistent one-decimal-place formatting
NEW_THRESHOLD=$(printf '%.1f' "$(echo "$CURRENT - 0.5" | bc -l)")
echo "Proposed new threshold: ${NEW_THRESHOLD}%"
# Only update if new threshold is higher than old threshold
if (( $(echo "$NEW_THRESHOLD > $OLD_THRESHOLD" | bc -l) )); then
echo "Updating threshold: ${OLD_THRESHOLD}% -> ${NEW_THRESHOLD}%"
# Update threshold file content
echo "${NEW_THRESHOLD}" > .coverage-threshold
# Use GitHub API to create a signed commit
# Get current file SHA
FILE_SHA=$(gh api repos/${{ github.repository }}/contents/.coverage-threshold?ref=${BRANCH} --jq '.sha')
# Create commit using GitHub API (automatically signed)
gh api repos/${{ github.repository }}/contents/.coverage-threshold \
-X PUT \
-f message="chore: auto-update coverage threshold to ${NEW_THRESHOLD}% (was ${OLD_THRESHOLD}%)" \
-f content="$(echo -n "${NEW_THRESHOLD}" | base64)" \
-f branch="${BRANCH}" \
-f sha="${FILE_SHA}"
echo "::notice::Coverage threshold updated to ${NEW_THRESHOLD}% on branch ${BRANCH}"
else
echo "New threshold (${NEW_THRESHOLD}%) is not higher than current (${OLD_THRESHOLD}%), no update needed"
fi