1+ name : Code Coverage
2+
3+ permissions :
4+ contents : read
5+
6+ on : [pull_request, workflow_dispatch]
7+
8+ jobs :
9+ coverage :
10+ runs-on : ubuntu-latest
11+ environment : azure-prod
12+ env :
13+ DATABRICKS_SERVER_HOSTNAME : ${{ secrets.DATABRICKS_HOST }}
14+ DATABRICKS_HTTP_PATH : ${{ secrets.TEST_PECO_WAREHOUSE_HTTP_PATH }}
15+ DATABRICKS_TOKEN : ${{ secrets.DATABRICKS_TOKEN }}
16+ DATABRICKS_CATALOG : peco
17+ DATABRICKS_USER : ${{ secrets.TEST_PECO_SP_ID }}
18+ steps :
19+ # ----------------------------------------------
20+ # check-out repo and set-up python
21+ # ----------------------------------------------
22+ - name : Check out repository
23+ uses : actions/checkout@v4
24+ with :
25+ fetch-depth : 0 # Needed for coverage comparison
26+ ref : ${{ github.event.pull_request.head.ref || github.ref_name }}
27+ repository : ${{ github.event.pull_request.head.repo.full_name || github.repository }}
28+ - name : Set up python
29+ id : setup-python
30+ uses : actions/setup-python@v5
31+ with :
32+ python-version : " 3.10"
33+ # ----------------------------------------------
34+ # ----- install & configure poetry -----
35+ # ----------------------------------------------
36+ - name : Install Poetry
37+ uses : snok/install-poetry@v1
38+ with :
39+ virtualenvs-create : true
40+ virtualenvs-in-project : true
41+ installer-parallel : true
42+
43+ # ----------------------------------------------
44+ # load cached venv if cache exists
45+ # ----------------------------------------------
46+ - name : Load cached venv
47+ id : cached-poetry-dependencies
48+ uses : actions/cache@v4
49+ with :
50+ path : .venv
51+ key : venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ github.event.repository.name }}-${{ hashFiles('**/poetry.lock') }}
52+ # ----------------------------------------------
53+ # install dependencies if cache does not exist
54+ # ----------------------------------------------
55+ - name : Install dependencies
56+ if : steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
57+ run : poetry install --no-interaction --no-root
58+ # ----------------------------------------------
59+ # install your root project, if required
60+ # ----------------------------------------------
61+ - name : Install library
62+ run : poetry install --no-interaction --all-extras
63+ # ----------------------------------------------
64+ # run test suite
65+ # ----------------------------------------------
66+ - name : Run tests with coverage
67+ continue-on-error : true
68+ run : poetry run python -m pytest \
69+ tests/e2e/test_driver.py::TestPySQLCoreSuite::test_escape_single_quotes \
70+ --cov=src --cov-report=xml --cov-report=term -v
71+ # ----------------------------------------------
72+ # check for coverage override
73+ # ----------------------------------------------
74+ - name : Check for coverage override
75+ id : override
76+ run : |
77+ OVERRIDE_COMMENT=$(echo "${{ github.event.pull_request.body }}" | grep -E "SKIP_COVERAGE_CHECK\s*=" || echo "")
78+ if [ -n "$OVERRIDE_COMMENT" ]; then
79+ echo "override=true" >> $GITHUB_OUTPUT
80+ REASON=$(echo "$OVERRIDE_COMMENT" | sed -E 's/.*SKIP_COVERAGE_CHECK\s*=\s*(.+)/\1/')
81+ echo "reason=$REASON" >> $GITHUB_OUTPUT
82+ echo "Coverage override found in PR description: $REASON"
83+ else
84+ echo "override=false" >> $GITHUB_OUTPUT
85+ echo "No coverage override found"
86+ fi
87+ # ----------------------------------------------
88+ # check coverage percentage
89+ # ----------------------------------------------
90+ - name : Report coverage percentage
91+ run : |
92+ COVERAGE_FILE="coverage.xml"
93+ if [ ! -f "$COVERAGE_FILE" ]; then
94+ echo "ERROR: Coverage file not found at $COVERAGE_FILE"
95+ exit 1
96+ fi
97+
98+ # Install xmllint if not available
99+ if ! command -v xmllint &> /dev/null; then
100+ sudo apt-get update && sudo apt-get install -y libxml2-utils
101+ fi
102+
103+ COVERED=$(xmllint --xpath "string(//coverage/@lines-covered)" "$COVERAGE_FILE")
104+ TOTAL=$(xmllint --xpath "string(//coverage/@lines-valid)" "$COVERAGE_FILE")
105+
106+ # Calculate percentage using Python for precision
107+ PERCENTAGE=$(python3 -c "covered=${COVERED}; total=${TOTAL}; print(round((covered/total)*100, 2))")
108+
109+ echo "📊 Branch Coverage: ${PERCENTAGE}%"
110+ # ----------------------------------------------
111+ # coverage enforcement summary
112+ # ----------------------------------------------
113+ - name : Coverage summary
114+ run : |
115+ echo "Coverage calculation complete. No minimum enforced."
0 commit comments