diff --git a/README.md b/README.md index 48b7dbb..36a2627 100644 --- a/README.md +++ b/README.md @@ -1165,6 +1165,7 @@ Script toggles: - `--auth all,groups` to re-auth before running - `--strict` to fail on optional features (groups/keep/enterprise) +- `--allow-nontest` to override the test-account guardrail Go test wrapper (opt-in): @@ -1172,7 +1173,7 @@ Go test wrapper (opt-in): GOG_LIVE=1 go test -tags=integration ./internal/integration -run Live ``` -Optional env: `GOG_LIVE_FAST=1`, `GOG_LIVE_SKIP=groups,keep`, `GOG_LIVE_AUTH=all,groups`. +Optional env: `GOG_LIVE_FAST=1`, `GOG_LIVE_SKIP=groups,keep`, `GOG_LIVE_AUTH=all,groups`, `GOG_LIVE_ALLOW_NONTEST=1`. ### Make Shortcut diff --git a/internal/integration/live_test.go b/internal/integration/live_test.go index 6220c1c..9f68811 100644 --- a/internal/integration/live_test.go +++ b/internal/integration/live_test.go @@ -35,6 +35,9 @@ func TestLiveScript(t *testing.T) { if v := os.Getenv("GOG_LIVE_AUTH"); v != "" { args = append(args, "--auth", v) } + if os.Getenv("GOG_LIVE_ALLOW_NONTEST") != "" { + args = append(args, "--allow-nontest") + } ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute) defer cancel() diff --git a/scripts/live-test.sh b/scripts/live-test.sh index 15f8e62..b306f3e 100755 --- a/scripts/live-test.sh +++ b/scripts/live-test.sh @@ -3,6 +3,7 @@ set -euo pipefail FAST=false STRICT=false +ALLOW_NONTEST=false ACCOUNT="" SKIP="" AUTH_SERVICES="" @@ -14,6 +15,7 @@ Usage: scripts/live-test.sh [options] Options: --fast Skip slower tests (docs/sheets/slides) --strict Fail on optional tests (groups/keep/enterprise) + --allow-nontest Allow running against non-test accounts --account Account to use (defaults to GOG_IT_ACCOUNT or first auth) --skip Comma-separated skip list (e.g., gmail,drive,docs) --auth Re-auth before running (e.g., all,groups) @@ -34,6 +36,9 @@ while [ $# -gt 0 ]; do --strict) STRICT=true ;; + --allow-nontest) + ALLOW_NONTEST=true + ;; --account) ACCOUNT="$2" shift @@ -92,10 +97,41 @@ fi echo "Using account: $ACCOUNT" +is_test_account() { + local a + a=$(echo "$1" | tr 'A-Z' 'a-z') + case "$a" in + *test*|*bot*|*sandbox*|*qa*|*staging*|*dev*|*@example.com) + return 0 + ;; + esac + case "$a" in + *+*) + return 0 + ;; + esac + return 1 +} + +if [ "$ALLOW_NONTEST" = false ] && [ -z "${GOG_LIVE_ALLOW_NONTEST:-}" ]; then + if ! is_test_account "$ACCOUNT"; then + echo "Refusing to run live tests against non-test account: $ACCOUNT" >&2 + echo "Pass --allow-nontest or set GOG_LIVE_ALLOW_NONTEST=1 to override." >&2 + exit 2 + fi +fi + if [ -n "$AUTH_SERVICES" ]; then $BIN auth add "$ACCOUNT" --services "$AUTH_SERVICES" fi +TS=$(date +%Y%m%d%H%M%S) +ACCOUNT_ARGS=(--account "$ACCOUNT") + +gog() { + "$BIN" "${ACCOUNT_ARGS[@]}" "$@" +} + skip() { local key="$1" [ -n "$SKIP" ] || return 1 @@ -211,7 +247,7 @@ run_optional() { run_required "time" "time now" "$BIN" time now --json >/dev/null if ! skip "auth-alias"; then - alias_name="smoke-$(date +%Y%m%d%H%M%S)" + alias_name="smoke-$TS" run_required "auth-alias" "auth alias set" "$BIN" auth alias set "$alias_name" "$ACCOUNT" --json >/dev/null run_required "auth-alias" "auth alias list" "$BIN" auth alias list --json >/dev/null run_required "auth-alias" "auth alias unset" "$BIN" auth alias unset "$alias_name" --json >/dev/null @@ -228,39 +264,45 @@ if ! skip "enable-commands"; then fi if ! skip "gmail"; then - DRAFT_JSON=$($BIN gmail drafts create --to "$ACCOUNT" --subject "gogcli smoke" --body "smoke" --json) + run_required "gmail" "gmail labels list" gog gmail labels list --json >/dev/null + DRAFT_JSON=$(gog gmail drafts create --to "$ACCOUNT" --subject "gogcli smoke $TS" --body "smoke" --json) DRAFT_ID=$(extract_field "$DRAFT_JSON" draftId) [ -n "$DRAFT_ID" ] || { echo "Failed to parse draft id" >&2; exit 1; } - run_required "gmail" "gmail drafts get" "$BIN" gmail drafts get "$DRAFT_ID" --json >/dev/null - run_required "gmail" "gmail drafts delete" "$BIN" gmail drafts delete "$DRAFT_ID" --force >/dev/null + run_required "gmail" "gmail drafts get" gog gmail drafts get "$DRAFT_ID" --json >/dev/null + run_required "gmail" "gmail drafts delete" gog gmail drafts delete "$DRAFT_ID" --force >/dev/null fi if ! skip "drive"; then - FOLDER_JSON=$($BIN drive mkdir "gogcli-smoke" --json) + run_required "drive" "drive ls" gog drive ls --json --max 1 >/dev/null + FOLDER_JSON=$(gog drive mkdir "gogcli-smoke-$TS" --json) FOLDER_ID=$(extract_id "$FOLDER_JSON") [ -n "$FOLDER_ID" ] || { echo "Failed to parse drive folder id" >&2; exit 1; } - run_required "drive" "drive delete folder" "$BIN" drive delete "$FOLDER_ID" --force >/dev/null + run_required "drive" "drive get folder" gog drive get "$FOLDER_ID" --json >/dev/null + run_required "drive" "drive delete folder" gog drive delete "$FOLDER_ID" --force >/dev/null fi if ! skip "docs"; then - DOC_JSON=$($BIN docs create "gogcli-smoke" --json) + DOC_JSON=$(gog docs create "gogcli-smoke-$TS" --json) DOC_ID=$(extract_id "$DOC_JSON") [ -n "$DOC_ID" ] || { echo "Failed to parse doc id" >&2; exit 1; } - run_required "docs" "drive delete doc" "$BIN" drive delete "$DOC_ID" --force >/dev/null + run_required "docs" "drive get doc" gog drive get "$DOC_ID" --json >/dev/null + run_required "docs" "drive delete doc" gog drive delete "$DOC_ID" --force >/dev/null fi if ! skip "sheets"; then - SHEET_JSON=$($BIN sheets create "gogcli-smoke" --json) + SHEET_JSON=$(gog sheets create "gogcli-smoke-$TS" --json) SHEET_ID=$(extract_id "$SHEET_JSON") [ -n "$SHEET_ID" ] || { echo "Failed to parse sheet id" >&2; exit 1; } - run_required "sheets" "drive delete sheet" "$BIN" drive delete "$SHEET_ID" --force >/dev/null + run_required "sheets" "drive get sheet" gog drive get "$SHEET_ID" --json >/dev/null + run_required "sheets" "drive delete sheet" gog drive delete "$SHEET_ID" --force >/dev/null fi if ! skip "slides"; then - SLIDES_JSON=$($BIN slides create "gogcli-smoke" --json) + SLIDES_JSON=$(gog slides create "gogcli-smoke-$TS" --json) SLIDES_ID=$(extract_id "$SLIDES_JSON") [ -n "$SLIDES_ID" ] || { echo "Failed to parse slides id" >&2; exit 1; } - run_required "slides" "drive delete slides" "$BIN" drive delete "$SLIDES_ID" --force >/dev/null + run_required "slides" "drive get slides" gog drive get "$SLIDES_ID" --json >/dev/null + run_required "slides" "drive delete slides" gog drive delete "$SLIDES_ID" --force >/dev/null fi if ! skip "calendar"; then @@ -273,46 +315,46 @@ print(start.strftime('%Y-%m-%dT%H:%M:%SZ'), end.strftime('%Y-%m-%dT%H:%M:%SZ'), PY )" - EV_JSON=$($BIN calendar create primary --summary "gogcli-smoke" --from "$START" --to "$END" --json) + EV_JSON=$(gog calendar create primary --summary "gogcli-smoke-$TS" --from "$START" --to "$END" --json) EV_ID=$(extract_id "$EV_JSON") [ -n "$EV_ID" ] || { echo "Failed to parse calendar event id" >&2; exit 1; } - run_required "calendar" "calendar event get" "$BIN" calendar event primary "$EV_ID" --json >/dev/null - run_required "calendar" "calendar propose-time" "$BIN" calendar propose-time primary "$EV_ID" --json >/dev/null - run_required "calendar" "calendar delete event" "$BIN" calendar delete primary "$EV_ID" --force >/dev/null + run_required "calendar" "calendar event get" gog calendar event primary "$EV_ID" --json >/dev/null + run_required "calendar" "calendar propose-time" gog calendar propose-time primary "$EV_ID" --json >/dev/null + run_required "calendar" "calendar delete event" gog calendar delete primary "$EV_ID" --force >/dev/null if ! skip "calendar-enterprise"; then - run_optional "calendar-enterprise" "calendar focus-time" "$BIN" calendar create primary --event-type focus-time --from "$START" --to "$END" --json >/dev/null 2>&1 || true - run_optional "calendar-enterprise" "calendar out-of-office" "$BIN" calendar create primary --event-type out-of-office --from "$DAY1" --to "$DAY2" --all-day --json >/dev/null 2>&1 || true - run_optional "calendar-enterprise" "calendar working-location" "$BIN" calendar create primary --event-type working-location --working-location-type office --working-office-label "HQ" --from "$DAY1" --to "$DAY2" --json >/dev/null 2>&1 || true + run_optional "calendar-enterprise" "calendar focus-time" gog calendar create primary --event-type focus-time --from "$START" --to "$END" --json >/dev/null 2>&1 || true + run_optional "calendar-enterprise" "calendar out-of-office" gog calendar create primary --event-type out-of-office --from "$DAY1" --to "$DAY2" --all-day --json >/dev/null 2>&1 || true + run_optional "calendar-enterprise" "calendar working-location" gog calendar create primary --event-type working-location --working-location-type office --working-office-label "HQ" --from "$DAY1" --to "$DAY2" --json >/dev/null 2>&1 || true fi fi if ! skip "tasks"; then - LIST_JSON=$($BIN tasks lists --json --max 1) + LIST_JSON=$(gog tasks lists --json --max 1) LIST_ID=$(extract_tasklist_id "$LIST_JSON") [ -n "$LIST_ID" ] || { echo "No task list found" >&2; exit 1; } - TASK_JSON=$($BIN tasks add "$LIST_ID" --title "gogcli-smoke" --due "$DAY1" --repeat daily --repeat-count 2 --json) + TASK_JSON=$(gog tasks add "$LIST_ID" --title "gogcli-smoke-$TS" --due "$DAY1" --repeat daily --repeat-count 2 --json) TASK_IDS=$(extract_task_ids "$TASK_JSON") [ -n "$TASK_IDS" ] || { echo "Failed to parse task ids" >&2; exit 1; } FIRST_TASK_ID=$(echo "$TASK_IDS" | head -n1) - run_required "tasks" "tasks get" "$BIN" tasks get "$LIST_ID" "$FIRST_TASK_ID" --json >/dev/null + run_required "tasks" "tasks get" gog tasks get "$LIST_ID" "$FIRST_TASK_ID" --json >/dev/null while IFS= read -r tid; do - [ -n "$tid" ] && run_required "tasks" "tasks delete" "$BIN" tasks delete "$LIST_ID" "$tid" --force >/dev/null + [ -n "$tid" ] && run_required "tasks" "tasks delete" gog tasks delete "$LIST_ID" "$tid" --force >/dev/null done <<<"$TASK_IDS" fi if ! skip "contacts"; then - CONTACT_JSON=$($BIN contacts create --given "gogcli" --family "smoke" --email "gogcli-smoke@example.com" --json) + run_required "contacts" "contacts list" gog contacts list --json --max 1 >/dev/null + CONTACT_JSON=$(gog contacts create --given "gogcli" --family "smoke-$TS" --email "gogcli-smoke-$TS@example.com" --json) CONTACT_ID=$(extract_field "$CONTACT_JSON" resourceName) [ -n "$CONTACT_ID" ] || { echo "Failed to parse contact resourceName" >&2; exit 1; } - run_required "contacts" "contacts delete" "$BIN" contacts delete "$CONTACT_ID" --force >/dev/null + run_required "contacts" "contacts delete" gog contacts delete "$CONTACT_ID" --force >/dev/null fi -run_required "people" "people me" "$BIN" people me --json >/dev/null +run_required "people" "people me" gog people me --json >/dev/null -run_optional "groups" "groups list" "$BIN" groups list --json --max 1 >/dev/null 2>&1 -run_optional "keep" "keep list" "$BIN" keep list --json >/dev/null 2>&1 - -run_optional "classroom" "classroom list" "$BIN" classroom courses list --json --max 1 >/dev/null 2>&1 +run_optional "groups" "groups list" gog groups list --json --max 1 >/dev/null 2>&1 +run_optional "keep" "keep list" gog keep list --json >/dev/null 2>&1 +run_optional "classroom" "classroom list" gog classroom courses list --json --max 1 >/dev/null 2>&1 echo "Live tests complete."