## What this fixes
This is a follow-up to #3770, not a second root-cause fix.
#3770 moved the docs data workflow from staging to production,
centralized the production API URL, removed staging hosts from the
committed data, and added the hostname guard. The committed toolkit
catalog still retained staging-derived `version` values, however,
because that PR intentionally did not regenerate the full catalog. After
#3770 merged, the scheduled production regeneration began failing with
`401 Unauthorized`: the repository's existing `COMPOSIO_API_KEY` secret
is staging-scoped.
The customer-visible result was that nearly every toolkit page showed
the internal staging version `20260703_00`; Gmail's production version
was `20260702_01`.
## Changes
- Correct every `version` in `docs/public/data/toolkits.json` from the
production toolkit changelog. Toolkits absent from that changelog
receive `null`, matching the full generator's semantics. No other JSON
field changes.
- Move production changelog fetching and version application into shared
`toolkit-versions.ts` logic used by the full catalog generator.
- Add `bun run generate:toolkit-versions` as the narrow, reproducible
generator for version-only repairs.
- Reject any non-production `COMPOSIO_API_BASE` in the toolkit and
meta-tool generators before a request is made.
- Keep the version-distribution check as a smoke signal for the known
whole-catalog staging-bump pattern, while testing the production source
boundary separately. The distribution heuristic is no longer described
as proof of provenance.
- Fail before writing when the production changelog response is
malformed or contains no versions.
## CI policy compatibility
- Replace the enterprise-blocked mise action with allowlisted tool setup
actions while continuing to resolve exact versions from mise.lock.
Install the existing pinned mise CLI release through a checksum-verified
repository script for lock freshness and preinstall validation.
- Run the existing GitHub Advanced Security alert check locally and
notify Slack through the already-allowlisted Slack action, avoiding the
central workflow dependency rejected by the enterprise action policy.
## Verification
- `bun test tests/static/` — 30 passed.
- Targeted ESLint for every changed script/test — passed.
- `bun run types:check` — passed.
- `bun run build` — passed.
- Explicit staging override of `generate-toolkits.ts` — rejected before
network access.
- Verified the JSON data change remains version-only; toolkit ordering,
tools, triggers, descriptions, and counts are unchanged.
## Remaining deployment action
An administrator still needs to replace `COMPOSIO_API_KEY` with a
production-scoped key. The scheduled `docs-update-data` workflow is
correctly pinned to production and therefore fails loudly with the
current staging credential instead of republishing staging data. Once
the secret is corrected, the normal full-catalog generator remains the
authoritative refresh path.
Triggered by: abhishek@composio.dev | Source: slack
Session: https://zen.corp.composio.io/dashboard/#/chat/zen-3a77f73eb146
---------
Co-authored-by: Zen Agent <zen@composio.dev>
Co-authored-by: abhishek <abhishek@composio.dev>
Co-authored-by: jkomyno <alberto@composio.dev>
This PR:
- adds `concurrency` to the ten PR/push CI workflows: superseded **PR**
runs are cancelled, while push runs use a per-run group
(`github.run_id`) so every commit on `next`/`master` still gets its own
run
- caches turbo outputs (`.turbo/cache`) via a new opt-in
`enable-turbo-cache` input on the `setup-node-pnpm-bun` composite (keyed
per job — concurrent jobs save different task graphs), enabled in
`ts.build`, `ts.test`, `ts.typecheck`, and all four `ts.test-e2e` jobs
- enables turbo caching for `typecheck`, removes the incorrect `dist/`
outputs from `test`, hashes root `tsconfig.base.json` in
`build`/`typecheck` inputs, and adds `mise.toml`/`mise.lock` to
`globalDependencies` so toolchain bumps bust every task hash (addresses
the Bugbot finding)
- fixes `@composio/slim`'s build to participate in the turbo graph: core
moves to slim's `devDependencies` (published `dependencies` unchanged)
and the script no longer shells out to `pnpm --filter @composio/core
build`, which raced concurrent dependents by wiping `core/dist`
mid-build and double-built core on every cold run — slim's `dist`
remains byte-identical to core's; no changeset added since the published
artifact is unchanged (say the word if policy wants one anyway)
- fixes the `py.test` matrix cache to `~/.cache/uv` (it cached
`~/.cache/pip` while installing via `uv pip`) and caches
`~/.bun/install/cache` in the five docs workflows
- adds `turbo.jsonc` to the TS workflows' path filters (previously
unwatched)
- release/publish workflows are deliberately untouched
Measured (same commit, cold first attempt vs `gh run rerun` warm):
ts.build 103s → 53s, ts.test 157s → 55s (`turbo test` 24/24 cached in
182ms), ts.typecheck 80s → 43s; py.test legs save a few seconds each (uv
was already fast). Warm floor is checkout + mise + pnpm-install
overhead.
## Context
Implements `plans/001-ci-speed-caching-and-concurrency.md` from the
advisor audit on `docs/sdk-v1-decision-records`. Implementation by codex
against the plan, then self-reviewed and counter-reviewed; warm-rerun
testing surfaced and fixed three latent issues (toolchain files absent
from turbo's hash, first-writer-wins cache-key collision across jobs,
and the slim out-of-band core rebuild race).
This PR:
- uses plain `tsdown` package scripts and a shared typed
`tsdown.config.base.ts` so Node 24 builds work without loader flags
- switches the repo dev/build toolchain to Node `24.17.0` and pnpm
`11.8.0` through `mise.toml`, `mise.lock`, and `pnpm-lock.yaml`
- marks the root package as ESM with `type: module`, matching the
TypeScript packages
- keeps Node `22.22.3` in the runtime/E2E matrices as the minimum
supported user runtime
- changes the TypeScript build workflow back to a single build on the
mise-managed toolchain and broadens path filters for
package-manager/build config files
- adds pnpm 11 build-script policy with `allowBuilds` and intentionally
ignored `sharp` builds
- enables tsdown ESM shims for the packaged CLI wrapper so `composio
--help` runs under Node 22 and Node 24
Verified locally:
- `CI=true pnpm install --frozen-lockfile`
- `pnpm lint`
- `pnpm run build:packages`
- `COMPOSIO_E2E_NODE_VERSION=22.22.3 pnpm --filter
@e2e-tests/node-esm-basic --filter @e2e-tests/node-cjs-basic run
test:e2e:node`
- `node ts/packages/cli/bin/composio.mjs --help` under Node `22.22.3`
and `24.17.0`
## Summary
Depends on #3492.
This completes the Phase 2 migration by removing the transitional
version-file layer and making `mise.toml` plus `mise.lock` the
repository toolchain source of truth. It also moves runtime test
matrices into `toolchain-versions.json`, so CI matrix changes are
explicit and reviewable without reintroducing `.nvmrc`, `.dvmrc`,
`.bun-version`, or `.python-version`.
The Node.js e2e matrix now starts at the latest Node 22 LTS line and
also covers the latest Node 24 and Node 25 lines. That removes Node 20
from the well-known e2e versions while keeping us covered on the
runtimes SDK users are moving toward.
## Rationale
Phase 1 introduced mise side by side with the existing version files to
keep the first PR low-risk. Phase 2 removes that compatibility layer so
there is one place to update tool versions. That avoids silent drift
between local setup, GitHub Actions, Docker E2E images, release docs,
and install-time checks.
The composite setup actions now install Node, Bun, Python, and uv
through mise by default, with explicit version overrides only where a
matrix needs them. New GitHub actions added in this PR are pinned by
release commit SHA and include the release version comment.
## What changed
- Deleted the transitional root/version files: `.nvmrc`, `.bun-version`,
`.dvmrc`, root `.python-version`, and `python/.python-version`.
- Removed `idiomatic_version_file_enable_tools` from `mise.toml` and
added a committed `mise.lock` for linux/macOS x64/arm64 tool resolution.
- Replaced `BYPASS_BUN_VERSION_CHECK` with `BYPASS_TOOLCHAIN_CHECK`, and
made Docker E2E image installs use that bypass because they receive
explicit build args instead of installing mise.
- Updated Node/Bun and Python/uv composite actions to default to mise,
remove `*-version-file` inputs, report resolved versions, and cache pnpm
after `corepack enable`.
- Centralized CI runtime matrices in `toolchain-versions.json` for TS
E2E, Python tests, and CLI npm fallback coverage.
- Updated the Node E2E matrix to `22.22.3`, `24.16.0`, and `25.9.0`,
removing Node 20 from the well-known runtime versions.
- Updated workflows, docs, E2E helpers, Dockerfiles, and release
guidance to reference `mise.toml` / `mise.lock`.
## Verification
- Verified latest Node 22/24/25 releases from the official Node dist
index: `22.22.3`, `24.16.0`, `25.9.0`
(https://nodejs.org/dist/index.json).
- `pnpm install --frozen-lockfile`
- `pnpm --filter @e2e-tests/utils typecheck`
- `pnpm --filter @e2e-tests/utils exec tsc --noEmit --target es2022
--module esnext --moduleResolution bundler --types bun
--resolveJsonModule --skipLibCheck --strict scripts/docker-build.ts`
- `bash -n ts/scripts/pre-install.sh && bun run
ts/scripts/pre-install/check-toolchain.ts && BYPASS_TOOLCHAIN_CHECK=1
bash ts/scripts/pre-install.sh`
- `pnpm exec prettier --check ...` on touched YAML/Markdown/TS/JSON
files
- `ruby -e "require \"yaml\"; ARGV.each { |f| YAML.load_file(f) }" ...`
on touched actions/workflows
- `mise lock --platform linux-x64,linux-arm64,macos-arm64,macos-x64 &&
git diff --exit-code mise.lock`
- `mise exec node@22.22.3 -- pnpm --filter @e2e-tests/utils typecheck`
- `mise exec node@22.22.3 -- pnpm --filter @e2e-tests/node-esm-basic
typecheck`
- `mise exec node@22.22.3 -- pnpm --filter @e2e-tests/node-cjs-basic
typecheck`
- `docker manifest inspect node:24.16.0-slim`
- `docker manifest inspect node:25.9.0-slim`
- `git diff --check`
## Summary
- Pin every remote GitHub Action used by `.github/workflows` and
`.github/actions` to a full 40-character commit SHA with a version
comment.
- Update each action to the latest upstream tag available at the time of
this change.
- Migrate Slack incoming-webhook steps to the latest
`slackapi/slack-github-action` major by passing `webhook` and
`webhook-type: incoming-webhook` explicitly.
- Keep the live Python integration test step non-blocking so an external
credential issue does not fail unrelated PR CI.
## Upgrade notes
- Read README/release notes for major-version upgrades:
`actions/checkout`, `actions/cache`, `actions/download-artifact`,
`actions/github-script`, `actions/setup-node`, `actions/setup-python`,
`actions/upload-artifact`, `astral-sh/setup-uv`, `pnpm/action-setup`,
and `slackapi/slack-github-action`.
- The GitHub-owned action upgrades keep existing workflow inputs
compatible; their README notes are mainly Node 24/runtime and minimum
runner-version requirements.
- `actions/github-script@v9` no longer supports requiring
`@actions/github` internals, but these workflows only use injected
`github`, `context`, and `core`.
- `slackapi/slack-github-action@v3` requires explicit webhook technique
configuration, now added in the four Slack notification steps.
## Verification
- Strict local audit: 83 remote `uses:` entries across 21 action
repos/reusable workflows are full SHAs with expected comments.
- Remote metadata audit: all 21 pinned remote refs resolve, and each
action metadata file or reusable workflow file exists at the pinned SHA.
- `.github/scripts/check-action-repos.sh`
- `ruby -e 'require "yaml"; Dir[".github/workflows/*.{yml,yaml}",
".github/actions/**/*.yml", ".github/actions/**/*.yaml"].each { |f|
YAML.load_file(f); puts "ok #{f}" }'`
- `git diff --check`
- `go run github.com/rhysd/actionlint/cmd/actionlint@latest -shellcheck=
-pyflakes= -ignore 'label "depot-ubuntu-[^\"]+" is unknown'`
`actionlint` without the ignore only reports the existing custom Depot
runner labels in `cli.test-installation.yml`.