mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-08-28 19:11:03 +08:00
fix(jetbrains): address release workflow review
This commit is contained in:
@@ -114,7 +114,12 @@ jobs:
|
|||||||
|
|
||||||
- name: Render release notes
|
- name: Render release notes
|
||||||
working-directory: packages/kilo-jetbrains
|
working-directory: packages/kilo-jetbrains
|
||||||
run: ./gradlew getChangelog --project-version "$VERSION" --no-header --no-empty-sections --output-file=build/release-notes.md
|
run: |
|
||||||
|
if ! grep -Fq "## [$VERSION]" CHANGELOG.md; then
|
||||||
|
echo "Missing packages/kilo-jetbrains/CHANGELOG.md entry for $VERSION. Create a release PR or add the changelog section before tagging." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
./gradlew getChangelog --project-version "$VERSION" --no-header --no-empty-sections --output-file=build/release-notes.md
|
||||||
env:
|
env:
|
||||||
VERSION: ${{ steps.version.outputs.version }}
|
VERSION: ${{ steps.version.outputs.version }}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
types:
|
types:
|
||||||
- closed
|
- closed
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ The workflow chooses a changelog base automatically:
|
|||||||
|
|
||||||
Use `from_tag` only to override this comparison range.
|
Use `from_tag` only to override this comparison range.
|
||||||
|
|
||||||
|
For the first stable JetBrains release, there may be no previous stable tag yet. In that case, pass the last RC or another reviewed JetBrains tag as `from_tag`.
|
||||||
|
|
||||||
## Review the PR
|
## Review the PR
|
||||||
|
|
||||||
The workflow creates or updates a branch like:
|
The workflow creates or updates a branch like:
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ async function base(ver: string, kind: "rc" | "stable") {
|
|||||||
.map((item) => ({ tag: item, ver: item.replace(/^jetbrains\/v/, "") }))
|
.map((item) => ({ tag: item, ver: item.replace(/^jetbrains\/v/, "") }))
|
||||||
.filter((item) => semver.valid(item.ver))
|
.filter((item) => semver.valid(item.ver))
|
||||||
|
|
||||||
const target = semver.parse(ver)!
|
const want = semver.parse(ver)!
|
||||||
const stable = tags
|
const stable = tags
|
||||||
.filter((item) => !semver.prerelease(item.ver) && semver.lt(item.ver, ver))
|
.filter((item) => !semver.prerelease(item.ver) && semver.lt(item.ver, ver))
|
||||||
.sort((a, b) => semver.rcompare(a.ver, b.ver))
|
.sort((a, b) => semver.rcompare(a.ver, b.ver))
|
||||||
@@ -110,7 +110,7 @@ async function base(ver: string, kind: "rc" | "stable") {
|
|||||||
.filter((item) => {
|
.filter((item) => {
|
||||||
const parsed = semver.parse(item.ver)
|
const parsed = semver.parse(item.ver)
|
||||||
if (!parsed) return false
|
if (!parsed) return false
|
||||||
if (parsed.major !== target.major || parsed.minor !== target.minor || parsed.patch !== target.patch) return false
|
if (parsed.major !== want.major || parsed.minor !== want.minor || parsed.patch !== want.patch) return false
|
||||||
return Boolean(semver.prerelease(item.ver)) && semver.lt(item.ver, ver)
|
return Boolean(semver.prerelease(item.ver)) && semver.lt(item.ver, ver)
|
||||||
})
|
})
|
||||||
.sort((a, b) => semver.rcompare(a.ver, b.ver))
|
.sort((a, b) => semver.rcompare(a.ver, b.ver))
|
||||||
@@ -137,17 +137,41 @@ async function release(from: string, tag: string) {
|
|||||||
|
|
||||||
function section(ver: string, notes: string) {
|
function section(ver: string, notes: string) {
|
||||||
const date = new Date().toISOString().slice(0, 10)
|
const date = new Date().toISOString().slice(0, 10)
|
||||||
const lines = bullets(notes)
|
const groups = entries(notes)
|
||||||
return [`## [${ver}] - ${date}`, "", "### Changed", ...lines, ""].join("\n")
|
const lines = [`## [${ver}] - ${date}`, ""]
|
||||||
|
for (const title of ["Added", "Fixed", "Changed"] as const) {
|
||||||
|
const items = groups.get(title)
|
||||||
|
if (!items?.length) continue
|
||||||
|
lines.push(`### ${title}`, ...items, "")
|
||||||
|
}
|
||||||
|
if (lines.length === 2) lines.push("### Changed", "- No notable changes.", "")
|
||||||
|
return lines.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
function bullets(notes: string) {
|
function entries(notes: string) {
|
||||||
const lines = notes
|
const groups = new Map<string, string[]>([
|
||||||
|
["Added", []],
|
||||||
|
["Fixed", []],
|
||||||
|
["Changed", []],
|
||||||
|
])
|
||||||
|
for (const line of notes
|
||||||
.split(/\r?\n/)
|
.split(/\r?\n/)
|
||||||
.map((item) => item.trim())
|
.map((item) => item.trim())
|
||||||
.filter((item) => item.startsWith("- ") || item.startsWith("* "))
|
.filter((item) => item.startsWith("- ") || item.startsWith("* "))
|
||||||
.map((item) => `- ${item.slice(2).trim()}`)
|
.map((item) => item.slice(2).trim())) {
|
||||||
return lines.length > 0 ? lines : ["- No notable changes."]
|
if (line.startsWith("@") && line.includes(" made their first contribution ")) continue
|
||||||
|
const text = `- ${line}`
|
||||||
|
if (/^(feat|add)(\(.+\))?:/i.test(line)) {
|
||||||
|
groups.get("Added")!.push(text)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (/^(fix|bug)(\(.+\))?:/i.test(line)) {
|
||||||
|
groups.get("Fixed")!.push(text)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
groups.get("Changed")!.push(text)
|
||||||
|
}
|
||||||
|
return groups
|
||||||
}
|
}
|
||||||
|
|
||||||
async function writepkg(ver: string) {
|
async function writepkg(ver: string) {
|
||||||
@@ -157,7 +181,10 @@ async function writepkg(ver: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function writelog(ver: string, entry: string) {
|
async function writelog(ver: string, entry: string) {
|
||||||
const current = await Bun.file(log).text().catch(() => "# Changelog\n\n## [Unreleased]\n")
|
const current = await Bun.file(log).text().catch((err: NodeJS.ErrnoException) => {
|
||||||
|
if (err.code === "ENOENT") return "# Changelog\n\n## [Unreleased]\n"
|
||||||
|
throw err
|
||||||
|
})
|
||||||
const clean = current.replace(regex(ver), "").replace(/\n{3,}/g, "\n\n")
|
const clean = current.replace(regex(ver), "").replace(/\n{3,}/g, "\n\n")
|
||||||
const marker = "## [Unreleased]"
|
const marker = "## [Unreleased]"
|
||||||
if (!clean.includes(marker)) throw new Error("CHANGELOG.md must contain ## [Unreleased]")
|
if (!clean.includes(marker)) throw new Error("CHANGELOG.md must contain ## [Unreleased]")
|
||||||
@@ -167,7 +194,7 @@ async function writelog(ver: string, entry: string) {
|
|||||||
|
|
||||||
function regex(ver: string) {
|
function regex(ver: string) {
|
||||||
const safe = ver.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
const safe = ver.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
||||||
return new RegExp(`\\n?## \\[${safe}\\][\\s\\S]*?(?=\\n## \\[|$)`, "m")
|
return new RegExp(`\\n?## \\[${safe}\\][\\s\\S]*?(?=\\n## \\[|$)`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function body(ver: string, kind: string, from: string, tag: string, notes: string) {
|
function body(ver: string, kind: string, from: string, tag: string, notes: string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user