mirror of
https://github.com/ComposioHQ/composio.git
synced 2026-09-22 11:46:35 +08:00
0abc629f5d
Rebuilds the Effect v4 port on top of `next` at `effect@4.0.0-rc.112` (the newest release that clears the repository's 3-day `minimumReleaseAge` gate). The three v3-compatible preparation PRs (#4358, #4359, #4360) already landed on `next`, so this PR is now only the cutover. ## What changes - Pins `effect`, `@effect/platform-bun`, and `@effect/vitest` to exact `4.0.0-rc.112`; drops `@effect/cli`, `@effect/platform`, `@effect/platform-node`, and the `toml` override that existed only for `@effect/cli`. The `ts/vendor/effect` source oracle moves to the `effect@4.0.0-rc.112` release commit. - Services become `Context.Service` classes with explicit `Default` layers; `Either` becomes `Result`; `ParseResult` becomes `Schema.SchemaError`; platform modules come from `effect/FileSystem`, `effect/Path`, `effect/PlatformError`, `effect/unstable/process`, and `effect/unstable/http`. - The runner drives `Command.runWith` with v4's default help and error rendering. `CliError.ShowHelp` carries its own exit code, help for non-explicit invocations renders on stderr, and "Did you mean?" suggestions render. `command-introspection.ts` is gone: v4 renders the resolved command's help and the "missing value" tip itself. - `composio --version`, `composio -v`, and `composio version` print the same bare semver (`GlobalFlag.Version` is not enabled; the flag spellings are rewritten to the `version` command before parsing). - Root `--log-level` is a shared flag applied after the subcommand tree is attached, so `composio --log-level Debug <subcommand>` both parses and takes effect. - Every `Flag.boolean` carries an explicit default, because rc.112 makes boolean flags required when omitted. - A `Result` is not an `Effect` at runtime in rc.112 even though the type checker accepts `yield*` on it (the fiber dies with "Not a valid effect"); every `Result` is lifted with `Effect.fromResult`, and the skill/AGENTS guidance says so. - Every `ChildProcess.make` site passes `extendEnv: true`, because rc.112 no longer inherits the parent environment by default. - `--log-level` and `COMPOSIO_LOG_LEVEL` are exact-match on the `LogLevel` names (`All`, `Fatal`, `Error`, `Warn`, `Info`, `Debug`, `Trace`, `None`) with no case folding, per the earlier review decision; README updated. - Spawned children pass `extendEnv: true`, because rc.112's `ChildProcess` no longer inherits the parent environment by default. - ISO timestamps decode through `Schema.DateTimeUtcFromString`; `Schema.DateTimeUtc` is no longer a string codec in rc.112. - `ConfigProvider.fromEnv()` snapshots the environment at construction in v4, so providers that must observe later changes are built per read (`plugin-hint.ts`, `install.cmd.ts`, `config.ts`) and tests use a live-env provider helper. - `cli-keyring` and `json-schema-to-effect-schema` are ported alongside (the latter on `Schema.makeFilter`). - The `effect-v4` skill, the `cli-command` and `typescript-testing` references, `ts/packages/cli/AGENTS.md`, and the oxlint config are updated to the rc.112 reality. The skill's example checker (`.agents/skills/effect-v4/scripts/check-examples.mjs`, lifted from #3851) compiles every TypeScript block in the skill against the pinned packages. - The `js-yaml` overrides move to the 4.3.2 / 3.15.2 lines that GHSA-2883-xcg3-v3hh requires; `pnpm audit --prod` is clean apart from the already-ignored `extract-zip` advisory. ## Behaviour notes - `composio <unknown> --help` now prints the root help with exit 0 (v4's global `--help` handling); `composio <unknown>` without `--help` still fails with the unknown-subcommand error. ## Validation - `pnpm --filter @composio/cli typecheck` (src + test): 0 errors - `pnpm --filter @composio/cli test`: 127 files, 1325 tests pass, 1 skipped; `validate:boundaries` and `validate:skills` pass - `@composio/cli-keyring` and `@composio/json-schema-to-effect-schema` typecheck, test, and build pass - `pnpm validate:agent-skills` and `pnpm validate:skill-routing` pass (19 skills) - oxlint clean on `ts/packages/cli`, `cli-keyring`, `json-schema-to-effect-schema` - CLI bundle and standalone binary build; smoke-checked `version`, `--version`, `-v`, `--help`, unknown subcommand, unrecognized flag, missing flag value - Docker CLI e2e suites pass against an image built from this branch: `version`, `toolkits-list`, `toolkits-info`, `toolkits-search`, `setup-plugins`, `run`. `whoami` (needs an API key), `install` (needs a release dir), and `upgrade` (needs network) were not run. No changeset: `@composio/cli` is Changesets-ignored and the ported sibling packages are private. Human-facing notes are in `ts/packages/cli/CHANGELOG.md`. https://claude.ai/code/session_01AW7ZPhfZuni6PrCJ9X86DX
392 lines
14 KiB
YAML
392 lines
14 KiB
YAML
name: E2E Test Typescript SDK
|
|
|
|
on:
|
|
push:
|
|
branches: [master, next]
|
|
paths:
|
|
- 'ts/**'
|
|
# A catalog pin or lockfile change swaps what every ts/** package
|
|
# resolves without touching one of their files -- @composio/client
|
|
# 0.1.0-alpha.76 -> 2.0.0-rc.5 skipped this suite entirely that way.
|
|
- 'pnpm-workspace.yaml'
|
|
- 'pnpm-lock.yaml'
|
|
- '.github/actions/setup-node-pnpm-bun/action.yml'
|
|
- '.github/workflows/ts.test-e2e.yml'
|
|
- 'mise.toml'
|
|
- 'mise.lock'
|
|
- 'toolchain-versions.json'
|
|
pull_request:
|
|
paths:
|
|
- 'ts/**'
|
|
# A catalog pin or lockfile change swaps what every ts/** package
|
|
# resolves without touching one of their files -- @composio/client
|
|
# 0.1.0-alpha.76 -> 2.0.0-rc.5 skipped this suite entirely that way.
|
|
- 'pnpm-workspace.yaml'
|
|
- 'pnpm-lock.yaml'
|
|
- '.github/actions/setup-node-pnpm-bun/action.yml'
|
|
- '.github/workflows/ts.test-e2e.yml'
|
|
- 'mise.toml'
|
|
- 'mise.lock'
|
|
- 'toolchain-versions.json'
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}
|
|
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
# Print Turborepo telemetry events to the logs instead of sending them.
|
|
env:
|
|
TURBO_TELEMETRY_DEBUG: 1
|
|
|
|
jobs:
|
|
toolchain-versions:
|
|
name: Read toolchain test matrix
|
|
runs-on: ubuntu-24.04
|
|
permissions: read-all
|
|
outputs:
|
|
node: ${{ steps.versions.outputs.node }}
|
|
deno: ${{ steps.versions.outputs.deno }}
|
|
steps:
|
|
- name: Checkout Code
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
|
|
- name: Read versions
|
|
id: versions
|
|
run: |
|
|
echo "node=$(jq -c '.node' toolchain-versions.json)" >> "$GITHUB_OUTPUT"
|
|
echo "deno=$(jq -c '.deno' toolchain-versions.json)" >> "$GITHUB_OUTPUT"
|
|
|
|
# Node.js E2E tests, running in Docker to isolate environment
|
|
# Each test suite defines its own versions.node in e2e.test.ts
|
|
# Tests that don't support the matrix version are automatically skipped
|
|
test-e2e-node-docker:
|
|
name: E2E Test Node.js ${{ matrix.node-version }}
|
|
needs: toolchain-versions
|
|
runs-on: ubuntu-24.04
|
|
permissions: read-all
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
node-version: ${{ fromJSON(needs.toolchain-versions.outputs.node) }}
|
|
env:
|
|
CI: 1
|
|
COMPOSIO_API_KEY: ${{ secrets.COMPOSIO_API_KEY }}
|
|
COMPOSIO_BASE_URL: ${{ secrets.COMPOSIO_BASE_URL_STAGING }}
|
|
COMPOSIO_USER_API_KEY: ${{ secrets.COMPOSIO_USER_API_KEY }}
|
|
COMPOSIO_E2E_NODE_VERSION: ${{ matrix.node-version }}
|
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
|
|
steps:
|
|
- name: Checkout Code
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
|
|
- name: Normalize Composio API keys
|
|
run: |
|
|
{
|
|
echo "COMPOSIO_USER_API_KEY=${COMPOSIO_USER_API_KEY}"
|
|
echo "COMPOSIO_API_KEY=${COMPOSIO_API_KEY}"
|
|
echo "COMPOSIO_BASE_URL=${COMPOSIO_BASE_URL}"
|
|
} >> "$GITHUB_ENV"
|
|
|
|
- name: Setup Node.js, pnpm, Bun
|
|
id: setup-toolchain
|
|
uses: ./.github/actions/setup-node-pnpm-bun
|
|
with:
|
|
enable-turbo-cache: 'true'
|
|
|
|
- name: Install Dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Build
|
|
run: pnpm run build:packages
|
|
|
|
- name: Check API keys
|
|
id: api-keys
|
|
env:
|
|
IS_FORK_PR: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork }}
|
|
run: |
|
|
missing=()
|
|
for name in COMPOSIO_API_KEY OPENAI_API_KEY ANTHROPIC_API_KEY; do
|
|
if [ -z "${!name}" ]; then
|
|
missing+=("$name")
|
|
fi
|
|
done
|
|
|
|
if [ "${#missing[@]}" -gt 0 ]; then
|
|
echo "available=false" >> "$GITHUB_OUTPUT"
|
|
if [ "$GITHUB_ACTOR" = "dependabot[bot]" ] || [ "$IS_FORK_PR" = "true" ]; then
|
|
echo "::notice::Skipping secret-backed E2E tests; missing ${missing[*]}."
|
|
exit 0
|
|
fi
|
|
|
|
printf '::error::%s is not set\n' "${missing[@]}"
|
|
exit 1
|
|
fi
|
|
|
|
echo "available=true" >> "$GITHUB_OUTPUT"
|
|
echo "✅ API keys are configured"
|
|
|
|
- name: Pre-build Docker image for e2e tests
|
|
if: steps.api-keys.outputs.available == 'true'
|
|
run: |
|
|
docker build -f ts/e2e-tests/_utils/Dockerfile.node \
|
|
--build-arg NODE_VERSION=${{ matrix.node-version }} \
|
|
--label composio.e2e=true \
|
|
--label composio.runtime=node \
|
|
--label "composio.node_version=${{ matrix.node-version }}" \
|
|
-t "composio-e2e-node:${{ matrix.node-version }}" \
|
|
.
|
|
|
|
- name: Run Node.js E2E Tests
|
|
if: steps.api-keys.outputs.available == 'true'
|
|
run: pnpm run test:e2e:node
|
|
|
|
# Deno E2E tests, running in Docker to isolate environment
|
|
# Each test suite defines its own versions.deno in e2e.test.ts
|
|
# Tests that don't support the matrix version are automatically skipped
|
|
test-e2e-deno-docker:
|
|
name: E2E Test Deno ${{ matrix.deno-version }}
|
|
needs: toolchain-versions
|
|
runs-on: ubuntu-24.04
|
|
permissions: read-all
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
deno-version: ${{ fromJSON(needs.toolchain-versions.outputs.deno) }}
|
|
env:
|
|
CI: 1
|
|
COMPOSIO_API_KEY: ${{ secrets.COMPOSIO_API_KEY }}
|
|
COMPOSIO_BASE_URL: ${{ secrets.COMPOSIO_BASE_URL_STAGING }}
|
|
COMPOSIO_USER_API_KEY: ${{ secrets.COMPOSIO_USER_API_KEY }}
|
|
COMPOSIO_E2E_DENO_VERSION: ${{ matrix.deno-version }}
|
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
|
|
steps:
|
|
- name: Checkout Code
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
|
|
- name: Normalize Composio API keys
|
|
run: |
|
|
{
|
|
echo "COMPOSIO_USER_API_KEY=${COMPOSIO_USER_API_KEY}"
|
|
echo "COMPOSIO_API_KEY=${COMPOSIO_API_KEY}"
|
|
echo "COMPOSIO_BASE_URL=${COMPOSIO_BASE_URL}"
|
|
} >> "$GITHUB_ENV"
|
|
|
|
- name: Setup Deno
|
|
uses: denoland/setup-deno@22d081ff2d3a40755e97629de92e3bcbfa7cf2ed # v2.0.5
|
|
with:
|
|
deno-version: ${{ matrix.deno-version }}
|
|
|
|
- name: Setup Node.js, pnpm, Bun
|
|
id: setup-toolchain
|
|
uses: ./.github/actions/setup-node-pnpm-bun
|
|
with:
|
|
enable-turbo-cache: 'true'
|
|
|
|
- name: Install Dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Build
|
|
run: pnpm run build:packages
|
|
|
|
- name: Check API keys
|
|
id: api-keys
|
|
env:
|
|
IS_FORK_PR: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork }}
|
|
run: |
|
|
missing=()
|
|
for name in COMPOSIO_API_KEY OPENAI_API_KEY; do
|
|
if [ -z "${!name}" ]; then
|
|
missing+=("$name")
|
|
fi
|
|
done
|
|
|
|
if [ "${#missing[@]}" -gt 0 ]; then
|
|
echo "available=false" >> "$GITHUB_OUTPUT"
|
|
if [ "$GITHUB_ACTOR" = "dependabot[bot]" ] || [ "$IS_FORK_PR" = "true" ]; then
|
|
echo "::notice::Skipping secret-backed E2E tests; missing ${missing[*]}."
|
|
exit 0
|
|
fi
|
|
|
|
printf '::error::%s is not set\n' "${missing[@]}"
|
|
exit 1
|
|
fi
|
|
|
|
echo "available=true" >> "$GITHUB_OUTPUT"
|
|
echo "✅ API keys are configured"
|
|
|
|
# Pre-build the Deno image like the Node and CLI jobs do. Without this,
|
|
# ensureDenoImage() builds the image inside a bun:test beforeAll hook,
|
|
# where the bun shell's quiet mode swallows all build output and a slow
|
|
# registry or apt moment turns into an opaque hook timeout instead of a
|
|
# visible, retryable step failure.
|
|
- name: Pre-build Docker image for e2e tests
|
|
if: steps.api-keys.outputs.available == 'true'
|
|
run: |
|
|
NODE_MAJOR="${{ steps.setup-toolchain.outputs.node-version }}"
|
|
docker build -f ts/e2e-tests/_utils/Dockerfile.deno \
|
|
--build-arg DENO_VERSION=${{ matrix.deno-version }} \
|
|
--build-arg NODE_MAJOR=${NODE_MAJOR%%.*} \
|
|
--label composio.e2e=true \
|
|
--label composio.runtime=deno \
|
|
--label "composio.deno_version=${{ matrix.deno-version }}" \
|
|
-t "composio-e2e-deno:${{ matrix.deno-version }}" \
|
|
.
|
|
|
|
- name: Run Deno E2E Tests
|
|
if: steps.api-keys.outputs.available == 'true'
|
|
run: pnpm run test:e2e:deno
|
|
|
|
# CLI E2E tests, running in scratch Docker to isolate environment
|
|
test-e2e-cli-docker:
|
|
name: E2E Test CLI (scratch)
|
|
runs-on: ubuntu-24.04
|
|
permissions: read-all
|
|
env:
|
|
CI: 1
|
|
COMPOSIO_USER_API_KEY: ${{ secrets.COMPOSIO_USER_API_KEY }}
|
|
COMPOSIO_API_KEY: ${{ secrets.COMPOSIO_API_KEY }}
|
|
COMPOSIO_BASE_URL: ${{ secrets.COMPOSIO_BASE_URL_STAGING }}
|
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
|
|
steps:
|
|
- name: Checkout Code
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
|
|
- name: Normalize Composio API keys
|
|
run: |
|
|
{
|
|
echo "COMPOSIO_USER_API_KEY=${COMPOSIO_USER_API_KEY}"
|
|
echo "COMPOSIO_API_KEY=${COMPOSIO_API_KEY}"
|
|
echo "COMPOSIO_BASE_URL=${COMPOSIO_BASE_URL}"
|
|
} >> "$GITHUB_ENV"
|
|
|
|
- name: Setup Node.js, pnpm, Bun
|
|
id: setup-toolchain
|
|
uses: ./.github/actions/setup-node-pnpm-bun
|
|
with:
|
|
enable-turbo-cache: 'true'
|
|
|
|
- name: Install Dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Build
|
|
run: pnpm run build:packages
|
|
|
|
- name: Check API keys
|
|
id: api-keys
|
|
env:
|
|
IS_FORK_PR: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork }}
|
|
run: |
|
|
missing=()
|
|
for name in COMPOSIO_API_KEY OPENAI_API_KEY COMPOSIO_USER_API_KEY; do
|
|
if [ -z "${!name}" ]; then
|
|
missing+=("$name")
|
|
fi
|
|
done
|
|
|
|
if [ "${#missing[@]}" -gt 0 ]; then
|
|
echo "available=false" >> "$GITHUB_OUTPUT"
|
|
if [ "$GITHUB_ACTOR" = "dependabot[bot]" ] || [ "$IS_FORK_PR" = "true" ]; then
|
|
echo "::notice::Skipping secret-backed E2E tests; missing ${missing[*]}."
|
|
exit 0
|
|
fi
|
|
|
|
printf '::error::%s is not set\n' "${missing[@]}"
|
|
exit 1
|
|
fi
|
|
|
|
echo "available=true" >> "$GITHUB_OUTPUT"
|
|
echo "✅ API keys are configured"
|
|
|
|
- name: Pre-build Docker image for CLI e2e tests
|
|
run: |
|
|
CLI_VERSION=$(node -p "require('./ts/packages/cli/package.json').version")
|
|
echo "COMPOSIO_E2E_CLI_VERSION=${CLI_VERSION}" >> "$GITHUB_ENV"
|
|
docker build -f ts/e2e-tests/_utils/Dockerfile.cli \
|
|
--build-arg CLI_VERSION="${CLI_VERSION}" \
|
|
--build-arg NODE_VERSION="${{ steps.setup-toolchain.outputs.node-version }}" \
|
|
--label composio.e2e=true \
|
|
--label composio.runtime=cli \
|
|
--label "composio.cli_version=${CLI_VERSION}" \
|
|
-t "composio-e2e-cli:${CLI_VERSION}" \
|
|
.
|
|
|
|
- name: Run CLI E2E Tests
|
|
if: steps.api-keys.outputs.available == 'true'
|
|
run: pnpm run test:e2e:cli
|
|
|
|
# Cloudflare Workerd E2E tests
|
|
test-e2e-cloudflare:
|
|
name: E2E Test Cloudflare Workerd
|
|
runs-on: ubuntu-24.04
|
|
permissions: read-all
|
|
env:
|
|
COMPOSIO_API_KEY: ${{ secrets.COMPOSIO_API_KEY }}
|
|
COMPOSIO_BASE_URL: ${{ secrets.COMPOSIO_BASE_URL_STAGING }}
|
|
COMPOSIO_USER_API_KEY: ${{ secrets.COMPOSIO_USER_API_KEY }}
|
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
|
|
steps:
|
|
- name: Checkout Code
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
|
|
- name: Normalize Composio API keys
|
|
run: |
|
|
{
|
|
echo "COMPOSIO_USER_API_KEY=${COMPOSIO_USER_API_KEY}"
|
|
echo "COMPOSIO_API_KEY=${COMPOSIO_API_KEY}"
|
|
echo "COMPOSIO_BASE_URL=${COMPOSIO_BASE_URL}"
|
|
} >> "$GITHUB_ENV"
|
|
|
|
- name: Setup Node.js, pnpm, Bun
|
|
uses: ./.github/actions/setup-node-pnpm-bun
|
|
with:
|
|
enable-turbo-cache: 'true'
|
|
|
|
- name: Install Dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Build
|
|
run: pnpm run build:packages
|
|
|
|
- name: Check API keys
|
|
id: api-keys
|
|
env:
|
|
IS_FORK_PR: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork }}
|
|
run: |
|
|
missing=()
|
|
for name in COMPOSIO_API_KEY OPENAI_API_KEY; do
|
|
if [ -z "${!name}" ]; then
|
|
missing+=("$name")
|
|
fi
|
|
done
|
|
|
|
if [ "${#missing[@]}" -gt 0 ]; then
|
|
echo "available=false" >> "$GITHUB_OUTPUT"
|
|
if [ "$GITHUB_ACTOR" = "dependabot[bot]" ] || [ "$IS_FORK_PR" = "true" ]; then
|
|
echo "::notice::Skipping secret-backed E2E tests; missing ${missing[*]}."
|
|
exit 0
|
|
fi
|
|
|
|
printf '::error::%s is not set\n' "${missing[@]}"
|
|
exit 1
|
|
fi
|
|
|
|
echo "available=true" >> "$GITHUB_OUTPUT"
|
|
echo "✅ API keys are configured"
|
|
|
|
- name: Run Cloudflare Workers E2E Tests
|
|
if: steps.api-keys.outputs.available == 'true'
|
|
run: pnpm run test:e2e:cloudflare
|
|
env:
|
|
COMPOSIO_USER_API_KEY: ${{ secrets.COMPOSIO_USER_API_KEY }}
|
|
COMPOSIO_API_KEY: ${{ secrets.COMPOSIO_API_KEY }}
|
|
COMPOSIO_BASE_URL: ${{ secrets.COMPOSIO_BASE_URL_STAGING }}
|
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|