chore: prepare GoodBuddy 0.8.1
This commit is contained in:
@@ -30,9 +30,9 @@ jobs:
|
|||||||
timeout-minutes: 20
|
timeout-minutes: 20
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v7
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v7
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
cache: npm
|
cache: npm
|
||||||
@@ -54,7 +54,7 @@ jobs:
|
|||||||
run: npm run build:bundle
|
run: npm run build:bundle
|
||||||
|
|
||||||
- name: Upload production bundle
|
- name: Upload production bundle
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: goodbuddy-production-bundle
|
name: goodbuddy-production-bundle
|
||||||
path: out
|
path: out
|
||||||
@@ -90,15 +90,15 @@ jobs:
|
|||||||
timeout-minutes: 75
|
timeout-minutes: 75
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v7
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v7
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
cache: npm
|
cache: npm
|
||||||
|
|
||||||
- name: Cache packaging toolsets
|
- name: Cache packaging toolsets
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v6
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
${{ runner.temp }}/electron
|
${{ runner.temp }}/electron
|
||||||
@@ -112,7 +112,7 @@ jobs:
|
|||||||
ELECTRON_CACHE: ${{ runner.temp }}/electron
|
ELECTRON_CACHE: ${{ runner.temp }}/electron
|
||||||
|
|
||||||
- name: Download production bundle
|
- name: Download production bundle
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: goodbuddy-production-bundle
|
name: goodbuddy-production-bundle
|
||||||
path: out
|
path: out
|
||||||
@@ -124,7 +124,7 @@ jobs:
|
|||||||
ELECTRON_BUILDER_CACHE: ${{ runner.temp }}/electron-builder
|
ELECTRON_BUILDER_CACHE: ${{ runner.temp }}/electron-builder
|
||||||
|
|
||||||
- name: Upload release packages
|
- name: Upload release packages
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: goodbuddy-${{ matrix.platform }}-${{ matrix.arch }}
|
name: goodbuddy-${{ matrix.platform }}-${{ matrix.arch }}
|
||||||
path: dist/release/${{ matrix.platform }}-${{ matrix.arch }}
|
path: dist/release/${{ matrix.platform }}-${{ matrix.arch }}
|
||||||
@@ -143,11 +143,11 @@ jobs:
|
|||||||
actions: read
|
actions: read
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v7
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
|
|
||||||
@@ -160,19 +160,19 @@ jobs:
|
|||||||
test "$(git rev-parse "refs/tags/$GITHUB_REF_NAME^{commit}")" = "$GITHUB_SHA"
|
test "$(git rev-parse "refs/tags/$GITHUB_REF_NAME^{commit}")" = "$GITHUB_SHA"
|
||||||
|
|
||||||
- name: Download Windows packages
|
- name: Download Windows packages
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
pattern: goodbuddy-windows-*
|
pattern: goodbuddy-windows-*
|
||||||
path: dist/release-downloads
|
path: dist/release-downloads
|
||||||
|
|
||||||
- name: Download macOS packages
|
- name: Download macOS packages
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
pattern: goodbuddy-macos-*
|
pattern: goodbuddy-macos-*
|
||||||
path: dist/release-downloads
|
path: dist/release-downloads
|
||||||
|
|
||||||
- name: Download Linux packages
|
- name: Download Linux packages
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
pattern: goodbuddy-linux-*
|
pattern: goodbuddy-linux-*
|
||||||
path: dist/release-downloads
|
path: dist/release-downloads
|
||||||
|
|||||||
@@ -76,8 +76,9 @@ Keep Electron security boundaries intact:
|
|||||||
- `build/build-release.cjs` verifies the unpacked application, `app.asar`,
|
- `build/build-release.cjs` verifies the unpacked application, `app.asar`,
|
||||||
bundled Continue and OpenCode runtimes, executable architecture, and package
|
bundled Continue and OpenCode runtimes, executable architecture, and package
|
||||||
signatures before atomically replacing a release directory.
|
signatures before atomically replacing a release directory.
|
||||||
- Keep electron-builder invocations on `--publish never`. Current CI uploads
|
- Keep electron-builder invocations on `--publish never`. Main-branch builds
|
||||||
30-day GitHub Actions artifacts and does not create GitHub Release assets.
|
upload 30-day GitHub Actions artifacts. Version-tag builds additionally
|
||||||
|
verify and aggregate packages before publishing GitHub Release assets.
|
||||||
Signing and macOS notarization are not configured.
|
Signing and macOS notarization are not configured.
|
||||||
- Keep `ELECTRON_CACHE` and `ELECTRON_BUILDER_CACHE` under
|
- Keep `ELECTRON_CACHE` and `ELECTRON_BUILDER_CACHE` under
|
||||||
`${{ runner.temp }}` in step-level workflow contexts. A cache beneath the
|
`${{ runner.temp }}` in step-level workflow contexts. A cache beneath the
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "goodbuddy",
|
"name": "goodbuddy",
|
||||||
"version": "0.8.0",
|
"version": "0.8.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "goodbuddy",
|
"name": "goodbuddy",
|
||||||
"version": "0.8.0",
|
"version": "0.8.1",
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "^1.30.0",
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "goodbuddy",
|
"name": "goodbuddy",
|
||||||
"version": "0.8.0",
|
"version": "0.8.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Secure desktop AI workspace with controlled Agent Runtimes",
|
"description": "Secure desktop AI workspace with controlled Agent Runtimes",
|
||||||
"desktopName": "GoodBuddy",
|
"desktopName": "GoodBuddy",
|
||||||
|
|||||||
+8
-5
@@ -24,17 +24,20 @@ node --check sites/site.config.js
|
|||||||
|
|
||||||
## Release 配置
|
## Release 配置
|
||||||
|
|
||||||
未来 v0.8.0 Release 地址集中在 `site.config.js`:
|
当前版本的 Release 地址集中在 `site.config.js`,版本号必须与根目录
|
||||||
|
`package.json` 保持一致:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
window.GOODBUDDY_SITE_CONFIG = Object.freeze({
|
window.GOODBUDDY_SITE_CONFIG = Object.freeze({
|
||||||
version: "0.8.0",
|
version: "0.8.1",
|
||||||
releasePublished: false,
|
releasePublished: true,
|
||||||
releaseUrl: "https://github.com/mesalogo/goodbuddy/releases/tag/v0.8.0",
|
releaseUrl: "https://github.com/mesalogo/goodbuddy/releases/tag/v0.8.1",
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
正式 Release 确认发布后,将 `releasePublished` 改为 `true`,页面上的下载入口才会指向 Release 页面。官网不配置或猜测具体安装资产名称。
|
准备尚未发布的版本时,将 `releasePublished` 暂时设为 `false`;正式
|
||||||
|
Release 确认发布后改回 `true`,页面上的下载入口才会指向 Release
|
||||||
|
页面。官网不配置或猜测具体安装资产名称。
|
||||||
|
|
||||||
## 文件
|
## 文件
|
||||||
|
|
||||||
|
|||||||
+7
-3
@@ -48,12 +48,16 @@
|
|||||||
|
|
||||||
const configureReleaseLinks = () => {
|
const configureReleaseLinks = () => {
|
||||||
const releaseLinks = document.querySelectorAll("[data-release-link]");
|
const releaseLinks = document.querySelectorAll("[data-release-link]");
|
||||||
|
const hasValidVersion =
|
||||||
|
typeof config?.version === "string" &&
|
||||||
|
/^\d+\.\d+\.\d+$/.test(config.version);
|
||||||
|
const expectedReleaseUrl = hasValidVersion
|
||||||
|
? `https://github.com/mesalogo/goodbuddy/releases/tag/v${config.version}`
|
||||||
|
: "";
|
||||||
const isReady =
|
const isReady =
|
||||||
config?.releasePublished === true &&
|
config?.releasePublished === true &&
|
||||||
typeof config.releaseUrl === "string" &&
|
typeof config.releaseUrl === "string" &&
|
||||||
/^https:\/\/github\.com\/mesalogo\/goodbuddy\/releases\/tag\/v0\.8\.0$/.test(
|
config.releaseUrl === expectedReleaseUrl;
|
||||||
config.releaseUrl,
|
|
||||||
);
|
|
||||||
|
|
||||||
releaseLinks.forEach((link) => {
|
releaseLinks.forEach((link) => {
|
||||||
if (!isReady) {
|
if (!isReady) {
|
||||||
|
|||||||
+4
-4
@@ -5,7 +5,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
content="GoodBuddy 是安全可控的桌面智能助手与 Agent 工作空间。0.8.0 即将带来 Subagent、智能路由与 IM 开发者预览。"
|
content="GoodBuddy 是安全可控的桌面智能助手与 Agent 工作空间。0.8.1 改进语音反馈、文档附件与桌面交互稳定性。"
|
||||||
/>
|
/>
|
||||||
<meta name="theme-color" content="#f6f8fb" />
|
<meta name="theme-color" content="#f6f8fb" />
|
||||||
<title>GoodBuddy|安全可控的桌面智能助手</title>
|
<title>GoodBuddy|安全可控的桌面智能助手</title>
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
<div class="hero-copy">
|
<div class="hero-copy">
|
||||||
<div class="eyebrow">
|
<div class="eyebrow">
|
||||||
<span class="status-dot" aria-hidden="true"></span>
|
<span class="status-dot" aria-hidden="true"></span>
|
||||||
GoodBuddy 0.8.0 即将发布
|
GoodBuddy 0.8.1 已发布
|
||||||
</div>
|
</div>
|
||||||
<h1 id="hero-title">把 AI 放在桌面,<br /><span>也把控制权留在手中。</span></h1>
|
<h1 id="hero-title">把 AI 放在桌面,<br /><span>也把控制权留在手中。</span></h1>
|
||||||
<p class="hero-lead">
|
<p class="hero-lead">
|
||||||
@@ -384,7 +384,7 @@
|
|||||||
<h2 id="download-title">准备好,在你的设备上运行</h2>
|
<h2 id="download-title">准备好,在你的设备上运行</h2>
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
v0.8.0 Release 尚未发布。下载入口将在发布后统一开放,目前不提供虚构的资产名称或下载地址。
|
v0.8.1 Release 提供经过校验的跨平台安装包与哈希清单,下载入口统一指向 GitHub Release。
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -484,7 +484,7 @@
|
|||||||
<div class="cta-card">
|
<div class="cta-card">
|
||||||
<div class="cta-orbit" aria-hidden="true"><span></span><span></span></div>
|
<div class="cta-orbit" aria-hidden="true"><span></span><span></span></div>
|
||||||
<div>
|
<div>
|
||||||
<p class="kicker">GoodBuddy 0.8.0</p>
|
<p class="kicker">GoodBuddy 0.8.1</p>
|
||||||
<h2 id="cta-title">一个更能做事,也更懂边界的桌面伙伴。</h2>
|
<h2 id="cta-title">一个更能做事,也更懂边界的桌面伙伴。</h2>
|
||||||
<p>关注 Release,第一时间获取正式版本、校验信息与完整更新说明。</p>
|
<p>关注 Release,第一时间获取正式版本、校验信息与完整更新说明。</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import path from "node:path";
|
|||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
const siteRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
const siteRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
|
const repositoryRoot = path.resolve(siteRoot, "..");
|
||||||
const errors = [];
|
const errors = [];
|
||||||
|
|
||||||
const requiredFiles = [
|
const requiredFiles = [
|
||||||
@@ -46,6 +47,14 @@ const [html, css, appJs, configJs] = await Promise.all([
|
|||||||
readSiteFile("app.js"),
|
readSiteFile("app.js"),
|
||||||
readSiteFile("site.config.js"),
|
readSiteFile("site.config.js"),
|
||||||
]);
|
]);
|
||||||
|
let packageVersion = "";
|
||||||
|
try {
|
||||||
|
packageVersion = JSON.parse(
|
||||||
|
await readFile(path.join(repositoryRoot, "package.json"), "utf8"),
|
||||||
|
).version;
|
||||||
|
} catch {
|
||||||
|
errors.push("无法读取 package.json 版本");
|
||||||
|
}
|
||||||
|
|
||||||
for (const [relativePath, content] of [
|
for (const [relativePath, content] of [
|
||||||
["index.html", html],
|
["index.html", html],
|
||||||
@@ -87,23 +96,27 @@ for (const copy of requiredCopy) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
report(
|
report(
|
||||||
/version:\s*"0\.8\.0"/.test(configJs),
|
configJs.includes(`version: "${packageVersion}"`),
|
||||||
"site.config.js 必须集中配置 0.8.0 版本",
|
`site.config.js 版本必须与 package.json 的 ${packageVersion} 一致`,
|
||||||
);
|
);
|
||||||
report(
|
report(
|
||||||
/releasePublished:\s*true/.test(configJs),
|
/releasePublished:\s*true/.test(configJs),
|
||||||
"v0.8.0 Release 发布后 releasePublished 必须为 true",
|
`v${packageVersion} Release 发布后 releasePublished 必须为 true`,
|
||||||
);
|
);
|
||||||
report(
|
report(
|
||||||
/releaseUrl:\s*"https:\/\/github\.com\/mesalogo\/goodbuddy\/releases\/tag\/v0\.8\.0"/.test(
|
configJs.includes(
|
||||||
configJs,
|
`releaseUrl: "https://github.com/mesalogo/goodbuddy/releases/tag/v${packageVersion}"`,
|
||||||
),
|
),
|
||||||
"v0.8.0 Release URL 配置不正确",
|
`v${packageVersion} Release URL 配置不正确`,
|
||||||
);
|
);
|
||||||
report(
|
report(
|
||||||
appJs.includes("config?.releasePublished === true"),
|
appJs.includes("config?.releasePublished === true"),
|
||||||
"下载链接必须受 releasePublished 配置保护",
|
"下载链接必须受 releasePublished 配置保护",
|
||||||
);
|
);
|
||||||
|
report(
|
||||||
|
appJs.includes("config.releaseUrl === expectedReleaseUrl"),
|
||||||
|
"下载链接必须与配置版本对应的 GitHub Release 地址一致",
|
||||||
|
);
|
||||||
|
|
||||||
const ids = [...html.matchAll(/\sid="([^"]+)"/g)].map((match) => match[1]);
|
const ids = [...html.matchAll(/\sid="([^"]+)"/g)].map((match) => match[1]);
|
||||||
const duplicateIds = ids.filter((id, index) => ids.indexOf(id) !== index);
|
const duplicateIds = ids.filter((id, index) => ids.indexOf(id) !== index);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
window.GOODBUDDY_SITE_CONFIG = Object.freeze({
|
window.GOODBUDDY_SITE_CONFIG = Object.freeze({
|
||||||
version: "0.8.0",
|
version: "0.8.1",
|
||||||
releasePublished: true,
|
releasePublished: true,
|
||||||
releaseUrl: "https://github.com/mesalogo/goodbuddy/releases/tag/v0.8.0",
|
releaseUrl: "https://github.com/mesalogo/goodbuddy/releases/tag/v0.8.1",
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { readFileSync } from 'node:fs'
|
||||||
|
import { join } from 'node:path'
|
||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
import { parse } from 'yaml'
|
||||||
|
|
||||||
|
const workflow = readFileSync(
|
||||||
|
join(process.cwd(), '.github', 'workflows', 'packages.yml'),
|
||||||
|
'utf8'
|
||||||
|
)
|
||||||
|
|
||||||
|
describe('packages workflow', () => {
|
||||||
|
it('uses valid YAML and Node.js 24 GitHub Actions', () => {
|
||||||
|
expect(() => parse(workflow)).not.toThrow()
|
||||||
|
|
||||||
|
const references = [
|
||||||
|
...workflow.matchAll(
|
||||||
|
/uses:\s+(actions\/(?:checkout|setup-node|cache|upload-artifact|download-artifact)@v\d+)/gu
|
||||||
|
)
|
||||||
|
].map((match) => match[1])
|
||||||
|
|
||||||
|
expect(new Set(references)).toEqual(
|
||||||
|
new Set([
|
||||||
|
'actions/checkout@v7',
|
||||||
|
'actions/setup-node@v7',
|
||||||
|
'actions/cache@v6',
|
||||||
|
'actions/upload-artifact@v7',
|
||||||
|
'actions/download-artifact@v8'
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user