Publish skills to ClawHub workflow (worldwonderer/oh-story-claudecode)
The Publish skills to ClawHub workflow from worldwonderer/oh-story-claudecode, explained and optimized by Latchkey.
CI health: C - fair
Point runs-on at Latchkey and get caching, job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Publish skills to ClawHub workflow from the worldwonderer/oh-story-claudecode repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: Publish skills to ClawHub
# Publishes changed skills to ClawHub on release. Triggers:
# - pushing a version tag (v*)
# - publishing a GitHub Release
# - manual "Run workflow" button (with optional dry-run / bump / changelog)
# - PRs that edit THIS file → runs auth + a dry-run only (never publishes), as a self-test
# story and browser-cdp are published manually and excluded here.
on:
push:
tags: ['v*']
release:
types: [published]
pull_request:
paths: ['.github/workflows/publish-clawhub.yml']
workflow_dispatch:
inputs:
bump:
description: Version bump for changed skills
type: choice
options: [patch, minor, major]
default: patch
changelog:
description: Changelog text (optional; defaults to the ref name)
type: string
default: ''
dry_run:
description: Preview only - do not publish
type: boolean
default: false
# Never let two publishes race (e.g. tag push + release published).
concurrency:
group: clawhub-publish
cancel-in-progress: false
permissions:
contents: read
jobs:
publish:
# Only the canonical repo may publish; skip on forks.
if: github.repository == 'worldwonderer/oh-story-claudecode'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Install ClawHub CLI
run: npm install -g clawhub
- name: Authenticate
env:
CLAWHUB_TOKEN: ${{ secrets.CLAWHUB_TOKEN }}
run: |
if [ -z "$CLAWHUB_TOKEN" ]; then
echo "::error::CLAWHUB_TOKEN secret is not set. Add it in repo Settings → Secrets → Actions."
exit 1
fi
clawhub login --token "$CLAWHUB_TOKEN" --no-browser
clawhub whoami
- name: Exclude manually-managed skills
# Affects only this ephemeral CI checkout, never your repo.
# `sync` scans the skills/ dir, so removing these folders excludes them.
run: |
for s in story browser-cdp; do rm -rf "skills/$s"; done
- name: Resolve changelog text
run: |
CL="${{ github.event.inputs.changelog }}"
if [ -z "$CL" ]; then CL="Synced from CI (${{ github.ref_name }})"; fi
echo "CLAWHUB_CHANGELOG=$CL" >> "$GITHUB_ENV"
- name: Show what would publish
run: clawhub --no-input sync --dry-run --bump "${{ github.event.inputs.bump || 'patch' }}"
- name: Publish changed skills
# Never publishes on pull_request events - those only run the dry-run above.
if: github.event_name != 'pull_request' && github.event.inputs.dry_run != 'true'
run: |
clawhub --no-input sync --all \
--bump "${{ github.event.inputs.bump || 'patch' }}" \
--changelog "$CLAWHUB_CHANGELOG"
The same workflow, on Latchkey
Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.
name: Publish skills to ClawHub # Publishes changed skills to ClawHub on release. Triggers: # - pushing a version tag (v*) # - publishing a GitHub Release # - manual "Run workflow" button (with optional dry-run / bump / changelog) # - PRs that edit THIS file → runs auth + a dry-run only (never publishes), as a self-test # story and browser-cdp are published manually and excluded here. on: push: tags: ['v*'] release: types: [published] pull_request: paths: ['.github/workflows/publish-clawhub.yml'] workflow_dispatch: inputs: bump: description: Version bump for changed skills type: choice options: [patch, minor, major] default: patch changelog: description: Changelog text (optional; defaults to the ref name) type: string default: '' dry_run: description: Preview only - do not publish type: boolean default: false # Never let two publishes race (e.g. tag push + release published). concurrency: group: clawhub-publish cancel-in-progress: false permissions: contents: read jobs: publish: timeout-minutes: 30 # Only the canonical repo may publish; skip on forks. if: github.repository == 'worldwonderer/oh-story-claudecode' runs-on: latchkey-small steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: cache: 'npm' node-version: 20 - name: Install ClawHub CLI run: npm install -g clawhub - name: Authenticate env: CLAWHUB_TOKEN: ${{ secrets.CLAWHUB_TOKEN }} run: | if [ -z "$CLAWHUB_TOKEN" ]; then echo "::error::CLAWHUB_TOKEN secret is not set. Add it in repo Settings → Secrets → Actions." exit 1 fi clawhub login --token "$CLAWHUB_TOKEN" --no-browser clawhub whoami - name: Exclude manually-managed skills # Affects only this ephemeral CI checkout, never your repo. # `sync` scans the skills/ dir, so removing these folders excludes them. run: | for s in story browser-cdp; do rm -rf "skills/$s"; done - name: Resolve changelog text run: | CL="${{ github.event.inputs.changelog }}" if [ -z "$CL" ]; then CL="Synced from CI (${{ github.ref_name }})"; fi echo "CLAWHUB_CHANGELOG=$CL" >> "$GITHUB_ENV" - name: Show what would publish run: clawhub --no-input sync --dry-run --bump "${{ github.event.inputs.bump || 'patch' }}" - name: Publish changed skills # Never publishes on pull_request events - those only run the dry-run above. if: github.event_name != 'pull_request' && github.event.inputs.dry_run != 'true' run: | clawhub --no-input sync --all \ --bump "${{ github.event.inputs.bump || 'patch' }}" \ --changelog "$CLAWHUB_CHANGELOG"
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cache dependency installs on the setup step so they are served from cache.
- Add a job timeout so a hung step cannot burn hours of runner time.
What Latchkey heals here
This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:
- Dependency installs
This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.