Cross-platform packages / Validate source (push) Canceled after 0s
Cross-platform packages / Authorize desktop packaging (push) Canceled after 0s
Cross-platform packages / linux arm64 (push) Canceled after 0s
Cross-platform packages / macos arm64 (push) Canceled after 0s
Cross-platform packages / windows arm64 (push) Canceled after 0s
Cross-platform packages / linux x64 (push) Canceled after 0s
Cross-platform packages / macos x64 (push) Canceled after 0s
Cross-platform packages / windows x64 (push) Canceled after 0s
Cross-platform packages / Publish GitHub and OSS release (push) Canceled after 0s
GoodBuddy Agents / Validate Agent source (push) Canceled after 0s
GoodBuddy Agents / Build darwin arm64 Agent (push) Canceled after 0s
GoodBuddy Agents / Build linux arm64 Agent (push) Canceled after 0s
GoodBuddy Agents / Build linux x64 Agent (push) Canceled after 0s
Record the approved bilingual release notes, classify long-task limits and premature truncation as fixes, and align both feature matrices with the verified workspace, browser, scheduling and Runtime behavior. Advance the Agent lock to 0.11.23 for remote file and Git management, optional model limits, larger bridge exchanges and the unlimited-duration connection fix. Agent publication reads version-specific approved notes and remains separate from Desktop Latest. Upgrade Desktop to 0.12.11 before updating Hosts. No LoongArch preview is included. Validation: release notes verification, all 3845 tests (66 skipped), typecheck and lint passed. Current-source Linux x64 workspace and bridge checks passed; managed ACP Ask and Execute completed two real model requests, both HTTP 200, with delivered results and cleaned test resources. Native production packages and publication remain subject to GitHub Actions after candidate approval. Release note: 准备 Desktop 0.12.11 与 Agent 0.11.23 发布;远程文件和 Git 管理、长任务限制及连接超时修复需先升级桌面端,再更新 Host 上的 Agent。
618 lines
24 KiB
YAML
618 lines
24 KiB
YAML
name: GoodBuddy Agent Release
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'agent-v*'
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: agent-release-${{ github.ref }}
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
authorize:
|
|
name: Authorize Agent release
|
|
if: >-
|
|
github.ref_type == 'tag' &&
|
|
startsWith(github.ref_name, 'agent-v')
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 5
|
|
outputs:
|
|
authorized: ${{ steps.policy.outputs.authorized }}
|
|
version: ${{ steps.policy.outputs.version }}
|
|
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Verify immutable Agent release tag
|
|
id: policy
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
version="$(node -p "require('./agent-runtime-lock.json').agentVersion")"
|
|
expected="agent-v$version"
|
|
test "$GITHUB_REF_NAME" = "$expected"
|
|
test "$(git cat-file -t "refs/tags/$GITHUB_REF_NAME")" = "tag"
|
|
test "$(git rev-parse "refs/tags/$GITHUB_REF_NAME^{commit}")" = "$GITHUB_SHA"
|
|
git fetch --no-tags origin main
|
|
git merge-base --is-ancestor "$GITHUB_SHA" refs/remotes/origin/main
|
|
echo "authorized=true" >> "$GITHUB_OUTPUT"
|
|
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
|
|
build:
|
|
name: Build ${{ matrix.platform }} ${{ matrix.arch }} compound package
|
|
needs: authorize
|
|
if: needs.authorize.outputs.authorized == 'true'
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- platform: linux
|
|
arch: x64
|
|
runner: ubuntu-24.04
|
|
- platform: linux
|
|
arch: arm64
|
|
runner: ubuntu-24.04-arm
|
|
- platform: darwin
|
|
arch: arm64
|
|
runner: macos-15
|
|
runs-on: ${{ matrix.runner }}
|
|
timeout-minutes: 25
|
|
environment:
|
|
name: agent-signing
|
|
permissions:
|
|
contents: read
|
|
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24.19.0
|
|
cache: npm
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- name: Verify native build target
|
|
run: node -e "if(process.platform !== '${{ matrix.platform }}' || process.arch !== '${{ matrix.arch }}') throw new Error('Native Agent target mismatch')"
|
|
|
|
- name: Resolve locked native inputs
|
|
id: inputs
|
|
shell: bash
|
|
env:
|
|
AGENT_ARCH: ${{ matrix.arch }}
|
|
AGENT_PLATFORM: ${{ matrix.platform }}
|
|
run: |
|
|
set -euo pipefail
|
|
node - <<'NODE'
|
|
const { appendFileSync } = require('node:fs')
|
|
const { createHash } = require('node:crypto')
|
|
const agent = require('./agent-runtime-lock.json')
|
|
const remote = require('./remote-runtime-lock.json')
|
|
const node = agent.node?.targets?.[`${process.env.AGENT_PLATFORM}-${process.env.AGENT_ARCH}`]
|
|
const runtime = remote.runtimes?.opencode
|
|
const runtimeKey = process.env.AGENT_PLATFORM === 'linux'
|
|
? process.env.AGENT_ARCH : `${process.env.AGENT_PLATFORM}-${process.env.AGENT_ARCH}`
|
|
const opencode = runtime?.targets?.[runtimeKey]
|
|
if (
|
|
!node ||
|
|
!opencode ||
|
|
!/^[A-Za-z0-9._-]+\.tar\.gz$/u.test(node.archive) ||
|
|
!/^[a-f0-9]{64}$/u.test(node.sha256) ||
|
|
!/^[a-z0-9][a-z0-9._-]*$/u.test(opencode.package) ||
|
|
!/^sha512-[A-Za-z0-9+/]+={0,2}$/u.test(opencode.integrity)
|
|
) {
|
|
throw new Error('Locked native Agent package inputs are invalid')
|
|
}
|
|
const nodeUrl = new URL(node.archive, agent.node.source)
|
|
if (
|
|
nodeUrl.protocol !== 'https:' ||
|
|
nodeUrl.hostname !== 'nodejs.org' ||
|
|
nodeUrl.username ||
|
|
nodeUrl.password ||
|
|
nodeUrl.search ||
|
|
nodeUrl.hash
|
|
) {
|
|
throw new Error('Agent Node runtime must use the official HTTPS origin')
|
|
}
|
|
const opencodeArchive =
|
|
`${opencode.package}-${runtime.version}.tgz`
|
|
appendFileSync(
|
|
process.env.GITHUB_OUTPUT,
|
|
[
|
|
`node-archive=${node.archive}`,
|
|
`node-sha256=${node.sha256}`,
|
|
`node-url=${nodeUrl.href}`,
|
|
`opencode-package=${opencode.package}`,
|
|
`opencode-version=${runtime.version}`,
|
|
`opencode-integrity=${opencode.integrity}`,
|
|
`opencode-archive=${opencodeArchive}`,
|
|
`cache-key=${createHash('sha256')
|
|
.update(`${node.sha256}:${opencode.integrity}`)
|
|
.digest('hex')}`,
|
|
''
|
|
].join('\n')
|
|
)
|
|
NODE
|
|
|
|
- name: Cache verified native inputs
|
|
uses: actions/cache@v6
|
|
with:
|
|
path: ${{ runner.temp }}/goodbuddy-agent-release-inputs
|
|
key: goodbuddy-agent-release-${{ matrix.platform }}-${{ matrix.arch }}-${{ steps.inputs.outputs.cache-key }}
|
|
|
|
- name: Acquire and verify native inputs
|
|
shell: bash
|
|
env:
|
|
NODE_ARCHIVE: ${{ steps.inputs.outputs.node-archive }}
|
|
NODE_SHA256: ${{ steps.inputs.outputs.node-sha256 }}
|
|
NODE_URL: ${{ steps.inputs.outputs.node-url }}
|
|
OPENCODE_ARCHIVE: ${{ steps.inputs.outputs.opencode-archive }}
|
|
OPENCODE_INTEGRITY: ${{ steps.inputs.outputs.opencode-integrity }}
|
|
OPENCODE_PACKAGE: ${{ steps.inputs.outputs.opencode-package }}
|
|
OPENCODE_VERSION: ${{ steps.inputs.outputs.opencode-version }}
|
|
run: |
|
|
set -euo pipefail
|
|
directory="$RUNNER_TEMP/goodbuddy-agent-release-inputs"
|
|
mkdir -p "$directory"
|
|
node_archive="$directory/$NODE_ARCHIVE"
|
|
if [[ ! -f "$node_archive" ]]; then
|
|
curl --proto '=https' --tlsv1.2 \
|
|
--fail --silent --show-error --location \
|
|
--retry 3 --retry-all-errors \
|
|
--connect-timeout 15 --max-time 300 \
|
|
--max-filesize 104857600 \
|
|
"$NODE_URL" --output "$node_archive.partial"
|
|
mv "$node_archive.partial" "$node_archive"
|
|
fi
|
|
node - "$node_archive" "$NODE_SHA256" <<'NODE'
|
|
const { createHash } = require('node:crypto')
|
|
const { readFileSync } = require('node:fs')
|
|
const [archive, expected] = process.argv.slice(2)
|
|
if (createHash('sha256').update(readFileSync(archive)).digest('hex') !== expected) {
|
|
throw new Error('Node runtime archive integrity mismatch')
|
|
}
|
|
NODE
|
|
|
|
opencode_archive="$directory/$OPENCODE_ARCHIVE"
|
|
if [[ ! -f "$opencode_archive" ]]; then
|
|
npm pack \
|
|
--ignore-scripts \
|
|
--registry https://registry.npmjs.org/ \
|
|
--pack-destination "$directory" \
|
|
"$OPENCODE_PACKAGE@$OPENCODE_VERSION"
|
|
fi
|
|
node - "$opencode_archive" "$OPENCODE_INTEGRITY" <<'NODE'
|
|
const { createHash } = require('node:crypto')
|
|
const { readFileSync, statSync } = require('node:fs')
|
|
const [archive, expected] = process.argv.slice(2)
|
|
const size = statSync(archive).size
|
|
if (size <= 0 || size > 536870912) {
|
|
throw new Error('OpenCode Runtime archive exceeds its safety limit')
|
|
}
|
|
const actual = `sha512-${createHash('sha512')
|
|
.update(readFileSync(archive))
|
|
.digest('base64')}`
|
|
if (actual !== expected) {
|
|
throw new Error('OpenCode Runtime archive integrity mismatch')
|
|
}
|
|
NODE
|
|
|
|
- name: Preflight production GoodBuddy signing identity
|
|
shell: bash
|
|
env:
|
|
GOODBUDDY_SIGNING_KEY_ID: ${{ vars.GOODBUDDY_SIGNING_KEY_ID }}
|
|
run: |
|
|
set -euo pipefail
|
|
node build/agent-bundle.cjs preflight
|
|
|
|
- name: Build production compound Agent package
|
|
shell: bash
|
|
env:
|
|
AGENT_ARCH: ${{ matrix.arch }}
|
|
AGENT_PLATFORM: ${{ matrix.platform }}
|
|
AGENT_VERSION: ${{ needs.authorize.outputs.version }}
|
|
GOODBUDDY_SIGNING_KEY_ID: ${{ vars.GOODBUDDY_SIGNING_KEY_ID }}
|
|
GOODBUDDY_SIGNING_PRIVATE_KEY: ${{ secrets.GOODBUDDY_SIGNING_PRIVATE_KEY }}
|
|
NODE_ARCHIVE: ${{ steps.inputs.outputs.node-archive }}
|
|
OPENCODE_ARCHIVE: ${{ steps.inputs.outputs.opencode-archive }}
|
|
run: |
|
|
set -euo pipefail
|
|
output="$RUNNER_TEMP/goodbuddy-agent-output"
|
|
mkdir -p "$output"
|
|
node build/agent-package.cjs build \
|
|
--platform "$AGENT_PLATFORM" \
|
|
--arch "$AGENT_ARCH" \
|
|
--minimum-desktop-version "$(node -p "require('./package.json').version")" \
|
|
--node-archive "$RUNNER_TEMP/goodbuddy-agent-release-inputs/$NODE_ARCHIVE" \
|
|
--runtime-archive "$RUNNER_TEMP/goodbuddy-agent-release-inputs/$OPENCODE_ARCHIVE" \
|
|
--output "$output/goodbuddy-agent-$AGENT_VERSION-$AGENT_PLATFORM-$AGENT_ARCH.gbagent" \
|
|
> "$output/result.json"
|
|
node - "$output/result.json" "$AGENT_ARCH" "$AGENT_VERSION" <<'NODE'
|
|
const { readFileSync } = require('node:fs')
|
|
const [resultPath, architecture, version] = process.argv.slice(2)
|
|
const result = JSON.parse(readFileSync(resultPath, 'utf8'))
|
|
if (
|
|
result.descriptor?.architecture !== architecture ||
|
|
result.descriptor?.platform !== process.env.AGENT_PLATFORM ||
|
|
result.descriptor?.version !== version ||
|
|
result.archive !==
|
|
`goodbuddy-agent-${version}-${process.env.AGENT_PLATFORM}-${architecture}.gbagent` ||
|
|
!/^[a-f0-9]{64}$/u.test(result.sha256)
|
|
) {
|
|
throw new Error('Production Agent package result is invalid')
|
|
}
|
|
NODE
|
|
|
|
- name: Upload verified compound package
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: goodbuddy-agent-package-${{ matrix.platform }}-${{ matrix.arch }}
|
|
path: ${{ runner.temp }}/goodbuddy-agent-output/goodbuddy-agent-*.gbagent
|
|
if-no-files-found: error
|
|
compression-level: 0
|
|
retention-days: 7
|
|
|
|
catalog:
|
|
name: Sign cumulative Agent catalog
|
|
needs:
|
|
- authorize
|
|
- build
|
|
if: needs.authorize.outputs.authorized == 'true'
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 10
|
|
environment:
|
|
name: agent-signing
|
|
permissions:
|
|
contents: read
|
|
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24.19.0
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- name: Download compound packages
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
pattern: goodbuddy-agent-package-*
|
|
path: dist/agent-release
|
|
merge-multiple: true
|
|
|
|
- name: Fetch previous signed catalog when available
|
|
id: previous
|
|
shell: bash
|
|
env:
|
|
AGENT_VERSION: ${{ needs.authorize.outputs.version }}
|
|
run: |
|
|
set -euo pipefail
|
|
root="https://goodbuddy.oss-cn-beijing.aliyuncs.com/agent-releases"
|
|
current_catalog_status="$(
|
|
curl --silent --show-error \
|
|
--output dist/agent-release/previous.json \
|
|
--write-out '%{http_code}' \
|
|
"$root/v$AGENT_VERSION/agent-catalog.json"
|
|
)"
|
|
current_signature_status="$(
|
|
curl --silent --show-error \
|
|
--output dist/agent-release/previous.sig \
|
|
--write-out '%{http_code}' \
|
|
"$root/v$AGENT_VERSION/agent-catalog.sig"
|
|
)"
|
|
if [[ "$current_catalog_status" == 200 && "$current_signature_status" == 200 ]]; then
|
|
echo "arguments=--previous-catalog dist/agent-release/previous.json --previous-signature dist/agent-release/previous.sig" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
if [[ "$current_catalog_status" != 404 || "$current_signature_status" != 404 ]]; then
|
|
echo "Current Agent catalog objects are inconsistent: $current_catalog_status / $current_signature_status" >&2
|
|
exit 1
|
|
fi
|
|
rm -f dist/agent-release/previous.json dist/agent-release/previous.sig
|
|
pointer_status="$(
|
|
curl --silent --show-error \
|
|
--output dist/agent-release/previous-pointer.json \
|
|
--write-out '%{http_code}' \
|
|
"$root/latest.json"
|
|
)"
|
|
if [[ "$pointer_status" == 200 ]]; then
|
|
readarray -t paths < <(
|
|
node - dist/agent-release/previous-pointer.json <<'NODE'
|
|
const { readFileSync } = require('node:fs')
|
|
const pointer = JSON.parse(readFileSync(process.argv[2], 'utf8'))
|
|
if (
|
|
pointer?.formatVersion !== 1 ||
|
|
!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u.test(pointer.version) ||
|
|
pointer.catalog !== `v${pointer.version}/agent-catalog.json` ||
|
|
pointer.signature !== `v${pointer.version}/agent-catalog.sig`
|
|
) {
|
|
throw new Error('Previous Agent catalog pointer is invalid')
|
|
}
|
|
process.stdout.write(`${pointer.catalog}\n${pointer.signature}\n`)
|
|
NODE
|
|
)
|
|
curl --fail --silent --show-error \
|
|
"$root/${paths[0]}" \
|
|
--output dist/agent-release/previous.json
|
|
curl --fail --silent --show-error \
|
|
"$root/${paths[1]}" \
|
|
--output dist/agent-release/previous.sig
|
|
echo "arguments=--previous-catalog dist/agent-release/previous.json --previous-signature dist/agent-release/previous.sig" >> "$GITHUB_OUTPUT"
|
|
elif [[ "$pointer_status" == 404 ]]; then
|
|
rm -f dist/agent-release/previous-pointer.json
|
|
echo "arguments=" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "Agent catalog pointer request failed: $pointer_status" >&2
|
|
exit 1
|
|
fi
|
|
|
|
- name: Sign cumulative Agent catalog
|
|
shell: bash
|
|
env:
|
|
AGENT_VERSION: ${{ needs.authorize.outputs.version }}
|
|
PREVIOUS_ARGUMENTS: ${{ steps.previous.outputs.arguments }}
|
|
GOODBUDDY_SIGNING_KEY_ID: ${{ vars.GOODBUDDY_SIGNING_KEY_ID }}
|
|
GOODBUDDY_SIGNING_PRIVATE_KEY: ${{ secrets.GOODBUDDY_SIGNING_PRIVATE_KEY }}
|
|
run: |
|
|
set -euo pipefail
|
|
generated_at="$(git show -s --format=%cI "$GITHUB_SHA")"
|
|
read -r -a previous <<< "$PREVIOUS_ARGUMENTS"
|
|
node build/agent-catalog.cjs create \
|
|
--x64-package "dist/agent-release/goodbuddy-agent-$AGENT_VERSION-linux-x64.gbagent" \
|
|
--arm64-package "dist/agent-release/goodbuddy-agent-$AGENT_VERSION-linux-arm64.gbagent" \
|
|
--darwin-arm64-package "dist/agent-release/goodbuddy-agent-$AGENT_VERSION-darwin-arm64.gbagent" \
|
|
"${previous[@]}" \
|
|
--catalog dist/agent-release/agent-catalog.json \
|
|
--signature dist/agent-release/agent-catalog.sig \
|
|
--generated-at "$generated_at"
|
|
node build/agent-catalog.cjs verify \
|
|
--catalog dist/agent-release/agent-catalog.json \
|
|
--signature dist/agent-release/agent-catalog.sig
|
|
|
|
- name: Upload signed release set
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: goodbuddy-agent-release-${{ needs.authorize.outputs.version }}
|
|
path: |
|
|
dist/agent-release/goodbuddy-agent-*.gbagent
|
|
dist/agent-release/agent-catalog.json
|
|
dist/agent-release/agent-catalog.sig
|
|
if-no-files-found: error
|
|
compression-level: 0
|
|
retention-days: 7
|
|
|
|
publish:
|
|
name: Publish Agent to GitHub and OSS
|
|
needs:
|
|
- authorize
|
|
- catalog
|
|
if: needs.authorize.outputs.authorized == 'true'
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 25
|
|
environment:
|
|
name: aliyun-oss-release
|
|
permissions:
|
|
contents: write
|
|
actions: read
|
|
id-token: write
|
|
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
|
|
- uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24.19.0
|
|
|
|
- name: Install verification dependencies
|
|
run: npm ci
|
|
|
|
- name: Download signed release set
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
name: goodbuddy-agent-release-${{ needs.authorize.outputs.version }}
|
|
path: dist/agent-release
|
|
|
|
- name: Verify signed release set
|
|
run: |
|
|
node build/agent-catalog.cjs verify \
|
|
--catalog dist/agent-release/agent-catalog.json \
|
|
--signature dist/agent-release/agent-catalog.sig
|
|
|
|
- name: Verify OSS release configuration
|
|
shell: bash
|
|
env:
|
|
OSS_BUCKET: ${{ vars.ALIYUN_OSS_BUCKET }}
|
|
OSS_ENDPOINT: ${{ vars.ALIYUN_OSS_ENDPOINT }}
|
|
OIDC_PROVIDER_ARN: ${{ vars.ALIYUN_OIDC_PROVIDER_ARN }}
|
|
ROLE_ARN: ${{ vars.ALIYUN_ROLE_ARN }}
|
|
run: |
|
|
set -euo pipefail
|
|
test "$OSS_BUCKET" = "goodbuddy"
|
|
test "$OSS_ENDPOINT" = "https://oss-cn-beijing.aliyuncs.com"
|
|
case "$OIDC_PROVIDER_ARN" in
|
|
acs:ram::*:oidc-provider/*) ;;
|
|
*) echo "OIDC Provider ARN 无效" >&2; exit 1 ;;
|
|
esac
|
|
case "$ROLE_ARN" in
|
|
acs:ram::*:role/*) ;;
|
|
*) echo "RAM Role ARN 无效" >&2; exit 1 ;;
|
|
esac
|
|
|
|
- name: Authenticate to Alibaba Cloud
|
|
uses: aliyun/configure-aliyun-credentials-action@v1
|
|
with:
|
|
role-to-assume: ${{ vars.ALIYUN_ROLE_ARN }}
|
|
oidc-provider-arn: ${{ vars.ALIYUN_OIDC_PROVIDER_ARN }}
|
|
role-session-name: goodbuddy-agent-${{ github.run_id }}
|
|
role-session-expiration: 3600
|
|
audience: sts.aliyuncs.com
|
|
|
|
- name: Install ossutil
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
version="2.3.0"
|
|
archive="$RUNNER_TEMP/ossutil.zip"
|
|
directory="$RUNNER_TEMP/ossutil"
|
|
curl --fail --silent --show-error --location \
|
|
"https://gosspublic.alicdn.com/ossutil/v2/$version/ossutil-$version-linux-amd64.zip" \
|
|
--output "$archive"
|
|
mkdir "$directory"
|
|
unzip -q "$archive" -d "$directory"
|
|
binary="$(find "$directory" -type f -name ossutil -print -quit)"
|
|
test -n "$binary"
|
|
chmod +x "$binary"
|
|
echo "$(dirname "$binary")" >> "$GITHUB_PATH"
|
|
|
|
- name: Upload immutable Agent release to OSS
|
|
id: oss
|
|
shell: bash
|
|
env:
|
|
AGENT_VERSION: ${{ needs.authorize.outputs.version }}
|
|
OSS_BUCKET: ${{ vars.ALIYUN_OSS_BUCKET }}
|
|
OSS_ENDPOINT: ${{ vars.ALIYUN_OSS_ENDPOINT }}
|
|
run: |
|
|
set -euo pipefail
|
|
export OSS_ACCESS_KEY_ID="$ALIBABA_CLOUD_ACCESS_KEY_ID"
|
|
export OSS_ACCESS_KEY_SECRET="$ALIBABA_CLOUD_ACCESS_KEY_SECRET"
|
|
export OSS_SESSION_TOKEN="$ALIBABA_CLOUD_SECURITY_TOKEN"
|
|
endpoint_host="${OSS_ENDPOINT#https://}"
|
|
region="${endpoint_host#oss-}"
|
|
region="${region%.aliyuncs.com}"
|
|
test "$region" = "cn-beijing"
|
|
for file in dist/agent-release/*; do
|
|
name="$(basename "$file")"
|
|
ossutil cp "$file" \
|
|
"oss://${OSS_BUCKET}/agent-releases/v${AGENT_VERSION}/${name}" \
|
|
--endpoint "$OSS_ENDPOINT" \
|
|
--region "$region" \
|
|
--update
|
|
done
|
|
echo "region=$region" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Verify public immutable OSS packages
|
|
shell: bash
|
|
env:
|
|
AGENT_VERSION: ${{ needs.authorize.outputs.version }}
|
|
run: |
|
|
set -euo pipefail
|
|
root="https://goodbuddy.oss-cn-beijing.aliyuncs.com/agent-releases/v$AGENT_VERSION"
|
|
for target in linux-x64 linux-arm64 darwin-arm64; do
|
|
name="goodbuddy-agent-$AGENT_VERSION-$target.gbagent"
|
|
curl --fail --silent --show-error --location \
|
|
"$root/$name" --output "$RUNNER_TEMP/$name"
|
|
cmp "dist/agent-release/$name" "$RUNNER_TEMP/$name"
|
|
done
|
|
for name in agent-catalog.json agent-catalog.sig; do
|
|
curl --fail --silent --show-error --location \
|
|
"$root/$name" --output "$RUNNER_TEMP/immutable-$name"
|
|
cmp "dist/agent-release/$name" \
|
|
"$RUNNER_TEMP/immutable-$name"
|
|
done
|
|
|
|
- name: Publish non-Latest GitHub Agent release
|
|
shell: bash
|
|
env:
|
|
AGENT_VERSION: ${{ needs.authorize.outputs.version }}
|
|
GH_TOKEN: ${{ github.token }}
|
|
run: |
|
|
set -euo pipefail
|
|
tag="agent-v$AGENT_VERSION"
|
|
title="GoodBuddy Agent $AGENT_VERSION"
|
|
notes="resources/agent-release-notes/$AGENT_VERSION.md"
|
|
test -s "$notes"
|
|
if gh release view "$tag" >/dev/null 2>&1; then
|
|
is_draft="$(gh release view "$tag" --json isDraft --jq .isDraft)"
|
|
if [[ "$is_draft" == true ]]; then
|
|
gh release edit "$tag" \
|
|
--title "$title" \
|
|
--notes-file "$notes" \
|
|
--latest=false
|
|
gh release upload "$tag" dist/agent-release/* --clobber
|
|
gh release edit "$tag" --draft=false --latest=false
|
|
else
|
|
verify="$RUNNER_TEMP/github-agent-release"
|
|
mkdir "$verify"
|
|
gh release download "$tag" --dir "$verify"
|
|
for file in dist/agent-release/*; do
|
|
cmp "$file" "$verify/$(basename "$file")"
|
|
done
|
|
fi
|
|
else
|
|
gh release create "$tag" \
|
|
--draft \
|
|
--verify-tag \
|
|
--title "$title" \
|
|
--notes-file "$notes" \
|
|
--latest=false
|
|
gh release upload "$tag" dist/agent-release/* --clobber
|
|
gh release edit "$tag" --draft=false --latest=false
|
|
fi
|
|
test "$(gh api repos/mesalogo/goodbuddy/releases/latest --jq .tag_name)" != "$tag"
|
|
|
|
- name: Point OSS Agent catalog to published release
|
|
shell: bash
|
|
env:
|
|
AGENT_VERSION: ${{ needs.authorize.outputs.version }}
|
|
OSS_BUCKET: ${{ vars.ALIYUN_OSS_BUCKET }}
|
|
OSS_ENDPOINT: ${{ vars.ALIYUN_OSS_ENDPOINT }}
|
|
OSS_REGION: ${{ steps.oss.outputs.region }}
|
|
run: |
|
|
set -euo pipefail
|
|
export OSS_ACCESS_KEY_ID="$ALIBABA_CLOUD_ACCESS_KEY_ID"
|
|
export OSS_ACCESS_KEY_SECRET="$ALIBABA_CLOUD_ACCESS_KEY_SECRET"
|
|
export OSS_SESSION_TOKEN="$ALIBABA_CLOUD_SECURITY_TOKEN"
|
|
node - "$AGENT_VERSION" > dist/agent-release/latest.json <<'NODE'
|
|
const version = process.argv[2]
|
|
process.stdout.write(`${JSON.stringify({
|
|
formatVersion: 1,
|
|
version,
|
|
catalog: `v${version}/agent-catalog.json`,
|
|
signature: `v${version}/agent-catalog.sig`
|
|
}, null, 2)}\n`)
|
|
NODE
|
|
ossutil cp dist/agent-release/latest.json \
|
|
"oss://${OSS_BUCKET}/agent-releases/latest.json" \
|
|
--endpoint "$OSS_ENDPOINT" \
|
|
--region "$OSS_REGION" \
|
|
--force
|
|
|
|
- name: Verify public Agent catalogs
|
|
shell: bash
|
|
env:
|
|
AGENT_VERSION: ${{ needs.authorize.outputs.version }}
|
|
run: |
|
|
set -euo pipefail
|
|
mirror="https://goodbuddy.oss-cn-beijing.aliyuncs.com/agent-releases"
|
|
github="https://github.com/mesalogo/goodbuddy/releases/download/agent-v$AGENT_VERSION"
|
|
curl --fail --silent --show-error --location \
|
|
"$mirror/latest.json" --output "$RUNNER_TEMP/mirror-pointer.json"
|
|
curl --fail --silent --show-error --location \
|
|
"$mirror/v$AGENT_VERSION/agent-catalog.json" \
|
|
--output "$RUNNER_TEMP/mirror.json"
|
|
curl --fail --silent --show-error --location \
|
|
"$mirror/v$AGENT_VERSION/agent-catalog.sig" \
|
|
--output "$RUNNER_TEMP/mirror.sig"
|
|
curl --fail --silent --show-error --location \
|
|
"$github/agent-catalog.json" --output "$RUNNER_TEMP/github.json"
|
|
curl --fail --silent --show-error --location \
|
|
"$github/agent-catalog.sig" --output "$RUNNER_TEMP/github.sig"
|
|
cmp dist/agent-release/latest.json "$RUNNER_TEMP/mirror-pointer.json"
|
|
cmp dist/agent-release/agent-catalog.json "$RUNNER_TEMP/mirror.json"
|
|
cmp dist/agent-release/agent-catalog.sig "$RUNNER_TEMP/mirror.sig"
|
|
cmp dist/agent-release/agent-catalog.json "$RUNNER_TEMP/github.json"
|
|
cmp dist/agent-release/agent-catalog.sig "$RUNNER_TEMP/github.sig"
|