-
Notifications
You must be signed in to change notification settings - Fork 3
144 lines (127 loc) · 4.72 KB
/
Copy pathtest-notebooks.yml
File metadata and controls
144 lines (127 loc) · 4.72 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
name: PR Notebook Tests
# Executes notebook examples changed in a PR end-to-end against Opik.
# - Notebook examples are credential-gated: they log live traces, so there is no
# secrets-free dry-run. Fork PRs (no secrets) skip execution; the compliance
# check still runs. Same-repo PRs run them live with real Opik credentials.
# - Each notebook is executed with `ipython <notebook>.ipynb`, which runs every cell
# top-to-bottom and exits non-zero on the first error.
# Any job failure blocks the PR.
on:
pull_request:
paths:
- "examples/**"
- "integrations/**"
- "scripts/**"
- "use-cases/**"
- "guides/**"
permissions:
contents: read
concurrency:
group: test-notebooks-${{ github.ref }}
cancel-in-progress: true
jobs:
detect-changes:
runs-on: ubuntu-latest
outputs:
folders: ${{ steps.detect.outputs.folders }}
has_changes: ${{ steps.detect.outputs.has_changes }}
has_secrets: ${{ steps.secrets.outputs.has_secrets }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Detect changed notebook example folders
id: detect
run: |
changed_files=$(git diff --name-only "origin/${{ github.base_ref }}...HEAD")
seen=()
folders_json="["
while IFS= read -r file; do
top=$(echo "$file" | cut -d'/' -f1)
case "$top" in
integrations)
folder=$(echo "$file" | cut -d'/' -f1,2,3)
;;
examples|scripts|use-cases|guides)
folder=$(echo "$file" | cut -d'/' -f1,2)
;;
*)
continue
;;
esac
# Notebook examples only: the folder must contain at least one .ipynb.
if [[ -z "$folder" ]] || [[ ! -d "$folder" ]]; then
continue
fi
if ! ls "$folder"/*.ipynb >/dev/null 2>&1; then
continue
fi
already_seen=false
for s in "${seen[@]}"; do
[[ "$s" == "$folder" ]] && already_seen=true && break
done
if [[ "$already_seen" == false ]]; then
seen+=("$folder")
[[ "${#seen[@]}" -gt 1 ]] && folders_json="$folders_json,"
folders_json="$folders_json\"$folder\""
fi
done <<< "$changed_files"
folders_json="$folders_json]"
if [[ "${#seen[@]}" -eq 0 ]]; then
echo "folders=[]" >> "$GITHUB_OUTPUT"
echo "has_changes=false" >> "$GITHUB_OUTPUT"
echo "No notebook example folders changed."
else
echo "folders=$folders_json" >> "$GITHUB_OUTPUT"
echo "has_changes=true" >> "$GITHUB_OUTPUT"
echo "Notebook folders to test: ${seen[*]}"
fi
- name: Check whether Opik secrets are available
id: secrets
# secrets.* is not available in job-level `if:`, so resolve it here and expose a
# boolean the run job gates on. Fork PRs get no secrets, so notebooks don't run.
env:
OPIK_API_KEY: ${{ secrets.OPIK_API_KEY }}
run: |
if [[ -n "$OPIK_API_KEY" ]]; then
echo "has_secrets=true" >> "$GITHUB_OUTPUT"
echo "Opik secrets available — notebooks will run live."
else
echo "has_secrets=false" >> "$GITHUB_OUTPUT"
echo "No Opik secrets (fork PR) — notebook execution skipped."
fi
run-notebooks:
needs: detect-changes
if: needs.detect-changes.outputs.has_changes == 'true' && needs.detect-changes.outputs.has_secrets == 'true'
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
folder: ${{ fromJson(needs.detect-changes.outputs.folders) }}
steps:
- uses: actions/checkout@v7
- uses: astral-sh/setup-uv@v7
with:
version: "latest"
enable-cache: true
python-version: "3.12"
- name: Execute notebooks (live, real Opik credentials)
uses: nick-fields/retry@v3
env:
OPIK_API_KEY: ${{ secrets.OPIK_API_KEY }}
OPIK_WORKSPACE: ${{ vars.OPIK_WORKSPACE }}
OPIK_ENVIRONMENT: ${{ vars.OPIK_ENVIRONMENT }}
OPIK_EXAMPLES_MODEL: ${{ vars.OPIK_EXAMPLES_MODEL }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
timeout_minutes: 25
max_attempts: 2
command: |
cd "${{ matrix.folder }}"
uv sync
for nb in *.ipynb; do
echo "Executing $nb ..."
uv run --with ipython --with nbformat ipython "$nb"
done