feat(website): wire whitepaper signup to Resend email pipeline + drip sequences #320
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| jobs: | |
| library: | |
| name: Library — lint / test / build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| - uses: actions/setup-node@v6.3.0 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - run: npm ci | |
| - run: npx nx lint agent | |
| - run: npx nx test agent --coverage | |
| - run: npx nx build agent --configuration=production | |
| website: | |
| name: Website — lint / build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| - uses: actions/setup-node@v6.3.0 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - run: npm ci | |
| - run: npx nx lint website | |
| - run: npm run generate-api-docs | |
| # nx build website triggers demo:build first (dependsOn in project.json) | |
| - run: npx nx build website | |
| cockpit: | |
| name: Cockpit — build / test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| - uses: actions/setup-node@v6.3.0 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - run: npm ci | |
| - run: npx nx build cockpit --skip-nx-cache | |
| - run: npx nx test cockpit --skip-nx-cache | |
| cockpit-examples-build: | |
| name: Cockpit — build all examples | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| - uses: actions/setup-node@v6.3.0 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - run: npm ci | |
| - run: npx nx run-many -t build --projects='cockpit-*-angular' --skip-nx-cache | |
| cockpit-smoke: | |
| name: Cockpit — representative capability smoke | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| - uses: actions/setup-node@v6.3.0 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - run: npm ci | |
| - run: npx nx run-many -t smoke --projects=cockpit-deep-agents-planning-python,cockpit-deep-agents-filesystem-python,cockpit-deep-agents-subagents-python,cockpit-deep-agents-memory-python,cockpit-deep-agents-skills-python,cockpit-deep-agents-sandboxes-python,cockpit-langgraph-persistence-python,cockpit-langgraph-durable-execution-python,cockpit-langgraph-streaming-python,cockpit-langgraph-interrupts-python,cockpit-langgraph-memory-python,cockpit-langgraph-subgraphs-python,cockpit-langgraph-time-travel-python,cockpit-langgraph-deployment-runtime-python --skip-nx-cache | |
| cockpit-secret-integration: | |
| name: Cockpit — secret-gated integration | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| - uses: actions/setup-node@v6.3.0 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - run: npm ci | |
| - run: | | |
| if [ -z "${COCKPIT_SECRET_TOKEN}" ]; then | |
| echo "Skipping secret-gated integration: COCKPIT_SECRET_TOKEN is not configured" | |
| exit 0 | |
| fi | |
| npx nx run cockpit-langgraph-deployment-runtime-python:integration --skip-nx-cache | |
| env: | |
| COCKPIT_SECRET_TOKEN: ${{ secrets.COCKPIT_SECRET_TOKEN }} | |
| cockpit-deploy-smoke: | |
| name: Cockpit — deploy smoke dry-run | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| - uses: actions/setup-node@v6.3.0 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - run: npm ci | |
| - run: npx tsx apps/cockpit/scripts/deploy-smoke.ts --url https://cockpit.cacheplane.ai --dry-run | |
| chat-agent-smoke: | |
| name: Chat Agent — smoke | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| - uses: actions/setup-node@v6.3.0 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v8.0.0 | |
| with: | |
| python-version: '3.12' | |
| - run: npm ci | |
| - working-directory: examples/chat-agent | |
| run: uv sync | |
| - run: npx nx run chat-agent:smoke --skip-nx-cache | |
| cockpit-e2e: | |
| name: Cockpit — e2e | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| - uses: actions/setup-node@v6.3.0 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - run: npm ci | |
| - run: npx playwright install --with-deps chromium | |
| - run: npx nx e2e cockpit --skip-nx-cache | |
| website-e2e: | |
| name: Website — e2e | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| - uses: actions/setup-node@v6.3.0 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - run: npm ci | |
| - run: npx playwright install --with-deps chromium | |
| - run: npx nx e2e website --skip-nx-cache | |
| deploy: | |
| name: Deploy → Vercel | |
| needs: [library, website, cockpit, cockpit-examples-build, cockpit-smoke, cockpit-secret-integration, cockpit-deploy-smoke, chat-agent-smoke, cockpit-e2e, website-e2e] | |
| runs-on: ubuntu-latest | |
| # Only deploy on pushes to main, not on pull requests | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-node@v6.3.0 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| # Required GitHub secrets (Settings → Secrets and variables → Actions): | |
| # VERCEL_TOKEN — vercel.com/account/tokens | |
| # VERCEL_ORG_ID — Vercel team id | |
| # VERCEL_WEBSITE_PROJECT_ID — website project id | |
| # VERCEL_COCKPIT_PROJECT_ID — cockpit project id | |
| # VERCEL_EXAMPLES_PROJECT_ID — examples project id | |
| - run: npm ci | |
| - run: npx playwright install --with-deps chromium | |
| - name: Resolve deploy targets | |
| id: affected | |
| run: | | |
| base_sha="${{ github.event.before }}" | |
| head_sha="${{ github.sha }}" | |
| if [ -z "$base_sha" ] || [ "$base_sha" = "0000000000000000000000000000000000000000" ]; then | |
| base_sha="$(git rev-parse "$head_sha^")" | |
| fi | |
| if ! git cat-file -e "$base_sha^{commit}" 2>/dev/null; then | |
| git fetch --no-tags origin "$base_sha" | |
| fi | |
| affected_projects="$(npx nx show projects --affected --base="$base_sha" --head="$head_sha")" | |
| changed_files="$(git diff --name-only "$base_sha" "$head_sha")" | |
| website_changed=false | |
| cockpit_changed=false | |
| if printf '%s\n' "$affected_projects" | grep -Fx 'website' >/dev/null; then | |
| website_changed=true | |
| fi | |
| if printf '%s\n' "$affected_projects" | grep -Fx 'cockpit' >/dev/null; then | |
| cockpit_changed=true | |
| fi | |
| if printf '%s\n' "$changed_files" | grep -E '^(\.github/workflows/ci\.yml|vercel\.json)$' >/dev/null; then | |
| website_changed=true | |
| fi | |
| if printf '%s\n' "$changed_files" | grep -E '^(\.github/workflows/ci\.yml|vercel\.cockpit\.json)$' >/dev/null; then | |
| cockpit_changed=true | |
| fi | |
| echo "website=$website_changed" >> "$GITHUB_OUTPUT" | |
| echo "cockpit=$cockpit_changed" >> "$GITHUB_OUTPUT" | |
| - name: Prepare website Vercel project | |
| if: steps.affected.outputs.website == 'true' | |
| run: | | |
| mkdir -p .vercel | |
| cat > .vercel/project.json <<EOF | |
| {"projectId":"${{ secrets.VERCEL_WEBSITE_PROJECT_ID }}","orgId":"${{ secrets.VERCEL_ORG_ID }}","projectName":"angular"} | |
| EOF | |
| npx vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }} | |
| rm -rf .vercel/output | |
| - name: Build and deploy website to Vercel (production) | |
| if: steps.affected.outputs.website == 'true' | |
| id: deploy_website | |
| run: | | |
| npx vercel build --prod --token=${{ secrets.VERCEL_TOKEN }} | |
| url=$(npx vercel deploy --prebuilt --archive=tgz --prod --yes --token=${{ secrets.VERCEL_TOKEN }} | tail -n 1) | |
| echo "deployment_url=$url" >> "$GITHUB_OUTPUT" | |
| - name: Verify deployed website | |
| if: steps.affected.outputs.website == 'true' | |
| run: npx nx e2e website --skip-nx-cache | |
| env: | |
| BASE_URL: https://cacheplane.ai | |
| - name: Prepare cockpit Vercel project | |
| if: steps.affected.outputs.cockpit == 'true' | |
| run: | | |
| mkdir -p .vercel | |
| cat > .vercel/project.json <<EOF | |
| {"projectId":"${{ secrets.VERCEL_COCKPIT_PROJECT_ID }}","orgId":"${{ secrets.VERCEL_ORG_ID }}","projectName":"cockpit"} | |
| EOF | |
| npx vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }} | |
| rm -rf .vercel/output | |
| - name: Build and deploy cockpit to Vercel (production) | |
| if: steps.affected.outputs.cockpit == 'true' | |
| id: deploy_cockpit | |
| run: | | |
| npx vercel build --prod --local-config vercel.cockpit.json --token=${{ secrets.VERCEL_TOKEN }} | |
| url=$(npx vercel deploy --prebuilt --archive=tgz --prod --yes --token=${{ secrets.VERCEL_TOKEN }} | tail -n 1) | |
| echo "deployment_url=$url" >> "$GITHUB_OUTPUT" | |
| - name: Verify deployed cockpit | |
| if: steps.affected.outputs.cockpit == 'true' | |
| run: | | |
| npx tsx apps/cockpit/scripts/deploy-smoke.ts --url https://cockpit.cacheplane.ai --retries 20 --retry-delay-ms 5000 | |
| # ── Angular examples deploy ────────────────────────────────────────── | |
| - name: Check if examples changed | |
| id: examples_changed | |
| run: | | |
| base_sha="${{ github.event.before }}" | |
| head_sha="${{ github.sha }}" | |
| if [ -z "$base_sha" ] || [ "$base_sha" = "0000000000000000000000000000000000000000" ]; then | |
| base_sha="$(git rev-parse "$head_sha^")" | |
| fi | |
| changed_files="$(git diff --name-only "$base_sha" "$head_sha")" | |
| examples_changed=false | |
| if printf '%s\n' "$changed_files" | grep -E '^cockpit/.*/angular/' >/dev/null; then | |
| examples_changed=true | |
| fi | |
| if printf '%s\n' "$changed_files" | grep -E '^(vercel\.examples\.json|scripts/assemble-examples\.ts)$' >/dev/null; then | |
| examples_changed=true | |
| fi | |
| if printf '%s\n' "$changed_files" | grep -E '^libs/(angular|chat|render)/' >/dev/null; then | |
| examples_changed=true | |
| fi | |
| echo "changed=$examples_changed" >> "$GITHUB_OUTPUT" | |
| - name: Build and assemble Angular examples | |
| if: steps.examples_changed.outputs.changed == 'true' | |
| run: npx tsx scripts/assemble-examples.ts | |
| - name: Deploy Angular examples to Vercel (production) | |
| if: steps.examples_changed.outputs.changed == 'true' | |
| working-directory: deploy/examples | |
| run: | | |
| mkdir -p .vercel | |
| cat > .vercel/project.json <<EOF | |
| {"projectId":"${{ secrets.VERCEL_EXAMPLES_PROJECT_ID }}","orgId":"${{ secrets.VERCEL_ORG_ID }}","projectName":"cockpit-examples"} | |
| EOF | |
| npx vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }} | |
| npx vercel deploy --prebuilt --prod --yes --token=${{ secrets.VERCEL_TOKEN }} | |
| production-smoke: | |
| name: Production smoke | |
| needs: [deploy] | |
| runs-on: ubuntu-latest | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| steps: | |
| - uses: actions/checkout@v6.0.2 | |
| - uses: actions/setup-node@v6.3.0 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - run: npm ci | |
| - run: npx playwright install --with-deps chromium | |
| - name: Verify LangGraph backends | |
| run: npx tsx scripts/verify-langgraph-deployments.ts | |
| - name: Run production smoke tests | |
| run: npx playwright test apps/cockpit/e2e/production-smoke.spec.ts --reporter=list | |
| env: | |
| BASE_URL: https://cockpit.cacheplane.ai | |
| EXAMPLES_URL: https://examples.cacheplane.ai | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} |