fix(ops): AGY 1.1.11 definitive wrapper and parser strict validation fix
This commit is contained in:
parent
546890a435
commit
a159c034f8
|
|
@ -2,39 +2,143 @@
|
|||
import sys
|
||||
import json
|
||||
import re
|
||||
import argparse
|
||||
|
||||
def parse_output(text: str) -> dict:
|
||||
fields = {
|
||||
"task_id": None,
|
||||
"esito_205": None,
|
||||
"repository": "ssh://git@git.netgescon.it:2222/michele/netgescon-day0.git",
|
||||
"branch": "stabilization/205-zero",
|
||||
"repository": None,
|
||||
"branch": None,
|
||||
"commit": None,
|
||||
"consolidated_unit_id": None,
|
||||
"blocco_dati": None,
|
||||
"dates_used": None,
|
||||
"test_eseguiti": None,
|
||||
"blocco_dati": "no",
|
||||
"note": None,
|
||||
"absorbed_legacy_fragments": None,
|
||||
"open_legacy_fragments": None,
|
||||
"raw_text": text
|
||||
}
|
||||
|
||||
try:
|
||||
json_match = re.search(r'\{.*\}', text, re.DOTALL)
|
||||
if json_match:
|
||||
data = json.loads(json_match.group(0))
|
||||
if isinstance(data, dict):
|
||||
source_dict = data.get("parsed", data)
|
||||
for k in fields:
|
||||
if k in source_dict and source_dict[k] is not None:
|
||||
fields[k] = source_dict[k]
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
patterns = {
|
||||
"esito_205": r"ESITO_205:\s*(.+)",
|
||||
"task_id": r"TASK_ID:\s*(.+)",
|
||||
"repository": r"REPOSITORY:\s*(.+)",
|
||||
"branch": r"BRANCH:\s*(.+)",
|
||||
"commit": r"COMMIT:\s*(.+)",
|
||||
"test_eseguiti": r"TEST_ESEGUITI:\s*(.+)",
|
||||
"blocco_dati": r"BLOCCO_DATI:\s*(.+)",
|
||||
"note": r"NOTE:\s*(.+)"
|
||||
"task_id": r"(?:TASK_ID|task_id):\s*(.+)",
|
||||
"esito_205": r"(?:ESITO_205|esito_205):\s*(.+)",
|
||||
"repository": r"(?:REPOSITORY|repository):\s*(.+)",
|
||||
"branch": r"(?:BRANCH|branch):\s*(.+)",
|
||||
"commit": r"(?:COMMIT|commit):\s*(.+)",
|
||||
"consolidated_unit_id": r"(?:CONSOLIDATED_UNIT_ID|UNITA_ID|consolidated_unit_id):\s*(.+)",
|
||||
"blocco_dati": r"(?:BLOCCO_DATI|blocco_dati):\s*(.+)",
|
||||
"dates_used": r"(?:DATES_USED|dates_used):\s*(.+)",
|
||||
"test_eseguiti": r"(?:TEST_ESEGUITI|test_eseguiti):\s*(.+)",
|
||||
"note": r"(?:NOTE|note):\s*(.+)",
|
||||
"absorbed_legacy_fragments": r"(?:ABSORBED_LEGACY_FRAGMENTS|absorbed_legacy_fragments):\s*(.+)",
|
||||
"open_legacy_fragments": r"(?:OPEN_LEGACY_FRAGMENTS|open_legacy_fragments):\s*(.+)"
|
||||
}
|
||||
|
||||
for key, pat in patterns.items():
|
||||
m = re.search(pat, text, re.IGNORECASE)
|
||||
if m:
|
||||
fields[key] = m.group(1).strip()
|
||||
if fields[key] is None:
|
||||
m = re.search(pat, text, re.IGNORECASE)
|
||||
if m:
|
||||
val = m.group(1).strip()
|
||||
fields[key] = val
|
||||
|
||||
return fields
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
def validate_fields(fields: dict, expected_repo: str = None, expected_branch: str = None, expected_commit: str = None) -> tuple[bool, list[str]]:
|
||||
missing = []
|
||||
|
||||
if expected_repo and fields.get("repository") != expected_repo:
|
||||
missing.append("repository")
|
||||
elif not fields.get("repository"):
|
||||
missing.append("repository")
|
||||
|
||||
if expected_branch and fields.get("branch") != expected_branch:
|
||||
missing.append("branch")
|
||||
elif not fields.get("branch"):
|
||||
missing.append("branch")
|
||||
|
||||
if expected_commit and fields.get("commit") != expected_commit:
|
||||
missing.append("commit")
|
||||
elif not fields.get("commit"):
|
||||
missing.append("commit")
|
||||
|
||||
mandatory_single_fields = [
|
||||
"task_id",
|
||||
"esito_205",
|
||||
"consolidated_unit_id",
|
||||
"blocco_dati",
|
||||
"dates_used",
|
||||
"test_eseguiti",
|
||||
"note",
|
||||
]
|
||||
|
||||
for key in mandatory_single_fields:
|
||||
val = fields.get(key)
|
||||
if val is None or (isinstance(val, str) and not val.strip()):
|
||||
missing.append(key)
|
||||
|
||||
abs_frag = fields.get("absorbed_legacy_fragments")
|
||||
open_frag = fields.get("open_legacy_fragments")
|
||||
has_abs = abs_frag is not None and (not isinstance(abs_frag, str) or bool(str(abs_frag).strip()))
|
||||
has_open = open_frag is not None and (not isinstance(open_frag, str) or bool(str(open_frag).strip()))
|
||||
|
||||
if not (has_abs or has_open):
|
||||
missing.append("absorbed_legacy_fragments|open_legacy_fragments")
|
||||
|
||||
dedup_missing = []
|
||||
for item in missing:
|
||||
if item not in dedup_missing:
|
||||
dedup_missing.append(item)
|
||||
|
||||
is_valid = len(dedup_missing) == 0
|
||||
return is_valid, dedup_missing
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Parse and validate 205 runner output.")
|
||||
parser.add_argument("--expected-repo", help="Expected git repository URL")
|
||||
parser.add_argument("--expected-branch", help="Expected git branch name")
|
||||
parser.add_argument("--expected-commit", help="Expected git commit hash")
|
||||
args = parser.parse_args()
|
||||
|
||||
input_text = sys.stdin.read()
|
||||
parsed = parse_output(input_text)
|
||||
print(json.dumps(parsed, ensure_ascii=False, indent=2))
|
||||
fields = parse_output(input_text)
|
||||
is_valid, missing = validate_fields(
|
||||
fields,
|
||||
expected_repo=args.expected_repo,
|
||||
expected_branch=args.expected_branch,
|
||||
expected_commit=args.expected_commit
|
||||
)
|
||||
|
||||
if is_valid:
|
||||
output_data = {
|
||||
"ok": True,
|
||||
"parsed": fields
|
||||
}
|
||||
print(json.dumps(output_data, ensure_ascii=False, indent=2))
|
||||
sys.exit(0)
|
||||
else:
|
||||
output_data = {
|
||||
"ok": False,
|
||||
"missing": missing,
|
||||
"parsed": fields
|
||||
}
|
||||
print(json.dumps(output_data, ensure_ascii=False, indent=2))
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
export PATH="$PATH:$HOME/.local/bin"
|
||||
unset ANTIGRAVITY_LS_ADDRESS ANTIGRAVITY_CSRF_TOKEN ANTIGRAVITY_AGENT
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
|
@ -43,24 +43,39 @@ else
|
|||
fi
|
||||
fi
|
||||
|
||||
RAW_OUTPUT="$("$EXEC_BIN" -p "$PROMPT" --model "$MODEL" --add-dir "$REPO_DIR" 2>&1)" || true
|
||||
set +e
|
||||
RAW_OUTPUT="$("$EXEC_BIN" -p "$PROMPT" --model "$MODEL" --add-dir "$REPO_DIR" 2>&1)"
|
||||
AGY_EXIT=$?
|
||||
set -e
|
||||
|
||||
REPO_VAL=$(git -C "$REPO_DIR" config --get remote.origin.url 2>/dev/null || echo "ssh://git@git.netgescon.it:2222/michele/netgescon-day0.git")
|
||||
BRANCH_VAL=$(git -C "$REPO_DIR" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "stabilization/205-zero")
|
||||
COMMIT_VAL=$(git -C "$REPO_DIR" rev-parse HEAD 2>/dev/null || echo "")
|
||||
|
||||
if ! grep -q "REPOSITORY:" <<< "$RAW_OUTPUT"; then
|
||||
RAW_OUTPUT="${RAW_OUTPUT}"$'\n'"REPOSITORY: ${REPO_VAL}"
|
||||
fi
|
||||
if ! grep -q "BRANCH:" <<< "$RAW_OUTPUT"; then
|
||||
RAW_OUTPUT="${RAW_OUTPUT}"$'\n'"BRANCH: ${BRANCH_VAL}"
|
||||
fi
|
||||
if ! grep -q "COMMIT:" <<< "$RAW_OUTPUT"; then
|
||||
RAW_OUTPUT="${RAW_OUTPUT}"$'\n'"COMMIT: ${COMMIT_VAL}"
|
||||
if [ $AGY_EXIT -ne 0 ]; then
|
||||
echo "ERROR: agy CLI binary failed with exit code $AGY_EXIT" >&2
|
||||
printf '%s\n' "$RAW_OUTPUT" >&2
|
||||
exit $AGY_EXIT
|
||||
fi
|
||||
|
||||
if [ -f "$PARSER_SCRIPT" ]; then
|
||||
python3 "$PARSER_SCRIPT" <<< "$RAW_OUTPUT"
|
||||
else
|
||||
echo "$RAW_OUTPUT"
|
||||
if [[ -z "${RAW_OUTPUT//[[:space:]]/}" ]]; then
|
||||
echo "ERROR: agy produced empty output" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LOWER_OUTPUT="$(echo "$RAW_OUTPUT" | tr '[:upper:]' '[:lower:]')"
|
||||
if [[ "$LOWER_OUTPUT" == *"jetski: no output produced"* ]] || \
|
||||
[[ "$LOWER_OUTPUT" == *"quota reached"* ]] || \
|
||||
[[ "$LOWER_OUTPUT" == *"permission auto-denied"* ]]; then
|
||||
echo "ERROR: agy output contains invalid execution condition (jetski/quota/permission)" >&2
|
||||
printf '%s\n' "$RAW_OUTPUT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REAL_REPO="$(git -C "$REPO_DIR" config --get remote.origin.url)"
|
||||
REAL_BRANCH="$(git -C "$REPO_DIR" rev-parse --abbrev-ref HEAD)"
|
||||
REAL_COMMIT="$(git -C "$REPO_DIR" rev-parse HEAD)"
|
||||
|
||||
set +e
|
||||
PARSER_OUT="$(python3 "$PARSER_SCRIPT" --expected-repo "$REAL_REPO" --expected-branch "$REAL_BRANCH" --expected-commit "$REAL_COMMIT" <<< "$RAW_OUTPUT")"
|
||||
PARSER_EXIT=$?
|
||||
set -e
|
||||
|
||||
printf '%s\n' "$PARSER_OUT"
|
||||
exit $PARSER_EXIT
|
||||
|
|
|
|||
151
scripts/ops/antigravity-cli/test_runner_and_parser.sh
Executable file
151
scripts/ops/antigravity-cli/test_runner_and_parser.sh
Executable file
|
|
@ -0,0 +1,151 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_DIR="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||
PARSER="$SCRIPT_DIR/parse_205_runner_output.py"
|
||||
WRAPPER="$SCRIPT_DIR/run_205_followup_via_agy.sh"
|
||||
|
||||
REAL_REPO="$(git -C "$REPO_DIR" config --get remote.origin.url)"
|
||||
REAL_BRANCH="$(git -C "$REPO_DIR" rev-parse --abbrev-ref HEAD)"
|
||||
REAL_COMMIT="$(git -C "$REPO_DIR" rev-parse HEAD)"
|
||||
|
||||
echo "=== ESECUZIONE TEST AUTOMATICI WRAPPER E PARSER AGY 1.1.11 ==="
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# Test 1: Output Jetski negato -> wrapper fallisce
|
||||
# -------------------------------------------------------------
|
||||
echo -n "Test 1: Output Jetski negato -> "
|
||||
TEST_BIN_DIR="$(mktemp -d)"
|
||||
cat << 'EOF' > "$TEST_BIN_DIR/agy-ultra"
|
||||
#!/usr/bin/env bash
|
||||
echo 'jetski: no output produced — a tool required permission auto-denied'
|
||||
exit 0
|
||||
EOF
|
||||
chmod +x "$TEST_BIN_DIR/agy-ultra"
|
||||
|
||||
set +e
|
||||
TEST1_OUT="$(PATH="$TEST_BIN_DIR:$PATH" "$WRAPPER" <<< "test prompt" 2>&1)"
|
||||
TEST1_EXIT=$?
|
||||
set -e
|
||||
rm -rf "$TEST_BIN_DIR"
|
||||
|
||||
if [ $TEST1_EXIT -ne 0 ]; then
|
||||
echo "PASS (Exit Code: $TEST1_EXIT)"
|
||||
else
|
||||
echo "FAIL (Expected non-zero exit code, got 0)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# Test 2: Output vuoto -> wrapper fallisce
|
||||
# -------------------------------------------------------------
|
||||
echo -n "Test 2: Output vuoto -> "
|
||||
TEST_BIN_DIR="$(mktemp -d)"
|
||||
cat << 'EOF' > "$TEST_BIN_DIR/agy-ultra"
|
||||
#!/usr/bin/env bash
|
||||
echo ''
|
||||
exit 0
|
||||
EOF
|
||||
chmod +x "$TEST_BIN_DIR/agy-ultra"
|
||||
|
||||
set +e
|
||||
TEST2_OUT="$(PATH="$TEST_BIN_DIR:$PATH" "$WRAPPER" <<< "test prompt" 2>&1)"
|
||||
TEST2_EXIT=$?
|
||||
set -e
|
||||
rm -rf "$TEST_BIN_DIR"
|
||||
|
||||
if [ $TEST2_EXIT -ne 0 ]; then
|
||||
echo "PASS (Exit Code: $TEST2_EXIT)"
|
||||
else
|
||||
echo "FAIL (Expected non-zero exit code, got 0)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# Test 3: task_id null -> parser fallisce
|
||||
# -------------------------------------------------------------
|
||||
echo -n "Test 3: task_id null -> "
|
||||
INCOMPLETE_REPORT="ESITO_205: riuscito
|
||||
REPOSITORY: ${REAL_REPO}
|
||||
BRANCH: ${REAL_BRANCH}
|
||||
COMMIT: ${REAL_COMMIT}
|
||||
CONSOLIDATED_UNIT_ID: 1545
|
||||
DATES_USED: 2026-08-10
|
||||
TEST_ESEGUITI: ./vendor/bin/pest
|
||||
BLOCCO_DATI: no
|
||||
NOTE: Incompleto
|
||||
ABSORBED_LEGACY_FRAGMENTS: id_cond=12"
|
||||
|
||||
set +e
|
||||
TEST3_OUT="$(python3 "$PARSER" --expected-repo "$REAL_REPO" --expected-branch "$REAL_BRANCH" --expected-commit "$REAL_COMMIT" <<< "$INCOMPLETE_REPORT" 2>&1)"
|
||||
TEST3_EXIT=$?
|
||||
set -e
|
||||
|
||||
if [ $TEST3_EXIT -eq 1 ] && [[ "$TEST3_OUT" == *'"ok": false'* ]] && [[ "$TEST3_OUT" == *'"task_id"'* ]]; then
|
||||
echo "PASS (Exit Code: $TEST3_EXIT)"
|
||||
else
|
||||
echo "FAIL (Expected exit code 1 with task_id in missing list)"
|
||||
echo "$TEST3_OUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# Test 4: Report completo -> passa
|
||||
# -------------------------------------------------------------
|
||||
echo -n "Test 4: Report completo -> "
|
||||
COMPLETE_REPORT="TASK_ID: CT-2026-08-10-TEST-001
|
||||
ESITO_205: riuscito
|
||||
REPOSITORY: ${REAL_REPO}
|
||||
BRANCH: ${REAL_BRANCH}
|
||||
COMMIT: ${REAL_COMMIT}
|
||||
CONSOLIDATED_UNIT_ID: 1545
|
||||
DATES_USED: 2026-08-10
|
||||
TEST_ESEGUITI: ./vendor/bin/pest
|
||||
BLOCCO_DATI: no
|
||||
NOTE: Task completato correttamente
|
||||
ABSORBED_LEGACY_FRAGMENTS: id_cond=12"
|
||||
|
||||
set +e
|
||||
TEST4_OUT="$(python3 "$PARSER" --expected-repo "$REAL_REPO" --expected-branch "$REAL_BRANCH" --expected-commit "$REAL_COMMIT" <<< "$COMPLETE_REPORT" 2>&1)"
|
||||
TEST4_EXIT=$?
|
||||
set -e
|
||||
|
||||
if [ $TEST4_EXIT -eq 0 ] && [[ "$TEST4_OUT" == *'"ok": true'* ]]; then
|
||||
echo "PASS (Exit Code: $TEST4_EXIT)"
|
||||
else
|
||||
echo "FAIL (Expected exit code 0 with ok: true)"
|
||||
echo "$TEST4_OUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# Test 5: Git diverso dal reale -> fallisce
|
||||
# -------------------------------------------------------------
|
||||
echo -n "Test 5: Git diverso dal reale -> "
|
||||
MISMATCH_REPORT="TASK_ID: CT-2026-08-10-TEST-001
|
||||
ESITO_205: riuscito
|
||||
REPOSITORY: ssh://git@wrong-repo.git
|
||||
BRANCH: wrong-branch
|
||||
COMMIT: deadbeef1234
|
||||
CONSOLIDATED_UNIT_ID: 1545
|
||||
DATES_USED: 2026-08-10
|
||||
TEST_ESEGUITI: ./vendor/bin/pest
|
||||
BLOCCO_DATI: no
|
||||
NOTE: Mismatch test
|
||||
ABSORBED_LEGACY_FRAGMENTS: id_cond=12"
|
||||
|
||||
set +e
|
||||
TEST5_OUT="$(python3 "$PARSER" --expected-repo "$REAL_REPO" --expected-branch "$REAL_BRANCH" --expected-commit "$REAL_COMMIT" <<< "$MISMATCH_REPORT" 2>&1)"
|
||||
TEST5_EXIT=$?
|
||||
set -e
|
||||
|
||||
if [ $TEST5_EXIT -eq 1 ] && [[ "$TEST5_OUT" == *'"ok": false'* ]] && [[ "$TEST5_OUT" == *'"repository"'* ]]; then
|
||||
echo "PASS (Exit Code: $TEST5_EXIT)"
|
||||
else
|
||||
echo "FAIL (Expected exit code 1 with git mismatch)"
|
||||
echo "$TEST5_OUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== TUTTI I TEST HANNO AVUTO ESITO POSITIVO ==="
|
||||
Loading…
Reference in New Issue
Block a user