Skip to content

fix(cloud-manager-client): build BYOG PR URLs (Azure/Bitbucket) + hostname detection + retry-once#1793

Merged
rpapani merged 8 commits into
mainfrom
fix/cm-client-pr-url-azure-bitbucket
Jul 16, 2026
Merged

fix(cloud-manager-client): build BYOG PR URLs (Azure/Bitbucket) + hostname detection + retry-once#1793
rpapani merged 8 commits into
mainfrom
fix/cm-client-pr-url-azure-bitbucket

Conversation

@rpapani

@rpapani rpapani commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Problem

CloudManagerClient#createPullRequest only constructed a pullRequestUrl for GitHub and GitLab. For Azure DevOps and Bitbucket BYOG repos it returned null, so pullRequestUrl was never set — even though the CM Repo API had created the PR (and returned its externalNumber). Downstream, the ASO UI showed no "View PR" link for those repos. Separately, PR creation had no resilience to transient CM-API blips.

Changes

  1. Azure DevOps + Bitbucket PR URLs. Added path templates: Azure DevOps /pullrequest/{n} (dev.azure.com, *.visualstudio.com), Bitbucket Cloud /pull-requests/{n} (bitbucket.org). Unknown hosts still return null.
  2. Hostname-based provider detection. Provider is now detected from the parsed hostname (extractRepoHost via URL()), not a substring match on the whole URL — so a provider domain appearing in the repo path (e.g. bitbucket.org/team/github.com-mirror) can't be misclassified. (Addresses review feedback.)
  3. Retry PR creation once on transient failure. createPullRequest retries a single time after a short delay on a transient failure (5xx / 429 / network error); permanent 4xx failures throw immediately.

Tests

Unit tests for all four providers (incl. legacy visualstudio.com), the path-false-positive case, an unparseable repoUrl, and the retry paths (transient-then-success, network error, two-consecutive-failures). Package stays at 100% coverage.

Related PRs (cross-repo)

  • adobe/spacecat-autofix-worker#666 — consumes this client; CWV code-patch fix lifecycle.
  • OneAdobe/experience-success-studio-ui#2093 — ASO UI Deployed-tab.

🤖 Generated with Claude Code

rpapani and others added 2 commits July 8, 2026 11:32
`createPullRequest` constructed a pullRequestUrl only for GitHub and
GitLab; for Azure DevOps and Bitbucket BYOG repos the provider detection
fell through to null, so `pullRequestUrl` was never set even though the CM
Repo API had actually created the PR (and returned its externalNumber).
Downstream (spacecat-autofix-worker CodeRepoManager) then stored an empty
`changeDetails.pullRequestUrl`, so the CWV "Deployed" tab showed no
"View PR" link for those repos.

Add path templates + host detection for:
  - Azure DevOps (dev.azure.com / *.visualstudio.com) -> /pullrequest/{n}
  - Bitbucket Cloud (bitbucket.org)                    -> /pull-requests/{n}

Unknown hosts still return null (unchanged). Adds unit tests for both new
providers and repoints the "unsupported provider" test at a generic host;
package stays at 100% coverage.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

This PR will trigger a patch release when merged.

@rpapani rpapani requested a review from ramboz July 8, 2026 23:44
createPullRequest issued a single POST and threw on any non-2xx, with no
retry — a brief 5xx/429 or network blip from the CM Repo API would fail the
whole autofix PR. Add one retry after a short wait (1.5s) for transient
failures only; permanent failures (4xx other than 429) still throw
immediately. The transient failure + retry is logged (log.warn).

Adds tests for transient-5xx-then-success, network-error-then-success, and
two-consecutive-transient-failures (throws after 2 attempts). Package stays
at 100% coverage.

Co-Authored-By: Claude <noreply@anthropic.com>

@ramboz ramboz left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review: fix(cloud-manager-client): build PR URL for Azure DevOps and Bitbucket

Summary

Adds Azure DevOps + Bitbucket Cloud provider detection and PR/MR path templates to #buildPullRequestUrl, and — not mentioned in the description — wraps the CM PR-creation fetch in a single-retry loop for transient (5xx / 429 / network) failures. The logic is correct, backward-compatible, and well-tested. Ready to merge; the one Should-Fix is doc-only.

This is one half of a cross-repo effort with adobe/spacecat-autofix-worker#666: this client must be released to npm first, then #666 bumps the dep. #666 relies on the new Azure/Bitbucket URL building here so the CWV "View PR" link renders for those BYOG repos, and the retry added here reduces how often #666's "branch pushed, PR failed" path is hit.

Strengths

  • The retry loop is carefully written. Permanent 4xx (except 429) throw immediately; transient 5xx/429 and thrown fetches (network/timeout) retry once; exhaustion throws a distinct ...failed after N attempts message. The if (response && !transient) guard correctly distinguishes a re-thrown permanent HTTP error from a network throw, and every attempt-2 path either breaks or throws — so the loop can never fall through to response.json() with an undefined/non-ok response.
  • #PR_PATH_BY_PROVIDER is a clean frozen lookup table; unknown hosts still return null, so there is no regression for providers CM doesn't map.
  • Good, targeted test coverage: all four providers (incl. legacy visualstudio.com), transient-5xx-then-success, network-error-then-success, and two-transient-then-throw.

Issues

Blockers (Must Fix Before Merge)

None.

Should Fix

S1. PR description + commit subject omit the retry behaviorpackages/spacecat-shared-cloud-manager-client/src/index.js
The title/body only describe the provider URL additions, but the diff also adds a single-retry loop to createPullRequest. That is a real behavior change for all callers of this shared method (eds-csp, accessibility, vulnerabilities, cwv): up to ~1.5s extra latency on a transient failure, plus a changed thrown-error message format (HTTP <status> - ... and ...failed after 2 attempts: ...). Since merging triggers a patch release, the semantic-release changelog — generated from the commit subject — will not mention the retry. Please update the PR body/commit subject so the shipped behavior is captured.
Perspective: Engineering Practices / Product

Nice to Have

N1. The 422 test doesn't guard the no-retry-on-4xx contractpackages/spacecat-shared-cloud-manager-client/test/cloud-manager-client.test.js:1945
it('throws on failed PR creation') uses a single nock interceptor and asserts rejectedWith('Pull request creation failed'). That matcher is a prefix that also matches the retry-exhausted message Pull request creation failed after 2 attempts, and there's no scope.isDone() assertion — so a regression that retried a 4xx would still pass this test. Consider asserting expect(scope.isDone()).to.be.true (proving exactly one request) or matching the exact Pull request creation failed: HTTP 422 message.
Perspective: QA / Testing

N2. Host detection via substring includes() — see inline comment. Pre-existing pattern extended to the new providers; low risk. Noted inline.
Perspective: Architecture

Verdict

Ready to merge: Yes (approving) — address S1 (description) before/at merge so the release notes are accurate.
Reasoning: Correct, backward-compatible, well-tested; the only Should-Fix is documentation of a shipped behavior change.


Note: reviewed against the PR branch with full repo context. I did not execute the test suite locally (monorepo node_modules not installed); relying on CI + static analysis. No downstream code in the sibling repos string-matches the old error message, so the message-format change is safe.

Comment thread packages/spacecat-shared-cloud-manager-client/src/index.js Outdated
rpapani and others added 3 commits July 14, 2026 17:51
…ot full URL

Addresses review feedback (N2): matching provider domains via substring
includes() on the whole repoUrl could misclassify a URL whose *path* contains
another provider's domain (e.g. https://bitbucket.org/team/github.com-mirror).
Parse the hostname with URL() and match on that instead. Behaviour is
unchanged for normal https repo URLs; adds tests for the path false-positive
and an unparseable repoUrl.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rpapani rpapani changed the title fix(cloud-manager-client): build PR URL for Azure DevOps and Bitbucket fix(cloud-manager-client): build BYOG PR URLs (Azure/Bitbucket) + hostname detection + retry-once Jul 15, 2026

@ramboz ramboz left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-approving at e03cc82.

The hostname-detection refactor cleanly closes the earlier N2 (path false-positive): provider is now resolved from the parsed hostname via extractRepoHost/URL(), with tests for both the bitbucket.org/team/github.com-mirror path false-positive and an unparseable repoUrl. Behavior is unchanged for normal https repo URLs. I re-traced the retry control-flow as well — every loop exit lands on either a break (ok response) or a throw, so response.json() never runs on a non-ok/undefined response.

S1 (retry undocumented) is resolved: the PR body + title now describe the retry, and it has its own fix: commit so semantic-release will capture it in the changelog regardless of merge strategy.

No blockers. One optional, non-blocking test-robustness nit left inline (N1).

Comment thread packages/spacecat-shared-cloud-manager-client/test/cloud-manager-client.test.js Outdated
rpapani and others added 2 commits July 15, 2026 17:12
…R-creation test

Addresses ramboz's re-review (N1) on #1793: the previous assertion matched
the prefix 'Pull request creation failed', which also matches the retry-
exhausted message, so a regression that retried a 4xx would still pass.

Now assert the exact permanent-failure message ('Pull request creation
failed: HTTP 422') and `scope.isDone()` — a single interceptor proves no
second request (retry) was attempted on a permanent 4xx.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rpapani rpapani merged commit a6c12a2 into main Jul 16, 2026
5 checks passed
@rpapani rpapani deleted the fix/cm-client-pr-url-azure-bitbucket branch July 16, 2026 01:19
solaris007 pushed a commit that referenced this pull request Jul 16, 2026
## [@adobe/spacecat-shared-cloud-manager-client-v1.4.6](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-cloud-manager-client-v1.4.5...@adobe/spacecat-shared-cloud-manager-client-v1.4.6) (2026-07-16)

### Bug Fixes

* build BYOG PR URLs (Azure/Bitbucket) + hostname detection + retry-once ([#1793](#1793)) ([a6c12a2](a6c12a2))
@solaris007

Copy link
Copy Markdown
Member

🎉 This PR is included in version @adobe/spacecat-shared-cloud-manager-client-v1.4.6 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants