publish-python now skips when dry-run=true (matching the npm lane). Add
set -euo pipefail to the tag step so a failed push no longer emits a ghost
tag output or proceeds to the GitHub Release. Pass GITHUB_TOKEN via env
instead of inline interpolation, guard against an empty dist/ before
uv publish, and surface curl errors from the PyPI verify-live loop.
Add set -euo pipefail and non-empty SHA validation to the pyproject-change
detection step so a null/stale merge_commit_sha fails loudly instead of
silently skipping a real version bump. Mirror the npm lane's success guard
on publish-python. Correct the python_publish input description (detection
still runs) and drop the dead checkout token (persist-credentials is false).
Fixes zizmor findings on .github/workflows/showcase_lint_prod.yml:
- unpinned-uses: pin actions/checkout to the repo-canonical SHA (v4)
- unpinned-uses: pin ruby/setup-ruby to v1.310.0 SHA
- artipacked: set persist-credentials: false on the checkout step
Matches the rest of the repo, which SHA-pins every uses: with a trailing
# vX.Y.Z comment for Dependabot to keep current.
The lint-prod step crashes today on a pre-existing snapshot bug (GraphQL
schema query for a "domains" field that no longer exists on Project).
The `--exit-zero` flag only suppresses exit-on-findings — it doesn't
catch fatal Ruby errors during snapshot building, so an error short-
circuits the whole job and the visibility surfaces never render.
Make the workflow truly advisory:
- Capture lint-prod stderr + exit code instead of failing the step.
- If lint-prod errors (or produces no JSON), synthesize a minimal
payload with an "error" field so the renderer has something to chew on.
- Renderer detects the error field and emits an "audit unavailable" block
with the captured error inside a <details> fold instead of leaving the
step summary / sticky comment blank.
Snapshot bug itself is out of scope for this change; tracked separately.
Make the lint-prod audit result legible without having to click into the
workflow logs. Two surfaces, both rendered from the same JSON payload:
1. `$GITHUB_STEP_SUMMARY` — structured markdown block at the top of every
workflow run page. Shows on every event (push, pull_request,
workflow_dispatch).
2. Sticky PR comment — one comment per PR, keyed by the HTML marker
`<!-- lint-prod-sticky-comment -->`. Re-runs update the same comment via
`gh api -X PATCH` instead of creating duplicates. Plain `gh` CLI only,
no third-party action.
Both surfaces show: one-line status, a table of the unpinned services only
(not all 27), and a Pacific-time run timestamp with the finding count.
To support the renderer, add `--format json` to `lint-prod`:
{services:[{name,source,status}], findings:N, timestamp:"ISO8601"}
The workflow consumes this shape and also writes `findings` to
`$GITHUB_OUTPUT` so downstream jobs (future Slack alert) can compare runs.
Idempotent: re-running the workflow finds the existing comment by marker
and PATCHes it — never duplicates.
Add --exit-zero flag to bin/railway lint-prod that makes the command exit 0
even when digest-pinning findings exist. Findings still print to stdout so
they remain visible in the CI step log.
Wire the showcase_lint_prod.yml workflow to pass --exit-zero so the job
cannot block PRs while we soak the check against real production state.
Once we have confidence the findings are clean, remove --exit-zero from
the workflow step to flip lint-prod to enforcing.
Updates README to document the advisory-mode behavior and the path to
flipping the check to enforcing.
Prerelease canary publishing is now an input mode on publish-release.yml's
workflow_dispatch. The dedicated prerelease.yml workflow is no longer
reachable and its workflow_call delegation never worked (npm matches the
OIDC token's caller `workflow_ref`, which was always prerelease.yml —
unregistered with any package's trust record).
Canaries are now dispatched via:
gh workflow run publish-release.yml \
-f scope=monorepo -f mode=prerelease -f suffix=<name>
The `bump-prerelease.ts` and `prerelease.ts` scripts remain unchanged; they
are invoked by publish-release.yml when `mode=prerelease`.
Folds prerelease.yml's canary publishing back into publish-release.yml, which
is the workflow registered as npm trusted publisher for all 15 @copilotkit/*
monorepo packages and @copilotkitnext/angular. Since npm matches on the OIDC
token's `workflow_ref` claim (the caller), the canary must dispatch from THIS
workflow file — not from a separate workflow that delegates via workflow_call.
Changes:
- Add `mode` (stable|prerelease) and `suffix` inputs to workflow_dispatch.
`mode` selects the publish script and gates post-publish tag/release steps;
`suffix` is forwarded to bump-prerelease.ts when mode=prerelease.
- Add a conditional `Bump prerelease versions` step in the build job that
runs `scripts/release/bump-prerelease.ts` before `Build packages` whenever
`inputs.mode == 'prerelease'`. The bumped versions flow through the
workspace artifact to the publish job exactly as in the deleted
prerelease.yml.
- Switch the publish step's `PUBLISH_SCRIPT` env var to be mode-driven:
`prerelease.ts` for canaries, `publish-release.ts` for stable. The old
`inputs.publish-script` plumbing was removed in the prior commit along
with the workflow_call inputs schema.
- Simplify the publish-job `meta` step now that workflow_call is gone: mode
defaults to `stable` unless workflow_dispatch passes `prerelease`.
- Rewrite the top-of-file comment to document both modes and the OIDC trust
binding, replacing the old "MANUAL RETRIGGER" wording which only covered
the stable retrigger path.
All post-publish gating (`steps.meta.outputs.mode != 'prerelease'` on the tag,
release, and stable-summary steps; `mode == 'prerelease'` on the prerelease
summary) was already in place from the prior PR-A architecture and is left
intact. The `Verify publish step emitted version` step keeps its prerelease
bypass.
Canary invocation after this lands:
gh workflow run publish-release.yml \
-f scope=monorepo -f mode=prerelease -f suffix=<name>
The workflow_call trigger was added in the PR-A/B architecture so prerelease.yml
could invoke this workflow as a reusable workflow. That architecture was wrong:
npm's trusted-publisher matching uses the OIDC token's `workflow_ref` claim,
which is the CALLER workflow (prerelease.yml), not the callee's
`job_workflow_ref` (publish-release.yml). Since prerelease.yml has no trust
record, every canary attempt failed at the npm publish step with ENEEDAUTH.
This commit removes the dead code:
- workflow_call: trigger block (inputs schema + secrets block)
- the `github.event_name != 'workflow_call'` guard on the build job
- the `needs.build.result == 'skipped' && github.event_name == 'workflow_call'`
branch on the publish job's `if:` (simplified to plain success check)
The follow-up commit folds prerelease support back into this workflow as a
`workflow_dispatch` mode, so the canary path executes from the workflow with
the trust record.
## Why
Follow-up to #5063. Together they unblock customer canary publishes that
have been failing with `npm ENEEDAUTH` since 2026-05-15.
#5063 parametrized `publish-release.yml` to support `workflow_call`.
This PR converts `prerelease.yml`'s publish path into a thin caller of
that reusable workflow. Because npm OIDC's `job_workflow_ref` claim
resolves to the callee in a reusable-workflow invocation, the existing
trust record on `publish-release.yml` covers both stable AND canary
publishes — no second trusted-publisher record needed (npm only allows
one per package).
## What changes
- `prerelease.yml`'s `build` job is preserved verbatim (checkout,
install, `bump-prerelease.ts --suffix`, build, test, upload `workspace`
artifact).
- The old `publish` job is replaced with `uses:
./.github/workflows/publish-release.yml` with `mode: prerelease`,
`publish-script: prerelease.ts`, `scope`, `dry-run`.
- The caller's `publish` job grants explicit `permissions: { contents:
write, id-token: write, actions: read }` — REQUIRED for the callee's npm
OIDC mint (per GitHub Actions, caller's per-job permissions cap the
callee's declared permissions).
- The caller's `workflow_dispatch.inputs.dry_run` (underscore, preserved
for backwards compat) maps to the callee's `dry-run` (hyphen) at the
`with:` boundary.
- No `secrets:` block — Notion not needed for prereleases; callee
declares `NOTION_API_KEY` optional and gates it on `mode == 'stable'`.
## Verification plan
1. Dispatch `prerelease.yml` with `scope: monorepo`, `suffix:
test-oidc-refactor`, `dry_run: true` → confirms plumbing without an
actual publish.
2. Dispatch again with `dry_run: false` → first OIDC-handshake-verifying
real canary.
3. `npm view @copilotkit/runtime@1.58.0-canary.test-oidc-refactor --json
| jq '.dist.attestations'` → confirm provenance attestation references
`publish-release.yml`.
## Test plan
- [ ] CI green.
- [ ] Post-merge: dispatch dry-run + real canary per Verification plan
above.
- [ ] Confirm provenance attestations land via `npm view`.
Supersedes #5066 (closed when #5063's base branch was deleted).
## Summary
- Unify authored and generated shell-docs navigation so the sidebar
keeps the same structure across framework modes.
- Restore setup-content bundling from integration-owned docs and wire
shell-docs to consume the generated bundle at runtime.
- Audit and fix the LangGraph TypeScript and Google ADK code regions so
the generated snippets are more useful and accurate.
- Tighten docs/build routing and workflow triggers so shell-docs
rebuilds when the relevant integration docs inputs change.
## Testing
- Shell-docs unit tests passed.
- Shell-docs typecheck passed.
- Shell-docs lint passed with existing repository warnings only.
- Setup-content bundle generation passed.
- Python integration files compiled successfully.
- Workflow YAML parsed successfully.
PR-B CR-r1 fix: reusable-workflow permissions in GitHub Actions are capped by
the caller's per-job permissions. The callee (publish-release.yml from PR-A)
declares id-token: write + contents: write on its publish job, but without
the caller (prerelease.yml) granting those at its own publish-job level, the
callee gets only the workflow-level default (contents: read). The OIDC token
mint then fails silently and npm publish errors.
4 of 7 CR agents independently flagged this. The spec missed it.
Adds contents: write (callee uses it in stable mode; gated off in prerelease
but matches the callee's declaration), id-token: write (required for OIDC),
and actions: read (required for actions/download-artifact in callee).
Spec updated to document this requirement.
PR-B of the two-PR refactor: prerelease.yml's build job is preserved verbatim
(checkout, install, bump-prerelease.ts with --suffix, build, test, upload-
artifact "workspace"); its publish job is replaced with a workflow_call
invocation into publish-release.yml from PR-A. The reusable workflow's
job_workflow_ref OIDC claim matches the existing trusted-publisher record on
publish-release.yml, so the canary publishes succeed without registering a
second trust binding (which npm does not allow).
The caller's workflow_dispatch.inputs.dry_run (underscore, preserved) maps
to the callee's dry-run (hyphen) at the with: boundary — independent keys
in independent namespaces. No secrets passed; Notion not needed for
prereleases.
Spec: https://www.notion.so/36d3aa381852811ba10ad1bcd228d6d8
Unblocks: @copilotkit/react-core canary --suffix thread-id-propagation.
Stacked on PR-A (fix/publish-release-workflow-call).
PR-A CR-r2 fixes (2 bucket-(a) findings from 7-agent confirmation round).
A4: Tighten publish-job `if:` so `needs.build.result == 'skipped'` is only honored when
the event is `workflow_call` (the intentional skip for the reusable workflow callee).
Previously, a `pull_request: closed` event on a release branch where the PR was closed
WITHOUT merging would cause the build job to skip (its own merged-true guard), then the
publish job's permissive `if:` would still run it — a phantom publish from an unmerged
release PR.
A5: Every post-publish step's custom `if:` overrode the default implicit `success()`
check, meaning a failure in `Publish to npm` or the `Verify version` guard would not
prevent downstream steps (tag push, GitHub Release create) from running. Prepended
`success() && ` to all post-publish step `if:` conditions to restore the implicit gate.
Spec: https://www.notion.so/36d3aa381852811ba10ad1bcd228d6d8
PR-A CR-r1 fixes (4 of 4 actionable findings from 7-agent CR + 1 cheap defense-in-depth).
A1: post-publish steps (Configure git user, Check for pre-existing tags, Create and push
git tag, Create GitHub Release) now gate on `inputs.dry-run != true && mode != 'prerelease'`
instead of just `mode`. On dry-run + stable, VERSION was empty so TAG="v" garbage was
pushed; this prevents that.
A2: Add explicit Verify-publish-step-emitted-version guard between Publish to npm and the
post-publish chain. Fails loud if publish-release.ts (or any inputs.publish-script
override) forgets to emit `version` to GITHUB_OUTPUT.
A3: Replace the single unconditional Release summary with three gated variants (stable,
prerelease, dry-run) so the summary no longer claims "Release Published" on dry-run or
prerelease.
B3: inputs.publish-script and steps.meta.outputs.scope now flow through env to the shell
(reduces injection surface even though caller is in-repo today).
Spec: https://www.notion.so/36d3aa381852811ba10ad1bcd228d6d8
prerelease.yml cannot register as a second npm trusted publisher (npm allows
exactly one per package; all 16 monorepo-scoped packages bind to
publish-release.yml). Refactor publish-release.yml to also support
workflow_call so prerelease.yml can invoke it as a reusable workflow — OIDC's
job_workflow_ref claim points at the callee, so the existing trust record
covers both flows.
This PR (PR-A) adds the workflow_call trigger, input schema, meta step for
scope+mode resolution, build-job gating to skip on workflow_call, publish-job
if: override for skipped-needs, post-publish step gating on
mode != prerelease, NOTION_API_KEY gating on stable mode, and the
publish-script input for the TS file selection.
Also adds a dry-run input on workflow_dispatch so PR-A can be verified
post-merge via a sacrificial release branch without an actual publish.
Spec: https://www.notion.so/36d3aa381852811ba10ad1bcd228d6d8
Customer block (Ben Taylor, #engr): @copilotkit/react-core canary with
suffix=thread-id-propagation.
PR-B (prerelease.yml caller conversion) follows.
upload-artifact's path filters are post-walk: even with !**/node_modules/**
exclusions, the action still descends into every node_modules and stats
every file (~6M for this monorepo with pnpm's .pnpm/ symlink farm) before
applying negations. That enumeration is the actual bottleneck — the
Upload workspace step runs 10+ minutes even with the filters added in
#5044.
Replace the filtered upload with: rm -rf the heavy dirs (node_modules,
.nx, .turbo, .next), tar the workspace into a single file, upload that.
Publish job tar -xzf's it after download and continues unchanged. Single-
file upload skips upload-artifact's per-file overhead entirely.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The prerelease workflow has been OOMing on Upload workspace since the
build/publish split in 770759a4be. The artifact upload enumerates
~6M files (root + per-package node_modules with pnpm symlinks all
materialized, plus build caches) and actions/upload-artifact builds
the full manifest in memory before streaming, blowing past the 4GB
Node heap limit.
publish-release.yml already had the working pattern: exclude
node_modules/.next/.turbo/.nx and re-run pnpm install --frozen-lockfile
in the publish job. Port it over so prerelease publishes succeed
again.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Zizmor's ref-version-mismatch audit flags the existing `# v1` comment
because the hash 5f3b3c2e5a00f0093de47f657aeaefcedff27d18 is the
v1.17.0 tag, not the v1 head. Update the trailing comment to match.
No behavior change — the SHA pin is what governs which commit Actions
fetches. This just keeps zizmor green so unrelated showcase-wiring PRs
don't trip on a pre-existing pin annotation.
Three companion workflows duplicate the showcase_build.yml service registry
and were missed in the initial wiring commit. Bring them in sync:
- .github/workflows/showcase_build_check.yml: add ms_agent_harness_dotnet
to the paths-filter and the ALL_SERVICES matrix (mirror of the
production build matrix, used for pre-merge Docker build verification).
- .github/workflows/showcase_deploy.yml: add ms-agent-harness-dotnet to
the workflow_dispatch options and the verification ALL_SERVICES with
railway_id 6343d7f9-6c3f-4c8d-9a6e-79f03d2f1e37 and /api/health.
- .github/workflows/showcase_keep-alive.yml: add ms-agent-harness-dotnet
to the keep-alive ping matrix.
Brings the Microsoft Agent Harness (.NET) integration live on the
showcase Railway project. Integration code itself landed in PR #4982.
Changes:
- Railway service `showcase-ms-agent-harness-dotnet` created
(id 6343d7f9-6c3f-4c8d-9a6e-79f03d2f1e37) with the public domain
showcase-ms-agent-harness-dotnet-production.up.railway.app, image
source ghcr.io/copilotkit/showcase-ms-agent-harness-dotnet:latest,
healthcheck /api/health, and env vars cloned from the sibling
showcase-ms-agent-dotnet service.
- .github/workflows/showcase_build.yml: add ms-agent-harness-dotnet to
workflow_dispatch options, paths-filter, and the ALL_SERVICES matrix
(mirroring the ms-agent-dotnet sibling entry).
- showcase/integrations/ms-agent-harness-dotnet/manifest.yaml: flip
deployed: false -> true so the dashboard surfaces the integration
once the image is live.
Skips test-and-check-packages pre-commit hook locally because
@copilotkit/web-inspector:test has a pre-existing failure on main
(window.localStorage.clear telemetry test setup) unrelated to these
YAML-only changes.
publish-release.ts now checks npm for each package before publishing
and skips versions that already exist. Makes publish idempotent —
safe to retry after partial failures. Removes the publish-remaining
one-shot workflow that's no longer needed.
Packages without repository.url fail npm OIDC provenance verification.
Adds the field to agentcore-runner, core, sqlite-runner, voice, and
web-inspector. Includes a one-shot workflow to publish the 14 remaining
v1.57.4 packages (a2ui-renderer already published via OIDC).
Replace pnpm publish with pnpm pack + npx npm@11.15.0 publish to
enable OIDC authentication. Set NODE_AUTH_TOKEN='' to prevent the
expired secret from blocking OIDC. Removes test workflow.
Without --bare, claude -p launches MCP servers defined in the project-level
.mcp.json before the model loads. A PR replacing .mcp.json with a malicious
entry gets an attacker-controlled subprocess launched on the CI runner —
same RCE surface as a SessionStart hook.
This repo already has .mcp.json committed (nx-mcp). Removing it before the
social copy generator runs is safe: the workflow's --allowedTools already
restricts Claude to specific read/diff tools and MCP servers are not needed
for social copy generation.
Call-site enumeration: rm -f is self-contained, no callers.
Extends the security fix to also cover .claude/settings.local.json, which
Claude Code reads with equal authority to settings.json. A PR author can
force-commit a gitignored file, so the .gitignore entry does not protect
against this vector.
Also moves the removal step to immediately after Checkout (before any other
step runs in the checked-out workspace), rather than after Install Claude Code.
Claude is not invoked during the intermediate steps, but this ordering is
strictly more defensive and prevents any future step insertions from reopening
the window.
Call-site enumeration: rm -f has no callers; step is self-contained YAML.
- Switch STORE_PATH from $GITHUB_ENV to $GITHUB_OUTPUT (step-scoped,
per GitHub Actions security hardening guide)
- Narrow hashFiles glob from '**/pnpm-lock.yaml' to 'pnpm-lock.yaml'
(root-only, avoids spurious cache busts from docs/examples lockfiles)
- Reword comment to show ABI mismatch is symmetric across all versions
- Document that actions/cache is equally fork-safe (GitHub platform guarantee)