feat(bitbucket): add bitbucketEmail field to Bitbucket provider settings and update related API and database schema

This commit is contained in:
Mauricio Siu
2025-09-21 13:54:53 -06:00
parent 0a789e1d6f
commit 063d51e442
8 changed files with 6767 additions and 52 deletions

View File

@@ -5,7 +5,10 @@ import type {
apiBitbucketTestConnection,
apiFindBitbucketBranches,
} from "@dokploy/server/db/schema";
import { findBitbucketById } from "@dokploy/server/services/bitbucket";
import {
type Bitbucket,
findBitbucketById,
} from "@dokploy/server/services/bitbucket";
import type { Compose } from "@dokploy/server/services/compose";
import type { InferResultType } from "@dokploy/server/types/with";
import { TRPCError } from "@trpc/server";
@@ -39,16 +42,21 @@ export const getBitbucketCloneUrl = (
: `https://${bitbucketProvider.bitbucketUsername}:${bitbucketProvider.appPassword}@${repoClone}`;
};
export const getBitbucketHeaders = (bitbucketProvider: {
apiToken?: string | null;
bitbucketUsername?: string | null;
appPassword?: string | null;
}) => {
return bitbucketProvider.apiToken
? { Authorization: `Bearer ${bitbucketProvider.apiToken}` }
: {
Authorization: `Basic ${Buffer.from(`${bitbucketProvider.bitbucketUsername}:${bitbucketProvider.appPassword}`).toString("base64")}`,
};
export const getBitbucketHeaders = (bitbucketProvider: Bitbucket) => {
if (bitbucketProvider.apiToken) {
// For API tokens, use HTTP Basic auth with email and token
// According to Bitbucket docs: email:token for API calls
const email =
bitbucketProvider.bitbucketEmail || bitbucketProvider.bitbucketUsername;
return {
Authorization: `Basic ${Buffer.from(`${email}:${bitbucketProvider.apiToken}`).toString("base64")}`,
};
}
// For app passwords, use HTTP Basic auth with username and app password
return {
Authorization: `Basic ${Buffer.from(`${bitbucketProvider.bitbucketUsername}:${bitbucketProvider.appPassword}`).toString("base64")}`,
};
};
export const cloneBitbucketRepository = async (
@@ -305,33 +313,43 @@ export const getBitbucketBranches = async (
}
const bitbucketProvider = await findBitbucketById(input.bitbucketId);
const { owner, repo } = input;
const url = `https://api.bitbucket.org/2.0/repositories/${owner}/${repo}/refs/branches?pagelen=100`;
let url = `https://api.bitbucket.org/2.0/repositories/${owner}/${repo}/refs/branches?pagelen=1`;
let allBranches: {
name: string;
commit: {
sha: string;
};
}[] = [];
try {
const response = await fetch(url, {
method: "GET",
headers: getBitbucketHeaders(bitbucketProvider),
});
if (!response.ok) {
throw new TRPCError({
code: "BAD_REQUEST",
message: `HTTP error! status: ${response.status}`,
while (url) {
const response = await fetch(url, {
method: "GET",
headers: getBitbucketHeaders(bitbucketProvider),
});
if (!response.ok) {
throw new TRPCError({
code: "BAD_REQUEST",
message: `HTTP error! status: ${response.status}`,
});
}
const data = await response.json();
const mappedData = data.values.map((branch: any) => {
return {
name: branch.name,
commit: {
sha: branch.target.hash,
},
};
});
allBranches = allBranches.concat(mappedData);
url = data.next || null;
}
const data = await response.json();
const mappedData = data.values.map((branch: any) => {
return {
name: branch.name,
commit: {
sha: branch.target.hash,
},
};
});
return mappedData as {
return allBranches as {
name: string;
commit: {
sha: string;