Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions apps/server/src/pullRequest/BitbucketPullRequestApi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,25 @@ layer("BitbucketPullRequestApi.layer", (it) => {
}),
);

it.effect(
"reads a removed permissions endpoint that answers 404 as granted rather than failing the merge",
() =>
Effect.gen(function* () {
mockedRequest.mockReturnValue(
Effect.fail(
new BitbucketApi.BitbucketResponseError({
operation: "request",
status: 404,
responseBodyLength: 0,
}),
),
);
const api = yield* BitbucketPullRequestApi.BitbucketPullRequestApi;

assert.isTrue(yield* api.getRepositoryPermission({ repository: "acme/web" }));
}),
);

it.effect("still fails the permission read on a failure that is not the removed endpoint", () =>
Effect.gen(function* () {
mockedRequest.mockReturnValue(
Expand Down
16 changes: 9 additions & 7 deletions apps/server/src/pullRequest/BitbucketPullRequestApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,12 @@ export type BitbucketPullRequestApiError =
/**
* `/user/permissions/repositories` answering CHANGE-2770's removal notice rather than a
* permission — Bitbucket sends this for every account now, not only ones it would have refused.
* Cloud answers 404. The original CHANGE-2770 notice was 410.
*/
function isRepositoryPermissionRemovedError(
error: BitbucketPullRequestApiError,
): error is BitbucketApi.BitbucketResponseError {
return error._tag === "BitbucketResponseError" && error.status === 410;
return error._tag === "BitbucketResponseError" && (error.status === 410 || error.status === 404);
}

/**
Expand Down Expand Up @@ -578,12 +579,13 @@ export const make = Effect.gen(function* () {
// may do, so this endpoint is the one request Bitbucket makes unavoidable. It is asked
// alongside the reads the detail was already making, so it costs no round trip of its own.
//
// Bitbucket permanently removed this endpoint (CHANGE-2770): every account now gets HTTP 410
// in place of an answer, whatever it may do. That is the deprecated-endpoint signal, not a
// permission being refused, so it is read the same way an unreachable read already is
// elsewhere — as a permission that could not be learned, which grants rather than blocks, and
// leaves the actual merge or write to say why if the account may not do it. Any other failure
// (a bad token, a network fault, an unreadable body) still fails as it did before.
// Bitbucket permanently removed this endpoint (CHANGE-2770): every account now gets HTTP 404
// (or 410, from the original removal notice) in place of an answer, whatever it may do. That
// is the deprecated-endpoint signal, not a permission being refused, so it is read the same
// way an unreachable read already is elsewhere — as a permission that could not be learned,
// which grants rather than blocks, and leaves the actual merge or write to say why if the
// account may not do it. Any other failure (a bad token, a network fault, an unreadable body)
// still fails as it did before.
getRepositoryPermission: (input) =>
withRepository(input.repository, () =>
readPage({
Expand Down
Loading