Jira Release Reporting
Provision the credential that lets a release tell Jira what shipped, and run the one-time cutover that put every deploy job back on a single Environment per tier.
Canonical sources. .github/scripts/report-jira-deployment.ts is the reporter, .github/scripts/jira-environment.ts declares each environment's Jira type and the site's cloud id, and .github/actions/record-deployment/action.yml is what calls them. This runbook is the HOWTO for the parts that live outside the repo.
TL;DR
Jira used to guess. Its GitHub integration read Deployment records as a release timeline, so a phantom record from a cancelled run silently dropped issues from the next release's window.
The release states its own contents. Version, environment type and issue keys are POSTed to Jira explicitly, so no window is inferred and no record can move one.
Nothing breaks. With no credential the reporting step warns and exits 0. Deploys are unaffected; only the Jira release panel goes unpopulated.
Cutover order — and why it is not negotiable
The trust-policy change NARROWS what each deploy role admits, from two OIDC subjects per tier down to one. Applying it before the workflow bindings are live leaves every deploy job presenting a subject the policy no longer trusts, which fails closed on AssumeRoleWithWebIdentity — the same break this whole change came out of, in the opposite direction.
Merge the PR first. This puts the workflow bindings back on the bare <env> Environment, which every deploy role already trusts. Nothing breaks at this point because the trust policy still admits both subjects — the old parallel one is simply unused from here on.
Instructions for the Jira site admin
Hand this section over verbatim. It needs Jira site admin, takes about two minutes, and grants nothing beyond writing DevOps metadata.
What this is. A system-to-system OAuth credential that lets our GitHub Actions release pipeline post deployment records to Jira. It is not associated with any Jira user account, cannot read or modify issues, and continues working regardless of user changes.
- In Jira Cloud, select the gear icon (Settings).
- Choose Marketplace apps.
- In the left sidebar, select OAuth credentials.
- Select Create credentials.
- Fill the form:
- App name —
OnRamp GitHub Actions release reporting - Data Center base URL —
https://github.com/OnRampTech/main-web-application - Logo URL — optional; leave blank or use any GitHub icon URL.
- Permissions — grant Deployments only. Do not grant Builds, Development information, or Feature flags; the pipeline does not call those APIs and the credential should not be able to.
- App name —
- Select Create.
- Copy the client ID and client secret and send them to the requester through a secret-sharing channel — not Slack, not email.
Permissions can be changed later from the credential's ⋯ Actions menu → Edit permissions, so an over-broad grant is fixable without recreating it.
Treat the secret as show-once. Atlassian's docs do not state whether the client secret can be re-read after creation, so assume it cannot. If it is lost, delete the credential and create a new one rather than hunting for it.
Rotation
The credential has no expiry, so rotation is only for suspected exposure or routine hygiene. It is a straight replace with no coordination needed:
- Admin creates a NEW credential per the steps above.
- Update both repository secrets to the new pair.
- Admin deletes the old credential.
Order matters only in that step 3 comes last. Reporting is best-effort, so even a window where both are briefly wrong costs warnings in a deploy log and nothing else.
Troubleshooting
| Log line | Cause | Fix |
|---|---|---|
JIRA_CLIENT_ID / JIRA_CLIENT_SECRET not set — skipping | Secrets absent | Steps 4–5 above |
Jira token request failed: HTTP 401 | Wrong or revoked credential | Rotate; confirm both secrets came from the same credential |
Jira accepted 0, rejected 1 | Payload refused | Read the quoted message — usually an empty issueKeys, which the script already guards |
unknown issue keys: ONRAMP-… | Key in a commit message does not exist in Jira | Usually a typo in a commit; harmless, the rest still associate |
no Jira environment type declared for "X" | A new environment reached record-deployment | Add it to JIRA_ENVIRONMENT_TYPE in .github/scripts/jira-environment.ts |
No ONRAMP issue keys in this release's commit range | Genuinely no keys, or a shallow clone | The action deepens history itself; if it persists, the range really is keyless |
Could not find <env>'s previous release in N deployment records | The previous rollout record is further back than MAX_HISTORY_PAGES pages of deployment history | Deliberate: reporting nothing beats reporting a window that would be wrong. Usually means an unusual burst of out-of-band deploys — raise MAX_HISTORY_PAGES in report-jira-deployment.ts if it recurs |
Never make the reporting step fail a release. Every failure path in report-jira-deployment.ts warns and exits 0 on purpose. A release that shipped must not be reported as failed because a metadata call did not land.