@openhands/extensions 0.28.0 → 0.30.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/.agents/skills/custom-codereview-guide.md +44 -1
- package/.claude-plugin/marketplace.json +7 -5
- package/.codex-plugin/marketplace.json +7 -5
- package/.github/workflows/build-vscode-app.yml +3 -3
- package/.github/workflows/check-extensions.yml +1 -1
- package/.github/workflows/tests.yml +1 -1
- package/.plugin/marketplace.json +7 -5
- package/.release-please-manifest.json +1 -1
- package/AGENTS.md +7 -2
- package/README.md +3 -3
- package/apps/vscode/README.md +8 -6
- package/apps/vscode/canvas-extension.json +11 -3
- package/apps/vscode/extension.js +60 -12
- package/apps/vscode/scripts/package.mjs +20 -74
- package/automations/bundle-index.js +9 -7
- package/automations/catalog/github-issue-to-pr/manifest.json +1 -1
- package/automations/catalog/github-issue-triage/manifest.json +4 -3
- package/automations/catalog/github-pr-reviewer/manifest.json +5 -4
- package/automations/catalog/gitlab-issue-to-mr/manifest.json +3 -3
- package/automations/catalog/jira-issue-to-bitbucket-pr/manifest.json +4 -4
- package/automations/catalog/jira-issue-to-gitlab-mr/manifest.json +5 -5
- package/automations/catalog/jira-issue-to-pr/manifest.json +1 -1
- package/integrations/catalog/atlassian-rovo.json +4 -3
- package/integrations/catalog/bitbucket.json +16 -1
- package/integrations/catalog/github.json +1 -0
- package/integrations/catalog/gitlab.json +1 -1
- package/marketplaces/openhands-extensions.json +7 -5
- package/package.json +1 -1
- package/plugins/openhands/skills/openhands-automation/references/custom-automation.md +76 -8
- package/plugins/pr-review/README.md +1 -0
- package/plugins/pr-review/scripts/prompt.py +44 -11
- package/plugins/runtime-api-configs/SKILL.md +1 -1
- package/plugins/vulnerability-remediation/skills/github/scripts/agent_conversation.py +224 -8
- package/pyproject.toml +1 -1
- package/python/openhands_extensions/_version.py +1 -1
- package/skills/canvas-extension-api/SKILL.md +4 -1
- package/skills/canvas-extension-api/references/backend-safety.md +3 -3
- package/skills/canvas-extension-api/references/native-design.md +250 -0
- package/skills/canvas-extension-api/references/v1-contract.md +7 -4
- package/skills/canvas-extension-api/scripts/validate-extension.mjs +17 -1
- package/skills/canvas-extension-api/scripts/validate-extension.test.mjs +49 -0
- package/skills/github/scripts/agent_conversation.py +224 -8
- package/skills/github-issue-to-pr/scripts/agent_conversation.py +224 -8
- package/skills/github-issue-triage/README.md +73 -14
- package/skills/github-issue-triage/SKILL.md +26 -46
- package/skills/github-issue-triage/scripts/agent_conversation.py +224 -8
- package/skills/github-issue-triage/scripts/triage_publication.py +293 -0
- package/skills/github-issue-triage/scripts/worker.py +153 -103
- package/skills/github-pr-reviewer/README.md +103 -1
- package/skills/github-pr-reviewer/SKILL.md +35 -8
- package/skills/github-pr-reviewer/references/state-schema.md +8 -0
- package/skills/github-pr-reviewer/scripts/agent_conversation.py +224 -8
- package/skills/github-pr-reviewer/scripts/main.py +163 -39
- package/skills/github-pr-reviewer/scripts/publication.py +193 -0
- package/skills/github-pr-reviewer/scripts/worker.py +297 -8
- package/skills/github-pr-reviewer/tests/test_main.py +73 -5
- package/skills/gitlab-issue-to-mr/README.md +10 -3
- package/skills/gitlab-issue-to-mr/SKILL.md +43 -9
- package/skills/gitlab-issue-to-mr/references/state-schema.md +4 -0
- package/skills/gitlab-issue-to-mr/scripts/main.py +359 -25
- package/skills/index.js +10 -10
- package/skills/jira-issue-to-pr/.claude-plugin/plugin.json +4 -1
- package/skills/jira-issue-to-pr/.codex-plugin/plugin.json +4 -1
- package/skills/jira-issue-to-pr/.plugin/plugin.json +4 -1
- package/skills/jira-issue-to-pr/README.md +18 -11
- package/skills/jira-issue-to-pr/SKILL.md +72 -23
- package/skills/jira-issue-to-pr/references/setup.md +43 -12
- package/skills/jira-issue-to-pr/scripts/main.py +136 -26
- package/skills/openhands-automation/references/custom-automation.md +76 -8
- package/skills/slack-channel-monitor/README.md +6 -1
- package/skills/slack-channel-monitor/SKILL.md +6 -3
- package/skills/slack-channel-monitor/scripts/main.py +36 -4
- package/skills/ticket-to-code-change/.claude-plugin/plugin.json +1 -2
- package/skills/ticket-to-code-change/.codex-plugin/plugin.json +1 -2
- package/skills/ticket-to-code-change/.plugin/plugin.json +1 -2
- package/skills/ticket-to-code-change/SKILL.md +5 -3
- package/skills/ticket-to-code-change/commands/ticket-to-code-change-setup.md +1 -1
- package/tests/fixtures/automations/github-pr-reviewer.json +9 -9
- package/tests/test_agent_conversation_dispatch.py +173 -6
- package/tests/test_automation_llm_provenance.py +1209 -0
- package/tests/test_github_review_publication.py +422 -0
- package/tests/test_github_reviewer_delivery.py +174 -21
- package/tests/test_github_triage_delivery.py +411 -238
- package/tests/test_gitlab_issue_to_mr.py +284 -0
- package/tests/test_jira_issue_to_pr.py +200 -6
- package/tests/test_pr_review_prompt_injection.py +353 -0
- package/tests/test_slack_channel_monitor.py +32 -1
- package/tests/test_vscode_app.py +8 -2
- package/tests/vscode-app.test.mjs +8 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jira-issue-to-pr",
|
|
3
3
|
"version": "1.0.0",
|
|
4
|
-
"description": "Deploy a cron-based OpenHands automation that
|
|
4
|
+
"description": "Deploy a cron-based OpenHands automation that opens a GitHub pull request, a GitLab merge request or a Bitbucket pull request for each Jira issue carrying a configurable label (default: create-pr). The target repository is read from the ticket body - no repo parameter required at deploy time.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "OpenHands",
|
|
7
7
|
"email": "contact@all-hands.dev"
|
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
"jira",
|
|
14
14
|
"atlassian",
|
|
15
15
|
"github",
|
|
16
|
+
"gitlab",
|
|
17
|
+
"bitbucket",
|
|
16
18
|
"pull-request",
|
|
19
|
+
"merge-request",
|
|
17
20
|
"automation"
|
|
18
21
|
]
|
|
19
22
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jira-issue-to-pr",
|
|
3
3
|
"version": "1.0.0",
|
|
4
|
-
"description": "Deploy a cron-based OpenHands automation that
|
|
4
|
+
"description": "Deploy a cron-based OpenHands automation that opens a GitHub pull request, a GitLab merge request or a Bitbucket pull request for each Jira issue carrying a configurable label (default: create-pr). The target repository is read from the ticket body - no repo parameter required at deploy time.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "OpenHands",
|
|
7
7
|
"email": "contact@all-hands.dev"
|
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
"jira",
|
|
14
14
|
"atlassian",
|
|
15
15
|
"github",
|
|
16
|
+
"gitlab",
|
|
17
|
+
"bitbucket",
|
|
16
18
|
"pull-request",
|
|
19
|
+
"merge-request",
|
|
17
20
|
"automation"
|
|
18
21
|
]
|
|
19
22
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jira-issue-to-pr",
|
|
3
3
|
"version": "1.0.0",
|
|
4
|
-
"description": "Deploy a cron-based OpenHands automation that
|
|
4
|
+
"description": "Deploy a cron-based OpenHands automation that opens a GitHub pull request, a GitLab merge request or a Bitbucket pull request for each Jira issue carrying a configurable label (default: create-pr). The target repository is read from the ticket body - no repo parameter required at deploy time.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "OpenHands",
|
|
7
7
|
"email": "contact@all-hands.dev"
|
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
"jira",
|
|
14
14
|
"atlassian",
|
|
15
15
|
"github",
|
|
16
|
+
"gitlab",
|
|
17
|
+
"bitbucket",
|
|
16
18
|
"pull-request",
|
|
19
|
+
"merge-request",
|
|
17
20
|
"automation"
|
|
18
21
|
]
|
|
19
22
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
# Jira Issue to GitHub
|
|
1
|
+
# Jira Issue to Pull Request (GitHub, GitLab, Bitbucket)
|
|
2
2
|
|
|
3
3
|
Deploy a cron-based OpenHands automation that polls a Jira Cloud project for
|
|
4
4
|
open issues carrying a configurable label (default: `create-pr`) and, for each
|
|
5
|
-
new issue, starts an OpenHands agent conversation that clones the
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
new issue, starts an OpenHands agent conversation that clones the repository
|
|
6
|
+
named in the ticket body on the configured git provider (GitHub by default,
|
|
7
|
+
GitLab or Bitbucket with `git_provider`), creates a branch, implements the
|
|
8
|
+
requested change, and opens a pull request (a merge request on GitLab). Once the
|
|
9
|
+
conversation starts, it posts a
|
|
8
10
|
comment on the Jira ticket: "I'm on it: `<conversation URL>`".
|
|
9
11
|
|
|
10
12
|
## Triggers
|
|
@@ -16,12 +18,16 @@ This skill is activated by keywords:
|
|
|
16
18
|
- `automatically create GitHub PRs from Jira tickets`
|
|
17
19
|
- `deploy a Jira issue-to-PR automation`
|
|
18
20
|
- `create a Jira to GitHub PR workflow`
|
|
21
|
+
- `set up the Jira issue to GitLab MR automation`
|
|
22
|
+
- `set up the Jira issue to Bitbucket PR automation`
|
|
19
23
|
- `automate GitHub PR creation from a Jira label`
|
|
20
24
|
|
|
21
25
|
## How It Works
|
|
22
26
|
|
|
23
|
-
1. **Poll** - every N minutes, the script
|
|
24
|
-
|
|
27
|
+
1. **Poll** - every N minutes, the script searches the Jira Cloud instance for
|
|
28
|
+
open issues with the configured label: through the user's connected
|
|
29
|
+
Atlassian Rovo MCP server on OpenHands Cloud and Enterprise, or with
|
|
30
|
+
`POST /rest/api/3/search/jql` and an API token.
|
|
25
31
|
2. **Deduplicate** - on the first run the script records a `first_run_at`
|
|
26
32
|
baseline timestamp in the KV store; issues whose `updated` timestamp
|
|
27
33
|
predates that baseline are skipped (no backfill blast on first deploy).
|
|
@@ -32,7 +38,8 @@ This skill is activated by keywords:
|
|
|
32
38
|
conversation with a PR-creation prompt: `POST /api/conversations` on the
|
|
33
39
|
agent server when running locally, `POST /api/v1/app-conversations` on
|
|
34
40
|
OpenHands Cloud and Enterprise. The prompt instructs the agent to extract the
|
|
35
|
-
target
|
|
41
|
+
target repository (`owner/repo` on GitHub; `group/project` or a URL on
|
|
42
|
+
GitLab; `workspace/repo` on Bitbucket) from the ticket body. On Cloud the
|
|
36
43
|
next poll confirms the conversation came up and starts it again when it did
|
|
37
44
|
not.
|
|
38
45
|
4. **Comment** - immediately after the conversation is created, the script
|
|
@@ -52,13 +59,13 @@ OpenHands and Jira. See "Event-Based Alternative" in `SKILL.md`.
|
|
|
52
59
|
|
|
53
60
|
| Requirement | Details |
|
|
54
61
|
|---|---|
|
|
55
|
-
| **Jira API token
|
|
56
|
-
| **
|
|
62
|
+
| **Jira access** | OpenHands Cloud and Enterprise: the user's connected Atlassian Rovo MCP server, with no API token. Local, or without that connection: a Jira API token stored as an OpenHands secret (see `references/setup.md`) |
|
|
63
|
+
| **Git provider access** | OpenHands Cloud and Enterprise: the connected GitHub, GitLab or Bitbucket integration named by `git_provider`, or a connected MCP server (GitHub's, GitLab's, or Atlassian Rovo for Bitbucket). Local: that provider's token stored as an OpenHands secret so the spawned conversation can push branches and open the request |
|
|
57
64
|
| **Jira label** | The label to watch for (default: `create-pr`) must exist in the Jira project |
|
|
58
|
-
| **
|
|
65
|
+
| **Target repository** | Must exist on the configured provider; the connected integration or token must have write access |
|
|
59
66
|
|
|
60
67
|
## Quick Start
|
|
61
68
|
|
|
62
69
|
See `SKILL.md` for the full step-by-step deployment guide, and
|
|
63
|
-
`references/setup.md` for Jira API token creation,
|
|
70
|
+
`references/setup.md` for Jira API token creation, git provider tokens, cron
|
|
64
71
|
schedule reference, and troubleshooting.
|
|
@@ -4,25 +4,31 @@ description: >
|
|
|
4
4
|
This skill should be used when the user asks to "set up a Jira automation to create pull requests",
|
|
5
5
|
"poll Jira for create-pr issues", "automatically create GitHub PRs from Jira tickets",
|
|
6
6
|
"deploy a Jira issue-to-PR automation", "create a Jira to GitHub PR workflow",
|
|
7
|
-
|
|
7
|
+
"set up the Jira issue to GitLab MR automation", "set up the Jira issue to Bitbucket PR automation",
|
|
8
|
+
"open GitLab merge requests from Jira tickets", "open Bitbucket pull requests from Jira tickets",
|
|
9
|
+
or mentions automating pull request or merge request creation from a Jira label.
|
|
8
10
|
Deploys a cron-based OpenHands automation that watches a Jira Cloud project for issues
|
|
9
11
|
labeled with a configurable label (default: "create-pr") and spawns an agent conversation
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
that opens a pull request on GitHub (the default), a merge request on GitLab, or a pull
|
|
13
|
+
request on Bitbucket for each new issue found, chosen with git_provider. The target
|
|
14
|
+
repository is read from the body of the Jira ticket - no repo parameter is required at deploy time.
|
|
12
15
|
---
|
|
13
16
|
|
|
14
|
-
# Jira → GitHub
|
|
17
|
+
# Jira → Pull Request Automation (GitHub, GitLab, Bitbucket)
|
|
15
18
|
|
|
16
19
|
Deploys a cron automation that polls a Jira Cloud instance for open issues carrying a
|
|
17
20
|
configurable label and, for each new issue, starts an OpenHands agent conversation that
|
|
18
|
-
clones the
|
|
19
|
-
or
|
|
21
|
+
clones the repository specified in the ticket body on the configured git provider (GitHub
|
|
22
|
+
by default, GitLab or Bitbucket with `git_provider`), creates a branch, implements or
|
|
23
|
+
placeholders the requested change, and opens a pull request (a merge request on GitLab).
|
|
24
|
+
Once the conversation
|
|
20
25
|
starts, it also posts a comment on the Jira ticket: "I'm on it: <conversation URL>".
|
|
21
26
|
|
|
22
27
|
## How It Works
|
|
23
28
|
|
|
24
|
-
1. **Poll** - every N minutes,
|
|
25
|
-
|
|
29
|
+
1. **Poll** - every N minutes, search the Jira Cloud instance for open issues with the
|
|
30
|
+
configured label: through the user's connected Atlassian Rovo MCP server on OpenHands
|
|
31
|
+
Cloud and Enterprise, or with `POST /rest/api/3/search/jql` and an API token.
|
|
26
32
|
2. **Deduplicate** - on the very first run the script records a `first_run_at` baseline
|
|
27
33
|
timestamp in the KV store; any issue whose `updated` timestamp predates that baseline
|
|
28
34
|
is skipped (no backfill blast on first deploy). Using `updated` rather than `created`
|
|
@@ -33,7 +39,8 @@ starts, it also posts a comment on the Jira ticket: "I'm on it: <conversation
|
|
|
33
39
|
3. **Dispatch** - for each new issue, start an independent agent conversation with a
|
|
34
40
|
PR-creation prompt: `POST /api/conversations` on the agent server when running locally,
|
|
35
41
|
or `POST /api/v1/app-conversations` on OpenHands Cloud. The prompt instructs the agent
|
|
36
|
-
to extract the target
|
|
42
|
+
to extract the target repository (`owner/repo` on GitHub; `group/project` or a URL on GitLab;
|
|
43
|
+
`workspace/repo` on Bitbucket) from the ticket body.
|
|
37
44
|
4. **Comment** - immediately after the conversation is created, post a Jira comment on the
|
|
38
45
|
issue: `I'm on it: <conversation URL>`.
|
|
39
46
|
5. **Persist** - record the processed issue key so re-runs never duplicate work.
|
|
@@ -47,11 +54,11 @@ Before deploying, ensure the following are in place:
|
|
|
47
54
|
|
|
48
55
|
| Requirement | Details |
|
|
49
56
|
|---|---|
|
|
50
|
-
| **Jira API token
|
|
51
|
-
| **
|
|
57
|
+
| **Jira access** | OpenHands Cloud and Enterprise: the user's connected Atlassian Rovo MCP server, with no API token. Local, or without that connection: a Jira API token stored as an OpenHands secret (see [Jira API token setup](#jira-api-token)) |
|
|
58
|
+
| **Git provider access** | OpenHands Cloud and Enterprise: the user's connected GitHub, GitLab or Bitbucket integration, whichever `git_provider` names. A connected MCP server also works - GitHub's (with the saved access token), GitLab's, or Atlassian Rovo for Bitbucket - with a private repository read through the tools rather than cloned. Local: a token for that provider stored as an OpenHands secret (`GITHUB_TOKEN` with `repo` + `workflow`, `GITLAB_TOKEN` with `api`, `BITBUCKET_TOKEN`) so the spawned conversation can push branches and open the request |
|
|
52
59
|
| **KV store** (OpenHands Cloud only) | The automation service must have its KV store enabled (`kvStore` in `GET /api/automation/v1/capabilities`); each cloud run starts in a fresh sandbox, so processed issues are remembered there |
|
|
53
60
|
| **Jira label** | The label to watch for (default: `create-pr`) must exist in the Jira project |
|
|
54
|
-
| **
|
|
61
|
+
| **Target repository** | Must exist on the configured provider; the connected integration or token must have write access |
|
|
55
62
|
|
|
56
63
|
## Deploying the Automation
|
|
57
64
|
|
|
@@ -72,24 +79,53 @@ Set `OPENHANDS_HOST` and `AUTH_HEADER` for the curl commands below:
|
|
|
72
79
|
|
|
73
80
|
### Step 1 - Collect parameters
|
|
74
81
|
|
|
75
|
-
|
|
82
|
+
First decide how the poller reaches Jira:
|
|
83
|
+
|
|
84
|
+
- **Connected Atlassian Rovo MCP server** - on OpenHands Cloud and Enterprise, when the
|
|
85
|
+
user has connected it. OpenHands calls Jira for the poller through that connection, so
|
|
86
|
+
do not ask for a Jira email or an API token and do not create a secret.
|
|
87
|
+
- **Jira API token** - on a local Agent Canvas, or when the Rovo server is not connected.
|
|
88
|
+
|
|
89
|
+
Then pick `git_provider` from the automation the user asked for: `github` for *Jira issue to
|
|
90
|
+
GitHub PR* (the default, so it can be left out), `gitlab` for *Jira issue to GitLab MR*,
|
|
91
|
+
`bitbucket` for *Jira issue to Bitbucket PR*. It changes only what the conversation is told;
|
|
92
|
+
the conversation pushes with the user's connected integration for that provider, or delivers
|
|
93
|
+
through the connected MCP server's tools when it has no token.
|
|
94
|
+
|
|
95
|
+
Then gather the parameters for that route, plus the shared ones, before proceeding:
|
|
76
96
|
|
|
77
97
|
| Parameter | Example | Notes |
|
|
78
98
|
|---|---|---|
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
99
|
+
| `jira_mcp_server` | `atlassian-rovo` | Rovo connection only. The name the server is stored under: the key in `agent_settings.mcp_config` of `GET ${OPENHANDS_HOST}/api/v1/settings` whose `url` is on `mcp.atlassian.com`. Look it up; do not ask the user |
|
|
100
|
+
| `jira_cloud_id` | `1324a887-45db-1bf4-1e99-ef0ff456d421` | Rovo connection only. The `id` of the Jira site, from the Rovo tool `getAccessibleAtlassianResources`. Ask which site only when it lists several |
|
|
101
|
+
| `jira_base_url` | `https://acme.atlassian.net` | API token only. No trailing slash |
|
|
102
|
+
| `jira_email` | `alice@acme.com` | API token only. Atlassian account email for Basic auth |
|
|
103
|
+
| `jira_token_secret` | `JIRA_CLOUD_KEY` | API token only. Name of the OpenHands secret holding the API token |
|
|
82
104
|
| `jira_label` | `create-pr` | Label to watch for (optional, defaults to `create-pr`) |
|
|
105
|
+
| `git_provider` | `gitlab` | `github` (default), `gitlab` or `bitbucket` - the provider the ticket names its repository on (optional) |
|
|
83
106
|
| `max_new_per_run` | `5` | Max conversations dispatched per cron firing (optional, defaults to `5`) |
|
|
84
107
|
| `cron_schedule` | `*/5 * * * *` | Polling frequency in cron syntax |
|
|
85
108
|
|
|
86
|
-
> **Note**: The
|
|
87
|
-
>
|
|
88
|
-
> The spawned agent extracts it from
|
|
109
|
+
> **Note**: The repository is not configured here. Each Jira ticket body must name it:
|
|
110
|
+
> `owner/repo` on GitHub, `group/subgroup/project` or a full URL on GitLab (self-managed
|
|
111
|
+
> hosts included), `workspace/repo` on bitbucket.org. The spawned agent extracts it from
|
|
112
|
+
> the ticket text.
|
|
89
113
|
|
|
90
114
|
### Step 2 - Create config.json
|
|
91
115
|
|
|
92
|
-
Create `config.json` next to `scripts/main.py` when packaging
|
|
116
|
+
Create `config.json` next to `scripts/main.py` when packaging. With the connected
|
|
117
|
+
Atlassian Rovo MCP server:
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"jira_mcp_server": "atlassian-rovo",
|
|
122
|
+
"jira_cloud_id": "1324a887-45db-1bf4-1e99-ef0ff456d421",
|
|
123
|
+
"jira_label": "create-pr",
|
|
124
|
+
"max_new_per_run": 5
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
With a Jira API token:
|
|
93
129
|
|
|
94
130
|
```json
|
|
95
131
|
{
|
|
@@ -101,6 +137,9 @@ Create `config.json` next to `scripts/main.py` when packaging:
|
|
|
101
137
|
}
|
|
102
138
|
```
|
|
103
139
|
|
|
140
|
+
For the GitLab and Bitbucket templates add `"git_provider": "gitlab"` or
|
|
141
|
+
`"git_provider": "bitbucket"` to either example; it is `github` when omitted.
|
|
142
|
+
|
|
104
143
|
### Step 3 - Package the tarball
|
|
105
144
|
|
|
106
145
|
Copy `scripts/main.py` from this skill and package it with the `config.json`:
|
|
@@ -143,7 +182,8 @@ curl -s -X POST "${OPENHANDS_HOST}/api/automation/v1" \
|
|
|
143
182
|
}" | python3 -m json.tool
|
|
144
183
|
```
|
|
145
184
|
|
|
146
|
-
Save the returned `id` - use it for updates and monitoring.
|
|
185
|
+
Save the returned `id` - use it for updates and monitoring. Name the automation after the
|
|
186
|
+
template the user picked, for example `Jira issue-to-MR Poller` for GitLab.
|
|
147
187
|
|
|
148
188
|
### Step 6 - Verify with a test dispatch
|
|
149
189
|
|
|
@@ -158,6 +198,14 @@ curl -s "${OPENHANDS_HOST}/api/automation/v1/<AUTOMATION_ID>/runs?limit=1" \
|
|
|
158
198
|
| python3 -c "import sys,json; r=json.load(sys.stdin)['runs'][0]; print(r['status'], r.get('error_detail'))"
|
|
159
199
|
```
|
|
160
200
|
|
|
201
|
+
With the Rovo connection, a run that fails on `/api/v1/mcp/servers/<name>/call-tool` says why:
|
|
202
|
+
|
|
203
|
+
- `404` with `No connected MCP server is named ...` - `jira_mcp_server` is not the name the
|
|
204
|
+
server is stored under, or the user switched the server off.
|
|
205
|
+
- `404` with `Not Found` - this deployment cannot call a connected MCP server for a run yet.
|
|
206
|
+
Set the automation up with a Jira API token instead.
|
|
207
|
+
- `502` - the server could not be reached, or the user has to reconnect it in the settings.
|
|
208
|
+
|
|
161
209
|
## Event-Based Alternative
|
|
162
210
|
|
|
163
211
|
Where Jira can reach the deployment over the internet (OpenHands Cloud and Enterprise),
|
|
@@ -287,7 +335,8 @@ The automation script lives at `scripts/main.py`. Key behaviors:
|
|
|
287
335
|
- **First-run baseline** - on the very first execution the script writes `first_run_at` (UTC timestamp) into the KV store and exits without dispatching; issues whose `updated` timestamp predates that baseline are skipped on all subsequent runs. Using `updated` (not `created`) means an old issue that has its label applied after deployment is correctly treated as new.
|
|
288
336
|
- **Per-run cap** - `max_new_per_run` (default 5) limits how many conversations are started per cron firing; any remaining new issues are dispatched on the next run.
|
|
289
337
|
- **KV store** - persists `{"processed_keys": [...], "first_run_at": "..."}` between runs; falls back to a local file in local dev environments where `AUTOMATION_KV_TOKEN` is absent (on OpenHands Cloud the run fails instead, since its sandbox does not persist).
|
|
290
|
-
- **Jira
|
|
338
|
+
- **Jira access** - with `jira_mcp_server` set, searches and comments through the user's connected Atlassian Rovo MCP server (`POST /api/v1/mcp/servers/<name>/call-tool` on OpenHands Cloud, tools `searchJiraIssuesUsingJql` and `addOrEditJiraIssueComment`, or `addCommentToJiraIssue` on a server that still offers the v1 tools), so the run reads no Jira credential. Otherwise uses the Jira REST API with the token secret: `POST /rest/api/3/search/jql` (the current non-deprecated endpoint).
|
|
339
|
+
- **Git provider** - `git_provider` selects the prompt's wording (GitHub pull request, GitLab merge request, Bitbucket pull request), the repository formats the agent looks for, and how it delivers without a token (GitLab's MCP tools, Rovo's Bitbucket tools); nothing else differs between the three templates.
|
|
291
340
|
- **Conversation dispatch** - locally, calls `POST /api/conversations` on the agent server with the current user's LLM/agent settings forwarded to the new conversation; on OpenHands Cloud, calls `POST /api/v1/app-conversations`, which runs each conversation in its own sandbox with the user's settings, secrets and connected git provider.
|
|
292
341
|
- **Start confirmation** (OpenHands Cloud only) - the API answers a start request before the conversation exists, so the next run checks each one. A start that failed is made again, up to three times, and after that the failure is posted on the Jira issue.
|
|
293
342
|
- **Error transparency** - captures Jira HTTP response bodies in error messages for fast diagnosis.
|
|
@@ -324,4 +373,4 @@ that issue again.
|
|
|
324
373
|
|
|
325
374
|
## Additional Resources
|
|
326
375
|
|
|
327
|
-
- **`references/setup.md`** - Jira API token creation,
|
|
376
|
+
- **`references/setup.md`** - Jira API token creation, git provider tokens, cron schedule reference, and troubleshooting guide.
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## Jira API Token
|
|
4
4
|
|
|
5
|
+
The poller needs this token only when it does not reach Jira through a connected
|
|
6
|
+
Atlassian Rovo MCP server (see Step 1 in `SKILL.md`).
|
|
7
|
+
|
|
5
8
|
### Create a token
|
|
6
9
|
|
|
7
10
|
1. Log in to [id.atlassian.com](https://id.atlassian.com/manage-profile/security/api-tokens).
|
|
@@ -38,11 +41,19 @@ The Jira Cloud REST API v3 requires this for all authenticated requests.
|
|
|
38
41
|
|
|
39
42
|
---
|
|
40
43
|
|
|
41
|
-
##
|
|
44
|
+
## Git Provider Access
|
|
42
45
|
|
|
43
46
|
The spawned agent conversation clones the target repository, pushes a new branch, and
|
|
44
|
-
opens
|
|
45
|
-
|
|
47
|
+
opens the pull or merge request. On OpenHands Cloud and Enterprise it uses the connected
|
|
48
|
+
integration for the provider named by `git_provider` (GitHub, GitLab or Bitbucket). With
|
|
49
|
+
only an MCP connection (GitHub's with its saved token, GitLab's, or Atlassian Rovo for
|
|
50
|
+
Bitbucket) it commits through the tools instead, and reads a private repository through
|
|
51
|
+
them rather than cloning it. On a local Agent Canvas a token for the provider must be
|
|
52
|
+
stored as an OpenHands secret.
|
|
53
|
+
|
|
54
|
+
### GitHub
|
|
55
|
+
|
|
56
|
+
The GitHub token must have the following scopes:
|
|
46
57
|
|
|
47
58
|
| Scope | Required for |
|
|
48
59
|
|---|---|
|
|
@@ -57,20 +68,39 @@ inherits the user's configured secrets automatically through the agent server.
|
|
|
57
68
|
Navigate to **Settings → Secrets** and store the token under the name `GITHUB_TOKEN`
|
|
58
69
|
(or whatever name is expected by the agent's GitHub skill).
|
|
59
70
|
|
|
71
|
+
### GitLab
|
|
72
|
+
|
|
73
|
+
Store a personal access token with the `api` scope and at least the Developer role on the
|
|
74
|
+
target projects under the name `GITLAB_TOKEN`.
|
|
75
|
+
|
|
76
|
+
Calling GitLab MCP directly, to commit without a token, needs GitLab 19.4 or later, where its
|
|
77
|
+
branch, commit and repository tools first appear. On OpenHands Cloud and Enterprise the token
|
|
78
|
+
of the user's GitLab sign-in or connected integration reaches the conversation as
|
|
79
|
+
`GITLAB_TOKEN`, so on an older GitLab sign in with GitLab or connect it under Settings ->
|
|
80
|
+
Integrations, and store this secret only if neither is possible.
|
|
81
|
+
|
|
82
|
+
### Bitbucket
|
|
83
|
+
|
|
84
|
+
Store the token under the name `BITBUCKET_TOKEN`; the `bitbucket` skill describes the token
|
|
85
|
+
type and permissions.
|
|
86
|
+
|
|
60
87
|
---
|
|
61
88
|
|
|
62
89
|
## config.json Field Reference
|
|
63
90
|
|
|
64
91
|
| Field | Required | Default | Description |
|
|
65
92
|
|---|---|---|---|
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
93
|
+
| `jira_mcp_server` | ❌ | - | Name the connected Atlassian Rovo MCP server is stored under. When set, the poller reaches Jira through it (OpenHands Cloud and Enterprise only) and the three fields after `jira_cloud_id` are not used |
|
|
94
|
+
| `jira_cloud_id` | with `jira_mcp_server` | - | Atlassian cloud id of the Jira site |
|
|
95
|
+
| `jira_base_url` | without `jira_mcp_server` | - | Full URL of your Atlassian instance, e.g. `https://acme.atlassian.net` |
|
|
96
|
+
| `jira_email` | without `jira_mcp_server` | - | Email address of the Atlassian account that owns the API token |
|
|
68
97
|
| `jira_token_secret` | ❌ | `"JIRA_CLOUD_KEY"` | Name of the OpenHands secret holding the Jira API token |
|
|
69
98
|
| `jira_label` | ❌ | `"create-pr"` | Jira issue label to watch for |
|
|
99
|
+
| `git_provider` | ❌ | `"github"` | `github`, `gitlab` or `bitbucket` - the provider the ticket names its repository on; changes only the prompt |
|
|
70
100
|
|
|
71
|
-
> **
|
|
72
|
-
> Jira ticket
|
|
73
|
-
>
|
|
101
|
+
> **Repository**: not a config field. The target repository is read from the body of each
|
|
102
|
+
> Jira ticket: `owner/repo` or a GitHub URL on GitHub, `group/subgroup/project` or a full
|
|
103
|
+
> URL on GitLab, `workspace/repo` on bitbucket.org.
|
|
74
104
|
|
|
75
105
|
---
|
|
76
106
|
|
|
@@ -142,11 +172,12 @@ The response is `SearchAndReconcileResults`; the script reads the `issues` array
|
|
|
142
172
|
- The Jira project has issues with the label but all are in a Done status category.
|
|
143
173
|
The JQL filter is `statusCategory != Done` - reopen or create a fresh issue.
|
|
144
174
|
|
|
145
|
-
### Conversation started but no PR appears
|
|
175
|
+
### Conversation started but no PR or MR appears
|
|
146
176
|
|
|
147
177
|
- The spawned conversation inherits the user's agent/LLM settings. Check the conversation
|
|
148
178
|
in the OpenHands UI (it appears in the conversations list under the automation run).
|
|
149
|
-
- The
|
|
179
|
+
- The connected integration or token may lack the scope to push or open the request
|
|
180
|
+
(GitHub `repo`, GitLab `api` with the Developer role).
|
|
150
181
|
- The target repo's default branch may be protected; the token must have bypass permission,
|
|
151
182
|
or the PR should be created against a different base branch.
|
|
152
183
|
|
|
@@ -166,13 +197,13 @@ The response is `SearchAndReconcileResults`; the script reads the `issues` array
|
|
|
166
197
|
|
|
167
198
|
## Multiple Deployments
|
|
168
199
|
|
|
169
|
-
To watch multiple Jira projects or multiple
|
|
200
|
+
To watch multiple Jira projects or multiple repositories, deploy separate automations —
|
|
170
201
|
one per `config.json`. Each automation has its own KV-store namespace (keyed by
|
|
171
202
|
automation ID), so processed-key sets do not cross-contaminate.
|
|
172
203
|
|
|
173
204
|
Example: two automations, one per project:
|
|
174
205
|
|
|
175
|
-
| Automation name | `jira_base_url` | `jira_label` |
|
|
206
|
+
| Automation name | `jira_base_url` | `jira_label` | Repository (in ticket body) |
|
|
176
207
|
|---|---|---|---|
|
|
177
208
|
| `Jira issue-to-PR - frontend` | `https://acme.atlassian.net` | `create-pr` | `acme/frontend` (written by ticket author) |
|
|
178
209
|
| `Jira issue-to-PR - backend` | `https://acme.atlassian.net` | `create-pr-backend` | `acme/backend` (written by ticket author) |
|