--- name: Test Code Samples permissions: contents: read on: pull_request: paths: - "src/code-samples/**" - ".github/workflows/test-code-samples.yml" workflow_dispatch: schedule: # Run every Sunday at 00:00 UTC - cron: "0 0 * * 0" concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: test-code-samples: # GitHub does not expose repository secrets to workflows triggered from fork PRs. # These tests require provider API keys for some samples, so skip on forks. if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false) runs-on: ubuntu-latest # Scheduled and manual runs test all samples; PR runs may touch many files in large refactors. timeout-minutes: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && 90 || 60 }} services: postgres: image: pgvector/pgvector:pg17 env: POSTGRES_PASSWORD: postgres POSTGRES_DB: postgres ports: - 5432:5432 options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - name: Checkout uses: actions/checkout@v6 with: fetch-depth: 0 - name: Get modified code sample paths id: files env: EVENT_NAME: ${{ github.event_name }} PR_BASE_REF: ${{ github.event.pull_request.base.ref }} BEFORE_SHA: ${{ github.event.before }} run: | if [[ "$EVENT_NAME" == "schedule" || "$EVENT_NAME" == "workflow_dispatch" ]]; then echo "run_all=true" >> "$GITHUB_OUTPUT" echo "Full run: testing all code samples" else echo "run_all=false" >> "$GITHUB_OUTPUT" if [[ "$EVENT_NAME" == "pull_request" ]]; then git fetch origin "$PR_BASE_REF" BASE=$(git merge-base HEAD "origin/$PR_BASE_REF") else BASE="$BEFORE_SHA" fi FILES=$(git diff --name-only "$BASE" HEAD -- src/code-samples/ \ | grep -E '\.(py|ts|java|kt|go|sh)$' \ | tr '\n' ' ' || true) { echo "files<> "$GITHUB_OUTPUT" if [[ -n "$FILES" ]]; then echo "Modified code samples: $FILES" else echo "No modified .py, .ts, .java, .kt, .go, or .sh files in src/code-samples/" fi fi - name: Set up Python and uv uses: ./.github/actions/uv_setup with: python-version: "3.13" - name: Install project dependencies run: uv sync - name: Install Node.js uses: actions/setup-node@v4 with: node-version: "20" - name: Set up Java (for JBang) uses: actions/setup-java@v4 with: distribution: "temurin" java-version: "21" - name: Install JBang uses: jbangdev/setup-jbang@v0.1.1 - name: Set up Go uses: actions/setup-go@v5 with: go-version-file: src/code-samples/go.mod - name: Wait for PostgreSQL run: | for i in $(seq 1 30); do if python3 -c " import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(2) try: s.connect(('127.0.0.1', 5432)) s.close() except OSError: exit(1) "; then echo "PostgreSQL is ready" exit 0 fi echo "Waiting for PostgreSQL... ($i/30)" sleep 2 done echo "PostgreSQL did not become ready" exit 1 - name: Test code samples id: test env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} ANTHROPIC_BASE_URL: ${{ secrets.ANTHROPIC_BASE_URL }} ANTHROPIC_CUSTOM_HEADERS: ${{ secrets.ANTHROPIC_CUSTOM_HEADERS }} LS_GATEWAY_KEY: ${{ secrets.LS_GATEWAY_KEY }} LANGSMITH_API_KEY: ${{ secrets.LANGSMITH_API_KEY }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} POSTGRES_URI: postgresql://postgres:postgres@127.0.0.1:5432/postgres?sslmode=disable TAVILY_API_KEY: ${{ secrets.TAVILY_API_KEY }} GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} DAYTONA_API_KEY: ${{ secrets.DAYTONA_API_KEY }} DAYTONA_API_URL: ${{ secrets.DAYTONA_API_URL }} RUN_ALL: ${{ steps.files.outputs.run_all }} MODIFIED_FILES: ${{ steps.files.outputs.files }} run: | if [[ "$RUN_ALL" == "true" ]]; then echo "Running all code samples..." make test-code-samples else FILES="$MODIFIED_FILES" FILES=$(echo "$FILES" | tr -d '\n' | xargs) if [[ -z "$FILES" ]]; then echo "No code samples to test" exit 0 fi make test-code-samples FILES="$FILES" fi