Jira GitHub Development-Link Health Check
Pricing
Pay per usage
Jira GitHub Development-Link Health Check
Find missing or stale Jira–GitHub development links. Free read-only scan of one Jira Cloud site + one GitHub org. Detects PRs that never linked and PRs still open in Jira after every matching PR closed. Actionable next steps.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
kjjkjjzyayufqza
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
20 days ago
Last modified
Categories
Share
This free public Apify Actor finds two silent integration failures without Jira or GitHub write access:
- a GitHub pull request contains a Jira key, but Jira reports no development link;
- every matching GitHub pull request is closed, but Jira still reports an open pull request.
After one-time setup, the product is designed to run without routine human labour. An encrypted Task supplies the scope, a schedule starts each run, the Actor proves source completeness, and returns deterministic next actions. The current Store release is free. Invalid input, failed authentication, partial evidence, and provider failure return controlled results instead of false healthy reports.
Version 0.2 supports Jira Cloud, one GitHub organisation, 1–5 repositories, 1–20 Jira projects, and a 1–90 day lookback. Jira Data Center, GitHub personal accounts, GitLab, Azure DevOps, automatic repair, and manual interpretation are outside this version.
Quick start in Apify Console
- Create dedicated read-only Jira and GitHub credentials using the access guidance below.
- Open the Actor's Input page. Each field includes a safe example and explanation. Replace every
your-*,acme-*, andreplace_with_*value; the examples are not real credentials. - Click Start. Read
statusfirst in the Results tab, then follow eachnextActionunderexceptionsorerror. - When the controlled run is correct, save the input as an Apify Task. Confirm Jira email/token and GitHub token remain secret fields.
- Add a UTC schedule to the Task. Scheduled
okandexceptionsruns need no operator action; controlled failures already say what the customer must correct.
The UI examples are validated in the automated test suite so they cannot drift away from runtime input rules.
Copyable input example
This is a scoped Atlassian-token example. Replace all values before starting. For a classic Atlassian API token, remove jiraCloudId. The optional repositories pin is intentionally omitted so the Actor discovers the complete organisation scope automatically.
{"jiraBaseUrl": "https://acme.atlassian.net","jiraCloudId": "123e4567-e89b-42d3-a456-426614174000","jiraEmail": "jira-bot@acme.example","jiraApiToken": "replace_with_your_atlassian_token","jiraProjectKeys": ["ENG", "OPS"],"githubToken": "github_pat_replace_with_your_token","githubOrganization": "acme-engineering","lookbackDays": 30}
| Field | Required | Example | Meaning |
|---|---|---|---|
jiraBaseUrl | Yes | https://acme.atlassian.net | Exact Jira Cloud tenant root. No path, custom domain, port, query, or credentials. |
jiraCloudId | Scoped token only | UUID | Jira cloud UUID used by Atlassian's scoped-token gateway. Leave empty for a classic token. |
jiraEmail | Yes | jira-bot@acme.example | Dedicated Jira account that created the token. Secret; never returned. |
jiraApiToken | Yes | replace_with_… | Read-only Atlassian API token. Secret; no UI prefill/default. |
jiraProjectKeys | Yes | ENG, OPS | 2+ character uppercase alphanumeric allowlist. Referenced keys outside it are reported and never queried. |
githubToken | Yes | github_pat_… | Expiring fine-grained read-only token for organisation metadata and every organisation repository. Other GitHub token types are rejected; secret; no UI prefill/default. |
githubOrganization | Yes | acme-engineering | Organisation login only, not a URL or personal username. |
repositories | No | acme-engineering/backend-api | Leave empty for zero-touch exhaustive discovery. Optionally enter the complete list as a change-control pin; a mismatch is incomplete and uncharged. |
lookbackDays | No | 30 | Recently updated PR window, 1–90 days. Every currently open PR is also read even when older. |
Jira access
Use a dedicated account that can Browse Projects for every configured project and can see relevant issue-security levels. Create an Atlassian API token in Atlassian account settings. A scoped token needs read:jira-work and the Jira cloud UUID; a classic token uses the tenant URL directly. The Actor never needs Jira write or administrator scopes.
Jira may deliberately return the same response for an absent issue and an issue hidden by permissions. The Actor therefore reports jiraKeyNotFoundOrInaccessible instead of claiming a distinction the API cannot prove.
GitHub access
For this public release, create a fine-grained token whose resource owner is the GitHub organisation. The authenticated user must be an organisation owner so GitHub returns the complete private-repository count. Select All repositories, keep the mandatory Metadata: Read, add Pull requests: Read-only, set an expiry, and grant no Contents, Actions, Workflows, or other write permission. GitHub documents that full organisation details require an owner and that listing organisation repositories uses Metadata read; see Get an organization, List organization repositories, and Keeping API credentials secure.
The Actor requires the organisation's declared public/private count to equal the complete API listing. It safely discovers that listing when repositories is empty; an optional supplied list must also match exactly. An empty organisation, a non-owner token that cannot expose the private count, or a token that cannot see even one repository returns INCOMPLETE_SOURCE_EVIDENCE; zero or partial evidence is never labelled healthy or charged. Newly added repositories are discovered on the next run without Task maintenance. A GitHub App is the preferred future organisation-wide credential model, but version 0.2 accepts a token for the private beta.
How to read Results
Open Results — run history for Dataset rows or Latest result — single JSON for automation. Both follow the same documented schema.
status | Completed check | Meaning |
|---|---|---|
ok | Yes | Exhaustive scan completed and found no supported exception. This is not a guarantee that every possible integration failure is absent. |
exceptions | Yes | Exhaustive scan completed and found one or more actionable mismatches. Follow each exception's nextAction. |
incomplete | No | The Actor refused to classify partial evidence or exceeded a declared scan limit. Follow error.nextAction; never interpret this as healthy. |
failed | No | Input, credentials, provider, storage, or another controlled execution path failed. Use error.code for automation. |
Healthy result
{"status": "ok","checkedAt": "2026-07-15T08:30:00.000Z","lookbackStartedAt": "2026-06-15T08:30:00.000Z","exceptions": []}
Completed result with an exception
{"status": "exceptions","checkedAt": "2026-07-15T08:30:00.000Z","lookbackStartedAt": "2026-06-15T08:30:00.000Z","exceptions": [{"jiraKey": "ENG-42","type": "missingDevelopmentLink","nextAction": "Reconnect GitHub for Jira to this repository or correct the Jira key in the pull request.","pullRequests": [{"url": "https://github.com/acme-engineering/backend-api/pull/123","state": "MERGED","updatedAt": "2026-07-14T10:20:30.000Z","mergedAt": "2026-07-14T10:15:00.000Z"}]}]}
Uncharged incomplete result
{"status": "incomplete","checkedAt": "2026-07-15T08:30:00.000Z","error": {"code": "INCOMPLETE_SOURCE_EVIDENCE","nextAction": "Use an organisation owner’s read-only GitHub credential with visibility of every repository, remove or correct any optional repository pin, then run again.","details": {"reason": "repositoryListMismatch","configuredRepositoryCount": 2,"visibleRepositoryCount": 1,"declaredRepositoryCount": 2}}}
Exception meanings
| Type | What the evidence proves | Typical action |
|---|---|---|
missingDevelopmentLink | Jira reports zero PR links for a visible referenced issue. | Restore connector repository access or correct the Jira key in the PR. |
staleOpenDevelopmentLink | Every matching GitHub PR is closed, while Jira still reports an open PR. | Restore connector access and refresh/backfill the PR event. |
jiraKeyRenamed | Jira resolved the referenced key to a different current key. | Update future source references to the current key. |
jiraKeyInaccessible | Jira explicitly denied this issue lookup. | Grant Browse Projects and applicable issue-security access. |
jiraKeyNotFoundOrInaccessible | Jira's response cannot distinguish absent from hidden. | Verify the key and permissions; do not assume deletion. |
jiraKeyOutOfScope | The PR references a project not in jiraProjectKeys. | Add the intended Jira project, or correct/remove the Jira key in the PR. Partial repository selection is not allowed. |
Completeness, limits, and billing
The Actor safely discovers GitHub's full visible organisation listing and proves it equals the declared public/private count both before and after the PR reads. If the optional repository pin is supplied, that must also match exactly. It then resolves historical Jira keys and queries supported Jira development fields only when that bracketed scope is stable. Jira search rows, PR pages, and overlapping PR snapshots must also be unique and internally consistent. Only after classification succeeds does it persist OUTPUT and request the completed-check Dataset event.
Fail-closed limits keep cost and memory predictable: five repositories, 90 lookback days, 100 Jira keys, 2,000 PRs per stream, 5,000 PR rows and key associations per run, 10 MiB per successful response, 50 MiB of successful response data across the run, four HTTP attempts, a 20-second full-response timeout, a 30-second maximum wait, and a 4-minute internal deadline under the 5-minute platform timeout. Raw PR text is discarded page by page. A product limit returns incomplete and is not a completed charge.
This Store release uses Apify's FREE pricing model: completed results have zero Actor charges, while the user's normal Apify platform usage still applies. The code retains a dormant fail-closed pay-per-event boundary for a future, separately announced pricing change. If PPE is ever enabled, its preflight requires exactly one positive-priced event named completed-check, rejects the synthetic default-Dataset-item charge, and refuses source API work when no event capacity remains. Private controlled runs measured approximately USD 0.000214–0.000252 in platform cost, but willingness to pay, acquisition cost, payout setup, and unrelated-user retention are not yet proven. This is technical unit-economics evidence, not a profit forecast.
Jira's supported development JQL exposes issue-level aggregate counts, not the official connector's private event store. Consequently, missingDevelopmentLink means Jira reports zero pull-request links for the referenced issue. If the same Jira issue already has one correctly linked PR, this Actor cannot prove that a different PR using the same key is individually missing. Version 0.2 fails no broader claim than the API evidence supports.
GitHub and Jira do not provide one transactional cross-service snapshot. A result reflects the bounded API responses observed during that run; a PR or repository changed immediately afterward is evaluated on the next scheduled run. If the same PR changes between overlapping recent/open reads, or the organisation scope changes between the before/after proofs, the run returns incomplete instead of deriving a conclusion from inconsistent snapshots.
Following Jira Cloud's development-link rules, candidate keys must use the canonical uppercase form, for example ENG-42; lowercase eng-42 is intentionally not treated as linked evidence. Underscores and other normal branch separators around a valid key are supported, such as feature/ENG-42_release. See Atlassian's development-work reference and project-key rules.
Privacy and security
Output never contains PR titles, PR bodies, branch names, Jira/GitHub response bodies, Jira email, or tokens. It does contain Jira keys and private PR URLs, so Dataset and OUTPUT must remain private. Authenticated redirects are rejected, Jira hosts are allowlisted to first-party Jira Cloud origins, error bodies are discarded, and controlled failures are recursively redacted. Public diagnostic details use a per-code key allowlist; arbitrary input field names, provider prose, and accessor values are never reflected.
Treat any token pasted into chat or another unapproved channel as exposed, regardless of perceived privacy, and rotate it. Read the complete ./SECURITY.md and ./OPERATIONS.md before deployment.
Local development
Node 24 is the reviewed runtime.
npm ci --ignore-scriptsnpm run verifynpm run test:coverage
Install Apify CLI 1.7.1+ to include official schema validation in npm run verify. Local input belongs in Apify local storage or environment state, never in this repository. .gitignore excludes storage/, .env*, credentials, logs, and common local artifacts.
The root github-pr-keys.mjs, jira-devlink-check.mjs, and configure-jira-auth.sh files are retained only as disposable research/regression tools. They are not the hosted customer workflow.
Release history is available in the Actor Changelog. Operators with source access can also review SECURITY.md, OPERATIONS.md, and the private validation records before publication.