@openhands/extensions 0.17.0 → 0.19.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.
Files changed (76) hide show
  1. package/.agents/skills/custom-codereview-guide.md +7 -0
  2. package/.github/dependabot.yml +24 -0
  3. package/.github/scripts/check_issue_readiness.py +272 -0
  4. package/.github/scripts/check_pr_description.py +226 -0
  5. package/.github/scripts/post-readiness-comment.mjs +184 -0
  6. package/.github/scripts/refresh_linked_pr_checks.py +171 -0
  7. package/.github/workflows/issue-readiness-check.yml +142 -0
  8. package/.github/workflows/pr-description-check.yml +37 -0
  9. package/.release-please-manifest.json +1 -1
  10. package/AGENTS.md +16 -0
  11. package/README.md +13 -2
  12. package/automations/README.md +3 -2
  13. package/automations/bundle-index.js +10 -1
  14. package/automations/catalog/github-agents-md-maintainer/manifest.json +101 -0
  15. package/automations/catalog/github-issue-to-pr/manifest.json +112 -0
  16. package/automations/catalog/github-pr-reviewer/manifest.json +6 -0
  17. package/automations/catalog/github-repo-monitor/manifest.json +6 -0
  18. package/automations/catalog/jira-issue-to-bitbucket-pr/manifest.json +23 -0
  19. package/automations/catalog/jira-issue-to-gitlab-mr/manifest.json +23 -0
  20. package/automations/catalog/linear-issue-to-bitbucket-pr/manifest.json +23 -0
  21. package/automations/catalog/linear-issue-to-github-pr/manifest.json +23 -0
  22. package/automations/catalog/linear-issue-to-gitlab-mr/manifest.json +23 -0
  23. package/automations/catalog/news-digest/manifest.json +81 -0
  24. package/automations/catalog/qa-changes/manifest.json +72 -0
  25. package/automations/catalog/slack-github-linear-daily-organization.json +27 -0
  26. package/automations/catalog-index.js +25 -7
  27. package/automations/catalog.schema.json +35 -2
  28. package/automations/index.d.ts +34 -1
  29. package/automations/interface.json +3 -1
  30. package/integrations/catalog/datadog.json +2 -2
  31. package/integrations/catalog/gitlab.json +41 -0
  32. package/integrations/catalog/notion.json +1 -1
  33. package/integrations/catalog-index.js +71 -69
  34. package/integrations/index.d.ts +1 -1
  35. package/marketplaces/openhands-extensions.json +59 -6
  36. package/package.json +1 -1
  37. package/plugins/pr-review/scripts/prompt.py +2 -0
  38. package/pyproject.toml +1 -1
  39. package/python/openhands_extensions/_version.py +1 -1
  40. package/skills/github-agents-md-maintainer/.plugin/plugin.json +19 -0
  41. package/skills/github-agents-md-maintainer/README.md +59 -0
  42. package/skills/github-agents-md-maintainer/SKILL.md +271 -0
  43. package/skills/github-agents-md-maintainer/commands/agents-md-setup.md +8 -0
  44. package/skills/github-agents-md-maintainer/references/state-schema.md +113 -0
  45. package/skills/github-agents-md-maintainer/scripts/main.py +1187 -0
  46. package/skills/github-issue-to-pr/.plugin/plugin.json +19 -0
  47. package/skills/github-issue-to-pr/README.md +84 -0
  48. package/skills/github-issue-to-pr/SKILL.md +373 -0
  49. package/skills/github-issue-to-pr/commands/issue-to-pr-setup.md +8 -0
  50. package/skills/github-issue-to-pr/references/state-schema.md +139 -0
  51. package/skills/github-issue-to-pr/scripts/main.py +1305 -0
  52. package/skills/github-pr-reviewer/SKILL.md +2 -1
  53. package/skills/github-pr-reviewer/scripts/main.py +45 -4
  54. package/skills/github-pr-reviewer/tests/test_main.py +74 -0
  55. package/skills/index.js +38 -2
  56. package/skills/news-digest/.plugin/plugin.json +19 -0
  57. package/skills/news-digest/README.md +71 -0
  58. package/skills/news-digest/SKILL.md +284 -0
  59. package/skills/news-digest/commands/news-digest-setup.md +8 -0
  60. package/skills/news-digest/references/state-schema.md +178 -0
  61. package/skills/news-digest/scripts/main.py +1250 -0
  62. package/skills/openhands-sdk/SKILL.md +1 -0
  63. package/skills/ticket-to-code-change/.plugin/plugin.json +21 -0
  64. package/skills/ticket-to-code-change/README.md +5 -0
  65. package/skills/ticket-to-code-change/SKILL.md +50 -0
  66. package/skills/ticket-to-code-change/commands/ticket-to-code-change-setup.md +8 -0
  67. package/tests/fixtures/automations/github-repo-monitor.json +77 -0
  68. package/tests/test_automation_setup.py +56 -0
  69. package/tests/test_catalogs.py +5 -3
  70. package/tests/test_check_issue_readiness.py +135 -0
  71. package/tests/test_check_pr_description.py +228 -0
  72. package/tests/test_github_agents_md_maintainer.py +352 -0
  73. package/tests/test_github_issue_to_pr.py +539 -0
  74. package/tests/test_news_digest.py +646 -0
  75. package/tests/test_pr_review_prompt.py +10 -0
  76. package/tests/test_refresh_linked_pr_checks.py +130 -0
@@ -0,0 +1,130 @@
1
+ from __future__ import annotations
2
+
3
+ import importlib.util
4
+ import json
5
+ import sys
6
+ from pathlib import Path
7
+
8
+
9
+ def _load(name: str, script_name: str):
10
+ script_path = (
11
+ Path(__file__).resolve().parents[1] / ".github" / "scripts" / script_name
12
+ )
13
+ spec = importlib.util.spec_from_file_location(name, script_path)
14
+ assert spec and spec.loader
15
+ mod = importlib.util.module_from_spec(spec)
16
+ sys.modules[name] = mod
17
+ spec.loader.exec_module(mod)
18
+ return mod
19
+
20
+
21
+ # Import check_pr_description first so refresh_linked_pr_checks can resolve its
22
+ # `from check_pr_description import ...` against the module we loaded above.
23
+ _load("check_pr_description", "check_pr_description.py")
24
+ _prod = _load("refresh_linked_pr_checks", "refresh_linked_pr_checks.py")
25
+
26
+
27
+ def _event(action="labeled", label="ready-for-dev", number=12):
28
+ return {
29
+ "action": action,
30
+ "issue": {"number": number},
31
+ "label": {"name": label},
32
+ "repository": {"full_name": "org/repo"},
33
+ }
34
+
35
+
36
+ def _write_event(monkeypatch, payload, tmp_path):
37
+ event_path = tmp_path / "event.json"
38
+ event_path.write_text(json.dumps(payload))
39
+ monkeypatch.setenv("GITHUB_EVENT_PATH", str(event_path))
40
+
41
+
42
+ class _FakeProc:
43
+ def __init__(self, stdout: str = ""):
44
+ self.returncode = 0
45
+ self.stdout = stdout
46
+ self.stderr = ""
47
+
48
+
49
+ def _recording_run(calls):
50
+ def _call(args):
51
+ calls.append(args)
52
+ # Listing runs returns one run; rerun is a no-op success.
53
+ if any("/actions/runs" in a for a in args):
54
+ return _FakeProc("8675309 2026-08-25T00:00:00Z\n")
55
+ return _FakeProc()
56
+
57
+ return _call
58
+
59
+
60
+ def _fail_on_call(value):
61
+ def _call(*args, **kwargs):
62
+ raise AssertionError(value)
63
+
64
+ return _call
65
+
66
+
67
+ def test_noop_for_unrelated_label(monkeypatch, tmp_path):
68
+ _write_event(monkeypatch, _event(label="bug"), tmp_path)
69
+ monkeypatch.setattr(_prod, "_linked_open_prs", _fail_on_call("unexpected"))
70
+ assert _prod.main() == 0
71
+
72
+
73
+ def test_noop_for_unrelated_action(monkeypatch, tmp_path):
74
+ _write_event(monkeypatch, _event(action="edited"), tmp_path)
75
+ monkeypatch.setattr(_prod, "_linked_open_prs", _fail_on_call("unexpected"))
76
+ assert _prod.main() == 0
77
+
78
+
79
+ def test_reruns_linked_pr_check_when_readiness_label_changes(monkeypatch, tmp_path):
80
+ _write_event(monkeypatch, _event(), tmp_path)
81
+ monkeypatch.setattr(
82
+ _prod,
83
+ "_linked_open_prs",
84
+ lambda repo, num: [{"number": 7, "headRefOid": "abc123"}],
85
+ )
86
+ monkeypatch.setattr(_prod, "_run", lambda args: _FakeProc("Fixes #12"))
87
+ seen = []
88
+ monkeypatch.setattr(
89
+ _prod,
90
+ "_rerun_pr_description_check",
91
+ lambda repo, sha: (seen.append((repo, sha)) or True),
92
+ )
93
+ assert _prod.main() == 0
94
+ assert seen == [("org/repo", "abc123")]
95
+
96
+
97
+ def test_skips_cross_referenced_pr_that_does_not_link_issue(monkeypatch, tmp_path):
98
+ _write_event(monkeypatch, _event(), tmp_path)
99
+ monkeypatch.setattr(
100
+ _prod,
101
+ "_linked_open_prs",
102
+ lambda repo, num: [{"number": 7, "headRefOid": "abc123"}],
103
+ )
104
+ # Body mentions #99 (the cross-reference) but not the event's issue #12.
105
+ monkeypatch.setattr(_prod, "_run", lambda args: _FakeProc("Fixes #99"))
106
+ seen = []
107
+ monkeypatch.setattr(
108
+ _prod,
109
+ "_rerun_pr_description_check",
110
+ lambda repo, sha: (seen.append((repo, sha)) or True),
111
+ )
112
+ assert _prod.main() == 0
113
+ assert seen == []
114
+
115
+
116
+ def test_rerun_pr_description_check_lists_runs_with_get(monkeypatch):
117
+ calls: list[list[str]] = []
118
+ monkeypatch.setattr(_prod, "_run", _recording_run(calls))
119
+ assert _prod._rerun_pr_description_check("org/repo", "abc123") is True
120
+ # Listing runs must be an explicit GET: `-f` args alone switch `gh api`
121
+ # to POST, which 404s on the runs collection endpoint (seen in the wild).
122
+ list_call = next(a for a in calls if "repos/org/repo/actions/runs" in a)
123
+ assert "-X" in list_call
124
+ assert list_call[list_call.index("-X") + 1] == "GET"
125
+ # The selected run is then re-run via an explicit POST.
126
+ rerun_call = next(a for a in calls if any("/rerun" in arg for arg in a))
127
+ assert rerun_call[rerun_call.index("api") + 1 : rerun_call.index("api") + 3] == [
128
+ "-X",
129
+ "POST",
130
+ ]