Jira Server / Data Center support (REST v2, PAT/Basic auth, wiki markup)#510
Conversation
…ata Center
Jira Server / Data Center differs from Cloud in payload formats, endpoint
existence, query parameters, pagination, and response shapes — not just
the API version number. Centralize every one of those differences in a
single module instead of scattering deployment ternaries through the
adapter:
- resolveAuthScheme / buildAuthHeader — Cloud pairs an email with an API
token (Basic); Data Center sends a Personal Access Token as Bearer even
when an email happens to be supplied, and a username+password pair as
Basic. An explicit override (from persisted settings) always wins.
- detectJiraDeployment — probes /rest/api/2/serverInfo (present on both
deployments) and falls back to a hostname heuristic
(*.atlassian.net/*.jiracloud.com => Cloud) when the probe is blocked.
- pickUserId / userRefField — Cloud addresses users by accountId; Server/
Data Center by name (falling back to key).
- mapCustomFieldUserRefs — the create-issue form always emits a
user-picker value as { accountId } regardless of deployment; on Data
Center this must become { name } or Jira rejects the write.
- contentToString — Data Center's REST API v2 expects descriptions and
comment bodies as plain strings, not Atlassian Document Format; extracts
plain text from TipTap/ADF JSON, strips HTML, or passes a plain string
through unchanged.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ta Center
The Jira integration was hardcoded for Atlassian Cloud: every call used
/rest/api/3 (Data Center only ships v2), API-key auth was always
Basic email:apiToken (a Data Center PAT must be sent as Bearer), and
users were addressed by accountId (Data Center uses name/key). Result:
HTTP 404/401 against any self-hosted Jira instance.
Using the new jiraDeployment.ts dialect module throughout JiraAdapter:
- Auth: detect the deployment via a v3 /myself probe with
redirect:"manual" (so a Data Center instance that redirects unknown v3
paths to its login page isn't misread as a successful Cloud probe);
any non-OK result falls back to serverInfo detection, then re-resolves
the auth scheme and retries on v2. An explicit deployment override
short-circuits detection entirely.
- Project list: Data Center's GET /project returns a bare array; Cloud's
GET /project/search returns { values: [...] }.
- Create meta: Data Center 9+ removed the classic
createmeta?expand=... endpoint in favor of
/issue/createmeta/{projectKey}/issuetypes/{issueTypeId}, which returns
a differently-shaped paginated { values } response.
- Create/update issue: descriptions and comment bodies are Atlassian
Document Format on Cloud (converting TipTap JSON, HTML, or plain
strings to ADF) and plain strings on Data Center. Reporter, assignee,
and user-picker custom fields are routed through one userRef mapper
instead of being sent as Cloud's { accountId } shape unconditionally.
- Search: Data Center's classic /search paginates via startAt/total;
Cloud's enhanced /search/jql pages via an opaque nextPageToken and
reports isLast instead of a total count. Data Center has no cursor of
its own, so one is synthesized from startAt so callers that only
advance via a page token (bulk project import) don't re-read page 1
forever.
- User search: Data Center's /user/search takes ?username=, not ?query=.
- makeRequest: Jira returns 204 No Content for several write endpoints
(issue update, transition execution) on both deployments; unconditionally
calling response.json() throws "Unexpected end of JSON input" on the
empty body. This was a real, previously-unexercised crash — a
transition would succeed in Jira and then the adapter would throw
immediately after.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The test-connection route carried its own hardcoded Cloud-only probe (fixed /rest/api/3, Basic email:apiToken) — a Data Center instance would always fail here even once the adapter itself supported it, since this route builds its own request rather than going through JiraAdapter. - Mirrors the adapter's detection: a v3 /myself probe with redirect:"manual" (so a Data Center login-page redirect isn't misread as a successful Cloud probe), falling back to serverInfo detection and a v2 retry with the auth scheme re-resolved for the discovered deployment. An explicit settings.deploymentType/authScheme override short-circuits detection. - Accepts all three API-key credential shapes (Cloud email+apiToken, Data Center PAT, Data Center username+password), not just the first. - The search-scope and read-issue capability probes use the correct endpoint per deployment (classic /search vs enhanced /search/jql; correct API version for /issue/picker). - A bare API token with no email that a Cloud serverInfo detection confirms is Cloud now returns an explicit "Jira Cloud requires an email address paired with the API token" error instead of an opaque 401 — the initial scheme guess (Bearer, since no email was paired) can never succeed against Cloud's Basic-only API-key auth. - On success, the route now persists the detected deploymentType and resolved authScheme into the integration's settings, merged fill-missing-only (an already-resolved key always wins, so a later re-test can't flip a working integration's settings). Previously these were only optional and typically never written, so every adapter-cache miss re-ran the full detection probe chain. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Data Center's documented Basic auth flow (username + password) had no
way to reach production: IntegrationConfigForm only had email/apiToken
fields, and IntegrationManager.getAdapter forwarded just
email/apiToken/personalAccessToken into the adapter's authData. The
adapter and test-connection route already accepted a
{ username, password } shape — it just wasn't reachable from the UI.
- IntegrationConfigForm: two new optional fields (Username, Password)
alongside Email/API Token, all now optional since Jira's three
credential shapes (Cloud email+token, Data Center PAT, Data Center
Basic) each use a different subset.
- IntegrationManager.getAdapter forwards credentials.username/password
into authData when present (a no-op for every other provider, which
never populates those keys).
- Docs: new "Jira Server / Data Center" section covering both supported
credential shapes, a Cloud-only callout on the OAuth section, and a
curl example for the Bearer PAT flow.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…US.json Caught during self-review: the previous commit's en-US.json came from a wholesale `git checkout fix/jira-datacenter-494 -- ...` off a branch that predates upstream's magic-link/passwordless sign-in feature, so it silently reverted every "passwordless" key that feature had added. Rebuilt from upstream/main's current file with only the Jira-specific keys layered on top; verified the diff against upstream/main now touches nothing outside the jira integration config strings. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Data Center's description field is Jira Wiki Markup, not unformatted plain text (verified live: a wiki-markup string round-trips to fully rendered HTML — bold, headings, lists, links, code — via Jira's own renderer). The integration was stripping every create/update description down to bare text through contentToString(), silently discarding all formatting a user entered in the rich-text editor. Write side: - Replace contentToString() with adfToWikiMarkup() in jiraDeployment.ts, a serializer that mirrors the adapter's existing ADF->HTML reader: bold/italic/underline/strike/code/link marks, headings, nested and mixed bullet/ordered lists, block quotes, code blocks (with language), horizontal rules, hard breaks, and tables. - JiraAdapter.toServerDescription() routes the editor's TipTap doc (and HTML) through the same tiptapToAdf/htmlToAdf converters already used for Cloud, then serializes to wiki markup; a bare string is already valid wiki markup and passes through unchanged. contentToString() and its extractTextFromNodes() helper are removed (now dead). Read side (so formatting survives the round trip instead of showing raw "*markup*" in TestPlanIt): - getIssue requests expand=renderedFields on Server/DC and prefers Jira's own rendered HTML for the description; getIssueComments does the same via expand=renderedBody. Cloud is untouched — it keeps returning ADF parsed by adfToHtml. Tests: 22 new adfToWikiMarkup unit tests (marks, headings, nested/mixed lists, code blocks, quotes, rules, hard breaks, tables, block separation) plus adapter-level DC tests asserting createIssue/updateIssue emit wiki-markup strings and getIssue/getIssueComments consume rendered HTML. Verified end-to-end against a live Jira DC 10.3.13 instance driving the real adapter (a formatted TipTap description came back as correct rendered HTML). eslint + tsc clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…conversion for descriptions and comments Addresses two review points on the rich-text change: 1. The wiki-markup serializer was a large, self-contained concern living in jiraDeployment.ts (which is about Cloud-vs-DC dialect decisions). Moved adfToWikiMarkup + its helpers to a dedicated jiraWikiMarkup.ts (with jiraWikiMarkup.test.ts), leaving jiraDeployment.ts focused on detection/auth/user-ref concerns. 2. Rich text is not description-only — issue comment bodies use the same wiki-markup (DC) / ADF (Cloud) grammar. The conversion was duplicated: createIssue and updateIssue each carried an identical ~35-line description block, and addComment had its own separate inline body construction. Unified all three onto one deployment-aware toJiraContent(input) helper (Server/DC -> wiki markup string, Cloud -> ADF doc, handling TipTap/HTML/plain input and empty values). Comments now go through the same pipeline, so they're no longer the one rich-text field silently limited to plain text. Behavior is unchanged for every current caller: descriptions convert exactly as before (unit assertions pin the wiki-markup output), and addComment's sole caller (linkToTestCase) passes plain text, which converts to itself on DC and a single ADF paragraph on Cloud — identical to the previous hand-built body. Verified: 131 unit tests green (dialect + wiki-markup + adapter); live end-to-end against Jira DC 10.3.13 — a formatted TipTap description and a comment both round-trip correctly through toJiraContent. eslint + tsc clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rich text on Server/DC is emitted as Jira Wiki Markup, which assumes the Description/Comment fields use the default Wiki Style Renderer. A field switched to the Default Text Renderer would show literal markup; Jira exposes no renderer in createmeta/editmeta so it can't be auto-detected, and the plain-text-renderer config is uncommon with a cosmetic, admin-fixable failure mode — so we assume the wiki renderer and document it rather than adding a setting. - jiraWikiMarkup.ts: note the renderer assumption, and clarify it's distinct from the per-user "Rich Text Editing" (WYSIWYG) preference, which does not affect the stored format. - integrations.md: user-facing note in the Server/DC section on rich-text support and how to fix a field stuck on the Default Text Renderer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Jira Server / Data Center work added six new form strings (username/password labels, placeholders, help texts) and rewrote four existing ones (email/API-token help, Jira URL placeholder/help) — but only in en-US.json. Every other locale rendered raw i18n keys for the new fields (admin.integrations.config.username, ...Placeholder, etc.) and stale pre-DC guidance for the changed ones. Caught during UAT on a ru-RU session. Adds translations for all six new keys and updates the four changed ones across the 15 non-source locales, matching each file's existing terminology (ru «API-токен» / «Введите свой…», zh-CN 帐户/令牌, zh-TW 帳戶/權杖 with 產生/設定, tr «belirteç», vi «mã thông báo», de Sie-form with „…“ quotes, pl «Twojego konta», etc.). Technical tokens (Jira Server / Data Center, Jira Cloud, Basic, Bearer, PAT) stay untranslated, as elsewhere in these files. ar-SA's Jira config section is untranslated English in the source file, so its new strings follow that existing state rather than introducing lone Arabic entries. Keys are inserted at the same position as in en-US (after apiTokenHelp), so every locale's config block stays structurally identical to the source — verified: key set AND order now match en-US in all 15 files, all files parse, and the diff is exactly the intended 10 lines per file (whole-file JSON round-trip proven byte-identical before rewriting). Note for upstreaming: upstream localizes via Crowdin (crowdin-sync workflow), which may retranslate these — these entries make the fork usable in non-English locales now and serve as seeds/suggestions for Crowdin later. IntegrationConfigForm + i18n tests: 29/29 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@shokurov Thanks for this — the dialect module and the live DC 10.3.13 validation (PAT + Basic, rich-text round-trip) make this a much stronger footing than testing against mocks alone. A few small items before merge, all minor: 1. In if (projectKey && !isEmail) {
// still query= on server
endpoint = `/rest/api/${this.apiVersion}/user/assignable/search?project=${projectKey}&query=${encodeURIComponent(query)}&startAt=${startAt}&maxResults=${maxResults}`;
} else {
// fixed
endpoint = `/rest/api/${this.apiVersion}/user/search?${this.deployment === "server" ? "username" : "query"}=${encodeURIComponent(query)}&...`;
}On Server/DC, const userParam = this.deployment === "server" ? "username" : "query";
endpoint = `/rest/api/${this.apiVersion}/user/assignable/search?project=${projectKey}&${userParam}=${encodeURIComponent(query)}&startAt=${startAt}&maxResults=${maxResults}`;(If your DC version happens to accept 2. Dead branch in the v3 probe flow (cosmetic) In both if (v3Probe.ok) { … }
else if (!v3Probe.ok) { … } // always true when reached
else { connection = v3Probe } // unreachableSince 3. The "opaque redirect (non-OK, status 0)" comment and the Everything else looks good to merge. One non-blocking question: I noticed the createmeta path is 9+/ |
|
https://github.com/TestPlanIt/testplanit/actions/runs/29085381733/job/86366369049 failed. Please run prettier on the branch so this passes next time. |
Review follow-ups for PR TestPlanIt#510: - /user/assignable/search: send username= instead of the Cloud-only query= param on Server/DC. Verified live on DC 10.3.13: query= is silently ignored (returns the full unfiltered assignable list, even for a term matching nothing), username= filters correctly. Covered by a new unit test. - Collapse the unreachable else branches in the v3 probe flows of JiraAdapter.authenticate and testJiraConnection (v3Probe.ok is boolean, so if/else-if(!ok)/else had a dead tail). - Reword the redirect: "manual" comments and test mock to describe server-side (undici) semantics: the probe sees the real 3xx response (non-OK), not a browser-style opaque status-0 response. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Formatting-only; fixes the failed format check in CI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@therealbrad Thanks for the careful read — all items addressed in dd91f31 + 55ead7b. 1. Confirmed on live DC 10.3.13: 2. Dead 3. Reworded the Re createmeta: yes, dropping the 8.x classic-createmeta fallback was deliberate — Jira 8.x is EOL, and the 9+ CI: prettier run on the branch (the |
|
🎉 This PR is included in version 0.41.6 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
…, wiki markup) (#510) * feat(jira): add a per-deployment dialect module for Cloud vs Server/Data Center Jira Server / Data Center differs from Cloud in payload formats, endpoint existence, query parameters, pagination, and response shapes — not just the API version number. Centralize every one of those differences in a single module instead of scattering deployment ternaries through the adapter: - resolveAuthScheme / buildAuthHeader — Cloud pairs an email with an API token (Basic); Data Center sends a Personal Access Token as Bearer even when an email happens to be supplied, and a username+password pair as Basic. An explicit override (from persisted settings) always wins. - detectJiraDeployment — probes /rest/api/2/serverInfo (present on both deployments) and falls back to a hostname heuristic (*.atlassian.net/*.jiracloud.com => Cloud) when the probe is blocked. - pickUserId / userRefField — Cloud addresses users by accountId; Server/ Data Center by name (falling back to key). - mapCustomFieldUserRefs — the create-issue form always emits a user-picker value as { accountId } regardless of deployment; on Data Center this must become { name } or Jira rejects the write. - contentToString — Data Center's REST API v2 expects descriptions and comment bodies as plain strings, not Atlassian Document Format; extracts plain text from TipTap/ADF JSON, strips HTML, or passes a plain string through unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(jira): dialect-aware endpoints, auth, and user refs for Server/Data Center The Jira integration was hardcoded for Atlassian Cloud: every call used /rest/api/3 (Data Center only ships v2), API-key auth was always Basic email:apiToken (a Data Center PAT must be sent as Bearer), and users were addressed by accountId (Data Center uses name/key). Result: HTTP 404/401 against any self-hosted Jira instance. Using the new jiraDeployment.ts dialect module throughout JiraAdapter: - Auth: detect the deployment via a v3 /myself probe with redirect:"manual" (so a Data Center instance that redirects unknown v3 paths to its login page isn't misread as a successful Cloud probe); any non-OK result falls back to serverInfo detection, then re-resolves the auth scheme and retries on v2. An explicit deployment override short-circuits detection entirely. - Project list: Data Center's GET /project returns a bare array; Cloud's GET /project/search returns { values: [...] }. - Create meta: Data Center 9+ removed the classic createmeta?expand=... endpoint in favor of /issue/createmeta/{projectKey}/issuetypes/{issueTypeId}, which returns a differently-shaped paginated { values } response. - Create/update issue: descriptions and comment bodies are Atlassian Document Format on Cloud (converting TipTap JSON, HTML, or plain strings to ADF) and plain strings on Data Center. Reporter, assignee, and user-picker custom fields are routed through one userRef mapper instead of being sent as Cloud's { accountId } shape unconditionally. - Search: Data Center's classic /search paginates via startAt/total; Cloud's enhanced /search/jql pages via an opaque nextPageToken and reports isLast instead of a total count. Data Center has no cursor of its own, so one is synthesized from startAt so callers that only advance via a page token (bulk project import) don't re-read page 1 forever. - User search: Data Center's /user/search takes ?username=, not ?query=. - makeRequest: Jira returns 204 No Content for several write endpoints (issue update, transition execution) on both deployments; unconditionally calling response.json() throws "Unexpected end of JSON input" on the empty body. This was a real, previously-unexercised crash — a transition would succeed in Jira and then the adapter would throw immediately after. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(jira): detect and persist deployment/auth scheme in test-connection The test-connection route carried its own hardcoded Cloud-only probe (fixed /rest/api/3, Basic email:apiToken) — a Data Center instance would always fail here even once the adapter itself supported it, since this route builds its own request rather than going through JiraAdapter. - Mirrors the adapter's detection: a v3 /myself probe with redirect:"manual" (so a Data Center login-page redirect isn't misread as a successful Cloud probe), falling back to serverInfo detection and a v2 retry with the auth scheme re-resolved for the discovered deployment. An explicit settings.deploymentType/authScheme override short-circuits detection. - Accepts all three API-key credential shapes (Cloud email+apiToken, Data Center PAT, Data Center username+password), not just the first. - The search-scope and read-issue capability probes use the correct endpoint per deployment (classic /search vs enhanced /search/jql; correct API version for /issue/picker). - A bare API token with no email that a Cloud serverInfo detection confirms is Cloud now returns an explicit "Jira Cloud requires an email address paired with the API token" error instead of an opaque 401 — the initial scheme guess (Bearer, since no email was paired) can never succeed against Cloud's Basic-only API-key auth. - On success, the route now persists the detected deploymentType and resolved authScheme into the integration's settings, merged fill-missing-only (an already-resolved key always wins, so a later re-test can't flip a working integration's settings). Previously these were only optional and typically never written, so every adapter-cache miss re-ran the full detection probe chain. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat(jira): add Username/Password fields for Data Center Basic auth Data Center's documented Basic auth flow (username + password) had no way to reach production: IntegrationConfigForm only had email/apiToken fields, and IntegrationManager.getAdapter forwarded just email/apiToken/personalAccessToken into the adapter's authData. The adapter and test-connection route already accepted a { username, password } shape — it just wasn't reachable from the UI. - IntegrationConfigForm: two new optional fields (Username, Password) alongside Email/API Token, all now optional since Jira's three credential shapes (Cloud email+token, Data Center PAT, Data Center Basic) each use a different subset. - IntegrationManager.getAdapter forwards credentials.username/password into authData when present (a no-op for every other provider, which never populates those keys). - Docs: new "Jira Server / Data Center" section covering both supported credential shapes, a Cloud-only callout on the OAuth section, and a curl example for the Bearer PAT flow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(jira): stop reverting upstream's passwordless i18n strings in en-US.json Caught during self-review: the previous commit's en-US.json came from a wholesale `git checkout fix/jira-datacenter-494 -- ...` off a branch that predates upstream's magic-link/passwordless sign-in feature, so it silently reverted every "passwordless" key that feature had added. Rebuilt from upstream/main's current file with only the Jira-specific keys layered on top; verified the diff against upstream/main now touches nothing outside the jira integration config strings. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(jira): preserve rich text on Server/Data Center via Jira Wiki Markup Data Center's description field is Jira Wiki Markup, not unformatted plain text (verified live: a wiki-markup string round-trips to fully rendered HTML — bold, headings, lists, links, code — via Jira's own renderer). The integration was stripping every create/update description down to bare text through contentToString(), silently discarding all formatting a user entered in the rich-text editor. Write side: - Replace contentToString() with adfToWikiMarkup() in jiraDeployment.ts, a serializer that mirrors the adapter's existing ADF->HTML reader: bold/italic/underline/strike/code/link marks, headings, nested and mixed bullet/ordered lists, block quotes, code blocks (with language), horizontal rules, hard breaks, and tables. - JiraAdapter.toServerDescription() routes the editor's TipTap doc (and HTML) through the same tiptapToAdf/htmlToAdf converters already used for Cloud, then serializes to wiki markup; a bare string is already valid wiki markup and passes through unchanged. contentToString() and its extractTextFromNodes() helper are removed (now dead). Read side (so formatting survives the round trip instead of showing raw "*markup*" in TestPlanIt): - getIssue requests expand=renderedFields on Server/DC and prefers Jira's own rendered HTML for the description; getIssueComments does the same via expand=renderedBody. Cloud is untouched — it keeps returning ADF parsed by adfToHtml. Tests: 22 new adfToWikiMarkup unit tests (marks, headings, nested/mixed lists, code blocks, quotes, rules, hard breaks, tables, block separation) plus adapter-level DC tests asserting createIssue/updateIssue emit wiki-markup strings and getIssue/getIssueComments consume rendered HTML. Verified end-to-end against a live Jira DC 10.3.13 instance driving the real adapter (a formatted TipTap description came back as correct rendered HTML). eslint + tsc clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(jira): extract wiki markup to its own module; unify content conversion for descriptions and comments Addresses two review points on the rich-text change: 1. The wiki-markup serializer was a large, self-contained concern living in jiraDeployment.ts (which is about Cloud-vs-DC dialect decisions). Moved adfToWikiMarkup + its helpers to a dedicated jiraWikiMarkup.ts (with jiraWikiMarkup.test.ts), leaving jiraDeployment.ts focused on detection/auth/user-ref concerns. 2. Rich text is not description-only — issue comment bodies use the same wiki-markup (DC) / ADF (Cloud) grammar. The conversion was duplicated: createIssue and updateIssue each carried an identical ~35-line description block, and addComment had its own separate inline body construction. Unified all three onto one deployment-aware toJiraContent(input) helper (Server/DC -> wiki markup string, Cloud -> ADF doc, handling TipTap/HTML/plain input and empty values). Comments now go through the same pipeline, so they're no longer the one rich-text field silently limited to plain text. Behavior is unchanged for every current caller: descriptions convert exactly as before (unit assertions pin the wiki-markup output), and addComment's sole caller (linkToTestCase) passes plain text, which converts to itself on DC and a single ADF paragraph on Cloud — identical to the previous hand-built body. Verified: 131 unit tests green (dialect + wiki-markup + adapter); live end-to-end against Jira DC 10.3.13 — a formatted TipTap description and a comment both round-trip correctly through toJiraContent. eslint + tsc clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(jira): document the Wiki Style Renderer assumption for DC rich text Rich text on Server/DC is emitted as Jira Wiki Markup, which assumes the Description/Comment fields use the default Wiki Style Renderer. A field switched to the Default Text Renderer would show literal markup; Jira exposes no renderer in createmeta/editmeta so it can't be auto-detected, and the plain-text-renderer config is uncommon with a cosmetic, admin-fixable failure mode — so we assume the wiki renderer and document it rather than adding a setting. - jiraWikiMarkup.ts: note the renderer assumption, and clarify it's distinct from the per-user "Rich Text Editing" (WYSIWYG) preference, which does not affect the stored format. - integrations.md: user-facing note in the Server/DC section on rich-text support and how to fix a field stuck on the Default Text Renderer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * i18n(jira): localize the Data Center auth strings in all 15 locales The Jira Server / Data Center work added six new form strings (username/password labels, placeholders, help texts) and rewrote four existing ones (email/API-token help, Jira URL placeholder/help) — but only in en-US.json. Every other locale rendered raw i18n keys for the new fields (admin.integrations.config.username, ...Placeholder, etc.) and stale pre-DC guidance for the changed ones. Caught during UAT on a ru-RU session. Adds translations for all six new keys and updates the four changed ones across the 15 non-source locales, matching each file's existing terminology (ru «API-токен» / «Введите свой…», zh-CN 帐户/令牌, zh-TW 帳戶/權杖 with 產生/設定, tr «belirteç», vi «mã thông báo», de Sie-form with „…“ quotes, pl «Twojego konta», etc.). Technical tokens (Jira Server / Data Center, Jira Cloud, Basic, Bearer, PAT) stay untranslated, as elsewhere in these files. ar-SA's Jira config section is untranslated English in the source file, so its new strings follow that existing state rather than introducing lone Arabic entries. Keys are inserted at the same position as in en-US (after apiTokenHelp), so every locale's config block stays structurally identical to the source — verified: key set AND order now match en-US in all 15 files, all files parse, and the diff is exactly the intended 10 lines per file (whole-file JSON round-trip proven byte-identical before rewriting). Note for upstreaming: upstream localizes via Crowdin (crowdin-sync workflow), which may retranslate these — these entries make the fork usable in non-English locales now and serve as seeds/suggestions for Crowdin later. IntegrationConfigForm + i18n tests: 29/29 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(jira): filter assignable user search by username= on Server/DC Review follow-ups for PR #510: - /user/assignable/search: send username= instead of the Cloud-only query= param on Server/DC. Verified live on DC 10.3.13: query= is silently ignored (returns the full unfiltered assignable list, even for a term matching nothing), username= filters correctly. Covered by a new unit test. - Collapse the unreachable else branches in the v3 probe flows of JiraAdapter.authenticate and testJiraConnection (v3Probe.ok is boolean, so if/else-if(!ok)/else had a dead tail). - Reword the redirect: "manual" comments and test mock to describe server-side (undici) semantics: the probe sees the real 3xx response (non-OK), not a browser-style opaque status-0 response. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * style: run prettier on the jira-server-datacenter branch Formatting-only; fixes the failed format check in CI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Egor Shokurov <egors@rapidsoft.ru> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
## [0.41.6](TestPlanIt/testplanit@v0.41.5...v0.41.6) (2026-07-10) ### Bug Fixes * **jira:** Jira Server / Data Center support (REST v2, PAT/Basic auth, wiki markup) ([TestPlanIt#510](TestPlanIt#510)) ([c18d812](TestPlanIt@c18d812))
Summary
Makes the Jira integration work against self-hosted Jira Server / Data Center
instances (closes #494).
Previously the integration was hardcoded for Atlassian Cloud: every call used
/rest/api/3(Data Center only ships v2), API-key auth was alwaysBasic email:apiToken(a DC PAT must be sent asBearer), users were addressedby
accountId(DC usesname/key), and descriptions were written as ADF(DC expects Jira Wiki Markup). Any self-hosted instance failed with 404/401 on
the very first probe.
What changed
jiraDeployment.ts— centralizes every Cloud vsServer/DC difference instead of scattering ternaries through the adapter:
deployment detection (
serverInfoprobe + hostname heuristic fallback),auth-scheme resolution (Cloud
Basic email:apiToken; DCBearerPAT — evenwhen an email is supplied — or
Basic username:password), user refs(
accountIdvsname/key), and user-picker custom-field remapping.JiraAdapter: dialect-aware endpoints — v3 vs v2 paths, DC's bare-arrayGET /projectvs Cloud's{ values }from/project/search, classic/searchvs enhanced/search/jql, createmeta differences for DC 9+.Deployment detection uses a v3
/myselfprobe withredirect: "manual"so aDC instance that 302-redirects unknown v3 paths to its login page isn't
misread as a healthy Cloud endpoint; the resolved deployment/auth scheme is
persisted in integration settings, so detection is a one-time event.
credential shapes, probes the correct per-deployment endpoints, and persists
the resolved
deploymentType/authScheme(fill-missing-only, so a re-testnever flips a working integration).
jiraWikiMarkup.tsserializes the editor'sADF to Jira Wiki Markup (marks, headings, lists, quotes, code blocks, tables)
instead of stripping descriptions/comments to plain text; the ADF path is
unchanged for Cloud.
accepted that shape but the form couldn't produce it), plus docs for both DC
credential flows.
15 non-source locales.
Testing
test-connection route (330), deployment detection/auth resolution (213), and
the wiki-markup serializer (179).
username/password flows): connection test, JQL search, issue read, and
rich-text round-trip (wiki markup renders bold/headings/lists/links/code via
Jira's own renderer).
routed through the dialect module; existing Cloud tests pass.
Notes for reviewers
it can be unit-tested exhaustively;
JiraAdapterand the test-connectionroute share it rather than duplicating detection.
zenstack generatememory fix.Type of Change
How Has This Been Tested?
Describe the tests you ran to verify your changes:
Test Configuration:
Checklist
Screenshots (if applicable)