Files
remove-ai-watermarks/.github/workflows/distribute.yml
T
Victor Kuznetsov 8eec0e5af4 Publish the agent skill to ClawHub from the release fan-out
The clawhub job in distribute.yml compares the SKILL.md version with
the published one on every GitHub Release and submits an update when
they differ. Gated on the CLAWHUB_TOKEN secret: without it the job
skips with a notice, so the workflow lands safely before the secret
exists. A submitted update waits for ClawHub security scans, so a
green job means submitted, not listed.
2026-09-07 11:34:13 -07:00

219 lines
8.1 KiB
YAML

name: Distribute on release
# Fans a published GitHub Release out to the channels that need a nudge.
# PyPI is handled by publish.yml. This workflow event-drives the four channels
# that would otherwise be manual:
# - Homebrew tap: rewrite the formula's url + sha256 to the new sdist.
# - HF Space: factory-rebuild the version already pinned in the Space repo.
# - ComfyUI: sync, test, and publish the node against the exact library release.
# - ClawHub: publish the agent skill when its own version moved.
# All wait for the freshly published sdist to appear on PyPI first, since the
# Release event fires in parallel with publish.yml's upload.
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: "Version to distribute (no leading v), e.g. 0.10.3. Blank = latest on PyPI."
required: false
jobs:
resolve:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.v.outputs.version }}
url: ${{ steps.sdist.outputs.url }}
sha: ${{ steps.sdist.outputs.sha }}
steps:
- name: Resolve target version
id: v
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "release" ]; then
v="${GITHUB_REF_NAME#v}"
elif [ -n "${{ github.event.inputs.version }}" ]; then
v="${{ github.event.inputs.version }}"
else
v=$(curl -fsSL https://pypi.org/pypi/remove-ai-watermarks/json \
| python3 -c "import sys,json;print(json.load(sys.stdin)['info']['version'])")
fi
echo "version=$v" >> "$GITHUB_OUTPUT"
echo "Target version: $v"
- name: Wait for the sdist on PyPI, capture url + sha256
id: sdist
run: |
set -euo pipefail
v="${{ steps.v.outputs.version }}"
for i in $(seq 1 30); do
if rel=$(curl -fsSL "https://pypi.org/pypi/remove-ai-watermarks/$v/json" 2>/dev/null); then
url=$(echo "$rel" | python3 -c "import sys,json;d=json.load(sys.stdin);print(next((u['url'] for u in d['urls'] if u['packagetype']=='sdist'),''))")
sha=$(echo "$rel" | python3 -c "import sys,json;d=json.load(sys.stdin);print(next((u['digests']['sha256'] for u in d['urls'] if u['packagetype']=='sdist'),''))")
if [ -n "$url" ] && [ -n "$sha" ]; then
echo "url=$url" >> "$GITHUB_OUTPUT"
echo "sha=$sha" >> "$GITHUB_OUTPUT"
echo "Found sdist for $v"
exit 0
fi
fi
echo "sdist for $v not on PyPI yet (attempt $i), waiting..."
sleep 20
done
echo "::error::sdist for $v did not appear on PyPI in time"
exit 1
homebrew:
needs: resolve
runs-on: ubuntu-latest
steps:
- name: Checkout the tap
uses: actions/checkout@v7
with:
repository: wiltodelta/homebrew-tap
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
- name: Bump the formula
env:
URL: ${{ needs.resolve.outputs.url }}
SHA: ${{ needs.resolve.outputs.sha }}
VERSION: ${{ needs.resolve.outputs.version }}
run: |
set -euo pipefail
F=Formula/remove-ai-watermarks.rb
sed -i -E "s|url \"[^\"]*\"|url \"$URL\"|" "$F"
sed -i -E "s|sha256 \"[^\"]*\"|sha256 \"$SHA\"|" "$F"
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add "$F"
git commit -m "remove-ai-watermarks $VERSION" || { echo "Formula already current"; exit 0; }
git push
hf-space:
needs: resolve
runs-on: ubuntu-latest
steps:
- name: Factory-rebuild the HuggingFace Space
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
run: |
python3 -m pip install --quiet huggingface_hub
python3 - <<'PY'
import os
from huggingface_hub import HfApi
HfApi(token=os.environ["HF_TOKEN"]).restart_space(
"wiltodelta/remove-ai-watermarks", factory_reboot=True
)
print("HF Space factory rebuild triggered")
PY
clawhub:
needs: resolve
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Publish the agent skill when its version moved
env:
CLAWHUB_TOKEN: ${{ secrets.CLAWHUB_TOKEN }}
run: |
set -euo pipefail
if [ -z "${CLAWHUB_TOKEN:-}" ]; then
echo "CLAWHUB_TOKEN secret is not set; skipping ClawHub publish."
exit 0
fi
npm install --silent --no-fund --no-audit clawhub
skill_version=$(python3 - <<'PY'
import re
text = open("skills/remove-ai-watermarks/SKILL.md", encoding="utf-8").read()
m = re.search(r"(?m)^ version:\s*[\"']?([^\"'\s]+)", text)
assert m, "skill version missing"
print(m.group(1))
PY
)
clawhub login --token "$CLAWHUB_TOKEN" >/dev/null
published=$(clawhub inspect remove-ai-watermarks --file SKILL.md 2>/dev/null \
| python3 -c 'import re,sys; t=sys.stdin.read(); m=re.search(r"(?m)^ version:\s*[\"'"'"']?([^\"'"'"'\s]+)", t); print(m.group(1) if m else "")' || true)
if [ "$published" = "$skill_version" ]; then
echo "ClawHub already at $skill_version; nothing to publish."
exit 0
fi
echo "ClawHub at ${published:-<none>}; publishing skill $skill_version."
clawhub skill publish skills/remove-ai-watermarks \
--slug remove-ai-watermarks \
--name "Remove AI Watermarks" \
--version "$skill_version" \
--changelog "Agent skill sync for the ${{ github.event.release.name || github.ref_name }} release."
echo "Submitted; ClawHub runs security scans before the listing goes public."
comfyui:
needs: resolve
runs-on: ubuntu-latest
steps:
- name: Sync and publish the ComfyUI nodes
env:
GH_TOKEN: ${{ secrets.COMFYUI_RELEASE_TOKEN }}
run: |
set -euo pipefail
repo=wiltodelta/ComfyUI-remove-ai-watermarks
workflow=sync-library.yml
dispatched_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)
gh workflow run "$workflow" \
--repo "$repo" \
--ref main \
--raw-field library_version="${{ needs.resolve.outputs.version }}"
run_id=""
for attempt in $(seq 1 30); do
run_id=$(
gh run list \
--repo "$repo" \
--workflow "$workflow" \
--event workflow_dispatch \
--limit 10 \
--json databaseId,createdAt \
| python3 -c '
import json
import sys
dispatched_at = sys.argv[1]
runs = json.load(sys.stdin)
print(next(
(run["databaseId"] for run in runs if run["createdAt"] >= dispatched_at),
"",
))
' "$dispatched_at"
)
if [ -n "$run_id" ]; then
break
fi
echo "ComfyUI sync run not visible yet (attempt $attempt), waiting..."
sleep 2
done
if [ -z "$run_id" ]; then
echo "::error::The dispatched ComfyUI sync run did not appear"
exit 1
fi
for attempt in $(seq 1 180); do
read -r status conclusion <<< "$(
gh run view "$run_id" \
--repo "$repo" \
--json status,conclusion \
--jq '[.status, (.conclusion // "")] | @tsv'
)"
if [ "$status" = "completed" ]; then
if [ "$conclusion" = "success" ]; then
echo "ComfyUI sync run $run_id succeeded"
exit 0
fi
echo "::error::ComfyUI sync run $run_id completed with $conclusion"
exit 1
fi
echo "ComfyUI sync run $run_id is $status (attempt $attempt), waiting..."
sleep 5
done
echo "::error::ComfyUI sync run $run_id did not finish in time"
exit 1