Record cancelled watcher state on ATVM run cancellation

- update the watcher cancel helper so it writes a final CANCELLED state into state.json before stopping the service
- record cancellation timestamps and a cancellation note in the watcher state file for clearer post-run inspection
- update the watcher service docs so the documented cancel behavior matches the state-file handling
This commit is contained in:
2026-03-25 18:24:17 -04:00
parent 9caa7deb94
commit c9706e9702
3 changed files with 42 additions and 1 deletions

View File

@@ -173,6 +173,13 @@ Cancel example:
--build-name e2e-redhat9.6-ubuntu24.04-w2k25-fc --build-name e2e-redhat9.6-ubuntu24.04-w2k25-fc
``` ```
The cancel helper should:
- write `cancelled.marker`
- update `state.json` so the final watcher state is `CANCELLED`
- stop the watcher instance
- avoid any Mattermost post for that run
## Operational Notes ## Operational Notes
- This is not a daemon. - This is not a daemon.
@@ -194,6 +201,7 @@ Expected terminal behavior:
- verify `ok` - verify `ok`
- exit - exit
- `CANCELLED` - `CANCELLED`
- write final `CANCELLED` state to `state.json`
- do not post - do not post
- exit - exit
- `TERMINATED` - `TERMINATED`

View File

@@ -99,7 +99,7 @@ That results in:
./cancel-atvm-run-watcher.sh --build-name e2e-redhat9.6-ubuntu24.04-w2k25-fc ./cancel-atvm-run-watcher.sh --build-name e2e-redhat9.6-ubuntu24.04-w2k25-fc
``` ```
This writes a cancellation marker and stops the watcher instance. The watcher will not send Mattermost results for that run. This writes a cancellation marker, updates `state.json` to `CANCELLED`, and stops the watcher instance. The watcher will not send Mattermost results for that run.
## Notes ## Notes

View File

@@ -1,6 +1,38 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
python3_write_cancelled_state() {
local state_file="$1"
python3 - "$state_file" <<'PY'
import json
import sys
from datetime import datetime, timezone
from pathlib import Path
state_path = Path(sys.argv[1])
state = {}
if state_path.exists():
try:
state = json.loads(state_path.read_text(encoding="utf-8"))
except json.JSONDecodeError:
state = {}
now = datetime.now(timezone.utc).isoformat()
state["last_state"] = "CANCELLED"
state["last_seen_at"] = now
state["closed_at"] = now
notes = state.get("notes", [])
if not isinstance(notes, list):
notes = [str(notes)]
if "Cancellation marker detected." not in notes:
notes.append("Cancellation marker detected.")
state["notes"] = notes
state_path.write_text(json.dumps(state, indent=2, sort_keys=True), encoding="utf-8")
PY
}
usage() { usage() {
cat <<'EOF' cat <<'EOF'
Usage: Usage:
@@ -29,4 +61,5 @@ fi
RUN_DIR="${STATE_ROOT}/${BUILD_NAME}" RUN_DIR="${STATE_ROOT}/${BUILD_NAME}"
mkdir -p "$RUN_DIR" mkdir -p "$RUN_DIR"
touch "${RUN_DIR}/cancelled.marker" touch "${RUN_DIR}/cancelled.marker"
python3_write_cancelled_state "${RUN_DIR}/state.json"
systemctl stop "atvm-run-watcher@${BUILD_NAME}.service" || true systemctl stop "atvm-run-watcher@${BUILD_NAME}.service" || true