From 5993826b79a2106bc66c4829abda49407a12b430 Mon Sep 17 00:00:00 2001 From: "Soren (Molty)" Date: Tue, 5 May 2026 18:56:21 +1000 Subject: [PATCH] Add quote template dry-run wrapper checkpoint --- PROJECT-PROGRESS.md | 28 +++++++++++++++++++++++--- poll_and_apply_quote_templates.sh | 33 +++++++++++++++++++++++++------ 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/PROJECT-PROGRESS.md b/PROJECT-PROGRESS.md index b86482f..b98c1b2 100644 --- a/PROJECT-PROGRESS.md +++ b/PROJECT-PROGRESS.md @@ -73,12 +73,17 @@ Current apply payload rules: - stores/parses results - applies any parsed Quote Template responses that are not already marked/applied - logs each run under `logs/poll-and-apply-YYYYMMDD-HHMMSS.log` +- Safety option now available: + - `--dry-run` runs the same poll/selection flow, but previews the ServiceM8 `jobmaterial` payloads only + - dry-run does **not** write to ServiceM8 + - dry-run does **not** mark quote responses as applied - Examples: - `./poll_and_apply_quote_templates.sh` - `./poll_and_apply_quote_templates.sh --hours 48` - `./poll_and_apply_quote_templates.sh --since '2026-05-04 08:00:00'` + - `./poll_and_apply_quote_templates.sh --dry-run --hours 48` -This is the proposed scheduled entry point for soft release, e.g. every 10–30 minutes. +This is the proposed scheduled entry point for soft release, e.g. every 10–30 minutes. For manual confidence checks, run it with `--dry-run` first, inspect the generated payloads/log, then rerun without `--dry-run` only when ready to apply. ## Live Webhook Receiver Status @@ -140,13 +145,29 @@ Operational soft-release pieces are now in place: - payload adjusted for current ServiceM8 requirements - duplicate-apply guard in place - wrapper script created for scheduled operation +- wrapper now has a first-class `--dry-run` mode - inspector updated for progress visibility +### Checkpoint — 2026-05-05 + +Latest verified state: +- `poll_and_apply_quote_templates.sh --dry-run` added and documented. +- `bash -n /opt/webhooks/poll_and_apply_quote_templates.sh` passes. +- `--help` output includes `--dry-run` usage/examples. +- A future-since dry-run (`--dry-run --since '2099-01-01 00:00:00'`) confirmed: + - wrapper reports `Mode: dry-run` + - poll step performs no ServiceM8 writes + - apply step calls the Python apply tool without `--apply` + - payload rows are emitted as `would_create` + - responses are not marked applied by dry-run +- At checkpoint time, there were still several unapplied parsed Quote Template responses available for preview/apply; this is expected while the soft release remains manual. + ## Not Yet Done / Next Steps - Restart/reload the live inspector process so the new poll/apply pages are available in the active web viewer. - Decide schedule interval for `poll_and_apply_quote_templates.sh` — likely every 10 or 30 minutes. -- Run the wrapper manually for a soft-release smoke test with a controlled recent form response. +- Run the wrapper manually in `--dry-run` mode against a controlled recent form response and inspect the payload/log. +- If payload is correct, rerun the wrapper without `--dry-run` for a controlled live apply smoke test. - After confidence builds, wire the wrapper into cron/system scheduling. - Future hardening: add reconciliation/update/delete behaviour if ServiceM8 quote form responses are edited after initial apply. @@ -155,4 +176,5 @@ Operational soft-release pieces are now in place: - Webhooks remain lightweight and non-mutating. - Polling is now the reliable source of completeness. - Applying to ServiceM8 is tracked locally and guarded against duplicates. -- The wrapper intentionally skips dry-run for soft release, but the underlying apply script still supports dry-run and duplicate protection. +- The wrapper defaults to live apply for scheduled soft release, but now supports `--dry-run` for manual preview/safety checks. +- The underlying apply script remains dry-run-by-default and provides the duplicate protection used by the wrapper. diff --git a/poll_and_apply_quote_templates.sh b/poll_and_apply_quote_templates.sh index 2f2eee7..84d1a40 100755 --- a/poll_and_apply_quote_templates.sh +++ b/poll_and_apply_quote_templates.sh @@ -9,8 +9,10 @@ set -euo pipefail # --since 'YYYY-MM-DD HH:MM:SS' # --hours 48 # -# This wrapper intentionally skips dry-run and calls --apply. The apply script -# still refuses duplicate applies unless --force is explicitly passed through. +# By default this wrapper applies unapplied parsed responses. Use --dry-run to +# run the poll and preview each pending apply without writing to ServiceM8. +# The apply script still refuses duplicate applies unless --force is explicitly +# passed through. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" POLL_SCRIPT="$SCRIPT_DIR/poll_form_responses_since.py" @@ -22,20 +24,25 @@ QUOTE_TEMPLATE_FORM_UUID="${SERVICEM8_QUOTE_TEMPLATE_FORM_UUID:-3621b6be-1d19-47 SINCE="" HOURS="24" FORCE="0" +DRY_RUN="0" usage() { cat < >(tee -a "$LOG_FILE") 2>&1 echo "== ServiceM8 Quote Template poll/apply run ==" echo "Started: $(date --iso-8601=seconds)" echo "Since: $SINCE" +echo "Mode: $([[ "$DRY_RUN" == "1" ]] && echo "dry-run" || echo "apply")" echo "DB: $DB_PATH" echo "Log: $LOG_FILE" echo @@ -121,15 +133,24 @@ printf 'Found %d unapplied Quote Template response(s):\n' "${#FORM_RESPONSE_UUID printf ' - %s\n' "${FORM_RESPONSE_UUIDS[@]}" echo -echo "== Applying to ServiceM8 ==" -APPLY_ARGS=(--apply --pretty) +if [[ "$DRY_RUN" == "1" ]]; then + echo "== Dry-run preview only; no ServiceM8 writes ==" + APPLY_ARGS=(--pretty) +else + echo "== Applying to ServiceM8 ==" + APPLY_ARGS=(--apply --pretty) +fi if [[ "$FORCE" == "1" ]]; then APPLY_ARGS+=(--force) fi for uuid in "${FORM_RESPONSE_UUIDS[@]}"; do echo - echo "-- Applying form_response_uuid=$uuid --" + if [[ "$DRY_RUN" == "1" ]]; then + echo "-- Dry-run form_response_uuid=$uuid --" + else + echo "-- Applying form_response_uuid=$uuid --" + fi "$APPLY_SCRIPT" --uuid "$uuid" "${APPLY_ARGS[@]}" done