ci(skill): publish OpenMAIC skill to ClawHub #12
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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. | |
| on: | |
| pull_request: | |
| branches: [main] | |
| paths: | |
| - "skills/openmaic/**" | |
| - ".github/scripts/check-clawhub-version.mjs" | |
| - ".github/workflows/publish-openmaic-skill.yml" | |
| push: | |
| branches: [main] | |
| paths: | |
| - "skills/openmaic/**" | |
| - ".github/scripts/check-clawhub-version.mjs" | |
| - ".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 version without build metadata; leave empty for 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 | |
| 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 ClawHub version script syntax | |
| run: node --check .github/scripts/check-clawhub-version.mjs | |
| - name: Install ClawHub CLI | |
| working-directory: ${{ runner.temp }} | |
| env: | |
| NPM_CONFIG_REGISTRY: https://registry.npmjs.org | |
| NPM_CONFIG_USERCONFIG: ${{ runner.temp }}/empty-npmrc | |
| run: | | |
| : > "$NPM_CONFIG_USERCONFIG" | |
| npm install --global --ignore-scripts clawhub@0.23.3 | |
| echo "CLAWHUB_PACKAGE_JSON=$(npm root --global)/clawhub/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: | |
| 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 | |
| publish_args=( | |
| skills/openmaic | |
| --slug openmaic | |
| --name OpenMAIC | |
| --owner wyuc | |
| --source-repo "$SOURCE_REPO" | |
| --source-commit "$source_commit" | |
| --source-path skills/openmaic | |
| ) | |
| if [[ -n "$PUBLISH_VERSION" ]]; then | |
| preflight_file="$RUNNER_TEMP/clawhub-version-preflight.json" | |
| clawhub skill publish "${publish_args[@]}" --dry-run --json | tee "$preflight_file" | |
| if ! decision="$(PREFLIGHT_FILE="$preflight_file" node .github/scripts/check-clawhub-version.mjs)"; then | |
| exit 1 | |
| fi | |
| IFS=$'\t' read -r action canonical_version extra <<< "$decision" | |
| if [[ -n "${extra:-}" || -z "$action" || -z "$canonical_version" ]]; then | |
| echo "::error::Invalid version preflight decision." | |
| exit 1 | |
| fi | |
| case "$action" in | |
| noop) | |
| echo "::notice::The requested version already has identical content." | |
| exit 0 | |
| ;; | |
| continue) | |
| publish_args+=(--version "$canonical_version") | |
| ;; | |
| *) | |
| echo "::error::Unknown version preflight action." | |
| exit 1 | |
| ;; | |
| esac | |
| fi | |
| clawhub skill publish "${publish_args[@]}" --dry-run --json | |
| 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 }} | |
| persist-credentials: false | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 | |
| with: | |
| node-version: 22 | |
| - name: Check ClawHub version script syntax | |
| run: node --check .github/scripts/check-clawhub-version.mjs | |
| - name: Install ClawHub CLI | |
| working-directory: ${{ runner.temp }} | |
| env: | |
| NPM_CONFIG_REGISTRY: https://registry.npmjs.org | |
| NPM_CONFIG_USERCONFIG: ${{ runner.temp }}/empty-npmrc | |
| run: | | |
| : > "$NPM_CONFIG_USERCONFIG" | |
| npm install --global --ignore-scripts clawhub@0.23.3 | |
| echo "CLAWHUB_PACKAGE_JSON=$(npm root --global)/clawhub/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: | |
| PUBLISH_VERSION: ${{ github.event_name == 'workflow_dispatch' && inputs.version || '' }} | |
| SOURCE_REPO: ${{ github.repository }} | |
| run: | | |
| set -euo pipefail | |
| source_commit="$(git rev-parse HEAD)" | |
| git fetch --no-tags origin main | |
| if ! git rev-parse --verify --quiet "refs/remotes/origin/main^{commit}" >/dev/null; then | |
| echo "::error::Unable to resolve the fetched origin/main commit." | |
| exit 1 | |
| fi | |
| 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 | |
| if ! git cat-file -e "origin/main^{tree}:skills/openmaic" 2>/dev/null; then | |
| echo "::notice::Skipping $source_commit because skills/openmaic was removed from main." | |
| exit 0 | |
| fi | |
| source_tree="$(git rev-parse HEAD:skills/openmaic)" | |
| main_tree="$(git rev-parse origin/main:skills/openmaic)" | |
| if [[ "$source_tree" != "$main_tree" ]]; then | |
| echo "::notice::Skipping $source_commit because skills/openmaic changed on main." | |
| exit 0 | |
| fi | |
| publish_args=( | |
| skills/openmaic | |
| --slug openmaic | |
| --name OpenMAIC | |
| --owner wyuc | |
| --source-repo "$SOURCE_REPO" | |
| --source-commit "$source_commit" | |
| --source-path skills/openmaic | |
| ) | |
| if [[ -n "$PUBLISH_VERSION" ]]; then | |
| preflight_file="$RUNNER_TEMP/clawhub-version-preflight.json" | |
| clawhub skill publish "${publish_args[@]}" --dry-run --json | tee "$preflight_file" | |
| if ! decision="$(PREFLIGHT_FILE="$preflight_file" node .github/scripts/check-clawhub-version.mjs)"; then | |
| exit 1 | |
| fi | |
| IFS=$'\t' read -r action canonical_version extra <<< "$decision" | |
| if [[ -n "${extra:-}" || -z "$action" || -z "$canonical_version" ]]; then | |
| echo "::error::Invalid version preflight decision." | |
| exit 1 | |
| fi | |
| case "$action" in | |
| noop) | |
| echo "::notice::The requested version already has identical content." | |
| exit 0 | |
| ;; | |
| continue) | |
| publish_args+=(--version "$canonical_version") | |
| ;; | |
| *) | |
| echo "::error::Unknown version preflight action." | |
| exit 1 | |
| ;; | |
| esac | |
| fi | |
| clawhub skill publish "${publish_args[@]}" --json |