Add GCP leoclean skill sync helper (#66)
Some checks are pending
CI / lint-and-test (push) Waiting to run
Some checks are pending
CI / lint-and-test (push) Waiting to run
This commit is contained in:
parent
3e6ac9b8e0
commit
93c480ea3c
2 changed files with 127 additions and 0 deletions
107
deploy/sync-gcp-leoclean-skills.sh
Executable file
107
deploy/sync-gcp-leoclean-skills.sh
Executable file
|
|
@ -0,0 +1,107 @@
|
|||
#!/usr/bin/env bash
|
||||
# Sync source-controlled GCP leoclean skills into the GCP parallel runtime.
|
||||
#
|
||||
# Defaults target the non-production GCP leoclean service. This script does not
|
||||
# touch the production Telegram token and does not read or print secrets.
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
PROJECT="${PROJECT:-teleo-501523}"
|
||||
ZONE="${ZONE:-europe-west6-a}"
|
||||
INSTANCE="${INSTANCE:-teleo-prod-1}"
|
||||
SERVICE="${SERVICE:-leoclean-gcp-prod-parallel.service}"
|
||||
REMOTE_SKILLS_DIR="${REMOTE_SKILLS_DIR:-/home/teleo/.hermes/profiles/leoclean/skills}"
|
||||
SOURCE_DIR="${SOURCE_DIR:-$REPO_ROOT/hermes-agent/leoclean-skills/gcp}"
|
||||
|
||||
DRY_RUN=false
|
||||
RESTART=false
|
||||
VERIFY_ONLY=false
|
||||
|
||||
usage() {
|
||||
cat <<'USAGE'
|
||||
Usage: deploy/sync-gcp-leoclean-skills.sh [--dry-run] [--restart] [--verify-only]
|
||||
|
||||
Environment overrides:
|
||||
PROJECT GCP project, default teleo-501523
|
||||
ZONE GCP zone, default europe-west6-a
|
||||
INSTANCE GCP VM, default teleo-prod-1
|
||||
SERVICE systemd service, default leoclean-gcp-prod-parallel.service
|
||||
REMOTE_SKILLS_DIR runtime skills dir, default /home/teleo/.hermes/profiles/leoclean/skills
|
||||
SOURCE_DIR local source dir, default hermes-agent/leoclean-skills/gcp
|
||||
USAGE
|
||||
}
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--dry-run) DRY_RUN=true ;;
|
||||
--restart) RESTART=true ;;
|
||||
--verify-only) VERIFY_ONLY=true ;;
|
||||
--help|-h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown arg: $arg" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ ! -d "$SOURCE_DIR" ]; then
|
||||
echo "ERROR: source skill directory not found: $SOURCE_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f "$SOURCE_DIR/teleo-kb-bridge/SKILL.md" ]; then
|
||||
echo "ERROR: source teleo-kb-bridge skill not found under $SOURCE_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
GCP_SSH=(
|
||||
gcloud compute ssh "$INSTANCE"
|
||||
--project="$PROJECT"
|
||||
--zone="$ZONE"
|
||||
--tunnel-through-iap
|
||||
)
|
||||
|
||||
verify_command=$(cat <<REMOTE
|
||||
set -euo pipefail
|
||||
sudo -n -u teleo grep -nE '/kb/claims/<claim_id>|wrap claim IDs, proposal IDs' '$REMOTE_SKILLS_DIR/teleo-kb-bridge/SKILL.md'
|
||||
systemctl show '$SERVICE' -p ActiveState -p SubState -p NRestarts -p MainPID --no-pager
|
||||
REMOTE
|
||||
)
|
||||
|
||||
if $DRY_RUN; then
|
||||
echo "DRY RUN: would stream $SOURCE_DIR to $INSTANCE:$REMOTE_SKILLS_DIR"
|
||||
echo "DRY RUN: project=$PROJECT zone=$ZONE service=$SERVICE restart=$RESTART verify_only=$VERIFY_ONLY"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if $VERIFY_ONLY; then
|
||||
"${GCP_SSH[@]}" --command="$verify_command"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
REMOTE_TMP="/tmp/teleo-gcp-leoclean-skills-$(date -u +%Y%m%dT%H%M%SZ)-$$"
|
||||
sync_command=$(cat <<REMOTE
|
||||
set -euo pipefail
|
||||
remote_tmp='$REMOTE_TMP'
|
||||
remote_skills='$REMOTE_SKILLS_DIR'
|
||||
service='$SERVICE'
|
||||
cleanup() { rm -rf "\$remote_tmp"; }
|
||||
trap cleanup EXIT
|
||||
rm -rf "\$remote_tmp"
|
||||
mkdir -p "\$remote_tmp"
|
||||
tar -C "\$remote_tmp" -xf -
|
||||
sudo install -d -o teleo -g teleo -m 0755 "\$remote_skills"
|
||||
tar -C "\$remote_tmp" -cf - . | sudo tar -C "\$remote_skills" -xf -
|
||||
sudo chown -R teleo:teleo "\$remote_skills"
|
||||
sudo -n -u teleo grep -nE '/kb/claims/<claim_id>|wrap claim IDs, proposal IDs' "\$remote_skills/teleo-kb-bridge/SKILL.md"
|
||||
if [ '$RESTART' = true ]; then
|
||||
sudo systemctl restart "\$service"
|
||||
fi
|
||||
systemctl show "\$service" -p ActiveState -p SubState -p NRestarts -p MainPID --no-pager
|
||||
REMOTE
|
||||
)
|
||||
|
||||
COPYFILE_DISABLE=1 tar --format=ustar -C "$SOURCE_DIR" -cf - . | "${GCP_SSH[@]}" --command="$sync_command"
|
||||
|
|
@ -90,3 +90,23 @@ def test_deploy_scripts_sync_leoclean_skills_and_restart_gateway_when_active():
|
|||
assert 'VPS_LEOCLEAN_SKILLS="/home/teleo/.hermes/profiles/leoclean/skills"' in manual_deploy
|
||||
assert 'hermes-agent/leoclean-skills/vps/' in manual_deploy
|
||||
assert 'systemctl is-active --quiet leoclean-gateway.service' in manual_deploy
|
||||
|
||||
|
||||
def test_gcp_leoclean_skill_sync_targets_parallel_runtime_without_secrets():
|
||||
script_path = REPO_ROOT / "deploy" / "sync-gcp-leoclean-skills.sh"
|
||||
script = script_path.read_text()
|
||||
|
||||
assert 'PROJECT="${PROJECT:-teleo-501523}"' in script
|
||||
assert 'ZONE="${ZONE:-europe-west6-a}"' in script
|
||||
assert 'INSTANCE="${INSTANCE:-teleo-prod-1}"' in script
|
||||
assert 'SERVICE="${SERVICE:-leoclean-gcp-prod-parallel.service}"' in script
|
||||
assert "hermes-agent/leoclean-skills/gcp" in script
|
||||
assert "--tunnel-through-iap" in script
|
||||
assert "/home/teleo/.hermes/profiles/leoclean/skills" in script
|
||||
assert "/kb/claims/<claim_id>|wrap claim IDs, proposal IDs" in script
|
||||
assert 'COPYFILE_DISABLE=1 tar --format=ustar -C "$SOURCE_DIR" -cf - .' in script
|
||||
assert 'sudo tar -C "\\$remote_skills" -xf -' in script
|
||||
assert "sudo systemctl restart" in script
|
||||
assert "sudo rsync" not in script
|
||||
assert "TELEGRAM_BOT_TOKEN" not in script
|
||||
assert "CLOUDSQL_PASSWORD" not in script
|
||||
|
|
|
|||
Loading…
Reference in a new issue