mirror of
https://github.com/cline/cline.git
synced 2026-09-19 02:05:44 +08:00
* Move bun to root * Fix scripts and pre-commit * Update scripts * Update workflows * Fix cd * fix pre-commit * fix cli publish
283 lines
10 KiB
YAML
283 lines
10 KiB
YAML
name: sdk-publish
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
channel:
|
|
description: "Publish channel"
|
|
required: true
|
|
type: choice
|
|
options:
|
|
- nightly
|
|
- latest
|
|
default: nightly
|
|
force_publish:
|
|
description: "Force publish even if there are no commits in the last 24 hours"
|
|
required: false
|
|
type: boolean
|
|
default: false
|
|
confirm_publish:
|
|
description: 'Required when channel=latest. Type "publish" to confirm release publish.'
|
|
required: false
|
|
type: string
|
|
schedule:
|
|
# Run nightly at 2:00 AM UTC
|
|
- cron: "0 2 * * *"
|
|
|
|
defaults:
|
|
run:
|
|
working-directory: .
|
|
|
|
jobs:
|
|
test:
|
|
permissions:
|
|
contents: read
|
|
uses: ./.github/workflows/sdk-test.yml
|
|
|
|
publish-sdk:
|
|
needs: test
|
|
name: Publish SDK Packages
|
|
permissions:
|
|
contents: write
|
|
id-token: write
|
|
if: |
|
|
github.repository == 'cline/cline' &&
|
|
github.ref == 'refs/heads/main' &&
|
|
(
|
|
github.event_name != 'workflow_dispatch' ||
|
|
inputs.channel != 'latest' ||
|
|
(
|
|
inputs.confirm_publish == 'publish' &&
|
|
!endsWith(github.actor, '[bot]')
|
|
)
|
|
)
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Determine publish channel
|
|
id: channel
|
|
env:
|
|
EVENT_NAME: ${{ github.event_name }}
|
|
INPUT_CHANNEL: ${{ inputs.channel }}
|
|
run: |
|
|
# Default to nightly for scheduled runs
|
|
if [ "$EVENT_NAME" = "schedule" ]; then
|
|
echo "channel=nightly" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "channel=$INPUT_CHANNEL" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Check for recent commits
|
|
id: check_commits
|
|
env:
|
|
CHANNEL: ${{ steps.channel.outputs.channel }}
|
|
FORCE_PUBLISH: ${{ inputs.force_publish }}
|
|
run: |
|
|
# Always publish for latest (production) releases
|
|
if [ "$CHANNEL" = "latest" ]; then
|
|
echo "Production release requested, proceeding with publish"
|
|
echo "skip=false" >> $GITHUB_OUTPUT
|
|
exit 0
|
|
fi
|
|
|
|
if [ "$FORCE_PUBLISH" = "true" ]; then
|
|
echo "force_publish enabled, proceeding with publish"
|
|
echo "skip=false" >> $GITHUB_OUTPUT
|
|
exit 0
|
|
fi
|
|
|
|
if [ "$(git rev-list --count HEAD --since="24 hours ago")" -eq 0 ]; then
|
|
echo "No commits in last 24 hours, skipping publish"
|
|
echo "skip=true" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "Found recent commits, proceeding with publish"
|
|
echo "skip=false" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Verify trusted publishing context
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
run: |
|
|
if [ -z "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" ] || [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ]; then
|
|
echo "GitHub OIDC request environment is unavailable. Ensure this job has id-token: write for npm trusted publishing."
|
|
exit 1
|
|
fi
|
|
echo "GitHub OIDC request environment is available for npm trusted publishing."
|
|
|
|
- name: Setup Bun
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
uses: oven-sh/setup-bun@v2
|
|
with:
|
|
bun-version: "1.3.13"
|
|
|
|
- name: Setup Node.js
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "24.x"
|
|
registry-url: "https://registry.npmjs.org"
|
|
|
|
- name: Verify publish tooling
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
run: |
|
|
NPM_VERSION=$(npm --version)
|
|
echo "npm ${NPM_VERSION}"
|
|
IFS=. read -r major minor patch <<EOF
|
|
${NPM_VERSION}
|
|
EOF
|
|
if [ "$major" -lt 11 ] || { [ "$major" -eq 11 ] && [ "$minor" -lt 5 ]; } || { [ "$major" -eq 11 ] && [ "$minor" -eq 5 ] && [ "$patch" -lt 1 ]; }; then
|
|
echo "npm 11.5.1 or newer is required for trusted publishing"
|
|
exit 1
|
|
fi
|
|
|
|
- name: Install dependencies
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
run: bun install
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Build SDK
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
run: bun run build:sdk
|
|
|
|
- name: Generate shared version
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
id: version
|
|
env:
|
|
CHANNEL: ${{ steps.channel.outputs.channel }}
|
|
run: |
|
|
BASE_VERSION=$(node -p "require('./sdk/packages/llms/package.json').version")
|
|
|
|
if [ "$CHANNEL" = "nightly" ]; then
|
|
TIMESTAMP=$(date +%s)
|
|
VERSION="${BASE_VERSION}-nightly.${TIMESTAMP}"
|
|
else
|
|
VERSION="$BASE_VERSION"
|
|
fi
|
|
|
|
echo "Base version: $BASE_VERSION"
|
|
echo "Channel: $CHANNEL"
|
|
echo "Publish version: $VERSION"
|
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
|
|
- name: Update all package versions and lockfile
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
env:
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
run: bun sdk/scripts/version.ts "$VERSION"
|
|
|
|
- name: Verify publishability
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
run: bun sdk/scripts/check-publish.ts
|
|
|
|
- name: Prepare package tarball directory
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
run: mkdir -p "$RUNNER_TEMP/sdk-npm-packs"
|
|
|
|
# Pack with Bun so workspace/catalog protocols are resolved in the tarball,
|
|
# then publish that tarball with npm so npm trusted publishing can use GitHub OIDC.
|
|
# Publish sequentially in dependency order: shared → llms → agents → core → sdk
|
|
- name: Publish @cline/shared
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
env:
|
|
NPM_CONFIG_PROVENANCE: "true"
|
|
CHANNEL: ${{ steps.channel.outputs.channel }}
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
run: |
|
|
echo "Publishing @cline/shared@${VERSION} with tag '${CHANNEL}'..."
|
|
cd sdk/packages/shared
|
|
TARBALL=$(bun pm pack --destination "$RUNNER_TEMP/sdk-npm-packs" --quiet)
|
|
npm publish "$RUNNER_TEMP/sdk-npm-packs/$(basename "$TARBALL")" --tag "$CHANNEL" --access public
|
|
|
|
- name: Publish @cline/llms
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
env:
|
|
NPM_CONFIG_PROVENANCE: "true"
|
|
CHANNEL: ${{ steps.channel.outputs.channel }}
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
run: |
|
|
echo "Publishing @cline/llms@${VERSION} with tag '${CHANNEL}'..."
|
|
cd sdk/packages/llms
|
|
TARBALL=$(bun pm pack --destination "$RUNNER_TEMP/sdk-npm-packs" --quiet)
|
|
npm publish "$RUNNER_TEMP/sdk-npm-packs/$(basename "$TARBALL")" --tag "$CHANNEL" --access public
|
|
|
|
- name: Publish @cline/agents
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
env:
|
|
NPM_CONFIG_PROVENANCE: "true"
|
|
CHANNEL: ${{ steps.channel.outputs.channel }}
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
run: |
|
|
echo "Publishing @cline/agents@${VERSION} with tag '${CHANNEL}'..."
|
|
cd sdk/packages/agents
|
|
TARBALL=$(bun pm pack --destination "$RUNNER_TEMP/sdk-npm-packs" --quiet)
|
|
npm publish "$RUNNER_TEMP/sdk-npm-packs/$(basename "$TARBALL")" --tag "$CHANNEL" --access public
|
|
|
|
- name: Publish @cline/core
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
env:
|
|
NPM_CONFIG_PROVENANCE: "true"
|
|
CHANNEL: ${{ steps.channel.outputs.channel }}
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
run: |
|
|
echo "Publishing @cline/core@${VERSION} with tag '${CHANNEL}'..."
|
|
cd sdk/packages/core
|
|
TARBALL=$(bun pm pack --destination "$RUNNER_TEMP/sdk-npm-packs" --quiet)
|
|
npm publish "$RUNNER_TEMP/sdk-npm-packs/$(basename "$TARBALL")" --tag "$CHANNEL" --access public
|
|
|
|
- name: Publish @cline/sdk
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
env:
|
|
NPM_CONFIG_PROVENANCE: "true"
|
|
CHANNEL: ${{ steps.channel.outputs.channel }}
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
run: |
|
|
echo "Publishing @cline/sdk@${VERSION} with tag '${CHANNEL}'..."
|
|
cd sdk/packages/sdk
|
|
TARBALL=$(bun pm pack --destination "$RUNNER_TEMP/sdk-npm-packs" --quiet)
|
|
npm publish "$RUNNER_TEMP/sdk-npm-packs/$(basename "$TARBALL")" --tag "$CHANNEL" --access public
|
|
|
|
- name: Create package tags for production publish
|
|
if: steps.check_commits.outputs.skip != 'true' && steps.channel.outputs.channel == 'latest'
|
|
env:
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
run: |
|
|
git config user.name "github-actions[bot]"
|
|
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
|
|
for PKG in shared llms agents core sdk; do
|
|
TAG="sdk/${PKG}/v${VERSION}"
|
|
if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then
|
|
echo "Tag already exists locally: ${TAG}"
|
|
else
|
|
git tag -a "${TAG}" -m "@cline/${PKG}@${VERSION}"
|
|
echo "Created tag: ${TAG}"
|
|
fi
|
|
|
|
# Ensure remote has the tag; this is idempotent if tag already exists remotely.
|
|
git push origin "refs/tags/${TAG}"
|
|
done
|
|
|
|
- name: Summary
|
|
if: steps.check_commits.outputs.skip != 'true'
|
|
env:
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
CHANNEL: ${{ steps.channel.outputs.channel }}
|
|
run: |
|
|
echo "Published SDK packages with tag '${CHANNEL}':"
|
|
echo " - @cline/shared@${VERSION}"
|
|
echo " - @cline/llms@${VERSION}"
|
|
echo " - @cline/agents@${VERSION}"
|
|
echo " - @cline/core@${VERSION}"
|
|
echo " - @cline/sdk@${VERSION}"
|
|
if [ "$CHANNEL" = "latest" ]; then
|
|
echo "Created git tags:"
|
|
echo " - sdk/shared/v${VERSION}"
|
|
echo " - sdk/llms/v${VERSION}"
|
|
echo " - sdk/agents/v${VERSION}"
|
|
echo " - sdk/core/v${VERSION}"
|
|
echo " - sdk/sdk/v${VERSION}"
|
|
fi
|