mirror of
https://github.com/actionbook/actionbook.git
synced 2026-09-19 03:28:06 +08:00
c6ddd3091d
Add version comparison before npm publish for platform packages and CLI main package, matching the existing pattern in publish-js job. Prevents 403 "cannot publish over previously published versions" on rerun.
748 lines
28 KiB
YAML
748 lines
28 KiB
YAML
name: Release
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
|
|
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
|
|
|
permissions:
|
|
contents: write
|
|
pull-requests: write
|
|
id-token: write
|
|
|
|
jobs:
|
|
# --------------------------------------------------------------------------
|
|
# Job 1: Create Version PR or determine what to 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 }}
|
|
extension-needs-release: ${{ steps.check-releases.outputs.extension }}
|
|
dify-plugin-needs-release: ${{ steps.check-releases.outputs.dify-plugin }}
|
|
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: 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 which packages need 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
|
|
|
|
EXT_LOCAL=$(node -e "console.log(JSON.parse(require('fs').readFileSync('packages/actionbook-extension/package.json','utf8')).version)")
|
|
EXT_TAG="actionbook-extension-v${EXT_LOCAL}"
|
|
if git tag -l "$EXT_TAG" | grep -q .; then
|
|
echo "extension=false" >> "$GITHUB_OUTPUT"
|
|
echo "Extension tag exists: $EXT_TAG"
|
|
else
|
|
echo "extension=true" >> "$GITHUB_OUTPUT"
|
|
echo "Extension needs release: $EXT_LOCAL (tag $EXT_TAG not found)"
|
|
fi
|
|
|
|
DIFY_LOCAL=$(node -e "console.log(JSON.parse(require('fs').readFileSync('packages/dify-plugin/package.json','utf8')).version)")
|
|
DIFY_TAG="actionbook-dify-plugin-v${DIFY_LOCAL}"
|
|
if git tag -l "$DIFY_TAG" | grep -q .; then
|
|
echo "dify-plugin=false" >> "$GITHUB_OUTPUT"
|
|
echo "Dify plugin tag exists: $DIFY_TAG"
|
|
else
|
|
echo "dify-plugin=true" >> "$GITHUB_OUTPUT"
|
|
echo "Dify plugin needs release: $DIFY_LOCAL (tag $DIFY_TAG not found)"
|
|
fi
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Job 2: Publish JS packages (sdk, mcp, tools-ai-sdk, json-ui)
|
|
# --------------------------------------------------------------------------
|
|
publish-js:
|
|
name: Publish JS Packages
|
|
needs: version-or-release
|
|
if: needs.version-or-release.outputs.should-release == 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- 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: Build packages
|
|
run: pnpm build:release
|
|
|
|
- name: Publish packages
|
|
id: publish
|
|
env:
|
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
run: |
|
|
PACKAGES=(
|
|
"@actionbookdev/sdk:packages/js-sdk"
|
|
"@actionbookdev/mcp:packages/mcp"
|
|
"@actionbookdev/tools-ai-sdk:packages/tools-ai-sdk"
|
|
"@actionbookdev/json-ui:packages/json-ui"
|
|
"@actionbookdev/openclaw-plugin:packages/openclaw-plugin"
|
|
)
|
|
|
|
PUBLISHED_LIST=""
|
|
for entry in "${PACKAGES[@]}"; do
|
|
PKG_NAME="${entry%%:*}"
|
|
PKG_DIR="${entry##*:}"
|
|
|
|
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
|
|
echo "Publishing ${PKG_NAME}@${LOCAL_VER} (npm has ${NPM_VER})..."
|
|
(cd "${PKG_DIR}" && pnpm publish --access public --provenance --no-git-checks)
|
|
PUBLISHED_LIST="${PUBLISHED_LIST}- **${PKG_NAME}** \`${LOCAL_VER}\`\n"
|
|
else
|
|
echo "Skipping ${PKG_NAME}@${LOCAL_VER} (already published)"
|
|
fi
|
|
done
|
|
|
|
echo "published_list<<PUBLISHED_EOF" >> "$GITHUB_OUTPUT"
|
|
echo -e "$PUBLISHED_LIST" >> "$GITHUB_OUTPUT"
|
|
echo "PUBLISHED_EOF" >> "$GITHUB_OUTPUT"
|
|
if [ -n "$PUBLISHED_LIST" ]; then
|
|
echo "has_published=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "has_published=false" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
- name: Notify Discord of npm publishes
|
|
if: steps.publish.outputs.has_published == 'true'
|
|
env:
|
|
WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
|
PUBLISHED_LIST: ${{ steps.publish.outputs.published_list }}
|
|
run: |
|
|
DESCRIPTION="The following packages have been published to npm:\n\n${PUBLISHED_LIST}"
|
|
PAYLOAD=$(jq -n \
|
|
--arg desc "$DESCRIPTION" \
|
|
'{
|
|
"username": "Actionbook Release",
|
|
"embeds": [{
|
|
"title": "New Release: npm Packages Published 🎉",
|
|
"url": "https://www.npmjs.com/org/actionbookdev",
|
|
"description": $desc,
|
|
"color": 15105570,
|
|
"footer": { "text": "npm Publish" },
|
|
"timestamp": (now | strftime("%Y-%m-%dT%H:%M:%SZ"))
|
|
}]
|
|
}')
|
|
curl -sf -X POST "$WEBHOOK_URL" \
|
|
-H "Content-Type: application/json" \
|
|
-d "$PAYLOAD"
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Job 3: 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'
|
|
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/actionbook-rs
|
|
|
|
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/actionbook-rs/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"
|
|
|
|
if [[ "${{ matrix.platform-suffix }}" == win32-* ]]; then
|
|
DEST="$ARTIFACT_DIR/actionbook-${{ matrix.platform-suffix }}.exe"
|
|
else
|
|
DEST="$ARTIFACT_DIR/actionbook-${{ matrix.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 4: 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'
|
|
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
|
|
echo "Publishing ${pkg_name}@${LOCAL_VER} (npm has ${NPM_VER})..."
|
|
(cd "${pkg_dir}" && npm publish --access public --provenance)
|
|
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: 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
|
|
echo "Publishing @actionbookdev/cli@${LOCAL_VER} (npm has ${NPM_VER})..."
|
|
(cd packages/cli && npm publish --access public --provenance)
|
|
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.dev"
|
|
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
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Job 5: Release Extension (package ZIPs + GitHub Release)
|
|
# --------------------------------------------------------------------------
|
|
release-extension:
|
|
name: Release Extension
|
|
needs: version-or-release
|
|
if: needs.version-or-release.outputs.extension-needs-release == 'true'
|
|
runs-on: ubuntu-latest
|
|
defaults:
|
|
run:
|
|
working-directory: packages/actionbook-extension
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Read extension version
|
|
id: version
|
|
run: |
|
|
VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('package.json','utf8')).version)")
|
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Verify manifest.json version matches
|
|
run: |
|
|
MANIFEST_VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('manifest.json','utf8')).version)")
|
|
PKG_VERSION="${{ steps.version.outputs.version }}"
|
|
if [ "$MANIFEST_VERSION" != "$PKG_VERSION" ]; then
|
|
echo "ERROR: manifest.json version ($MANIFEST_VERSION) does not match package.json version ($PKG_VERSION)"
|
|
exit 1
|
|
fi
|
|
echo "Version verified: $PKG_VERSION"
|
|
|
|
- name: Package extension
|
|
run: node scripts/package.js
|
|
|
|
- name: Create Extension GitHub Release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
token: ${{ secrets.RELEASE_PAT || github.token }}
|
|
tag_name: actionbook-extension-v${{ steps.version.outputs.version }}
|
|
name: Actionbook Extension v${{ steps.version.outputs.version }}
|
|
files: |
|
|
packages/actionbook-extension/dist/actionbook-extension-v${{ steps.version.outputs.version }}.zip
|
|
packages/actionbook-extension/dist/actionbook-extension-v${{ steps.version.outputs.version }}-cws.zip
|
|
body: |
|
|
## Actionbook Chrome Extension v${{ steps.version.outputs.version }}
|
|
|
|
### Install
|
|
|
|
**Option 1: CLI (recommended)**
|
|
```bash
|
|
actionbook extension install
|
|
```
|
|
|
|
**Option 2: Manual**
|
|
1. Download `actionbook-extension-v${{ steps.version.outputs.version }}.zip` below
|
|
2. Unzip to a local folder
|
|
3. Open `chrome://extensions` in Chrome
|
|
4. Enable **Developer mode**
|
|
5. Click **Load unpacked** and select the unzipped folder
|
|
|
|
**Option 3: Chrome Web Store**
|
|
Download `actionbook-extension-v${{ steps.version.outputs.version }}-cws.zip` for Chrome Web Store submission (manifest without `key` field).
|
|
|
|
### After installing
|
|
```bash
|
|
actionbook browser open https://example.com
|
|
```
|
|
The extension auto-connects to the local bridge at `127.0.0.1:19222`.
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Job 6: Release Dify Plugin (package .difypkg + GitHub Release)
|
|
# --------------------------------------------------------------------------
|
|
release-dify-plugin:
|
|
name: Release Dify Plugin
|
|
needs: version-or-release
|
|
if: needs.version-or-release.outputs.dify-plugin-needs-release == 'true'
|
|
runs-on: ubuntu-latest
|
|
defaults:
|
|
run:
|
|
working-directory: packages/dify-plugin
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "20"
|
|
|
|
- name: Read dify-plugin version
|
|
id: version
|
|
run: |
|
|
VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('package.json','utf8')).version)")
|
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Verify manifest.yaml version matches
|
|
run: |
|
|
PKG_VERSION="${{ steps.version.outputs.version }}"
|
|
ROOT_VERSION=$(grep -m1 '^version:' manifest.yaml | awk '{gsub(/"/,"",$2); print $2}')
|
|
META_VERSION=$(awk '/^meta:/{found=1} found && /^ version:/{gsub(/"/,"",$2); print $2; exit}' manifest.yaml)
|
|
if [ "$ROOT_VERSION" != "$PKG_VERSION" ]; then
|
|
echo "ERROR: manifest.yaml root version ($ROOT_VERSION) != package.json ($PKG_VERSION)"
|
|
exit 1
|
|
fi
|
|
if [ "$META_VERSION" != "$PKG_VERSION" ]; then
|
|
echo "ERROR: manifest.yaml meta.version ($META_VERSION) != package.json ($PKG_VERSION)"
|
|
exit 1
|
|
fi
|
|
echo "Version verified: $PKG_VERSION"
|
|
|
|
- name: Setup Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.12"
|
|
|
|
- name: Install uv
|
|
uses: astral-sh/setup-uv@v4
|
|
|
|
- name: Install dependencies
|
|
run: uv sync
|
|
|
|
- name: Install Dify CLI
|
|
env:
|
|
DIFY_CLI_VERSION: "0.5.3"
|
|
run: |
|
|
mkdir -p "$HOME/.local/bin"
|
|
curl -fsSL \
|
|
"https://github.com/langgenius/dify-plugin-daemon/releases/download/${DIFY_CLI_VERSION}/dify-plugin-linux-amd64" \
|
|
-o "$HOME/.local/bin/dify"
|
|
chmod +x "$HOME/.local/bin/dify"
|
|
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
"$HOME/.local/bin/dify" version
|
|
|
|
- name: Package dify plugin
|
|
run: |
|
|
mkdir -p dist
|
|
dify plugin package "$PWD" \
|
|
--output_path "$PWD/dist/actionbook.difypkg"
|
|
ls -la dist/
|
|
|
|
- name: Rename artifact with version
|
|
run: |
|
|
VERSION="${{ steps.version.outputs.version }}"
|
|
mv dist/actionbook.difypkg "dist/actionbook-v${VERSION}.difypkg"
|
|
|
|
- name: Create Dify Plugin GitHub Release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
token: ${{ secrets.RELEASE_PAT || github.token }}
|
|
tag_name: actionbook-dify-plugin-v${{ steps.version.outputs.version }}
|
|
name: Actionbook Dify Plugin v${{ steps.version.outputs.version }}
|
|
files: |
|
|
packages/dify-plugin/dist/actionbook-v${{ steps.version.outputs.version }}.difypkg
|
|
body: |
|
|
## Actionbook Dify Plugin v${{ steps.version.outputs.version }}
|
|
|
|
### Install
|
|
|
|
**Option 1: Upload to Dify**
|
|
1. Download `actionbook-v${{ steps.version.outputs.version }}.difypkg` below
|
|
2. Go to your Dify instance → Plugins
|
|
3. Upload the `.difypkg` file
|
|
|
|
**Option 2: Dify Marketplace**
|
|
Search for "Actionbook" in the Dify plugin marketplace.
|
|
generate_release_notes: true
|