Skip to content

Commit 82d42c3

Browse files
NinjaRocksclaude
andcommitted
Add CI workflow per Verification-2 plan
Implements the build-samples GitHub Actions workflow from user-action-plan.md section 4: matrix build per chapter, weekly cron, optional manual smoke-tests-live job gated on workflow_dispatch. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent a9490dc commit 82d42c3

1 file changed

Lines changed: 136 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
name: build-samples
2+
3+
on:
4+
push:
5+
branches: [master]
6+
pull_request:
7+
schedule:
8+
# 04:00 UTC every Monday -- catches NuGet package drift between releases.
9+
- cron: "0 4 * * 1"
10+
workflow_dispatch:
11+
12+
permissions:
13+
contents: read
14+
15+
env:
16+
DOTNET_NOLOGO: true
17+
DOTNET_CLI_TELEMETRY_OPTOUT: true
18+
19+
jobs:
20+
build:
21+
name: Build ${{ matrix.chapter }}
22+
runs-on: ubuntu-latest
23+
strategy:
24+
fail-fast: false
25+
matrix:
26+
chapter:
27+
- ch01-foundations
28+
- ch02-extensions-ai
29+
- ch03-rag
30+
- ch04-agent-framework
31+
- ch05-mcp
32+
- ch06-production
33+
steps:
34+
- name: Checkout
35+
uses: actions/checkout@v4
36+
37+
- name: Setup .NET
38+
uses: actions/setup-dotnet@v4
39+
with:
40+
dotnet-version: "9.0.x"
41+
42+
- name: Discover projects
43+
id: discover
44+
shell: bash
45+
run: |
46+
mapfile -t projects < <(find samples/${{ matrix.chapter }} -name '*.csproj' | sort)
47+
if [ "${#projects[@]}" -eq 0 ]; then
48+
echo "::warning::No .csproj files under samples/${{ matrix.chapter }}"
49+
fi
50+
printf ' - %s\n' "${projects[@]}"
51+
{
52+
echo "projects<<EOF"
53+
printf '%s\n' "${projects[@]}"
54+
echo "EOF"
55+
} >> "$GITHUB_OUTPUT"
56+
57+
- name: Restore
58+
shell: bash
59+
run: |
60+
while IFS= read -r project; do
61+
[ -z "$project" ] && continue
62+
echo "::group::restore $project"
63+
dotnet restore "$project"
64+
echo "::endgroup::"
65+
done <<< "${{ steps.discover.outputs.projects }}"
66+
67+
- name: Build
68+
shell: bash
69+
run: |
70+
while IFS= read -r project; do
71+
[ -z "$project" ] && continue
72+
echo "::group::build $project"
73+
dotnet build "$project" --no-restore -c Release
74+
echo "::endgroup::"
75+
done <<< "${{ steps.discover.outputs.projects }}"
76+
77+
- name: Test (only test projects)
78+
shell: bash
79+
run: |
80+
while IFS= read -r project; do
81+
[ -z "$project" ] && continue
82+
if grep -q "Microsoft.NET.Test.Sdk" "$project"; then
83+
echo "::group::test $project"
84+
dotnet test "$project" --no-build -c Release \
85+
--logger "trx;LogFileName=test-results.trx" \
86+
--results-directory "${{ runner.temp }}/test-results/${{ matrix.chapter }}"
87+
echo "::endgroup::"
88+
fi
89+
done <<< "${{ steps.discover.outputs.projects }}"
90+
91+
- name: Upload test results
92+
if: always()
93+
uses: actions/upload-artifact@v4
94+
with:
95+
name: test-results-${{ matrix.chapter }}
96+
path: ${{ runner.temp }}/test-results/${{ matrix.chapter }}
97+
if-no-files-found: ignore
98+
retention-days: 14
99+
100+
# Optional manual smoke tests against live providers.
101+
# Triggers only on workflow_dispatch so live API tokens are never spent on
102+
# ordinary push/PR builds. Configure the secrets in the repo Settings before
103+
# creating tests/Smoke.
104+
smoke-tests-live:
105+
name: Smoke tests (live providers)
106+
runs-on: ubuntu-latest
107+
if: ${{ github.event_name == 'workflow_dispatch' }}
108+
needs: build
109+
env:
110+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
111+
AZURE_OPENAI_ENDPOINT: ${{ secrets.AZURE_OPENAI_ENDPOINT }}
112+
AZURE_OPENAI_KEY: ${{ secrets.AZURE_OPENAI_KEY }}
113+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
114+
steps:
115+
- uses: actions/checkout@v4
116+
- uses: actions/setup-dotnet@v4
117+
with:
118+
dotnet-version: "9.0.x"
119+
- name: Run smoke tests (if present)
120+
shell: bash
121+
run: |
122+
if [ -d tests/Smoke ]; then
123+
dotnet test tests/Smoke -c Release \
124+
--logger "trx;LogFileName=smoke.trx" \
125+
--results-directory "${{ runner.temp }}/smoke-results"
126+
else
127+
echo "tests/Smoke does not exist yet -- nothing to run."
128+
fi
129+
- name: Upload smoke results
130+
if: always()
131+
uses: actions/upload-artifact@v4
132+
with:
133+
name: smoke-results
134+
path: ${{ runner.temp }}/smoke-results
135+
if-no-files-found: ignore
136+
retention-days: 14

0 commit comments

Comments
 (0)