-
Notifications
You must be signed in to change notification settings - Fork 85
161 lines (134 loc) · 5.54 KB
/
ci.yml
File metadata and controls
161 lines (134 loc) · 5.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
name: CI - tests and reporting
on:
# Scheduled runs twice weekly.
# These runs execute tests on both Python versions, save the pytest output to a file,
# upload the file as an artifact, and commit the 3.12 report back to main.
schedule:
- cron: "0 16 * * 1,4"
# Push runs only when package code or tests change.
# These runs execute tests normally and fail immediately on test failure.
push:
paths:
- "gget/**"
- "tests/**"
# Avoid recursively triggering on committed pytest result files.
- "!tests/pytest_results_py*.txt"
# Manual runs behave like scheduled runs:
# save output, upload artifact, and optionally commit report back to main.
workflow_dispatch:
permissions:
contents: write
jobs:
build:
name: Test on Python ${{ matrix.python }}
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
python: ["3.11", "3.12"]
steps:
- name: Checkout branch
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: Install dependencies
run: |
python -m pip install -r requirements.txt
python -m pip install -r dev-requirements.txt
# Push behavior:
# run pytest normally and let this step fail the job immediately if tests fail.
- name: Run tests on push
if: github.event_name == 'push'
run: |
pytest -ra -v --tb=long --maxfail=5 --durations=10 \
--cov=gget --cov-report=term-missing tests
# Scheduled/manual behavior:
# run pytest, save full output to a file, and capture the real pytest exit code.
#
# Important:
# - GitHub bash shells may stop on non-zero commands before later lines run.
# - We temporarily disable errexit with "set +e" so failed tests do not prevent
# us from recording PIPESTATUS[0] and writing it to GITHUB_OUTPUT.
# - continue-on-error keeps later artifact/commit steps running.
- name: Run tests and save output for scheduled/manual runs
id: pytest_saved
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
continue-on-error: true
shell: bash
run: |
set -o pipefail
OUT="tests/pytest_results_py${{ matrix.python }}.txt"
echo "Pytest results (Python ${{ matrix.python }}) - $(date -u +"%Y-%m-%dT%H:%M:%SZ")" > "$OUT"
echo "" >> "$OUT"
set +e
pytest -ra -v --tb=long --maxfail=5 --durations=10 \
--cov=gget --cov-report=term-missing tests 2>&1 | tee -a "$OUT"
code=${PIPESTATUS[0]}
set -e
echo "exit_code=$code" >> "$GITHUB_OUTPUT"
echo "pytest exit code: $code"
# Do not fail here; a later step fails the job after artifacts/report handling.
exit 0
# Upload the saved pytest report as an artifact.
# Only do this once (3.12) to avoid duplicate artifacts from the matrix.
- name: Upload pytest results artifact
if: always() && matrix.python == '3.12' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
uses: actions/upload-artifact@v4
with:
name: pytest-results-py${{ matrix.python }}
path: tests/pytest_results_py${{ matrix.python }}.txt
# Commit the saved pytest report back to the repository.
# Safety guards:
# - only on scheduled/manual runs
# - only once (3.12) to avoid matrix push races
# - commits back to the branch that the run was triggered from
# Retry logic helps if the branch moved while this job was running.
- name: Commit and push pytest results
if: >
always() &&
matrix.python == '3.12' &&
(github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
shell: bash
run: |
set -euo pipefail
BRANCH="${GITHUB_REF#refs/heads/}"
echo "Current branch: $BRANCH"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add tests/pytest_results_py*.txt
if git diff --cached --quiet; then
echo "No changes to commit."
exit 0
fi
git commit -m "CI: update pytest results ($BRANCH)"
for attempt in 1 2 3 4 5; do
echo "Push attempt $attempt..."
git pull --rebase --autostash origin "$BRANCH" || true
if git push origin "$BRANCH"; then
exit 0
fi
sleep $((attempt * 5))
done
echo "Push failed after retries."
exit 1
# After scheduled/manual runs, explicitly fail the job if pytest failed.
# This step is separate so that artifact upload and report commit can still happen
# even when tests fail.
- name: Fail job if pytest failed
if: always() && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
shell: bash
run: |
code="${{ steps.pytest_saved.outputs.exit_code }}"
echo "Captured pytest exit code: ${code:-<missing>}"
# Missing output means something went wrong before exit code capture.
if [ -z "${code:-}" ]; then
echo "pytest exit code was not captured"
exit 1
fi
if [ "$code" != "0" ]; then
exit "$code"
fi