263 lines
15 KiB
YAML
263 lines
15 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/**"
|
|
- ".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 }}
|
|
steps:
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Detect changed paths
|
|
uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
|
|
id: filter
|
|
with:
|
|
filters: |
|
|
workflow_config:
|
|
- '.github/workflows/showcase_build.yml'
|
|
- '.github/workflows/showcase_build_check.yml'
|
|
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/**'
|
|
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, lfs, 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,"lfs":true,"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,"lfs":false,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"mastra","filter_key":"mastra","context":"showcase/integrations/mastra","image":"showcase-mastra","timeout":15,"lfs":false,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"crewai-crews","filter_key":"crewai_crews","context":"showcase/integrations/crewai-crews","image":"showcase-crewai-crews","timeout":15,"lfs":false,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"pydantic-ai","filter_key":"pydantic_ai","context":"showcase/integrations/pydantic-ai","image":"showcase-pydantic-ai","timeout":15,"lfs":false,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"google-adk","filter_key":"google_adk","context":"showcase/integrations/google-adk","image":"showcase-google-adk","timeout":15,"lfs":false,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"ag2","filter_key":"ag2","context":"showcase/integrations/ag2","image":"showcase-ag2","timeout":15,"lfs":false,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"agno","filter_key":"agno","context":"showcase/integrations/agno","image":"showcase-agno","timeout":15,"lfs":false,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"llamaindex","filter_key":"llamaindex","context":"showcase/integrations/llamaindex","image":"showcase-llamaindex","timeout":15,"lfs":false,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"langgraph-fastapi","filter_key":"langgraph_fastapi","context":"showcase/integrations/langgraph-fastapi","image":"showcase-langgraph-fastapi","timeout":15,"lfs":false,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"langgraph-typescript","filter_key":"langgraph_typescript","context":"showcase/integrations/langgraph-typescript","image":"showcase-langgraph-typescript","timeout":15,"lfs":false,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"langroid","filter_key":"langroid","context":"showcase/integrations/langroid","image":"showcase-langroid","timeout":15,"lfs":false,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"spring-ai","filter_key":"spring_ai","context":"showcase/integrations/spring-ai","image":"showcase-spring-ai","timeout":15,"lfs":false,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"strands","filter_key":"strands","context":"showcase/integrations/strands","image":"showcase-strands","timeout":15,"lfs":false,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"strands-typescript","filter_key":"strands_typescript","context":"showcase/integrations/strands-typescript","image":"showcase-strands-typescript","timeout":15,"lfs":false,"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,"lfs":false,"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,"lfs":false,"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,"lfs":false,"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,"lfs":false,"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,"lfs":false,"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,"lfs":false,"build_args":"","dockerfile":""},
|
|
{"dispatch_name":"shell-dojo","filter_key":"shell_dojo","context":".","image":"showcase-shell-dojo","timeout":10,"lfs":false,"build_args":"","dockerfile":"showcase/shell-dojo/Dockerfile"},
|
|
{"dispatch_name":"shell-dashboard","filter_key":"shell_dashboard","context":".","image":"showcase-shell-dashboard","timeout":10,"lfs":true,"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,"lfs":true,"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,"lfs":false,"build_args":"","dockerfile":"showcase/harness/Dockerfile"},
|
|
{"dispatch_name":"showcase-aimock","filter_key":"showcase_aimock","context":"showcase/aimock","image":"showcase-aimock","timeout":5,"lfs":false,"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)
|
|
))]
|
|
')
|
|
|
|
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
|
|
if [ "$MATRIX" = "[]" ]; then
|
|
echo "has_changes=false" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "has_changes=true" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
build-check:
|
|
needs: [detect-changes]
|
|
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@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
with:
|
|
lfs: ${{ matrix.service.lfs }}
|
|
persist-credentials: false
|
|
|
|
- name: Setup Depot
|
|
uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # 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
|
|
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/, 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 _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
|
|
|
|
- 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 }}
|