Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/RELEASE_CHECKLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ Create or update the GitHub Release body before publishing the release. Use Engl
- [macOS Intel](https://github.com/Astro-Han/pawwork/releases/download/vX.Y.Z/pawwork-mac-x64.dmg)
- [Windows](https://github.com/Astro-Han/pawwork/releases/download/vX.Y.Z/pawwork-win-x64.exe)

## App Update Notice

- Short product-facing sentence for the in-app post-update modal. Do not include download links, PR numbers, verification details, or maintenance-only notes.

## Highlights

- User-facing changes, bug fixes, or packaging fixes.
Expand Down
8 changes: 4 additions & 4 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/app",
"version": "0.2.5",
"version": "0.2.6",
"description": "",
"type": "module",
"exports": {
Expand Down
32 changes: 27 additions & 5 deletions packages/app/src/context/highlights.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { describe, expect, test } from "bun:test"
import { loadReleaseHighlights } from "./highlights"

describe("loadReleaseHighlights (GitHub Releases API)", () => {
test("synthesizes a single PawWork highlight from the release body", () => {
test("reads the app-facing update notice section from the release body", () => {
const payload = [
{
tag_name: "v0.2.3",
name: "v0.2.3",
body: "Fixed first-message crash\n- bumped Minimax-M2.5\n",
body: "## Downloads\n\n- [macOS](https://example.com/app.dmg)\n\n## App Update Notice\n\nFixed first-message crash\n",
},
]
const highlights = loadReleaseHighlights(payload, "0.2.3", "0.2.2")
Expand All @@ -18,11 +18,11 @@ describe("loadReleaseHighlights (GitHub Releases API)", () => {
})
})

test("skips markdown headings and strips bullet markers on the first summary line", () => {
test("skips markdown headings and strips bullet markers inside the app update notice section", () => {
const payload = [
{
tag_name: "v0.3.0",
body: "## Desktop\n\n- Added dark theme\n- Fixed dock icon\n",
body: "## Downloads\n\n- [macOS](https://example.com/app.dmg)\n\n## App Update Notice\n\n### Desktop\n\n- Added dark theme\n- Fixed dock icon\n\n## Verification\n\n- CI passed\n",
},
]
const highlights = loadReleaseHighlights(payload, "0.3.0", "0.2.3")
Expand All @@ -31,12 +31,34 @@ describe("loadReleaseHighlights (GitHub Releases API)", () => {

test("truncates long summaries with an ellipsis", () => {
const long = "a".repeat(300)
const payload = [{ tag_name: "v1.0.0", body: long }]
const payload = [{ tag_name: "v1.0.0", body: `## App Update Notice\n\n${long}` }]
const highlights = loadReleaseHighlights(payload, "1.0.0", "0.9.0")
expect(highlights[0].description.endsWith("…")).toBe(true)
expect(highlights[0].description.length).toBe(201)
})

test("does not guess from downloads when the app update notice section is missing", () => {
const payload = [
{
tag_name: "v0.2.6",
body: "## Downloads\n\n- [macOS Apple Silicon](https://github.com/Astro-Han/pawwork/releases/download/v0.2.6/pawwork-mac-arm64.dmg)\n\n## Highlights\n\n- Maintenance fixes\n",
},
]
expect(loadReleaseHighlights(payload, "0.2.6", "0.2.5")).toHaveLength(0)
})

test("stops app update notice parsing at empty same-level headings", () => {
const payload = [
{
tag_name: "v0.2.6",
body: "## App Update Notice\n\n- Fixed update notices\n\n##\n\n- [macOS](https://example.com/app.dmg)\n",
},
]
const highlights = loadReleaseHighlights(payload, "0.2.6", "0.2.5")
expect(highlights).toHaveLength(1)
expect(highlights[0].description).toBe("Fixed update notices")
})

test("returns no highlights when the body is empty or only headings", () => {
const payload = [{ tag_name: "v0.2.4", body: "# Title only\n\n## Heading only\n" }]
expect(loadReleaseHighlights(payload, "0.2.4", "0.2.3")).toHaveLength(0)
Expand Down
23 changes: 20 additions & 3 deletions packages/app/src/context/highlights.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,25 @@ function parseHighlight(value: unknown): Highlight | undefined {
return { title, description, media }
}

function summarizeBody(body: string): string | undefined {
const lines = body
function findAppUpdateNotice(body: string): string | undefined {
const lines = body.split(/\r?\n/)
const start = lines.findIndex((line) => /^#{2,6}\s+App Update Notice\s*$/i.test(line.trim()))
if (start === -1) return

const headingLevel = lines[start].trim().match(/^#+/)?.[0].length ?? 2
const section = lines.slice(start + 1)
const end = section.findIndex((line) => {
const heading = line.trim().match(/^(#{1,6})(?:\s|$)/)
return heading !== null && heading[1].length <= headingLevel
})
return (end === -1 ? section : section.slice(0, end)).join("\n")
}

function summarizeAppUpdateNotice(body: string): string | undefined {
const notice = findAppUpdateNotice(body)
if (!notice) return

const lines = notice
.split(/\r?\n/)
.map((line) => line.trim())
.filter((line) => line.length > 0 && !line.startsWith("#"))
Expand Down Expand Up @@ -97,7 +114,7 @@ function parseRelease(value: unknown): ParsedRelease | undefined {

const body = getText(value.body)
if (tag && body) {
const summary = summarizeBody(body)
const summary = summarizeAppUpdateNotice(body)
if (summary) {
return {
tag,
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop-electron/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@opencode-ai/desktop-electron",
"private": true,
"version": "0.2.5",
"version": "0.2.6",
"type": "module",
"license": "Apache-2.0",
"homepage": "https://pawwork.ai",
Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/package.json",
"version": "0.2.5",
"version": "0.2.6",
"name": "opencode",
"type": "module",
"license": "Apache-2.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/util/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/util",
"version": "0.2.5",
"version": "0.2.6",
"private": true,
"type": "module",
"license": "Apache-2.0",
Expand Down
Loading