Commit Graph

12 Commits

Author SHA1 Message Date
Maxim adaeda2dc6 fix(release): enforce GHA-safe output keys and tighten publish guards
Round-2 review fixes for the GITHUB_OUTPUT helper and the release scripts
that emit through it.

emitGithubOutputs (scripts/release/lib/github-output.ts):
- Replace the key newline/CR check with a full GitHub-Actions-safe charset
  check: /^[A-Za-z_][A-Za-z0-9_-]*$/. A key containing "=" or whitespace
  would silently corrupt the key=value line; rejecting up-front is
  strictly safer. Value validation (single-line) is unchanged — "=" in
  values is legal because GitHub splits on the first "=".
- Update the docblock accordingly.

prerelease.ts:
- Remove the dead `?? getCurrentVersion(scope)` fallback. The empty-list
  guard above makes packages[0] guaranteed, and the fallback would have
  masked a package.json missing its version field by emitting a version
  divergent from what the loop publishes. Fail loudly with an explicit
  exit instead.
- Drop the now-unused getCurrentVersion import.
- Add a comment above the dry-run emitGithubOutputs call explaining that
  emitting in dry-run is safe — the publish workflow gates publish + the
  verify guard on inputs.dry-run != true, so the dry-run emission only
  serves local/e2e contract verification.

publish-release.ts:
- Hoist getPackagesForScope + empty-list guard above the prerelease-suffix
  and registry checks. A misconfigured scope now fails with the clear
  "no packages found" error instead of a misleading "not greater than
  published" one. Loop is unchanged.

github-output.test.ts:
- Loosen the key-newline assertion from the JSON.stringify-coupled
  /bad\\nkey/ to the stable /alphanumeric/ phrase from the new message.
- Add tests: "=" in key throws, space in key throws, empty key throws,
  and "=" in value is accepted and written verbatim (note=a=b).
- Move vi.restoreAllMocks() to the top of afterEach so spies cannot leak
  into env restore + rmSync cleanup.

Call sites audited:
- emitGithubOutputs: only ever called with {version, scope} (prerelease,
  publish-release) — all valid under the new charset.
- publishVersion derivation: only used inside prerelease.ts main().
- getCurrentVersion: still imported by publish-release.ts, bump-prerelease.ts,
  prepare-release.ts; only the prerelease.ts import was removed.
- getPackagesForScope hoist in publish-release.ts: `packages` was only
  read inside the publish loop below; nothing earlier depended on it.
2026-06-10 22:58:03 +02:00
Maxim e8fa74ce45 fix(release): validate GITHUB_OUTPUT values and fail loudly on empty package lists
Hardens the new GITHUB_OUTPUT emission path so a malformed value can't smuggle
extra `key=value` lines into the workflow's step outputs, and so the workflow's
"Verify publish step emitted version" guard can't be fooled by a publish that
did nothing.

emitGithubOutputs now validates every key/value for `\n`/`\r` BEFORE the
GITHUB_OUTPUT early-return — a malformed value is a caller bug and should fail
loudly even when running locally. A multi-line value would need the heredoc
form, which this helper deliberately does not support.

prerelease.ts and publish-release.ts now fail loud when getPackagesForScope
returns an empty list. Without this, the new GITHUB_OUTPUT emission would make
the workflow's "Verify publish step emitted version" guard pass on a run that
published nothing — previously the missing output made such a run fail. The
guard runs BEFORE the dry-run branch in prerelease.ts. In publish-release.ts,
the inline iteration of getPackagesForScope(scope) is hoisted to a `packages`
const so the same guard fires before the publish loop.

The "no-op when GITHUB_OUTPUT is unset" test now spies on fs.appendFileSync
and asserts it wasn't called (the previous read of the unrelated temp file
was vacuously true). New tests cover newline/CR in value and newline in key.

The prerelease.ts usage string previously advertised `[--suffix <label>]`,
but the script never parses --suffix (suffix handling lives in
bump-prerelease.ts per the header comment). Removed.

Call sites enumerated:
- emitGithubOutputs: prerelease.ts (dry-run + post-publish), publish-release.ts
- getPackagesForScope: prerelease.ts, publish-release.ts (this commit);
  bump-prerelease.ts, prepare-release.ts, versions.ts (not changed — out of
  scope for this hardening)

Verification:
- npx vitest run --config scripts/release/vitest.config.mts → 91 passed
- Red-green for the newline validation: temporarily removed the validation,
  the 3 new newline/CR tests failed (assertion: expected fn to throw); restored,
  back to green.
- E2E: GITHUB_OUTPUT="$OUT" pnpm release:prerelease:dry succeeded and the
  output file contained `version=1.59.5` and `scope=monorepo`.

Note: Fix 2's empty-list guard fires only on a misconfigured scope (no unit
test reachable — prerelease.ts is outside the vitest include glob and the
guard is boundary validation against a misconfigured scope, not a behavior
worth contriving a test harness for).
2026-06-10 22:58:02 +02:00
Maxim afef53de65 fix(release): emit version/scope to GITHUB_OUTPUT from prerelease.ts
prerelease.ts published canaries successfully but never wrote the
version output the publish-release workflow's "Verify publish step
emitted version" guard reads, so every canary dispatch ended red after
a successful publish. Extract the GITHUB_OUTPUT append (previously
inline in publish-release.ts) into a shared lib/github-output.ts helper
and call it from both publish scripts.

Call-site enumeration:
- emitGithubOutputs: declared lib/github-output.ts; called from
  prerelease.ts (dry-run path + after publish) and publish-release.ts
  (replaces the inline appendFileSync block, same version=/scope= keys).
- No symbols removed; fs import in publish-release.ts still used (3
  remaining call sites).
2026-06-10 22:58:02 +02:00
Tyler Slaton fe685eb46f feat(release): npm release scopes for bot(+bot-ui) and bot-slack
- release.config.json: 'bot' scope versions @copilotkit/bot and
  @copilotkit/bot-ui together (sharedVersion: true, source: bot);
  'bot-slack' is its own scope, mirroring the angular precedent
- ReleaseScope type + VALID_SCOPES arrays + usage strings extended across
  release scripts
- stable-release.yml / publish-release.yml: scope choice options
- bot, bot-ui, bot-slack manifests: drop private, add publishConfig (public),
  repository/homepage/keywords, publint/attw targets; first release v0.0.1
- internal bot-package deps use workspace:~ (tilde): caret on a 0.0.x version
  pins the exact patch, tilde tracks the 0.0.x line; core/shared stay
  workspace:^ (caret is correct at 1.x)

Verified: release-script tests 85/85; prepare-release --scope bot --dry-run
bumps bot AND bot-ui in lockstep; actionlint clean on touched lines.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 12:57:13 -07:00
Jordan Ritter b11e87c33f fix(release): route release notifications to #engr instead of #oss-alerts
Release alerts belong in #engr per corrected routing. SLACK_WEBHOOK_ENGR
is the org-wide secret (visibility=all), so no provisioning is needed.
2026-06-03 20:58:57 -07:00
Jordan Ritter 76bbac5073 feat(release): add tested #oss-alerts release-notification builder
Add a pure builder that renders one concise #oss-alerts Slack message
per release from a unit-tested truth table: suppresses canary/dry-run
runs, gates npm/PyPI failure arms on event-derived release intent, and
pages on uncertain state. The CLI wrapper serializes env input to the
builder and writes the result to GITHUB_OUTPUT, failing loud on any
malformed or missing input.
2026-06-03 20:30:57 -07:00
Mike Ryan 8648e4a838 chore: remove CopilotKit CLI 2026-05-01 13:16:49 -07:00
Tyler Slaton beff7a859e test: add bumpPackages tests, wire release tests into CI
- 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
2026-04-10 23:08:12 -07:00
Tyler Slaton 04edbd6593 fix: preserve workspace:* protocol when bumping package versions
bumpPackages was overwriting internal dependency references like
"workspace:*" with the new version string, causing pnpm to try
resolving the version from the npm registry (which fails because
it hasn't been published yet). Now skips deps using workspace protocol.
2026-04-10 23:07:03 -07:00
Tyler Slaton 2a880fb09c ci: add scope dropdown (monorepo, cli, angular) to release workflows
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.
2026-04-10 23:04:48 -07:00
Tyler Slaton 5b84c16b55 ci: fix Node 20 compat, rename workflows, add unit tests
- 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
2026-04-10 22:43:53 -07:00
Tyler Slaton 387784c7bd ci: add bespoke stateless release system
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
2026-04-10 22:20:43 -07:00