tools/jira-patch/Capability: contract:change-request
Kind: implementation
Vendor: Atlassian
Organization: ASF
JIRA-patch change-request adapter — the backend that lets a JIRA-tracker, SVN-hosted project drive the pr-management-* skills over patches attached to JIRA issues instead of GitHub pull requests. It implements the tools/change-request/ contract for projects whose proposed changes arrive as a .patch file on a JIRA issue and are committed to an SVN trunk.
This adapter owns the proposal lifecycle (the JIRA issue + its attached patch + its comment stream); it does not own the commit. Its land verb delegates the actual apply-and-commit to the project's contract:source-control adapter — svn patch followed by svn commit against svn.apache.org — and then records the landed revision back on the JIRA issue. This split is why change-request and source-control are separate contracts: on an SVN-first project the review gate (JIRA) and the commit substrate (SVN) are two different systems.
The read/write JIRA plumbing is the existing tools/jira/ tracker bridge (JQL search, comment, transition, label, attach). This adapter adds the change-request semantics on top of those verbs; it does not re-implement the JIRA REST client.
tools/jira/ bridge and the tools/asf-svn/ recipes, no local package of its own.jira bridge (JIRA REST over curl) and svn (for the delegated land).list_open/get/get_discussion, write for post_review/reject), plus ASF committer credentials for the SVN commit that land delegates to tools/asf-svn/. The adapter never commits under its own identity — it uses the running committer’s svn auth, exactly as a manual svn commit would, so patch-author-vs-committer attribution is preserved (see Attribution).issues.apache.org/jira) and svn.apache.org for the delegated land.The JIRA-patch backend resolves the change-request as: a JIRA issue carrying a patch attachment is one change proposal. The issue key is the proposal id; the newest .patch/.diff attachment is the diff; the issue's comment stream is the review discussion.
Each change-request verb resolves onto the JIRA + SVN surfaces as follows. The verb names are the contract‘s; the right column is this adapter’s concrete resolution.
| Verb | JIRA-patch resolution |
|---|---|
list_open(filter) | JQL: project = <KEY> AND status = Open AND attachments IS NOT EMPTY (plus the filter's author/component/age narrowers), via jira search. One proposal_summary per issue that carries a patch attachment. |
get(id) | jira issue <KEY> for metadata; download the newest .patch/.diff attachment for the diff. base is the trunk path from change_request.jira_patch.trunk_url; commits is [] (a bare patch has none); mergeable is unknown until an svn patch --dry-run is run. |
get_discussion(id) | The issue's comment stream, normalised to {author, date, body, kind}. A comment carrying the configured approval token maps to kind: approval. |
post_review(id, verdict, body) | jira comment <KEY> --body-file <draft>; the verdict is additionally encoded as a jira transition / jira label move (approve → Reviewed, request-changes → Needs work). |
land(id, strategy) | Delegates to contract:source-control. Fetches the patch via get, calls the source-control adapter's apply + commit (svn patch <file> then svn commit against the trunk working copy — see tools/asf-svn/source-control.md), then transitions the issue to Resolved/Fixed and comments the landed revision. strategy is advisory — SVN applies a patch as a single commit, so squash is the only honoured strategy and the adapter reports that. |
reject(id, reason) | jira transition <KEY> "Won't Fix" (or the configured rejected transition) with reason as a closing comment. No commit — the absence of a land is the rejection. |
status(id) | checks: none, mergeable from an svn patch --dry-run (clean / conflicting). JIRA has no CI gate unless a pipeline is wired to the issue; skills degrade the checks gate to advisory (see the contract's status graceful-degradation note). |
The delegated land preserves patch-author vs. committer attribution the way ASF SVN commits always have: the svn commit runs under the landing committer‘s identity, and the commit message credits the patch author (Patch by <author>. / This closes #<KEY>. per the project’s convention). The adapter reads the patch author from the JIRA issue reporter / attachment uploader and templates it into the commit message; it never impersonates the author‘s SVN identity. This is the answer to #669’s “patch-author vs. committer attribution” open question for the JIRA-patch backend.
Declared under the change-request block in projects/<project>/project.md:
change_request: backend: jira-patch land_via: source-control # land delegates to the VCS adapter review_channel: jira-comment default_strategy: squash # SVN applies a patch as one commit jira_patch: site_url: https://issues.apache.org/jira project_key: <KEY> # the JIRA project the proposals live in trunk_url: https://svn.apache.org/repos/asf/<project>/trunk approval_token: "+1" # comment token that counts as an approval rejected_transition: "Won't Fix" resolved_transition: "Resolved"
site_url / project_key — locate the JIRA project whose patch-bearing issues are the proposals.trunk_url — the SVN trunk the delegated land applies the patch to.approval_token — the comment string get_discussion reads as a kind: approval.rejected_transition / resolved_transition — the JIRA workflow transitions reject and land drive.Backend-specific keys live under change_request.jira_patch.*; the generic keys (backend, land_via, review_channel, default_strategy) are the contract's.
tools/change-request/tools/jira/tools/asf-svn/source-control.md