Files
docs/.github/workflows/test-code-samples.yml
John Kennedy 0e7fba2d52 ci: harden docs workflow inputs (#4970)
## Summary
- Pin `ctriolo/action-create-linear-issue` to the immutable commit SHA
for `v0.7` so the `LINEAR_API_KEY` is no longer exposed to a mutable
third-party action tag.
- Pass GitHub PR base refs/SHAs and workflow output values through
environment variables before shell use.
- Apply the same base-ref hardening to adjacent docs diff-check
workflows to avoid the same pattern recurring.

## Corridor findings
- Fixes
https://app.corridor.dev/projects/86f45f70-3153-46d0-b0f6-5ec9dba1ace1/findings/eb002ea1-903e-4a2b-94a5-5ebc4b60bab2
- Fixes
https://app.corridor.dev/projects/86f45f70-3153-46d0-b0f6-5ec9dba1ace1/findings/1bbe3c85-75f4-4ece-8c96-cd857c5be291

## Validation
- `ruby -e 'require \"yaml\";
Dir[\"/tmp/docs/.github/workflows/*.yml\"].each { |p| YAML.load_file(p)
}; puts \"parsed workflows\"'`
- `git diff --check`

Co-authored-by: langsmith-fleet[bot] <langsmith-fleet[bot]@users.noreply.github.com>
2026-07-20 09:44:15 -07:00

158 lines
5.1 KiB
YAML

---
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<<FILESEND"; echo "$FILES"; echo "FILESEND"; } >> "$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