Setting the file. One moment. Persist Skill · Turnstile Spin · cloudflare/skills · Skills Docs11.11
README
(opens in a new tab)
scripts/persist-skill.sh
Shell·114 lines·3 KB
11
12need_arg() {
13 if [[ -z "${2-}" || "$2" == --* ]]; then
14 echo "persist-skill: missing value for $1" >&2
15 exit 2
16 fi
17}
18
19PATH_ARG=""
20while [[ $# -gt 0 ]]; do
21 case "$1" in
22 --path) need_arg "$1" "${2-}"; PATH_ARG="$2"; shift 2 ;;
23 *) echo "persist-skill: unknown arg $1" >&2; exit 2 ;;
24 esac
25done
26
27[[ -n "$PATH_ARG" ]] || { echo "persist-skill: --path required" >&2; exit 2; }
28if [[ "$(basename "$PATH_ARG")" != "SKILL.md" ]]; then
29 echo "persist-skill: --path must end in SKILL.md for a directory-based skill bundle" >&2
30 echo '{"status":"error","reason":"file_target_not_supported"}'
31 exit 2
32fi
33
34for command_name in git python3; do
35 command -v "$command_name" >/dev/null 2>&1 || {
36 echo "persist-skill: $command_name is required" >&2
37 echo "{\"status\":\"error\",\"reason\":\"${command_name}_not_available\"}"
38 exit 1
39 }
40done
41
42PROJECT_ROOT="$(pwd -P)"
43TARGET_DIR="$(python3 -I -c 'import os,sys; print(os.path.realpath(os.path.abspath(sys.argv[1])))' "$(dirname "$PATH_ARG")")"
44if [[ "$TARGET_DIR" != "$PROJECT_ROOT" && "$TARGET_DIR" != "$PROJECT_ROOT/"* ]]; then
45 echo "persist-skill: target must be inside the current project" >&2
46 echo '{"status":"error","reason":"target_outside_project"}'
47 exit 1
48fi
49if [[ -e "$TARGET_DIR" ]] && ! python3 -I -c 'import os,sys; raise SystemExit(0 if not os.listdir(sys.argv[1]) else 1)' "$TARGET_DIR"; then
50 echo "persist-skill: target directory is not empty" >&2
51 echo '{"status":"error","reason":"target_not_empty"}'
52 exit 1
53fi
54
55if ! TEMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/turnstile-spin-persist.XXXXXX")"; then
56 echo "persist-skill: could not create a temporary directory" >&2
57 echo '{"status":"error","reason":"temporary_directory_failed"}'
58 exit 1
59fi
60trap 'rm -rf "$TEMP_DIR"' EXIT
61
62if ! git -c core.hooksPath=/dev/null clone \
63 --quiet \
64 --depth 1 \
65 --filter=blob:none \
66 --sparse \
67 "https://github.com/cloudflare/skills.git" \
68 "$TEMP_DIR/repo"; then
69 echo "persist-skill: clone failed" >&2
70 echo '{"status":"error","reason":"clone_failed"}'
71 exit 1
72fi
73if ! git -C "$TEMP_DIR/repo" -c core.hooksPath=/dev/null sparse-checkout set skills/turnstile-spin; then
74 echo "persist-skill: sparse checkout failed" >&2
75 echo '{"status":"error","reason":"sparse_checkout_failed"}'
76 exit 1
77fi
78
79SOURCE_DIR="$TEMP_DIR/repo/skills/turnstile-spin"
80if [[ ! -f "$SOURCE_DIR/SKILL.md" ]]; then
81 echo "persist-skill: canonical bundle is missing SKILL.md" >&2
82 echo '{"status":"error","reason":"skill_missing"}'
83 exit 1
84fi
85
86python3 -I - "$SOURCE_DIR" "$TARGET_DIR" <<'PY'
87import pathlib
88import shutil
89import sys
90
91source = pathlib.Path(sys.argv[1])
92target = pathlib.Path(sys.argv[2])
93if target.exists():
94 target.rmdir()
95target.parent.mkdir(parents=True, exist_ok=True)
96shutil.copytree(source, target, dirs_exist_ok=False)
97for script in (target / "scripts").glob("*.sh"):
98 script.chmod(0o755)
99PY
100
101python3 -I - "$PATH_ARG" "$TARGET_DIR" <<'PY'
102import json
103import pathlib
104import sys
105
106path_arg, bundle_root = sys.argv[1], pathlib.Path(sys.argv[2])
107scripts = sorted(path.name for path in (bundle_root / "scripts").glob("*.sh"))
108print(json.dumps({
109 "status": "ok",
110 "path": path_arg,
111 "bundle_root": str(bundle_root),
112 "scripts": scripts,
113}))
114PY