Files
sen 4feb29121c chore: migrate actionbook.dev to actionbook.app (#614)
* [packages/actionbook-extension]fix: point Cloud Mode OAuth and edge WebSocket at actionbook.app

clerk.actionbook.dev is now only a 307 redirect shim to clerk.actionbook.app
and its JWKS endpoint no longer responds, so hardcoding it left the extension
depending on a half-decommissioned host. Both edge hosts already advertise
clerk.actionbook.app as their OAuth authorization server, so switching is a
no-op for existing sessions.

- CLERK_AUTHORIZE_URL / CLERK_TOKEN_URL -> clerk.actionbook.app
- DEFAULT_CLOUD_ENDPOINT -> wss://edge.actionbook.app/extension/ws
- popup / callback "Learn more" links -> actionbook.app/docs
- PRIVACY.md + README.md updated to match the new hosts

manifest.json uses host_permissions ["<all_urls>"], so no permission change
is required.

* [root]docs: migrate actionbook.dev links to actionbook.app

Domain migration for everything that resolves on the new domain, verified
live before the swap: actionbook.app (+ /docs, /discord, /request-website),
edge.actionbook.app/mcp (401 + self-consistent OAuth metadata) and
accounts.actionbook.app/waitlist.

Deliberately left on actionbook.dev:
- api.actionbook.dev (57 refs) - api.actionbook.app has no DNS record yet,
  and it is still the default in mcp/js-sdk/dify-plugin/openclaw-plugin.
- @actionbook.dev addresses - actionbook.app has no MX records.
- .docs/ reports and the extension CHANGELOG - historical records.
- dify-plugin search_actions.py SSRF hints - they refer to the API host.

Also repoints dify-plugin's Documentation URL from docs.actionbook.dev
(no DNS, dead link) to actionbook.app/docs.

* [packages/actionbook-extension]fix: bump to 0.5.1 so the endpoint migration ships

The extension is distributed through the Chrome Web Store, which refuses an
update that does not increase manifest.json's version. Leaving it at 0.5.0
meant installed Cloud Mode users would keep pointing at the degraded
clerk.actionbook.dev host despite the source change.

@actionbookdev/extension is in .changeset/config.json's ignore list, so
`changeset version` never bumps it — the bump has to be manual here.
package.json and manifest.json are set to the same value, so
scripts/sync-versions.js stays a no-op.
2026-07-31 14:15:51 +08:00

504 lines
18 KiB
YAML

name: Release CLI
on:
push:
branches:
- main
workflow_dispatch:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: write
pull-requests: write
id-token: write
jobs:
# --------------------------------------------------------------------------
# Job 1: Create Version PR or determine whether CLI needs a release
# --------------------------------------------------------------------------
version-or-release:
name: Version or Release
runs-on: ubuntu-latest
outputs:
should-release: ${{ steps.changesets.outputs.hasChangesets == 'false' }}
cli-needs-release: ${{ steps.check-releases.outputs.cli }}
cli-changed: ${{ steps.changes.outputs.cli }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Detect changed packages
id: changes
run: |
# workflow_dispatch or first push: treat CLI as changed
if [ "${{ github.event_name }}" = "workflow_dispatch" ] || \
[ "${{ github.event.before }}" = "0000000000000000000000000000000000000000" ]; then
echo "cli=true" >> "$GITHUB_OUTPUT"
exit 0
fi
CHANGED=$(git diff --name-only "${{ github.event.before }}" "${{ github.sha }}")
echo "Changed files:"
echo "$CHANGED"
if echo "$CHANGED" | grep -qE "^packages/cli[-/]"; then
echo "cli=true" >> "$GITHUB_OUTPUT"
else
echo "cli=false" >> "$GITHUB_OUTPUT"
fi
- name: Create Release Pull Request
id: changesets
uses: changesets/action@v1
with:
version: pnpm version-packages
commit: "chore: version packages"
title: "chore: version packages"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check whether CLI needs release
id: check-releases
if: steps.changesets.outputs.hasChangesets == 'false'
run: |
CLI_LOCAL=$(node -e "console.log(JSON.parse(require('fs').readFileSync('packages/cli/package.json','utf8')).version)")
CLI_NPM=$(npm view @actionbookdev/cli version 2>/dev/null || echo "0.0.0")
if [ "$CLI_LOCAL" != "$CLI_NPM" ]; then
echo "cli=true" >> "$GITHUB_OUTPUT"
echo "CLI needs release: $CLI_LOCAL (local) vs $CLI_NPM (npm)"
else
echo "cli=false" >> "$GITHUB_OUTPUT"
echo "CLI is up to date: $CLI_LOCAL"
fi
# --------------------------------------------------------------------------
# Job 2: Build CLI binaries (cross-platform Rust compilation)
# --------------------------------------------------------------------------
build-cli:
name: Build CLI (${{ matrix.platform-suffix }})
needs: version-or-release
if: needs.version-or-release.outputs.cli-needs-release == 'true' && needs.version-or-release.outputs.cli-changed == 'true'
strategy:
matrix:
include:
- target: aarch64-apple-darwin
os: macos-latest
platform-suffix: darwin-arm64
- target: x86_64-apple-darwin
os: macos-latest
platform-suffix: darwin-x64
- target: x86_64-unknown-linux-gnu
os: ubuntu-22.04
platform-suffix: linux-x64
- target: aarch64-unknown-linux-gnu
os: ubuntu-latest
platform-suffix: linux-arm64
use-cross: true
- target: x86_64-pc-windows-msvc
os: windows-latest
platform-suffix: win32-x64
- target: aarch64-pc-windows-msvc
os: windows-latest
platform-suffix: win32-arm64
runs-on: ${{ matrix.os }}
defaults:
run:
working-directory: packages/cli
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install cross (Linux ARM64)
if: matrix.use-cross
run: cargo install cross --git https://github.com/cross-rs/cross
- name: Build (cross)
if: matrix.use-cross
working-directory: .
run: cross build --release --target ${{ matrix.target }} --manifest-path packages/cli/Cargo.toml
- name: Build (native)
if: ${{ !matrix.use-cross }}
run: cargo build --release --target ${{ matrix.target }}
- name: Determine binary name
id: binary
shell: bash
run: |
if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
echo "name=actionbook.exe" >> "$GITHUB_OUTPUT"
else
echo "name=actionbook" >> "$GITHUB_OUTPUT"
fi
- name: Rename binary for platform
shell: bash
run: |
CANDIDATES=(
"target/${{ matrix.target }}/release/${{ steps.binary.outputs.name }}"
"../target/${{ matrix.target }}/release/${{ steps.binary.outputs.name }}"
)
SRC=""
for candidate in "${CANDIDATES[@]}"; do
if [[ -f "$candidate" ]]; then
SRC="$candidate"
break
fi
done
if [[ -z "$SRC" ]]; then
echo "ERROR: Built binary not found in expected target directories."
printf 'Checked:\n - %s\n' "${CANDIDATES[@]}"
exit 1
fi
ARTIFACT_DIR="${RUNNER_TEMP}/actionbook-binaries"
mkdir -p "$ARTIFACT_DIR"
PLATFORM_SUFFIX="${{ matrix.platform-suffix }}"
if [[ "$PLATFORM_SUFFIX" == win32-* ]]; then
DEST="$ARTIFACT_DIR/actionbook-${PLATFORM_SUFFIX}.exe"
else
DEST="$ARTIFACT_DIR/actionbook-${PLATFORM_SUFFIX}"
fi
cp "$SRC" "$DEST"
chmod +x "$DEST"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: actionbook-${{ matrix.platform-suffix }}
path: ${{ runner.temp }}/actionbook-binaries/actionbook-${{ matrix.platform-suffix }}*
if-no-files-found: error
# --------------------------------------------------------------------------
# Job 3: Publish CLI npm packages + GitHub Release
# --------------------------------------------------------------------------
publish-cli:
name: Publish CLI
needs: [version-or-release, build-cli]
if: needs.version-or-release.outputs.cli-needs-release == 'true' && needs.version-or-release.outputs.cli-changed == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Read CLI version
id: version
run: |
VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('packages/cli/package.json','utf8')).version)")
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
- name: Prepare platform package binaries
run: |
declare -A PLATFORM_PKG_DIRS=(
["darwin-arm64"]="packages/cli-darwin-arm64"
["darwin-x64"]="packages/cli-darwin-x64"
["linux-x64"]="packages/cli-linux-x64-gnu"
["linux-arm64"]="packages/cli-linux-arm64-gnu"
["win32-x64"]="packages/cli-win32-x64"
["win32-arm64"]="packages/cli-win32-arm64"
)
for suffix in "${!PLATFORM_PKG_DIRS[@]}"; do
artifact_dir="artifacts/actionbook-${suffix}"
package_dir="${PLATFORM_PKG_DIRS[$suffix]}"
if [[ "$suffix" == win32-* ]]; then
src_name="actionbook-${suffix}.exe"
dest_name="actionbook.exe"
else
src_name="actionbook-${suffix}"
dest_name="actionbook"
fi
cp "${artifact_dir}/${src_name}" "${package_dir}/bin/${dest_name}"
chmod +x "${package_dir}/bin/${dest_name}"
echo "Copied ${src_name} -> ${package_dir}/bin/${dest_name}"
done
- name: Validate platform binaries
run: |
declare -A PLATFORM_PKG_DIRS=(
["darwin-arm64"]="packages/cli-darwin-arm64"
["darwin-x64"]="packages/cli-darwin-x64"
["linux-x64"]="packages/cli-linux-x64-gnu"
["linux-arm64"]="packages/cli-linux-arm64-gnu"
["win32-x64"]="packages/cli-win32-x64"
["win32-arm64"]="packages/cli-win32-arm64"
)
min_size=100000
failures=0
for suffix in "${!PLATFORM_PKG_DIRS[@]}"; do
package_dir="${PLATFORM_PKG_DIRS[$suffix]}"
if [[ "$suffix" == win32-* ]]; then
binary_path="${package_dir}/bin/actionbook.exe"
else
binary_path="${package_dir}/bin/actionbook"
fi
if [[ ! -f "${binary_path}" ]]; then
echo "ERROR: Missing binary ${binary_path}"
failures=$((failures + 1))
continue
fi
size=$(stat -c%s "${binary_path}")
if [[ "$size" -lt "$min_size" ]]; then
echo "ERROR: Binary too small ${binary_path} (${size} bytes)"
failures=$((failures + 1))
continue
fi
echo "OK: ${binary_path} (${size} bytes)"
done
if [[ "$failures" -gt 0 ]]; then
echo "Found ${failures} platform binary validation errors"
exit 1
fi
- name: Generate SHA256 checksums for CLI binaries
run: |
EXPECTED_ASSETS=(
"actionbook-darwin-arm64"
"actionbook-darwin-x64"
"actionbook-linux-x64"
"actionbook-linux-arm64"
"actionbook-win32-x64.exe"
"actionbook-win32-arm64.exe"
)
missing=0
for asset in "${EXPECTED_ASSETS[@]}"; do
artifact_dir="${asset%.exe}"
binary_path="artifacts/${artifact_dir}/${asset}"
if [[ ! -f "$binary_path" ]]; then
echo "ERROR: Expected binary not found: $binary_path"
missing=$((missing + 1))
fi
done
if [[ "$missing" -gt 0 ]]; then
echo "Missing $missing expected binaries — aborting checksum generation"
exit 1
fi
mkdir -p artifacts/checksums
: > artifacts/checksums/SHA256SUMS
for asset in "${EXPECTED_ASSETS[@]}"; do
artifact_dir="${asset%.exe}"
binary_path="artifacts/${artifact_dir}/${asset}"
checksum=$(sha256sum "$binary_path" | awk '{print $1}')
printf '%s %s\n' "$checksum" "$asset" >> artifacts/checksums/SHA256SUMS
done
echo "--- SHA256SUMS ---"
cat artifacts/checksums/SHA256SUMS
- name: Publish platform packages
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
declare -A PLATFORM_PKG_DIRS=(
["darwin-arm64"]="packages/cli-darwin-arm64"
["darwin-x64"]="packages/cli-darwin-x64"
["linux-x64"]="packages/cli-linux-x64-gnu"
["linux-arm64"]="packages/cli-linux-arm64-gnu"
["win32-x64"]="packages/cli-win32-x64"
["win32-arm64"]="packages/cli-win32-arm64"
)
declare -A PLATFORM_PKG_NAMES=(
["darwin-arm64"]="@actionbookdev/cli-darwin-arm64"
["darwin-x64"]="@actionbookdev/cli-darwin-x64"
["linux-x64"]="@actionbookdev/cli-linux-x64-gnu"
["linux-arm64"]="@actionbookdev/cli-linux-arm64-gnu"
["win32-x64"]="@actionbookdev/cli-win32-x64"
["win32-arm64"]="@actionbookdev/cli-win32-arm64"
)
for suffix in darwin-arm64 darwin-x64 linux-x64 linux-arm64 win32-x64 win32-arm64; do
pkg_dir="${PLATFORM_PKG_DIRS[$suffix]}"
pkg_name="${PLATFORM_PKG_NAMES[$suffix]}"
LOCAL_VER=$(node -e "console.log(JSON.parse(require('fs').readFileSync('${pkg_dir}/package.json','utf8')).version)")
NPM_VER=$(npm view "${pkg_name}" version 2>/dev/null || echo "0.0.0")
if [ "$LOCAL_VER" != "$NPM_VER" ]; then
TAG_FLAGS=()
if [[ "$LOCAL_VER" == *-alpha* ]]; then
TAG_FLAGS=(--tag alpha)
fi
echo "Publishing ${pkg_name}@${LOCAL_VER} (npm has ${NPM_VER})..."
(cd "${pkg_dir}" && npm publish --access public --provenance "${TAG_FLAGS[@]}")
else
echo "Skipping ${pkg_name}@${LOCAL_VER} (already published)"
fi
done
- name: Replace workspace protocol in CLI package
run: |
VERSION="${{ steps.version.outputs.version }}"
node -e "
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('packages/cli/package.json', 'utf8'));
for (const [name, ver] of Object.entries(pkg.optionalDependencies || {})) {
if (ver.startsWith('workspace:')) {
pkg.optionalDependencies[name] = '${VERSION}';
}
}
fs.writeFileSync('packages/cli/package.json', JSON.stringify(pkg, null, 2) + '\n');
console.log('Replaced workspace:* with ${VERSION} in CLI optionalDependencies');
"
- name: Copy root README to CLI package
run: cp README.md packages/cli/README.md
- name: Publish CLI package
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
LOCAL_VER="${{ steps.version.outputs.version }}"
NPM_VER=$(npm view @actionbookdev/cli version 2>/dev/null || echo "0.0.0")
if [ "$LOCAL_VER" != "$NPM_VER" ]; then
TAG_FLAGS=()
if [[ "$LOCAL_VER" == *-alpha* ]]; then
TAG_FLAGS=(--tag alpha)
fi
echo "Publishing @actionbookdev/cli@${LOCAL_VER} (npm has ${NPM_VER})..."
(cd packages/cli && npm publish --access public --provenance "${TAG_FLAGS[@]}")
else
echo "Skipping @actionbookdev/cli@${LOCAL_VER} (already published)"
fi
- name: Create CLI GitHub Release
uses: softprops/action-gh-release@v2
with:
token: ${{ secrets.RELEASE_PAT || github.token }}
tag_name: actionbook-cli-v${{ steps.version.outputs.version }}
name: Actionbook CLI v${{ steps.version.outputs.version }}
files: |
artifacts/actionbook-darwin-arm64/actionbook-darwin-arm64
artifacts/actionbook-darwin-x64/actionbook-darwin-x64
artifacts/actionbook-linux-x64/actionbook-linux-x64
artifacts/actionbook-linux-arm64/actionbook-linux-arm64
artifacts/actionbook-win32-x64/actionbook-win32-x64.exe
artifacts/actionbook-win32-arm64/actionbook-win32-arm64.exe
artifacts/checksums/SHA256SUMS
generate_release_notes: true
- name: Update Homebrew formula
env:
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
run: |
VERSION="${{ steps.version.outputs.version }}"
TAG="actionbook-cli-v${VERSION}"
# Read SHA256SUMS generated earlier in this job
CHECKSUMS_FILE="artifacts/checksums/SHA256SUMS"
if [[ ! -f "$CHECKSUMS_FILE" ]]; then
echo "WARNING: SHA256SUMS not found, skipping Homebrew formula update"
exit 0
fi
get_sha() {
local asset="$1"
grep " ${asset}$" "$CHECKSUMS_FILE" | cut -d' ' -f1
}
SHA_DARWIN_ARM64=$(get_sha "actionbook-darwin-arm64")
SHA_DARWIN_X64=$(get_sha "actionbook-darwin-x64")
SHA_LINUX_ARM64=$(get_sha "actionbook-linux-arm64")
SHA_LINUX_X64=$(get_sha "actionbook-linux-x64")
# Generate the updated formula
cat > /tmp/actionbook.rb << RUBY_EOF
# typed: false
# frozen_string_literal: true
# Formula auto-updated by actionbook/actionbook release CI.
# Manual edits will be overwritten on the next release.
class Actionbook < Formula
desc "CLI for Actionbook - run AI actions from your terminal"
homepage "https://actionbook.app"
version "${VERSION}"
license "MIT"
on_macos do
if Hardware::CPU.arm?
url "https://github.com/actionbook/actionbook/releases/download/${TAG}/actionbook-darwin-arm64"
sha256 "${SHA_DARWIN_ARM64}"
else
url "https://github.com/actionbook/actionbook/releases/download/${TAG}/actionbook-darwin-x64"
sha256 "${SHA_DARWIN_X64}"
end
end
on_linux do
if Hardware::CPU.arm?
url "https://github.com/actionbook/actionbook/releases/download/${TAG}/actionbook-linux-arm64"
sha256 "${SHA_LINUX_ARM64}"
else
url "https://github.com/actionbook/actionbook/releases/download/${TAG}/actionbook-linux-x64"
sha256 "${SHA_LINUX_X64}"
end
end
def install
binary_name = "actionbook"
if OS.mac?
bin.install (Hardware::CPU.arm? ? "actionbook-darwin-arm64" : "actionbook-darwin-x64") => binary_name
else
bin.install (Hardware::CPU.arm? ? "actionbook-linux-arm64" : "actionbook-linux-x64") => binary_name
end
end
test do
assert_match version.to_s, shell_output("#{bin}/actionbook --version")
end
end
RUBY_EOF
# Remove leading whitespace (heredoc indentation)
sed -i "s/^ //" /tmp/actionbook.rb
# Push to homebrew-tap repo
cd "$(mktemp -d)"
git clone "https://x-access-token:${HOMEBREW_TAP_TOKEN}@github.com/actionbook/homebrew-tap.git" .
cp /tmp/actionbook.rb Formula/actionbook.rb
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Formula/actionbook.rb
git commit -m "actionbook ${VERSION}" || echo "No changes to commit"
git push