## Summary
- The docs-sync warning notification was sending "see workflow run for
details" with no actionable information
- Now reads `review-items.txt` and includes the file list directly in
the Slack message
- Recipients can see which files need attention without digging through
CI logs
## Test plan
- [ ] Trigger docs-sync with a file that has showcase-local
modifications (exit code 3 path)
- [ ] Verify Slack notification includes the file list in a code block
- [ ] Verify auto-push-only path (exit code 0) still does NOT send the
warning notification
The warning notification for files needing manual review was sending
'see workflow run for details' with no actionable information.
- Read review-items.txt and include file list in the Slack message
- Use jq for proper JSON escaping (handles newlines, quotes, special chars)
- Guard against missing review-items.txt with fallback and ::warning::
- Review-needed notification fires independently of push/merge outcome
New workflow running starter health/agent/chat tests against Railway:
- Triggers: 6h cron, after showcase deploy, manual dispatch
- Alerts on schedule + workflow_run failures (Slack + GitHub issue)
- Issue dedup by title match, continue-on-error on Slack
- Proper working-directory for npm ci and Playwright install
## Summary
- **drift-detection**: Split inline payload into `jq`-built file +
`payload-file-path`; sanitize playwright output (strip ANSI, head -3,
cap 200 chars)
- **starter-smoke**: Replace `toJSON(format(...))` double-encoding with
`jq` payload builder
- **showcase_deploy**: Replace 300-char inline ternary with readable
shell conditional + `jq`
All three workflows now use the same pattern: build a sanitized JSON
file with `jq -n`, then reference it via `payload-file-path`. This
eliminates raw `%0A` in Slack messages, unformatted stack traces, and
double-encoded JSON.
## Test plan
- [ ] Trigger `showcase_drift-detection.yml` manually — verify Slack
alert formats correctly on failure
- [ ] Trigger `starter-smoke.yml` manually — verify Slack alert on a
known-failing starter
- [ ] Trigger `showcase_deploy.yml` with `service: shell` — verify
deploy notification renders cleanly
- [ ] Confirm no `%0A` or raw escape sequences appear in any Slack
message
Use jq to build JSON payloads safely and payload-file-path to avoid
inline multiline content. Limits error context to 3 lines, strips ANSI
codes, and caps field length at 200 chars.
- drift-detection: split payload build from post, sanitize playwright output
- starter-smoke: replace toJSON(format(...)) double-encoding with jq
- showcase_deploy: replace 300-char inline ternary with readable shell conditional
The RAILWAY_TOKEN in GitHub secrets can't call serviceInstanceUpdate
(403 Forbidden). Services are now all configured to pull :latest, so
serviceInstanceRedeploy will pull the latest image automatically.
Railway was pinned to old SHA tags — serviceInstanceRedeploy just
restarts the existing image. Now the deploy step calls
serviceInstanceUpdate to set the image to the exact SHA just pushed,
then triggers the redeploy. Also re-enables Docker cache.
The GHA Docker layer cache was serving stale builds — renderer adapter
code wasn't in the deployed images despite successful builds. Disabling
cache-from forces a full rebuild. Will re-enable after cache is fresh.
- Remove test-integration-tmp from workflow (package was deleted)
- starter-langgraph-python: disable Turbopack for Next.js build
(serverExternalPackages incompatible with Turbopack)
- starter-crewai-crews: pin crewai-tools~=0.47.1 to avoid version
conflict with crewai==0.130.0
- shell-dojolike: add missing zod dependency (required by shared
frontend modules)
The paths-filter YAML had test_integration_tmp defined twice (lines 71
and 90), causing a "duplicated mapping key" parse error that blocked all
deploy runs.
The CI workflow's shared module copy step used trailing slashes on both
source and destination (cp -r src/ dest/src/), which on Linux copies the
*contents* into an already-created dest/src/ — resulting in
shared_frontend/src/src/ instead of shared_frontend/src/. Same issue
for shared_typescript/tools/.
Root cause confirmed via diagnostic instrumentation: index.ts existed at
the wrong depth, leaving the webpack alias target empty.
Fix: mkdir only the parent, cp without trailing slashes so the directory
itself is placed correctly. Also removes the diagnostic debug line from
pydantic-ai Dockerfile.
- Node 20 → 22 in all Dockerfiles + CI workflows
- CI copies shared_python, shared_frontend/src, shared_typescript/tools
- tsconfig paths for @copilotkit/showcase-shared
- .gitignore for CI artifacts
The v1 action uses SubtleCrypto.importKey() which fails with 'Invalid keyData'
on certain PEM key formats. v2 handles this more robustly.
Also adds step-level failure info to the Slack notification so we know
WHICH step failed instead of just 'workflow failed'.
## Summary
Two fixes:
### 1. AG2 showcase agent blocks on human feedback
The `ConversableAgent` defaults to `human_input_mode="TERMINATE"`, which
prompts for user feedback when the conversation terminates. In the AG-UI
streaming context via `AGUIStream`, this blocks with:
> "Please give feedback to the sender. Press enter to skip and use
auto-reply, or type 'exit' to stop the conversation:"
This was broken from day one (showcase deployed April 8, first L4 test
ran April 9 and failed). The ag2 image was never rebuilt since — the
unpinned `ag2>=0.9.0` dep resolved to 0.11.5 at build time.
Fix: set `human_input_mode="NEVER"`.
### 2. Showcase E2E Slack alerts lack detail
The Slack notification only said "Showcase E2E suite failed" with a
link. Now captures playwright output and includes failed test names +
error messages:
```
❌ Showcase E2E suite failed
View run
1) [L4: tools] ag2 renders tool results @tools
Error: ag2 response doesn't contain weather info: "Please give feedback..."
```
Test names now carry their level prefix (`[L1: health]`, `[L2: agent]`,
`[L3: chat]`, `[L4: tools]`) so you can tell what broke from the Slack
message alone.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The Slack notification for E2E failures only said "Showcase E2E suite
failed" with a link. Now captures playwright output, extracts failed
test names and error messages, and includes them in the Slack message
as a code block so the team can see what broke without clicking through.
## Summary
The drift detection workflow runs `npx playwright test --grep
"@health|@agent|@chat"` which matches BOTH `integration-smoke.spec.ts`
(deployed Railway backends) and `starter-smoke.spec.ts` (Docker-built
starters). The starter-smoke tests try to connect to `localhost:3000`
which doesn't exist in CI, causing all runs to fail.
Fix: scope to `npx playwright test integration-smoke --grep ...` so only
the showcase integration tests run.
## Test plan
- [x] Verified locally: 13 integration-smoke tests pass, 0 starter-smoke
tests included
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Add tests for bumpPackages: verifies workspace:* protocol is
preserved and exact version deps are updated
- Add vitest config for scripts/release/
- Add release script test step to test_unit.yml so these run on
every PR and push to main
Each release scope has its own packages, version source, and
independent version track:
- monorepo: 12 core @copilotkit/* packages (shared version)
- cli: copilotkit CLI (independent version)
- angular: @copilotkitnext/angular (independent version)
Branch pattern is now release/publish/<scope>/v<version> and git
tags use <scope>/v<version> for non-monorepo scopes.
- Replace import.meta.dirname (Node 21.2+) with fileURLToPath
workaround for Node 20 compatibility
- Rename workflows to release / pre, release / publish, release /
create-pr so they group together in the Actions UI
- Fix semver regex to allow hyphens in prerelease identifiers
- Add unit tests for parseSemver, computeNextStableVersion,
computePrereleaseVersion
Replace changesets with a simple, stateless release system:
Stable release (PR-gated):
Actions → "create release PR" → pick patch/minor/major → CI runs →
merge → publishes to npm, creates git tag + GitHub Release
Prerelease (ad-hoc):
Actions → "publish / prerelease" → publishes current version with
-canary.<suffix|timestamp> to npm under "canary" tag
Key features:
- All 12 core @copilotkit/* packages share a single version
- AI-generated release notes via Anthropic API
- Notion draft for team editing before merge
- Notion link commented on the release PR
- Guards: concurrent release PR check, version > npm check, clean
semver check, canary-only prerelease tag
- release/publish/v* branch pattern (hard to accidentally match)
- TypeScript throughout (tsx runner)
- release.config.json with versionedTogether/versionedIndependently
## Summary
The showcase image drift detection compared image tags against `main`
HEAD SHA, but deploys only trigger when `showcase/` or
`examples/integrations/` paths change. Any non-showcase commit to main
(package bumps, workflow changes, docs, etc.) made ALL images appear
stale, triggering unnecessary rebuild workflows and Slack alerts.
## Root Cause
```bash
# Before: always stale after non-showcase commits
MAIN_SHA=$(git ls-remote ... main | cut -f1)
```
## Fix
Query the GitHub API for the last commit that actually touched
showcase-related paths, then check image tags against those SHAs:
```bash
SHOWCASE_SHA=$(gh api "repos/.../commits?path=showcase&per_page=1" --jq '.[0].sha')
EXAMPLES_SHA=$(gh api "repos/.../commits?path=examples/integrations&per_page=1" --jq '.[0].sha')
# Image is up-to-date if it matches EITHER SHA
```
## Impact
- No more false-positive drift alerts flooding #oss-alerts
- No more unnecessary rebuild triggers for every non-showcase commit
- Drift detection now only fires when showcase code actually changed but
images weren't rebuilt
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The drift check compared image tags against main HEAD SHA, but deploys
only trigger when showcase/ or examples/integrations/ paths change. Any
non-showcase commit to main made ALL images appear stale, triggering
unnecessary rebuild workflows and Slack alerts.
Fix: query the GitHub API for the last commit that touched each path
and check image tags against those SHAs instead.
Replaced 23 identical build jobs with one parameterized matrix job.
1200 lines to ~250. Service config as JSON, matrix generated from
path-filter results. Shell special cases (LFS, build-args, custom
Dockerfile) handled via matrix properties and dedicated prep step.
Merged standalone commitlint into static_quality as 4th parallel job.
Upgraded all actions to v4, added concurrency group. Format job now
auto-fixes and commits back to same-repo PR branches. Commitlint
posts helpful PR comment with valid prefixes on failure.