From 697de3e199dd3e97676fc941850c99ab563f406d Mon Sep 17 00:00:00 2001 From: Timothy Kim Date: Thu, 26 Mar 2026 13:13:41 -0400 Subject: [PATCH] add uptimerobot monitor subcommand to app.sh --- README.md | 3 ++- USECASES.md | 1 + tools/app.sh | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 779aa12..92fd553 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ server. Everything is idempotent. This single command handles everything: DNS records (Vultr), Gitea repo (from `static-site-template`), nginx/compose/workflow configs, SSL cert, -Garage media bucket, first build, and verification. +Garage media bucket, first build, verification, and UptimeRobot monitoring. **Prerequisites:** domain nameservers pointed to Vultr, `bws`/`jq`/`dig` installed, `BWS_ACCESS_TOKEN` env var or token at `~/.config/hantim/bws-token`. @@ -194,6 +194,7 @@ Project: `hantim`. Fetched via `bws` CLI on the server. | `hantim-garage-admin-token` | Garage admin API token | `deploy.sh`, `app.sh` | | `hantim-garage-media-key-id` | S3 access key ID for media uploads | `app.sh`, `aws` CLI | | `hantim-garage-media-secret-key` | S3 secret key for media uploads | `aws` CLI | +| `hantim-uptimerobot-api-key` | UptimeRobot API key for monitors | `app.sh` | Machine accounts: `hantim-server` (token at `/etc/bws-token`), `hantim-ci` (reserved). diff --git a/USECASES.md b/USECASES.md index 62c1884..972fddf 100644 --- a/USECASES.md +++ b/USECASES.md @@ -50,6 +50,7 @@ for stateless static sites. - Garage media bucket created with media-key access - First build triggered - `https://www.example.com` responds within 3 minutes +- UptimeRobot HTTPS monitor created (skipped if already exists) - Site ready for customization via git clone + push ## 4. Update app code diff --git a/tools/app.sh b/tools/app.sh index 5f58e2b..88a98a6 100755 --- a/tools/app.sh +++ b/tools/app.sh @@ -28,7 +28,8 @@ usage() { echo " garage Create Garage media bucket and grant access" echo " build Trigger initial build workflow" echo " verify Check if site is live" - echo " all Run all steps (dns, repo, files, cert, garage, commit, build, verify)" + echo " monitor Create UptimeRobot HTTPS monitor" + echo " all Run all steps (dns, repo, files, cert, garage, commit, build, verify, monitor)" echo "" echo "Requires: bws, jq, dig" exit 1 @@ -467,6 +468,48 @@ cmd_verify() { echo " - The container is running on the server: docker ps" } +cmd_monitor() { + require_bws + + echo "==> Fetching UptimeRobot API key..." + UPTIMEROBOT_API_KEY=$(bws_get "hantim-uptimerobot-api-key") + UPTIMEROBOT_API="https://api.uptimerobot.com/v3" + UPTIMEROBOT_AUTH="Authorization: Bearer $UPTIMEROBOT_API_KEY" + + MONITOR_URL="https://www.$APP" + + echo "==> Checking for existing UptimeRobot monitor for $MONITOR_URL..." + EXISTING=$(curl -s -G "$UPTIMEROBOT_API/monitors" \ + -H "$UPTIMEROBOT_AUTH" \ + --data-urlencode "search=$APP") + + MATCH=$(echo "$EXISTING" | jq -r --arg url "$MONITOR_URL" \ + '.monitors[]? | select(.url == $url) | .id') + if [ -n "$MATCH" ]; then + echo " Monitor already exists (id: $MATCH), skipping." + return + fi + + echo "==> Fetching alert contacts..." + ALERT_CONTACTS=$(curl -s "$UPTIMEROBOT_API/user/alert-contacts" \ + -H "$UPTIMEROBOT_AUTH" | jq '[.[] | {alertContactId: .id, threshold: 5, recurrence: 30}]') + + echo "==> Creating UptimeRobot HTTPS monitor for $MONITOR_URL..." + RESP=$(curl -s -X POST "$UPTIMEROBOT_API/monitors" \ + -H "$UPTIMEROBOT_AUTH" \ + -H "Content-Type: application/json" \ + -d "$(jq -n --arg name "$APP" --arg url "$MONITOR_URL" --argjson contacts "$ALERT_CONTACTS" \ + '{friendlyName: $name, url: $url, type: 1, interval: 300, timeout: 30, assignedAlertContacts: $contacts, tagNames: ["hantim"]}')") + + MONITOR_ID=$(echo "$RESP" | jq -r '.id // empty') + if [ -n "$MONITOR_ID" ]; then + echo " Monitor created (id: $MONITOR_ID)." + else + ERROR_MSG=$(echo "$RESP" | jq -r 'if .message then (.message | if type == "array" then join("; ") else . end) else .error // "unknown error" end') + echo " Warning: Failed to create monitor: $ERROR_MSG" + fi +} + cmd_all() { cmd_dns cmd_repo @@ -486,6 +529,7 @@ cmd_all() { cmd_garage cmd_build cmd_verify + cmd_monitor } # --- Dispatch --- @@ -498,6 +542,7 @@ case "$COMMAND" in garage) cmd_garage ;; build) cmd_build ;; verify) cmd_verify ;; + monitor) cmd_monitor ;; all) cmd_all ;; *) echo "Unknown command: $COMMAND"