From 3c5d3e027811b536c8d4e9d10dbfdef61a5198f8 Mon Sep 17 00:00:00 2001 From: Hiroshi Nishio Date: Fri, 17 Apr 2026 20:32:12 -0700 Subject: [PATCH] Detect AWS IAM errors as infra failures, allow `date` in run_command AccessDeniedException from SSM/SecretsManager caused GA to waste iterations trying to "fix" testing/setup.ts instead of skipping. Adding `date` lets GA check current date for debugging date-sensitive test failures. --- constants/shell.py | 2 ++ pyproject.toml | 2 +- services/shell/run_command.py | 4 ++-- services/shell/test_run_command.py | 7 +++++++ utils/logs/detect_infra_failure.py | 3 +++ utils/logs/test_detect_infra_failure.py | 16 +++++++++++++++- uv.lock | 2 +- 7 files changed, 31 insertions(+), 5 deletions(-) diff --git a/constants/shell.py b/constants/shell.py index 8e12ebe1e..e83e934e9 100644 --- a/constants/shell.py +++ b/constants/shell.py @@ -24,4 +24,6 @@ "pip index", "pip list", "pip show", + # System info (read-only) + "date", ) diff --git a/pyproject.toml b/pyproject.toml index 906341971..3f0e0c5fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "GitAuto" -version = "1.12.0" +version = "1.12.2" requires-python = ">=3.14" dependencies = [ "annotated-doc==0.0.4", diff --git a/services/shell/run_command.py b/services/shell/run_command.py index 9cbf386c2..7b436349a 100644 --- a/services/shell/run_command.py +++ b/services/shell/run_command.py @@ -16,9 +16,9 @@ RUN_COMMAND: ToolUnionParam = { "name": "run_command", "description": ( - "Run a read-only shell command to look up package versions or dependencies. " + "Run a read-only shell command to look up package versions, dependencies, or system info. " "Allowed: npm (view/list/outdated/search), yarn (info/list/why), " - "composer (show/outdated), pip (show/list/index), node -v, php -v/-m. " + "composer (show/outdated), pip (show/list/index), node -v, php -v/-m, date. " "Use this instead of fetching HTML pages for package version lookups." ), "input_schema": { diff --git a/services/shell/test_run_command.py b/services/shell/test_run_command.py index 8537a9f24..7fa7dabbb 100644 --- a/services/shell/test_run_command.py +++ b/services/shell/test_run_command.py @@ -82,6 +82,13 @@ def test_ls_blocked_outside_tmp(self, _mock_slack, create_test_base_args): assert result is not None assert "not allowed" in result.lower() + @patch("services.shell.run_command.slack_notify") + def test_date_returns_current_date(self, _mock_slack, create_test_base_args): + base_args = create_test_base_args() + result = run_command(base_args, "date") + assert result is not None + assert len(result.strip()) > 0 + @pytest.mark.parametrize("prefix", ALLOWED_PREFIXES) def test_all_allowed_prefixes_are_read_only(self, prefix): # Verify no write commands snuck into the whitelist diff --git a/utils/logs/detect_infra_failure.py b/utils/logs/detect_infra_failure.py index 8b771f9bb..2dbcc8c43 100644 --- a/utils/logs/detect_infra_failure.py +++ b/utils/logs/detect_infra_failure.py @@ -25,6 +25,9 @@ # MongoMemoryServer binary crash (version/distro mismatch with cached S3 binary) "MongoMemoryServer Instance failed", 'signal "SIGABRT"', + # AWS IAM permission errors (Lambda role lacks access to SSM/SecretsManager/etc.) + "AccessDeniedException", + "no identity-based policy allows", ] diff --git a/utils/logs/test_detect_infra_failure.py b/utils/logs/test_detect_infra_failure.py index d3279e877..21a318121 100644 --- a/utils/logs/test_detect_infra_failure.py +++ b/utils/logs/test_detect_infra_failure.py @@ -24,7 +24,7 @@ def test_detect_infra_failure_real_segfault_log(): - real_log = SEGFAULT_LOG_PATH.read_text() + real_log = SEGFAULT_LOG_PATH.read_text(encoding="utf-8") result = detect_infra_failure(real_log) assert result == "Segmentation fault" @@ -75,6 +75,18 @@ def test_detect_infra_failure_real_segfault_log(): " at ChildProcess.emit (node:events:519:28)", 'signal "SIGABRT"', ), + # AWS IAM permission errors + ( + "AccessDeniedException: User: arn:aws:sts::948023073771:assumed-role/pr-agent-prod-role/pr-agent-prod " + "is not authorized to perform: secretsmanager:GetSecretValue on resource: dev/foxden-billing " + "because no identity-based policy allows the secretsmanager:GetSecretValue action", + "AccessDeniedException", + ), + ( + "User: arn:aws:sts::123:assumed-role/role/func is not authorized to perform: ssm:GetParameter " + "because no identity-based policy allows the ssm:GetParameter action", + "no identity-based policy allows", + ), ], ids=[ "yarn_502", @@ -91,6 +103,8 @@ def test_detect_infra_failure_real_segfault_log(): "enomem", "mongoms_instance_failed", "sigabrt", + "aws_access_denied", + "aws_iam_policy_denied", ], ) def test_detect_infra_failure_matches(error_log, expected): diff --git a/uv.lock b/uv.lock index 88c8fb8bc..d56a0aaaf 100644 --- a/uv.lock +++ b/uv.lock @@ -596,7 +596,7 @@ wheels = [ [[package]] name = "gitauto" -version = "1.12.0" +version = "1.12.2" source = { virtual = "." } dependencies = [ { name = "annotated-doc" },