feat: migrate repo releases to manual release-please (#293)

This commit is contained in:
Trevin Chow
2026-03-17 17:58:13 -07:00
committed by GitHub
parent 74fb71731a
commit f47f829d81
44 changed files with 1967 additions and 801 deletions

View File

@@ -1,3 +1,6 @@
import { mkdtempSync, rmSync, writeFileSync } from "fs"
import os from "os"
import path from "path"
import { describe, expect, test } from "bun:test"
import { convertClaudeToKiro, transformContentForKiro } from "../src/converters/claude-to-kiro"
import { parseFrontmatter } from "../src/utils/frontmatter"
@@ -274,7 +277,7 @@ describe("convertClaudeToKiro", () => {
expect(warnings.some((w) => w.includes("Kiro"))).toBe(true)
})
test("steering file not generated when CLAUDE.md missing", () => {
test("steering file not generated when repo instruction files are missing", () => {
const plugin: ClaudePlugin = {
...fixturePlugin,
root: "/tmp/nonexistent-plugin-dir",
@@ -287,6 +290,27 @@ describe("convertClaudeToKiro", () => {
expect(bundle.steeringFiles).toHaveLength(0)
})
test("steering file prefers AGENTS.md over CLAUDE.md", () => {
const root = mkdtempSync(path.join(os.tmpdir(), "kiro-steering-"))
writeFileSync(path.join(root, "AGENTS.md"), "# AGENTS\nUse AGENTS instructions.")
writeFileSync(path.join(root, "CLAUDE.md"), "# CLAUDE\nUse CLAUDE instructions.")
const plugin: ClaudePlugin = {
...fixturePlugin,
root,
agents: [],
commands: [],
skills: [],
}
const bundle = convertClaudeToKiro(plugin, defaultOptions)
rmSync(root, { recursive: true, force: true })
expect(bundle.steeringFiles).toHaveLength(1)
expect(bundle.steeringFiles[0].content).toContain("Use AGENTS instructions.")
expect(bundle.steeringFiles[0].content).not.toContain("Use CLAUDE instructions.")
})
test("name normalization handles various inputs", () => {
const plugin: ClaudePlugin = {
...fixturePlugin,

View File

@@ -0,0 +1,102 @@
import { describe, expect, test } from "bun:test"
import {
applyOverride,
bumpVersion,
detectComponentsFromFiles,
inferBumpFromIntent,
parseReleaseIntent,
resolveComponentWarnings,
} from "../src/release/components"
describe("release component detection", () => {
test("maps plugin-only changes to the matching plugin component", () => {
const components = detectComponentsFromFiles([
"plugins/compound-engineering/skills/ce-plan/SKILL.md",
])
expect(components.get("compound-engineering")).toEqual([
"plugins/compound-engineering/skills/ce-plan/SKILL.md",
])
expect(components.get("cli")).toEqual([])
expect(components.get("coding-tutor")).toEqual([])
expect(components.get("marketplace")).toEqual([])
})
test("maps cli and plugin changes independently", () => {
const components = detectComponentsFromFiles([
"src/commands/install.ts",
"plugins/coding-tutor/.claude-plugin/plugin.json",
])
expect(components.get("cli")).toEqual(["src/commands/install.ts"])
expect(components.get("coding-tutor")).toEqual([
"plugins/coding-tutor/.claude-plugin/plugin.json",
])
})
test("maps marketplace metadata without bumping plugin components", () => {
const components = detectComponentsFromFiles([".claude-plugin/marketplace.json"])
expect(components.get("marketplace")).toEqual([".claude-plugin/marketplace.json"])
expect(components.get("compound-engineering")).toEqual([])
expect(components.get("coding-tutor")).toEqual([])
})
})
describe("release intent parsing", () => {
test("parses conventional titles with optional scope and breaking marker", () => {
const parsed = parseReleaseIntent("feat(coding-tutor)!: add tutor reset flow")
expect(parsed.type).toBe("feat")
expect(parsed.scope).toBe("coding-tutor")
expect(parsed.breaking).toBe(true)
expect(parsed.description).toBe("add tutor reset flow")
})
test("supports conventional titles without scope", () => {
const parsed = parseReleaseIntent("fix: adjust ce:plan-beta wording")
expect(parsed.type).toBe("fix")
expect(parsed.scope).toBeNull()
expect(parsed.breaking).toBe(false)
})
test("infers bump levels from parsed intent", () => {
expect(inferBumpFromIntent(parseReleaseIntent("feat: add release preview"))).toBe("minor")
expect(inferBumpFromIntent(parseReleaseIntent("fix: correct preview output"))).toBe("patch")
expect(inferBumpFromIntent(parseReleaseIntent("docs: update requirements"))).toBeNull()
expect(inferBumpFromIntent(parseReleaseIntent("refactor!: break compatibility"))).toBe("major")
})
})
describe("override handling", () => {
test("keeps inferred bump when override is auto", () => {
expect(applyOverride("patch", "auto")).toBe("patch")
})
test("promotes inferred bump when override is explicit", () => {
expect(applyOverride("patch", "minor")).toBe("minor")
expect(applyOverride(null, "major")).toBe("major")
})
test("increments semver versions", () => {
expect(bumpVersion("2.42.0", "patch")).toBe("2.42.1")
expect(bumpVersion("2.42.0", "minor")).toBe("2.43.0")
expect(bumpVersion("2.42.0", "major")).toBe("3.0.0")
})
})
describe("scope mismatch warnings", () => {
test("does not require scope when omitted", () => {
const warnings = resolveComponentWarnings(
parseReleaseIntent("fix: update ce plan copy"),
["compound-engineering"],
)
expect(warnings).toEqual([])
})
test("warns when explicit scope contradicts detected files", () => {
const warnings = resolveComponentWarnings(
parseReleaseIntent("fix(cli): update coding tutor text"),
["coding-tutor"],
)
expect(warnings[0]).toContain('Optional scope "cli" does not match')
})
})

View File

@@ -0,0 +1,23 @@
import { describe, expect, test } from "bun:test"
import { buildCompoundEngineeringDescription, renderChangelogEntry } from "../src/release/metadata"
describe("release metadata", () => {
test("builds the current compound-engineering manifest description from repo counts", async () => {
const description = await buildCompoundEngineeringDescription(process.cwd())
expect(description).toBe(
"AI-powered development tools. 29 agents, 44 skills, 1 MCP server for code review, research, design, and workflow automation.",
)
})
test("renders root changelog entries with component-version headings", () => {
const entry = renderChangelogEntry("compound-engineering", "2.43.0", "2026-04-10", {
Features: ["Add release preview"],
Fixes: ["Correct changelog rendering"],
})
expect(entry).toContain("## compound-engineering v2.43.0 - 2026-04-10")
expect(entry).toContain("### Features")
expect(entry).toContain("- Add release preview")
expect(entry).toContain("### Fixes")
})
})

View File

@@ -0,0 +1,41 @@
import { describe, expect, test } from "bun:test"
import { buildReleasePreview } from "../src/release/components"
describe("release preview", () => {
test("uses changed files to determine affected components and next versions", async () => {
const preview = await buildReleasePreview({
title: "fix: adjust ce:plan-beta wording",
files: ["plugins/compound-engineering/skills/ce-plan-beta/SKILL.md"],
})
expect(preview.components).toHaveLength(1)
expect(preview.components[0].component).toBe("compound-engineering")
expect(preview.components[0].inferredBump).toBe("patch")
expect(preview.components[0].nextVersion).toBe("2.42.1")
})
test("supports per-component overrides without affecting unrelated components", async () => {
const preview = await buildReleasePreview({
title: "fix: update coding tutor prompts",
files: ["plugins/coding-tutor/README.md"],
overrides: {
"coding-tutor": "minor",
},
})
expect(preview.components).toHaveLength(1)
expect(preview.components[0].component).toBe("coding-tutor")
expect(preview.components[0].inferredBump).toBe("patch")
expect(preview.components[0].effectiveBump).toBe("minor")
expect(preview.components[0].nextVersion).toBe("1.3.0")
})
test("docs-only changes remain non-releasable by default", async () => {
const preview = await buildReleasePreview({
title: "docs: update release planning notes",
files: ["docs/plans/2026-03-17-001-feat-release-automation-migration-beta-plan.md"],
})
expect(preview.components).toHaveLength(0)
})
})