mirror of
https://github.com/CopilotKit/CopilotKit.git
synced 2026-09-14 16:26:20 +08:00
349 lines
18 KiB
YAML
349 lines
18 KiB
YAML
name: "Showcase: Build Check (PR)"
|
|
|
|
# Pre-merge Docker build check. Runs the same Depot Docker builds as the
|
|
# post-merge showcase_build.yml pipeline but with push: false, so
|
|
# Dockerfile-specific failures (missing deps that exist in the monorepo
|
|
# but not in the isolated Docker context) are caught before merge.
|
|
|
|
on:
|
|
pull_request:
|
|
paths:
|
|
- "showcase/**"
|
|
- "packages/a2ui-renderer/**"
|
|
- "packages/angular/**"
|
|
- "packages/core/**"
|
|
- "packages/shared/**"
|
|
- "packages/web-components/**"
|
|
- ".github/workflows/showcase_build.yml"
|
|
- ".github/workflows/showcase_build_check.yml"
|
|
|
|
concurrency:
|
|
group: showcase-build-check-${{ github.event.pull_request.number }}
|
|
cancel-in-progress: true
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
detect-changes:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
permissions:
|
|
contents: read
|
|
outputs:
|
|
matrix: ${{ steps.build-matrix.outputs.matrix }}
|
|
has_changes: ${{ steps.build-matrix.outputs.has_changes }}
|
|
needs_angular: ${{ steps.build-matrix.outputs.needs_angular }}
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Detect changed paths
|
|
uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3
|
|
id: filter
|
|
with:
|
|
filters: |
|
|
workflow_config:
|
|
- '.github/workflows/showcase_build.yml'
|
|
- '.github/workflows/showcase_build_check.yml'
|
|
angular:
|
|
- 'showcase/angular/**'
|
|
- 'packages/a2ui-renderer/**'
|
|
- 'packages/angular/**'
|
|
- 'packages/core/**'
|
|
- 'packages/shared/**'
|
|
- 'packages/web-components/**'
|
|
shell:
|
|
- 'showcase/shell/**'
|
|
- 'showcase/shared/**'
|
|
- 'showcase/scripts/**'
|
|
- 'showcase/integrations/*/manifest.yaml'
|
|
langgraph_python:
|
|
- 'showcase/integrations/langgraph-python/**'
|
|
mastra:
|
|
- 'showcase/integrations/mastra/**'
|
|
crewai_crews:
|
|
- 'showcase/integrations/crewai-crews/**'
|
|
crewai_conversational_flows:
|
|
- 'showcase/integrations/crewai-conversational-flows/**'
|
|
pydantic_ai:
|
|
- 'showcase/integrations/pydantic-ai/**'
|
|
google_adk:
|
|
- 'showcase/integrations/google-adk/**'
|
|
ag2:
|
|
- 'showcase/integrations/ag2/**'
|
|
agno:
|
|
- 'showcase/integrations/agno/**'
|
|
llamaindex:
|
|
- 'showcase/integrations/llamaindex/**'
|
|
langgraph_fastapi:
|
|
- 'showcase/integrations/langgraph-fastapi/**'
|
|
langgraph_typescript:
|
|
- 'showcase/integrations/langgraph-typescript/**'
|
|
langroid:
|
|
- 'showcase/integrations/langroid/**'
|
|
spring_ai:
|
|
- 'showcase/integrations/spring-ai/**'
|
|
strands:
|
|
- 'showcase/integrations/strands/**'
|
|
strands_typescript:
|
|
- 'showcase/integrations/strands-typescript/**'
|
|
ms_agent_python:
|
|
- 'showcase/integrations/ms-agent-python/**'
|
|
claude_sdk_typescript:
|
|
- 'showcase/integrations/claude-sdk-typescript/**'
|
|
ms_agent_dotnet:
|
|
- 'showcase/integrations/ms-agent-dotnet/**'
|
|
ms_agent_harness_dotnet:
|
|
- 'showcase/integrations/ms-agent-harness-dotnet/**'
|
|
claude_sdk_python:
|
|
- 'showcase/integrations/claude-sdk-python/**'
|
|
built_in_agent:
|
|
- 'showcase/integrations/built-in-agent/**'
|
|
shell_dojo:
|
|
- 'showcase/shell-dojo/**'
|
|
- 'showcase/shared/**'
|
|
- 'showcase/scripts/**'
|
|
- 'showcase/integrations/*/manifest.yaml'
|
|
shell_dashboard:
|
|
- 'showcase/shell-dashboard/**'
|
|
- 'showcase/shared/**'
|
|
- 'showcase/scripts/**'
|
|
- 'showcase/integrations/*/manifest.yaml'
|
|
shell_docs:
|
|
- 'showcase/shell-docs/**'
|
|
- 'showcase/shared/**'
|
|
- 'showcase/scripts/**'
|
|
- 'showcase/integrations/*/manifest.yaml'
|
|
- 'showcase/integrations/*/docs-links.json'
|
|
- 'showcase/integrations/*/docs/setup/**'
|
|
- 'showcase/integrations/*/src/**'
|
|
showcase_harness:
|
|
- 'showcase/harness/**'
|
|
- 'showcase/shared/**'
|
|
- 'showcase/scripts/**'
|
|
- 'showcase/integrations/*/manifest.yaml'
|
|
showcase_aimock:
|
|
- 'showcase/aimock/**'
|
|
|
|
- name: Build service matrix
|
|
id: build-matrix
|
|
env:
|
|
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
PR_HEAD_REF: ${{ github.head_ref }}
|
|
FILTER_CHANGES: ${{ steps.filter.outputs.changes }}
|
|
run: |
|
|
# Mirror of the ALL_SERVICES definition from showcase_build.yml.
|
|
# Keep in sync — the matrix here must match the production build
|
|
# workflow so that every service buildable post-merge is also
|
|
# checked pre-merge.
|
|
#
|
|
# Fields carried over: dispatch_name, filter_key, context, image,
|
|
# timeout, build_args_*, dockerfile.
|
|
# Fields omitted (not needed for build-only): railway_id, health_path.
|
|
ALL_SERVICES='[
|
|
{"dispatch_name":"shell","filter_key":"shell","context":".","image":"showcase-shell","timeout":10,"build_args_sha":"__GH_SHA__","build_args_branch":"__GH_REF_NAME__","dockerfile":"showcase/shell/Dockerfile"},
|
|
{"dispatch_name":"langgraph-python","filter_key":"langgraph_python","context":"showcase/integrations/langgraph-python","image":"showcase-langgraph-python","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"mastra","filter_key":"mastra","context":"showcase/integrations/mastra","image":"showcase-mastra","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"crewai-crews","filter_key":"crewai_crews","context":"showcase/integrations/crewai-crews","image":"showcase-crewai-crews","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"crewai-conversational-flows","filter_key":"crewai_conversational_flows","context":"showcase/integrations/crewai-conversational-flows","image":"showcase-crewai-conversational-flows","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"pydantic-ai","filter_key":"pydantic_ai","context":"showcase/integrations/pydantic-ai","image":"showcase-pydantic-ai","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"google-adk","filter_key":"google_adk","context":"showcase/integrations/google-adk","image":"showcase-google-adk","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"ag2","filter_key":"ag2","context":"showcase/integrations/ag2","image":"showcase-ag2","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"agno","filter_key":"agno","context":"showcase/integrations/agno","image":"showcase-agno","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"llamaindex","filter_key":"llamaindex","context":"showcase/integrations/llamaindex","image":"showcase-llamaindex","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"langgraph-fastapi","filter_key":"langgraph_fastapi","context":"showcase/integrations/langgraph-fastapi","image":"showcase-langgraph-fastapi","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"langgraph-typescript","filter_key":"langgraph_typescript","context":"showcase/integrations/langgraph-typescript","image":"showcase-langgraph-typescript","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"langroid","filter_key":"langroid","context":"showcase/integrations/langroid","image":"showcase-langroid","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"spring-ai","filter_key":"spring_ai","context":"showcase/integrations/spring-ai","image":"showcase-spring-ai","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"strands","filter_key":"strands","context":"showcase/integrations/strands","image":"showcase-strands","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"strands-typescript","filter_key":"strands_typescript","context":"showcase/integrations/strands-typescript","image":"showcase-strands-typescript","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"ms-agent-python","filter_key":"ms_agent_python","context":"showcase/integrations/ms-agent-python","image":"showcase-ms-agent-python","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"claude-sdk-typescript","filter_key":"claude_sdk_typescript","context":"showcase/integrations/claude-sdk-typescript","image":"showcase-claude-sdk-typescript","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"ms-agent-dotnet","filter_key":"ms_agent_dotnet","context":"showcase/integrations/ms-agent-dotnet","image":"showcase-ms-agent-dotnet","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"ms-agent-harness-dotnet","filter_key":"ms_agent_harness_dotnet","context":"showcase/integrations/ms-agent-harness-dotnet","image":"showcase-ms-agent-harness-dotnet","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"claude-sdk-python","filter_key":"claude_sdk_python","context":"showcase/integrations/claude-sdk-python","image":"showcase-claude-sdk-python","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"built-in-agent","filter_key":"built_in_agent","context":"showcase/integrations/built-in-agent","image":"showcase-built-in-agent","timeout":15,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"shell-dojo","filter_key":"shell_dojo","context":".","image":"showcase-shell-dojo","timeout":10,"build_args":"","dockerfile":"showcase/shell-dojo/Dockerfile"},
|
|
{"dispatch_name":"shell-dashboard","filter_key":"shell_dashboard","context":".","image":"showcase-shell-dashboard","timeout":10,"build_args_sha":"__GH_SHA__","build_args_branch":"__GH_REF_NAME__","dockerfile":"showcase/shell-dashboard/Dockerfile"},
|
|
{"dispatch_name":"shell-docs","filter_key":"shell_docs","context":".","image":"showcase-shell-docs","timeout":10,"build_args_sha":"__GH_SHA__","build_args_branch":"__GH_REF_NAME__","dockerfile":"showcase/shell-docs/Dockerfile"},
|
|
{"dispatch_name":"showcase-harness","filter_key":"showcase_harness","context":".","image":"showcase-harness","timeout":20,"build_args":"","dockerfile":"showcase/harness/Dockerfile"},
|
|
{"dispatch_name":"showcase-aimock","filter_key":"showcase_aimock","context":"showcase/aimock","image":"showcase-aimock","timeout":5,"build_args":"","dockerfile":"showcase/aimock/Dockerfile"}
|
|
]'
|
|
|
|
CHANGES="${FILTER_CHANGES:-[]}"
|
|
|
|
# PR event only — filter to changed services. Use jq --arg for
|
|
# untrusted PR metadata so branch names are encoded as JSON data,
|
|
# not interpolated into shell source.
|
|
MATRIX=$(echo "$ALL_SERVICES" | jq -c --argjson changes "$CHANGES" --arg sha "$PR_HEAD_SHA" --arg ref "$PR_HEAD_REF" '
|
|
[.[] |
|
|
if .build_args_sha == "__GH_SHA__" then .build_args_sha = $sha else . end |
|
|
if .build_args_branch == "__GH_REF_NAME__" then .build_args_branch = $ref else . end |
|
|
(.filter_key as $fk | select(
|
|
($changes | index("workflow_config") != null) or
|
|
($changes | index($fk) != null) or
|
|
(($changes | index("angular") != null) and (
|
|
(.context | startswith("showcase/integrations/")) or
|
|
.dispatch_name == "shell"
|
|
))
|
|
))]
|
|
')
|
|
|
|
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
|
|
echo "needs_angular=$(echo "$MATRIX" | jq -r 'any(.[]; (.context | startswith("showcase/integrations/")))')" >> $GITHUB_OUTPUT
|
|
if [ "$MATRIX" = "[]" ]; then
|
|
echo "has_changes=false" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "has_changes=true" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
build-angular:
|
|
name: Build canonical Angular browser artifact
|
|
needs: [detect-changes]
|
|
if: needs.detect-changes.outputs.has_changes == 'true'
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 30
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- name: Checkout
|
|
if: needs.detect-changes.outputs.needs_angular == 'true'
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup pnpm
|
|
if: needs.detect-changes.outputs.needs_angular == 'true'
|
|
uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
|
|
|
|
- name: Setup Node
|
|
if: needs.detect-changes.outputs.needs_angular == 'true'
|
|
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
with:
|
|
node-version: 22.x
|
|
|
|
- name: Install
|
|
if: needs.detect-changes.outputs.needs_angular == 'true'
|
|
run: pnpm install --frozen-lockfile --ignore-scripts
|
|
|
|
- name: Build
|
|
if: needs.detect-changes.outputs.needs_angular == 'true'
|
|
run: pnpm nx build @copilotkit/showcase-angular-host
|
|
|
|
- name: Upload canonical Angular browser artifact
|
|
if: needs.detect-changes.outputs.needs_angular == 'true'
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: showcase-angular-browser-${{ github.sha }}
|
|
path: showcase/angular/dist/showcase-angular/browser
|
|
if-no-files-found: error
|
|
retention-days: 1
|
|
|
|
build-check:
|
|
needs: [detect-changes, build-angular]
|
|
if: needs.detect-changes.outputs.has_changes == 'true'
|
|
runs-on: depot-ubuntu-24.04-4
|
|
timeout-minutes: ${{ fromJSON(matrix.service.timeout) }}
|
|
permissions:
|
|
id-token: write
|
|
contents: read
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
service: ${{ fromJSON(needs.detect-changes.outputs.matrix) }}
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
# Uniform `lfs: true`, matching showcase_build.yml. Every integration
|
|
# ships LFS-tracked demo assets under public/ (demo-files/*.png|*.pdf,
|
|
# demo-audio/*.wav per the repo-root .gitattributes). Without the
|
|
# fetch these check out as ~130-byte pointer stubs and get COPYed into
|
|
# the image as text, so this job would "successfully" build an image
|
|
# whose multimodal demo is broken — the exact failure showcase_build.yml
|
|
# already fixed for the deploy path. Hardcoded rather than read from
|
|
# `matrix.service.lfs` so a new integration is covered automatically,
|
|
# with no per-slot flag to forget.
|
|
lfs: true
|
|
persist-credentials: false
|
|
|
|
- name: Download canonical Angular browser artifact
|
|
if: startsWith(matrix.service.context, 'showcase/integrations/')
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
name: showcase-angular-browser-${{ github.sha }}
|
|
path: ${{ runner.temp }}/showcase-angular-browser
|
|
|
|
- name: Setup Depot
|
|
uses: depot/setup-action@91bc8495a33ebfc504ffc89e5674379ccf23c29c # v1
|
|
|
|
- name: Prepare build args
|
|
id: build-args
|
|
env:
|
|
BUILD_ARGS_SHA: ${{ matrix.service.build_args_sha }}
|
|
BUILD_ARGS_BRANCH: ${{ matrix.service.build_args_branch }}
|
|
run: |
|
|
ARGS=""
|
|
if [ -n "$BUILD_ARGS_SHA" ]; then
|
|
ARGS="COMMIT_SHA=${BUILD_ARGS_SHA}"
|
|
ARGS="${ARGS}"$'\n'"BRANCH=${BUILD_ARGS_BRANCH}"
|
|
fi
|
|
# Use delimiter to safely pass multiline value
|
|
echo "args<<BUILDARGS_EOF" >> $GITHUB_OUTPUT
|
|
echo "$ARGS" >> $GITHUB_OUTPUT
|
|
echo "BUILDARGS_EOF" >> $GITHUB_OUTPUT
|
|
|
|
- name: Copy shared modules into build context
|
|
env:
|
|
ANGULAR_BROWSER: ${{ runner.temp }}/showcase-angular-browser
|
|
run: |
|
|
set -euo pipefail
|
|
CONTEXT="${{ matrix.service.context }}"
|
|
if [ -d "showcase/shared/python" ] && [ -d "$CONTEXT" ]; then
|
|
rm -rf "$CONTEXT/shared_python"
|
|
cp -r showcase/shared/python "$CONTEXT/shared_python"
|
|
fi
|
|
if [ -d "showcase/shared/typescript/tools" ] && [ -d "$CONTEXT" ]; then
|
|
rm -rf "$CONTEXT/shared_typescript"
|
|
mkdir -p "$CONTEXT/shared_typescript"
|
|
cp -r showcase/shared/typescript/tools "$CONTEXT/shared_typescript/tools"
|
|
fi
|
|
|
|
# Dereference tools/, shared-tools/, data/, and _shared/ symlinks for the
|
|
# Docker context. Integration directories use symlinks pointing
|
|
# outside the build context (tools -> ../../shared/python/tools,
|
|
# _shared -> ../_shared for the CVDIAG bootstrap modules). Docker
|
|
# build contexts cannot follow a symlink whose target escapes the
|
|
# context root — buildkit fails the checksum with "too many
|
|
# symlinks: /_shared" — so each symlink is replaced with a real
|
|
# copy of its target. Mirrors stage_shared() in
|
|
# showcase/scripts/cli/_common.sh (the local bin/showcase path).
|
|
for link_name in tools shared-tools data _shared; do
|
|
link_path="$CONTEXT/$link_name"
|
|
if [ -L "$link_path" ]; then
|
|
target="$(readlink -f "$link_path")"
|
|
if [ -d "$target" ]; then
|
|
rm "$link_path"
|
|
cp -r "$target" "$link_path"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
if [ -L "$CONTEXT/public/angular" ]; then
|
|
source showcase/scripts/cli/_common.sh
|
|
stage_angular "$CONTEXT" "$ANGULAR_BROWSER"
|
|
fi
|
|
|
|
- name: Build Docker image (no push)
|
|
uses: depot/build-push-action@98e78adca7817480b8185f474a400b451d74e287 # v1.18.0
|
|
with:
|
|
project: m2kw2wmmcp
|
|
context: ${{ matrix.service.context }}
|
|
file: ${{ matrix.service.dockerfile != '' && matrix.service.dockerfile || format('{0}/Dockerfile', matrix.service.context) }}
|
|
platforms: linux/amd64
|
|
push: false
|
|
build-args: ${{ steps.build-args.outputs.args }}
|