claude-dev-env 1.38.1 → 1.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +10 -36
- package/_shared/pr-loop/audit-reply-template.md +147 -0
- package/_shared/pr-loop/fix-protocol.md +25 -4
- package/_shared/pr-loop/gh-payloads.md +37 -50
- package/_shared/pr-loop/scripts/code_rules_gate.py +0 -60
- package/_shared/pr-loop/scripts/config/post_audit_thread_constants.py +199 -0
- package/_shared/pr-loop/scripts/config/reviews_disabled_constants.py +8 -0
- package/_shared/pr-loop/scripts/post_audit_thread.py +1242 -0
- package/_shared/pr-loop/scripts/preflight.py +129 -2
- package/_shared/pr-loop/scripts/reviews_disabled.py +59 -0
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +0 -19
- package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +1116 -0
- package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +127 -0
- package/_shared/pr-loop/scripts/tests/test_preflight.py +41 -0
- package/_shared/pr-loop/scripts/tests/test_reviews_disabled.py +36 -0
- package/_shared/pr-loop/state-schema.md +1 -1
- package/agents/clean-coder.md +2 -2
- package/agents/pr-description-writer.md +150 -52
- package/bin/install.mjs +6 -7
- package/bin/install.test.mjs +8 -0
- package/commands/doc-gist.md +16 -0
- package/commands/plan.md +0 -2
- package/commands/review-plan.md +1 -1
- package/docs/CODE_RULES.md +122 -2
- package/docs/PR_DESCRIPTION_GUIDE.md +127 -64
- package/hooks/blocking/bot_mention_comment_blocker.py +75 -0
- package/hooks/blocking/code_rules_enforcer.py +1143 -129
- package/hooks/blocking/convergence_gate_blocker.py +130 -0
- package/hooks/blocking/destructive_command_blocker.py +74 -0
- package/hooks/blocking/gh_body_arg_blocker.py +30 -0
- package/hooks/blocking/md_to_html_blocker.py +119 -0
- package/hooks/blocking/pr_description_enforcer.py +57 -22
- package/hooks/blocking/test_bot_mention_comment_blocker.py +131 -0
- package/hooks/blocking/test_code_rules_enforcer.py +21 -0
- package/hooks/blocking/test_code_rules_enforcer_any_exempt_files.py +70 -0
- package/hooks/blocking/test_code_rules_enforcer_any_imports_and_cast.py +92 -0
- package/hooks/blocking/test_code_rules_enforcer_banned_import_alias.py +143 -0
- package/hooks/blocking/test_code_rules_enforcer_banned_prefixes.py +152 -0
- package/hooks/blocking/test_code_rules_enforcer_bare_except.py +120 -0
- package/hooks/blocking/test_code_rules_enforcer_boundary_types.py +175 -0
- package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +0 -1
- package/hooks/blocking/test_code_rules_enforcer_collection_prefix.py +50 -0
- package/hooks/blocking/test_code_rules_enforcer_docstring_format.py +255 -0
- package/hooks/blocking/test_code_rules_enforcer_inline_tuple_string_magic.py +130 -0
- package/hooks/blocking/test_code_rules_enforcer_stub_implementations.py +141 -0
- package/hooks/blocking/test_code_rules_enforcer_test_branching.py +143 -0
- package/hooks/blocking/test_code_rules_enforcer_thin_wrapper_files.py +169 -0
- package/hooks/blocking/test_code_rules_enforcer_todo_markers.py +99 -0
- package/hooks/blocking/test_code_rules_enforcer_typed_dict_pairs.py +141 -0
- package/hooks/blocking/test_convergence_gate_blocker.py +63 -0
- package/hooks/blocking/test_destructive_command_blocker.py +146 -0
- package/hooks/blocking/test_destructive_command_blocker_no_verify.py +102 -0
- package/hooks/blocking/test_gh_body_arg_blocker.py +45 -0
- package/hooks/blocking/test_md_to_html_blocker.py +317 -0
- package/hooks/blocking/test_pr_description_enforcer.py +69 -8
- package/hooks/config/any_type_config.py +7 -0
- package/hooks/config/banned_identifiers_constants.py +11 -0
- package/hooks/config/blocking_check_limits.py +38 -0
- package/hooks/config/bot_mention_comment_blocker_constants.py +20 -0
- package/hooks/config/code_rules_enforcer_constants.py +53 -0
- package/hooks/config/convergence_branch_constants.py +9 -0
- package/hooks/config/doc_gist_auto_publish_constants.py +18 -0
- package/hooks/config/html_companion_constants.py +20 -0
- package/hooks/config/inline_tuple_string_magic_constants.py +22 -0
- package/hooks/config/pr_description_enforcer_constants.py +14 -0
- package/hooks/config/test_banned_identifiers_constants.py +17 -0
- package/hooks/hooks.json +28 -20
- package/hooks/pyproject.toml +69 -0
- package/hooks/validators/mypy_integration.py +47 -1
- package/hooks/validators/run_all_validators.py +3 -3
- package/hooks/validators/test_mypy_integration.py +50 -1
- package/hooks/workflow/doc_gist_auto_publish.py +144 -0
- package/hooks/workflow/md_to_html_companion.py +365 -0
- package/hooks/workflow/test_doc_gist_auto_publish.py +117 -0
- package/hooks/workflow/test_md_to_html_companion.py +452 -0
- package/package.json +1 -1
- package/rules/gh-body-file.md +2 -0
- package/scripts/Install-SweepEmptyDirs.ps1 +111 -0
- package/scripts/check.ps1 +106 -0
- package/scripts/config/timing.py +11 -0
- package/scripts/sweep_empty_dirs.py +138 -0
- package/scripts/sync_to_cursor/rules.py +1 -1
- package/scripts/test_sweep_empty_dirs.py +183 -0
- package/skills/_shared/pr-loop/prompts/pr-consistency-audit.xml +323 -0
- package/skills/_shared/pr-loop/scripts/_cli_utils.py +22 -0
- package/skills/_shared/pr-loop/scripts/_path_resolver.py +165 -0
- package/skills/_shared/pr-loop/scripts/_xml_utils.py +20 -0
- package/skills/_shared/pr-loop/scripts/build_audit_prompt.py +182 -0
- package/skills/_shared/pr-loop/scripts/build_fix_prompt.py +185 -0
- package/skills/_shared/pr-loop/scripts/config/__init__.py +0 -0
- package/skills/_shared/pr-loop/scripts/config/path_resolver_constants.py +78 -0
- package/skills/_shared/pr-loop/scripts/init_loop_state.py +135 -0
- package/skills/_shared/pr-loop/scripts/teardown_worktrees.py +175 -0
- package/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +182 -0
- package/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +206 -0
- package/skills/bugteam/CONSTRAINTS.md +21 -22
- package/skills/bugteam/EXAMPLES.md +3 -3
- package/skills/bugteam/PROMPTS.md +227 -67
- package/skills/bugteam/SKILL.md +132 -455
- package/skills/bugteam/reference/README.md +1 -1
- package/skills/bugteam/reference/audit-and-teammates.md +112 -39
- package/skills/bugteam/reference/audit-contract.md +4 -22
- package/skills/bugteam/reference/copilot-gap-analysis.md +8 -5
- package/skills/bugteam/reference/design-rationale.md +2 -2
- package/skills/bugteam/reference/github-pr-reviews.md +50 -57
- package/skills/bugteam/reference/obstacles/audit-assign-ids.md +13 -0
- package/skills/bugteam/reference/obstacles/audit-capture-excerpts.md +13 -0
- package/skills/bugteam/reference/obstacles/audit-walk-categories.md +13 -0
- package/skills/bugteam/reference/obstacles/audit-write-xml.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-append-summary.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-apply-fixes.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-git-add-commit.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-git-push.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-post-reply.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-publish-summary.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-py-compile.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-read-files.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-resolve-thread.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-test-suite.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-violation-count.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-write-xml.md +13 -0
- package/skills/bugteam/reference/team-setup.md +111 -9
- package/skills/bugteam/reference/teardown-publish-permissions.md +39 -8
- package/skills/bugteam/scripts/README.md +60 -0
- package/skills/bugteam/scripts/_claude_permissions_common.py +358 -0
- package/skills/bugteam/scripts/bugteam_code_rules_gate.py +976 -0
- package/skills/bugteam/scripts/bugteam_fix_hookspath.py +375 -0
- package/skills/bugteam/scripts/bugteam_preflight.py +328 -0
- package/skills/bugteam/scripts/config/bugteam_code_rules_gate_constants.py +25 -0
- package/skills/bugteam/scripts/config/bugteam_fix_hookspath_constants.py +26 -0
- package/skills/bugteam/scripts/config/bugteam_preflight_constants.py +35 -0
- package/skills/bugteam/scripts/config/claude_permissions_common_constants.py +20 -0
- package/skills/bugteam/scripts/config/probe_code_rules_enforcer_check_constants.py +12 -0
- package/skills/bugteam/scripts/config/windows_safe_rmtree_constants.py +7 -0
- package/skills/bugteam/scripts/grant_project_claude_permissions.py +175 -0
- package/skills/bugteam/scripts/probe_code_rules_enforcer_check.py +107 -0
- package/skills/bugteam/scripts/revoke_project_claude_permissions.py +220 -0
- package/skills/bugteam/scripts/test__claude_permissions_common.py +112 -0
- package/skills/bugteam/scripts/test_bugteam_code_rules_gate.py +400 -0
- package/skills/bugteam/scripts/test_bugteam_fix_hookspath.py +384 -0
- package/skills/bugteam/scripts/test_bugteam_preflight.py +309 -0
- package/skills/bugteam/scripts/test_claude_permissions_common.py +195 -0
- package/skills/bugteam/scripts/test_grant_project_claude_permissions.py +55 -0
- package/skills/bugteam/scripts/test_probe_code_rules_enforcer_check.py +76 -0
- package/skills/bugteam/scripts/test_revoke_project_claude_permissions.py +55 -0
- package/skills/bugteam/scripts/test_windows_safe_rmtree.py +108 -0
- package/skills/bugteam/scripts/windows_safe_rmtree.py +100 -0
- package/skills/bugteam/test_skill_additions.py +1 -11
- package/skills/code/SKILL.md +176 -0
- package/skills/copilot-review/SKILL.md +16 -0
- package/skills/doc-gist/SKILL.md +99 -0
- package/skills/doc-gist/references/examples/01-exploration-code-approaches.html +453 -0
- package/skills/doc-gist/references/examples/02-exploration-visual-designs.html +515 -0
- package/skills/doc-gist/references/examples/03-code-review-pr.html +638 -0
- package/skills/doc-gist/references/examples/04-code-understanding.html +491 -0
- package/skills/doc-gist/references/examples/05-design-system.html +629 -0
- package/skills/doc-gist/references/examples/06-component-variants.html +605 -0
- package/skills/doc-gist/references/examples/07-prototype-animation.html +455 -0
- package/skills/doc-gist/references/examples/08-prototype-interaction.html +396 -0
- package/skills/doc-gist/references/examples/09-slide-deck.html +592 -0
- package/skills/doc-gist/references/examples/10-svg-illustrations.html +492 -0
- package/skills/doc-gist/references/examples/11-status-report.html +528 -0
- package/skills/doc-gist/references/examples/12-incident-report.html +596 -0
- package/skills/doc-gist/references/examples/13-flowchart-diagram.html +395 -0
- package/skills/doc-gist/references/examples/14-research-feature-explainer.html +381 -0
- package/skills/doc-gist/references/examples/15-research-concept-explainer.html +368 -0
- package/skills/doc-gist/references/examples/16-implementation-plan.html +702 -0
- package/skills/doc-gist/references/examples/17-pr-writeup.html +595 -0
- package/skills/doc-gist/references/examples/18-editor-triage-board.html +573 -0
- package/skills/doc-gist/references/examples/19-editor-feature-flags.html +663 -0
- package/skills/doc-gist/references/examples/20-editor-prompt-tuner.html +722 -0
- package/skills/doc-gist/references/examples/README.md +5 -0
- package/skills/doc-gist/scripts/config/__init__.py +0 -0
- package/skills/doc-gist/scripts/config/gist_upload_constants.py +16 -0
- package/skills/doc-gist/scripts/gist_upload.py +177 -0
- package/skills/doc-gist/scripts/test_gist_upload.py +51 -0
- package/skills/findbugs/SKILL.md +96 -2
- package/skills/monitor-open-prs/SKILL.md +14 -32
- package/skills/monitor-open-prs/test_skill_contract.py +0 -11
- package/skills/pr-consistency-audit/SKILL.md +112 -0
- package/skills/pr-consistency-audit/reference/detection-rules.md +96 -0
- package/skills/pr-consistency-audit/reference/illustrations.md +78 -0
- package/skills/pr-converge/SKILL.md +229 -23
- package/skills/pr-converge/config/__init__.py +0 -0
- package/skills/pr-converge/config/constants.py +63 -0
- package/skills/pr-converge/reference/convergence-gates.md +138 -44
- package/skills/pr-converge/reference/examples.md +43 -11
- package/skills/pr-converge/reference/fix-protocol.md +6 -5
- package/skills/pr-converge/reference/ground-rules.md +5 -3
- package/skills/pr-converge/reference/multi-pr-orchestration.md +44 -19
- package/skills/pr-converge/reference/obstacles/fix-post-replies.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-publish-summary.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-push.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-read-filelines.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-reset-state.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-resolve-threads.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-spawn-clean-coder.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-stage-commit.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-trigger-bugbot.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-write-test.md +13 -0
- package/skills/pr-converge/reference/per-tick.md +107 -31
- package/skills/pr-converge/reference/state-schema.md +22 -1
- package/skills/pr-converge/reference/stop-conditions.md +9 -7
- package/skills/pr-converge/scripts/README.md +34 -46
- package/skills/pr-converge/scripts/check_bugbot_ci.py +279 -0
- package/skills/pr-converge/scripts/check_convergence.py +497 -0
- package/skills/pr-converge/scripts/check_pending_reviews.py +154 -0
- package/skills/pr-converge/scripts/config/pr_converge_constants.py +118 -0
- package/skills/pr-converge/scripts/fetch_copilot_reviews.py +134 -0
- package/skills/pr-converge/scripts/post_fix_reply.py +168 -0
- package/skills/pr-converge/scripts/test_check_bugbot_ci.py +312 -0
- package/skills/pr-converge/workflows/schedule-wakeup-loop.md +5 -12
- package/skills/qbug/SKILL.md +157 -27
- package/skills/session-log/SKILL.md +216 -114
- package/skills/session-tidy/SKILL.md +1 -1
- package/skills/skill-builder/SKILL.md +138 -56
- package/skills/skill-builder/references/delegation-map.md +72 -113
- package/skills/skill-builder/references/progressive-disclosure.md +122 -0
- package/skills/skill-builder/references/self-audit-checklist.md +92 -0
- package/skills/skill-builder/references/skill-types.md +228 -0
- package/skills/skill-builder/references/thariq-x-post-skills.json +33 -0
- package/skills/skill-builder/templates/gap-analysis.md +15 -8
- package/skills/skill-builder/workflows/improve-skill.md +86 -57
- package/skills/skill-builder/workflows/new-skill.md +80 -168
- package/skills/skill-builder/workflows/polish-skill.md +78 -54
- package/skills/structure-prompt/SKILL.md +50 -0
- package/skills/structure-prompt/reference/adversarial-tuning.md +62 -0
- package/skills/structure-prompt/reference/block-classification.md +27 -0
- package/skills/structure-prompt/reference/canonical-case.md +48 -0
- package/skills/structure-prompt/reference/citation-depth.md +70 -0
- package/skills/structure-prompt/reference/cleanup.md +33 -0
- package/skills/structure-prompt/reference/constraints.md +33 -0
- package/skills/structure-prompt/reference/directives.md +37 -0
- package/skills/structure-prompt/reference/examples.md +72 -0
- package/skills/structure-prompt/reference/instantiation.md +51 -0
- package/skills/structure-prompt/reference/output-contract.md +72 -0
- package/skills/structure-prompt/reference/per-category.md +23 -0
- package/skills/structure-prompt/reference/persona.md +38 -0
- package/skills/structure-prompt/reference/research.md +33 -0
- package/skills/structure-prompt/reference/structure.md +28 -0
- package/agents/code-standards-agent.md +0 -93
- package/agents/groq-coder.md +0 -113
- package/agents/plan-executor.md +0 -226
- package/agents/project-docs-analyzer.md +0 -53
- package/agents/project-structure-organizer-agent.md +0 -72
- package/agents/skill-to-agent-converter.md +0 -370
- package/agents/skill-writer-agent.md +0 -470
- package/agents/user-docs-writer.md +0 -67
- package/agents/workflow-visual-documenter.md +0 -82
- package/commands/readability-review.md +0 -20
- package/hooks/mypy.ini +0 -2
- package/hooks/notification/attention_needed_notify.py +0 -71
- package/hooks/notification/claude_notification_handler.py +0 -67
- package/hooks/notification/notification_utils.py +0 -267
- package/hooks/notification/subagent_complete_notify.py +0 -381
- package/hooks/notification/test_attention_needed_notify.py +0 -47
- package/hooks/notification/test_claude_notification_handler.py +0 -54
- package/hooks/notification/test_notification_utils.py +0 -91
- package/hooks/notification/test_subagent_complete_notify.py +0 -79
- package/scripts/config/groq_bugteam_config.py +0 -230
- package/scripts/config/test_groq_bugteam_config.py +0 -83
- package/scripts/config/test_spec_implementer_prompt.py +0 -32
- package/scripts/groq_bugteam.README.md +0 -131
- package/scripts/groq_bugteam.py +0 -647
- package/scripts/groq_bugteam_dotenv.py +0 -40
- package/scripts/groq_bugteam_spec.py +0 -226
- package/scripts/test_groq_bugteam.py +0 -529
- package/scripts/test_groq_bugteam_apply_fix_from_spec.py +0 -426
- package/scripts/test_groq_bugteam_dotenv.py +0 -66
- package/scripts/test_groq_bugteam_spec.py +0 -338
- package/skills/bugteam/SKILL_EVALS.md +0 -309
- package/skills/dream/SKILL.md +0 -118
- package/skills/ingest/SKILL.md +0 -40
- package/skills/npm-creator/SKILL.md +0 -187
- package/skills/readability-review/SKILL.md +0 -127
- package/skills/resume-review/SKILL.md +0 -261
- package/skills/rule-audit/SKILL.md +0 -307
- package/skills/rule-creator/SKILL.md +0 -150
- package/skills/searching-obsidian-vault/SKILL.md +0 -131
- package/skills/skill-writer/REFERENCE.md +0 -284
- package/skills/skill-writer/SKILL.md +0 -222
- package/skills/tdd-team/SKILL.md +0 -128
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"""Check for bugbot CI check runs on a commit.
|
|
2
|
+
|
|
3
|
+
Usage:
|
|
4
|
+
python scripts/check_bugbot_ci.py --owner <O> --repo <R> --sha <SHA>
|
|
5
|
+
python scripts/check_bugbot_ci.py --owner <O> --repo <R> --sha <SHA> --check-active
|
|
6
|
+
python scripts/check_bugbot_ci.py --owner <O> --repo <R> --sha <SHA> --check-clean
|
|
7
|
+
|
|
8
|
+
Default mode (no flag):
|
|
9
|
+
0 — bugbot check run found (printed to stdout as JSON)
|
|
10
|
+
1 — no bugbot check run found
|
|
11
|
+
EXIT_CODE_GH_ERROR — gh CLI error
|
|
12
|
+
|
|
13
|
+
``--check-active`` mode:
|
|
14
|
+
0 — bugbot check run is queued or in_progress
|
|
15
|
+
1 — bugbot check run is absent or no longer active
|
|
16
|
+
|
|
17
|
+
``--check-clean`` mode (silent-pass detection):
|
|
18
|
+
0 — bugbot check run is completed with success/neutral conclusion
|
|
19
|
+
1 — bugbot check run is absent, still active, or completed with a
|
|
20
|
+
non-clean conclusion (failure, action_required, etc.)
|
|
21
|
+
EXIT_CODE_GH_ERROR — gh CLI error
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import argparse
|
|
27
|
+
import json
|
|
28
|
+
import subprocess
|
|
29
|
+
import sys
|
|
30
|
+
from pathlib import Path
|
|
31
|
+
|
|
32
|
+
_pr_converge_dir = Path(__file__).resolve().parent.parent
|
|
33
|
+
if str(_pr_converge_dir) not in sys.path:
|
|
34
|
+
sys.path.insert(0, str(_pr_converge_dir))
|
|
35
|
+
|
|
36
|
+
from config.constants import (
|
|
37
|
+
ALL_BUGBOT_CHECK_RUN_ACTIVE_STATUSES,
|
|
38
|
+
ALL_BUGBOT_CHECK_RUN_COMPLETE_CONCLUSIONS,
|
|
39
|
+
BUGBOT_CHECK_RUN_COMPLETED_STATUS,
|
|
40
|
+
BUGBOT_CHECK_RUN_NAME_SUBSTRING,
|
|
41
|
+
CHECK_RUNS_PER_PAGE,
|
|
42
|
+
EXIT_CODE_GH_ERROR,
|
|
43
|
+
GH_CHECK_RUNS_PATH_TEMPLATE,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _run_check_runs_api(
|
|
48
|
+
*, owner: str, repo: str, sha: str
|
|
49
|
+
) -> subprocess.CompletedProcess[str]:
|
|
50
|
+
endpoint_path = GH_CHECK_RUNS_PATH_TEMPLATE.format(owner=owner, repo=repo, sha=sha)
|
|
51
|
+
jq_filter = ".check_runs[] | {name, status, conclusion}"
|
|
52
|
+
return subprocess.run(
|
|
53
|
+
[
|
|
54
|
+
"gh",
|
|
55
|
+
"api",
|
|
56
|
+
f"{endpoint_path}?per_page={CHECK_RUNS_PER_PAGE}",
|
|
57
|
+
"--jq",
|
|
58
|
+
jq_filter,
|
|
59
|
+
],
|
|
60
|
+
capture_output=True,
|
|
61
|
+
text=True,
|
|
62
|
+
encoding="utf-8",
|
|
63
|
+
errors="replace",
|
|
64
|
+
check=False,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def check_bugbot_ci(*, owner: str, repo: str, sha: str) -> int:
|
|
69
|
+
"""Check whether a bugbot CI check run exists on the given commit.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
owner: GitHub repository owner.
|
|
73
|
+
repo: GitHub repository name.
|
|
74
|
+
sha: Commit SHA to check.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
0 when a bugbot check run is found, 1 when absent,
|
|
78
|
+
EXIT_CODE_GH_ERROR on gh CLI error.
|
|
79
|
+
"""
|
|
80
|
+
completed_process = _run_check_runs_api(owner=owner, repo=repo, sha=sha)
|
|
81
|
+
if completed_process.returncode != 0:
|
|
82
|
+
print(f"gh api error: {completed_process.stderr}", file=sys.stderr)
|
|
83
|
+
return EXIT_CODE_GH_ERROR
|
|
84
|
+
for each_line in completed_process.stdout.splitlines():
|
|
85
|
+
stripped_line = each_line.strip()
|
|
86
|
+
if not stripped_line:
|
|
87
|
+
continue
|
|
88
|
+
try:
|
|
89
|
+
check_entry: dict[str, object] = json.loads(stripped_line)
|
|
90
|
+
except json.JSONDecodeError:
|
|
91
|
+
continue
|
|
92
|
+
each_name: object = check_entry.get("name")
|
|
93
|
+
if not isinstance(each_name, str):
|
|
94
|
+
continue
|
|
95
|
+
if BUGBOT_CHECK_RUN_NAME_SUBSTRING.lower() in each_name.lower():
|
|
96
|
+
json.dump(check_entry, sys.stdout)
|
|
97
|
+
sys.stdout.write("\n")
|
|
98
|
+
return 0
|
|
99
|
+
return 1
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def is_bugbot_run_active(*, owner: str, repo: str, sha: str) -> bool:
|
|
103
|
+
"""Check whether bugbot has an active (queued/in-progress) check run.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
owner: GitHub repository owner.
|
|
107
|
+
repo: GitHub repository name.
|
|
108
|
+
sha: Commit SHA to check.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
True when a bugbot check run with an active status exists.
|
|
112
|
+
"""
|
|
113
|
+
completed_process = _run_check_runs_api(owner=owner, repo=repo, sha=sha)
|
|
114
|
+
if completed_process.returncode != 0:
|
|
115
|
+
return False
|
|
116
|
+
for each_line in completed_process.stdout.splitlines():
|
|
117
|
+
stripped_line = each_line.strip()
|
|
118
|
+
if not stripped_line:
|
|
119
|
+
continue
|
|
120
|
+
try:
|
|
121
|
+
check_entry: dict[str, object] = json.loads(stripped_line)
|
|
122
|
+
except json.JSONDecodeError:
|
|
123
|
+
continue
|
|
124
|
+
each_name: object = check_entry.get("name")
|
|
125
|
+
if not isinstance(each_name, str):
|
|
126
|
+
continue
|
|
127
|
+
if BUGBOT_CHECK_RUN_NAME_SUBSTRING.lower() not in each_name.lower():
|
|
128
|
+
continue
|
|
129
|
+
each_status: object = check_entry.get("status")
|
|
130
|
+
if (
|
|
131
|
+
isinstance(each_status, str)
|
|
132
|
+
and each_status in ALL_BUGBOT_CHECK_RUN_ACTIVE_STATUSES
|
|
133
|
+
):
|
|
134
|
+
return True
|
|
135
|
+
return False
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _classify_bugbot_check_run(
|
|
139
|
+
completed_process: subprocess.CompletedProcess[str],
|
|
140
|
+
) -> bool | None:
|
|
141
|
+
"""Classify the bugbot check run state from a gh API process result.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
completed_process: Result of calling ``_run_check_runs_api``.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
True when the captured stdout contains a bugbot check run with a
|
|
148
|
+
``completed`` status and a conclusion in
|
|
149
|
+
``ALL_BUGBOT_CHECK_RUN_COMPLETE_CONCLUSIONS``. False when no such
|
|
150
|
+
check run is present (absent, still active, or completed with a
|
|
151
|
+
non-clean conclusion). None when ``completed_process.returncode``
|
|
152
|
+
is non-zero, signalling a gh CLI failure that the caller must
|
|
153
|
+
surface separately from "not clean".
|
|
154
|
+
"""
|
|
155
|
+
if completed_process.returncode != 0:
|
|
156
|
+
return None
|
|
157
|
+
for each_line in completed_process.stdout.splitlines():
|
|
158
|
+
stripped_line = each_line.strip()
|
|
159
|
+
if not stripped_line:
|
|
160
|
+
continue
|
|
161
|
+
try:
|
|
162
|
+
check_entry: dict[str, object] = json.loads(stripped_line)
|
|
163
|
+
except json.JSONDecodeError:
|
|
164
|
+
continue
|
|
165
|
+
each_name: object = check_entry.get("name")
|
|
166
|
+
if not isinstance(each_name, str):
|
|
167
|
+
continue
|
|
168
|
+
if BUGBOT_CHECK_RUN_NAME_SUBSTRING.lower() not in each_name.lower():
|
|
169
|
+
continue
|
|
170
|
+
each_status: object = check_entry.get("status")
|
|
171
|
+
if each_status != BUGBOT_CHECK_RUN_COMPLETED_STATUS:
|
|
172
|
+
return False
|
|
173
|
+
each_conclusion: object = check_entry.get("conclusion")
|
|
174
|
+
return (
|
|
175
|
+
isinstance(each_conclusion, str)
|
|
176
|
+
and each_conclusion in ALL_BUGBOT_CHECK_RUN_COMPLETE_CONCLUSIONS
|
|
177
|
+
)
|
|
178
|
+
return False
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def is_bugbot_run_clean(*, owner: str, repo: str, sha: str) -> bool | None:
|
|
182
|
+
"""Check whether bugbot has a completed check run with a clean conclusion.
|
|
183
|
+
|
|
184
|
+
A "silent pass" is bugbot's signal that it found no issues: the CI
|
|
185
|
+
check run completes with a ``success`` or ``neutral`` conclusion and
|
|
186
|
+
no review comment is posted. This function detects that signal so
|
|
187
|
+
callers can treat it as equivalent to an explicit clean review.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
owner: GitHub repository owner.
|
|
191
|
+
repo: GitHub repository name.
|
|
192
|
+
sha: Commit SHA to check.
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
True when a bugbot check run is completed with a conclusion in
|
|
196
|
+
``ALL_BUGBOT_CHECK_RUN_COMPLETE_CONCLUSIONS``. False when the
|
|
197
|
+
check run is absent, still active, or completed with a non-clean
|
|
198
|
+
conclusion. None when the gh CLI returns an error so the caller
|
|
199
|
+
can distinguish a transient API failure from a "not clean"
|
|
200
|
+
result.
|
|
201
|
+
"""
|
|
202
|
+
completed_process = _run_check_runs_api(owner=owner, repo=repo, sha=sha)
|
|
203
|
+
return _classify_bugbot_check_run(completed_process)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def parse_arguments(all_argv: list[str]) -> argparse.Namespace:
|
|
207
|
+
"""Parse command-line arguments.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
all_argv: Command-line argument list.
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
Parsed namespace with owner, repo, sha, and mode flags.
|
|
214
|
+
"""
|
|
215
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
216
|
+
parser.add_argument("--owner", required=True, help="GitHub repository owner")
|
|
217
|
+
parser.add_argument("--repo", required=True, help="GitHub repository name")
|
|
218
|
+
parser.add_argument("--sha", required=True, help="Commit SHA to check")
|
|
219
|
+
mode_group = parser.add_mutually_exclusive_group()
|
|
220
|
+
mode_group.add_argument(
|
|
221
|
+
"--check-active",
|
|
222
|
+
action="store_true",
|
|
223
|
+
default=False,
|
|
224
|
+
help="Check for active (queued/in-progress) check runs only",
|
|
225
|
+
)
|
|
226
|
+
mode_group.add_argument(
|
|
227
|
+
"--check-clean",
|
|
228
|
+
action="store_true",
|
|
229
|
+
default=False,
|
|
230
|
+
help=(
|
|
231
|
+
"Check for a completed bugbot check run with a "
|
|
232
|
+
"success/neutral conclusion (silent-pass detection)"
|
|
233
|
+
),
|
|
234
|
+
)
|
|
235
|
+
return parser.parse_args(all_argv)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def main(all_arguments: list[str]) -> int:
|
|
239
|
+
"""Entry point for check_bugbot_ci.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
all_arguments: Command-line arguments.
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
Exit code per the mode-specific contract documented in the
|
|
246
|
+
module docstring.
|
|
247
|
+
"""
|
|
248
|
+
arguments = parse_arguments(all_arguments)
|
|
249
|
+
if arguments.check_clean:
|
|
250
|
+
completed_process = _run_check_runs_api(
|
|
251
|
+
owner=arguments.owner,
|
|
252
|
+
repo=arguments.repo,
|
|
253
|
+
sha=arguments.sha,
|
|
254
|
+
)
|
|
255
|
+
if completed_process.returncode != 0:
|
|
256
|
+
print(f"gh api error: {completed_process.stderr}", file=sys.stderr)
|
|
257
|
+
return EXIT_CODE_GH_ERROR
|
|
258
|
+
is_clean = _classify_bugbot_check_run(completed_process)
|
|
259
|
+
if is_clean is not True:
|
|
260
|
+
print("bugbot: not clean")
|
|
261
|
+
return 0 if is_clean is True else 1
|
|
262
|
+
if arguments.check_active:
|
|
263
|
+
is_active = is_bugbot_run_active(
|
|
264
|
+
owner=arguments.owner,
|
|
265
|
+
repo=arguments.repo,
|
|
266
|
+
sha=arguments.sha,
|
|
267
|
+
)
|
|
268
|
+
if not is_active:
|
|
269
|
+
print("bugbot: not found")
|
|
270
|
+
return 0 if is_active else 1
|
|
271
|
+
return check_bugbot_ci(
|
|
272
|
+
owner=arguments.owner,
|
|
273
|
+
repo=arguments.repo,
|
|
274
|
+
sha=arguments.sha,
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
if __name__ == "__main__":
|
|
279
|
+
raise SystemExit(main(sys.argv[1:]))
|