Skip to content

feat(openmaic-skill): add secondary-development (二开) flow #28

feat(openmaic-skill): add secondary-development (二开) flow

feat(openmaic-skill): add secondary-development (二开) flow #28

name: Publish OpenMAIC skill
# Required repository setup:
# - Create a GitHub Environment named `clawhub-release`.
# - Restrict its deployment branches to `main` with a custom policy.
# - Store `CLAWHUB_TOKEN` as an Environment secret.
# - Do not also store `CLAWHUB_TOKEN` as a repository secret.
# This workflow is path-filtered. Do not configure it as a required check for every PR;
# require it only through rules that apply to the paths below.
# PR previews execute the checked-out head scripts, so they intentionally receive no secrets,
# have read-only contents permission, and disable persisted checkout credentials.
# Deleting skills/openmaic does not unpublish or deprecate an existing ClawHub release;
# that registry lifecycle action must be performed manually in ClawHub.
on:
pull_request:
branches: [main]
paths:
- "skills/openmaic/**"
- ".github/scripts/check-clawhub-version.mjs"
- ".github/scripts/publish-openmaic-skill.sh"
- ".github/workflows/publish-openmaic-skill.yml"
push:
branches: [main]
paths:
- "skills/openmaic/**"
- ".github/scripts/check-clawhub-version.mjs"
- ".github/scripts/publish-openmaic-skill.sh"
- ".github/workflows/publish-openmaic-skill.yml"
workflow_dispatch:
inputs:
dry_run:
description: "Preview the current main branch without publishing"
type: boolean
default: true
version:
description: "Optional stable SemVer version (no prerelease/build); empty means automatic patch"
type: string
default: ""
jobs:
reject-invalid-dispatch:
name: Reject publish outside main
if: >-
github.event_name == 'workflow_dispatch' &&
!inputs.dry_run && github.ref != 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Reject publish outside main
run: |
echo "::error::Publishing is only allowed from the main branch."
exit 1
bash-3-compatibility:
name: Verify macOS Bash 3.2 publish compatibility
if: github.event_name == 'pull_request'
runs-on: macos-15
permissions:
contents: read
concurrency:
group: clawhub-bash3-${{ github.event.pull_request.number }}
cancel-in-progress: true
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
persist-credentials: false
- name: Run publish paths with macOS Bash 3.2
run: |
set -euo pipefail
bash_version="$(/bin/bash -c 'printf "%s.%s" "${BASH_VERSINFO[0]}" "${BASH_VERSINFO[1]}"')"
if [[ "$bash_version" != "3.2" ]]; then
echo "::error::Expected macOS system Bash 3.2, found $bash_version."
exit 1
fi
CLAWHUB=/usr/bin/true \
PUBLISH_VERSION='' \
SOURCE_REPO='THU-MAIC/OpenMAIC' \
/bin/bash .github/scripts/publish-openmaic-skill.sh
compat_dir="$RUNNER_TEMP/clawhub-bash3"
mkdir -p "$compat_dir"
cat > "$compat_dir/clawhub" <<'BASH'
#!/bin/bash
printf '%s\t' "$@" >> "$CLAWHUB_CALLS"
printf '\n' >> "$CLAWHUB_CALLS"
if [[ " $* " != *" --version 0.4.0 "* ]]; then
printf '%s\n' '{"status":"would-publish","version":"0.4.0","latestVersion":"0.3.1","fingerprint":"bash3-fixture"}'
fi
BASH
cat > "$compat_dir/node" <<'BASH'
#!/bin/bash
printf 'continue\t0.4.0\n'
BASH
chmod 700 "$compat_dir/clawhub" "$compat_dir/node"
: > "$compat_dir/calls"
CLAWHUB="$compat_dir/clawhub" \
CLAWHUB_CALLS="$compat_dir/calls" \
PATH="$compat_dir:$PATH" \
PUBLISH_VERSION='0.4.0' \
RUNNER_TEMP="$compat_dir" \
SOURCE_REPO='THU-MAIC/OpenMAIC' \
/bin/bash .github/scripts/publish-openmaic-skill.sh
if [[ "$(wc -l < "$compat_dir/calls" | tr -d ' ')" != "2" ]] ||
! grep -q -- $'--version\t0.4.0\t' "$compat_dir/calls"; then
echo "::error::Bash 3.2 manual-version path did not reach canonical publish."
exit 1
fi
preview:
name: Preview ClawHub publish
if: >-
github.event_name == 'pull_request' ||
(github.event_name == 'workflow_dispatch' && inputs.dry_run)
runs-on: ubuntu-latest
permissions:
contents: read
concurrency:
group: clawhub-preview-${{ github.event_name == 'pull_request' && github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
repository: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name || github.repository }}
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || 'main' }}
persist-credentials: false
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22
- name: Check publish script syntax
run: |
node --check .github/scripts/check-clawhub-version.mjs
bash -n .github/scripts/publish-openmaic-skill.sh
- name: Install ClawHub CLI
working-directory: ${{ runner.temp }}
env:
NPM_CONFIG_REGISTRY: https://registry.npmjs.org
NPM_CONFIG_USERCONFIG: ${{ runner.temp }}/empty-npmrc
run: |
set -euo pipefail
: > "$NPM_CONFIG_USERCONFIG"
npm install --global --ignore-scripts clawhub@0.23.3 semver@7.8.5
global_root="$(npm root --global)"
if [[ -z "$global_root" ]]; then
echo "::error::npm returned an empty global package root."
exit 1
fi
echo "SEMVER_PACKAGE_JSON=$global_root/semver/package.json" >> "$GITHUB_ENV"
- name: Configure ClawHub registry
run: |
python3 - <<'PY'
import json
import os
from pathlib import Path
path = Path(os.environ["RUNNER_TEMP"]) / "clawhub-preview-config.json"
path.write_text(
json.dumps({"registry": "https://clawhub.ai"}, indent=2) + "\n",
encoding="utf-8",
)
path.chmod(0o600)
PY
echo "CLAWHUB_CONFIG_PATH=$RUNNER_TEMP/clawhub-preview-config.json" >> "$GITHUB_ENV"
- name: Preview OpenMAIC skill publish
env:
CLAWHUB: clawhub
PUBLISH_VERSION: ${{ github.event_name == 'workflow_dispatch' && inputs.version || '' }}
SOURCE_REPO: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name || github.repository }}
run: |
set -euo pipefail
source_commit="$(git rev-parse HEAD)"
if ! git cat-file -e "HEAD^{tree}:skills/openmaic" 2>/dev/null; then
echo "::notice::Skipping $source_commit because skills/openmaic was deleted."
exit 0
fi
bash .github/scripts/publish-openmaic-skill.sh --dry-run
publish:
name: Publish to ClawHub
if: >-
github.event_name == 'push' ||
(github.event_name == 'workflow_dispatch' &&
github.ref == 'refs/heads/main' && !inputs.dry_run)
runs-on: ubuntu-latest
environment: clawhub-release
permissions:
contents: read
concurrency:
group: publish-openmaic-skill
cancel-in-progress: false
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
ref: ${{ github.sha }}
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22
- name: Check publish script syntax
run: |
node --check .github/scripts/check-clawhub-version.mjs
bash -n .github/scripts/publish-openmaic-skill.sh
- name: Install ClawHub CLI
working-directory: ${{ runner.temp }}
env:
NPM_CONFIG_REGISTRY: https://registry.npmjs.org
NPM_CONFIG_USERCONFIG: ${{ runner.temp }}/empty-npmrc
run: |
set -euo pipefail
: > "$NPM_CONFIG_USERCONFIG"
npm install --global --ignore-scripts clawhub@0.23.3 semver@7.8.5
global_root="$(npm root --global)"
if [[ -z "$global_root" ]]; then
echo "::error::npm returned an empty global package root."
exit 1
fi
echo "SEMVER_PACKAGE_JSON=$global_root/semver/package.json" >> "$GITHUB_ENV"
- name: Verify ClawHub token is configured
env:
CLAWHUB_TOKEN: ${{ secrets.CLAWHUB_TOKEN }}
run: |
if [[ -z "$CLAWHUB_TOKEN" ]]; then
echo "::error::CLAWHUB_TOKEN is not configured in the clawhub-release environment."
exit 1
fi
- name: Write ClawHub config
env:
CLAWHUB_TOKEN: ${{ secrets.CLAWHUB_TOKEN }}
run: |
set -euo pipefail
python3 - <<'PY'
import json
import os
import sys
from pathlib import Path
path = Path(os.environ["RUNNER_TEMP"]) / "clawhub-config.json"
flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL
try:
fd = os.open(path, flags, 0o600)
except FileExistsError:
print("::error::ClawHub config already exists in RUNNER_TEMP.", file=sys.stderr)
sys.exit(1)
with os.fdopen(fd, "w", encoding="utf-8") as config:
json.dump(
{"registry": "https://clawhub.ai", "token": os.environ["CLAWHUB_TOKEN"]},
config,
indent=2,
)
config.write("\n")
PY
echo "CLAWHUB_CONFIG_PATH=$RUNNER_TEMP/clawhub-config.json" >> "$GITHUB_ENV"
- name: Verify ClawHub authentication
run: clawhub whoami
- name: Publish OpenMAIC skill
env:
CLAWHUB: clawhub
EVENT_NAME: ${{ github.event_name }}
PUBLISH_VERSION: ${{ github.event_name == 'workflow_dispatch' && inputs.version || '' }}
SOURCE_REPO: ${{ github.repository }}
run: |
set -euo pipefail
source_commit="$(git rev-parse HEAD)"
handle_divergence() {
reason="$1"
case "$EVENT_NAME" in
workflow_dispatch)
echo "::error::Refusing manual publish because $reason."
exit 1
;;
push)
echo "::notice::Skipping $source_commit because $reason."
exit 0
;;
*)
echo "::error::Unexpected publish event: $EVENT_NAME."
exit 1
;;
esac
}
if ! git rev-parse --verify --quiet "refs/remotes/origin/main^{commit}" >/dev/null; then
echo "::error::Unable to resolve the checked-out origin/main commit."
exit 1
fi
if ! git cat-file -e "HEAD^{tree}:skills/openmaic" 2>/dev/null; then
handle_divergence "skills/openmaic was deleted"
fi
if ! git cat-file -e "origin/main^{tree}:skills/openmaic" 2>/dev/null; then
handle_divergence "skills/openmaic was removed from main"
fi
source_tree="$(git rev-parse HEAD:skills/openmaic)"
main_tree="$(git rev-parse origin/main:skills/openmaic)"
if [[ "$source_tree" != "$main_tree" ]]; then
handle_divergence "skills/openmaic changed on main"
fi
bash .github/scripts/publish-openmaic-skill.sh