chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
import { type PrismaClient } from "@trigger.dev/database";
|
||||
import { prisma } from "~/db.server";
|
||||
import { logger } from "./logger.server";
|
||||
import { nanoid } from "nanoid";
|
||||
import { controlPlaneResolver } from "~/v3/runOpsMigration/controlPlaneResolver.server";
|
||||
|
||||
export class ArchiveBranchService {
|
||||
#prismaClient: PrismaClient;
|
||||
|
||||
constructor(prismaClient: PrismaClient = prisma) {
|
||||
this.#prismaClient = prismaClient;
|
||||
}
|
||||
|
||||
public async call(
|
||||
// The orgFilter approach is not ideal but we need to keep it this way for now because of how the service is used in routes and api endpoints.
|
||||
// Currently authorization checks are spread across the controller/route layer and the service layer. Often we check in multiple places for org/project membership.
|
||||
// Ideally we would take care of both the authentication and authorization checks in the controllers and routes.
|
||||
// That would unify how we handle authorization and org/project membership checks. Also it would make the service layer queries simpler.
|
||||
orgFilter:
|
||||
| { type: "userMembership"; userId: string }
|
||||
| { type: "orgId"; organizationId: string },
|
||||
{
|
||||
environmentId,
|
||||
}: {
|
||||
environmentId: string;
|
||||
}
|
||||
) {
|
||||
try {
|
||||
const environment = await this.#prismaClient.runtimeEnvironment.findFirstOrThrow({
|
||||
where: {
|
||||
id: environmentId,
|
||||
organization:
|
||||
orgFilter.type === "userMembership"
|
||||
? {
|
||||
members: {
|
||||
some: {
|
||||
userId: orgFilter.userId,
|
||||
},
|
||||
},
|
||||
}
|
||||
: { id: orgFilter.organizationId },
|
||||
// Dev branches are per-org-member, so org membership alone isn't enough:
|
||||
// only the owner may archive their own dev branch. Non-dev branches (e.g.
|
||||
// preview) remain scoped by org membership only.
|
||||
...(orgFilter.type === "userMembership"
|
||||
? {
|
||||
OR: [
|
||||
{ type: { not: "DEVELOPMENT" as const } },
|
||||
{ orgMember: { userId: orgFilter.userId } },
|
||||
],
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
include: {
|
||||
organization: {
|
||||
select: {
|
||||
id: true,
|
||||
slug: true,
|
||||
maximumConcurrencyLimit: true,
|
||||
},
|
||||
},
|
||||
project: {
|
||||
select: {
|
||||
id: true,
|
||||
slug: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// A branch is defined by having a parent; any root (dev/preview parent,
|
||||
// prod, staging) has none and can't be archived. For dev, that root is
|
||||
// the default branch, so give the clearer message.
|
||||
if (!environment.parentEnvironmentId) {
|
||||
return {
|
||||
success: false as const,
|
||||
error:
|
||||
environment.type === "DEVELOPMENT"
|
||||
? "The default development branch cannot be archived."
|
||||
: "This isn't a branch, and cannot be archived.",
|
||||
};
|
||||
}
|
||||
|
||||
// Branch archive is a SOFT update — do NOT hard-delete run-ops rows here (it would destroy a
|
||||
// retained branch's history). Any env hard-delete/purge belongs on a dedicated purge path
|
||||
// (owned by the cloud env-purge runbook), which has no site today.
|
||||
const slug = `${environment.slug}-${nanoid(6)}`;
|
||||
const shortcode = slug;
|
||||
|
||||
const updatedBranch = await this.#prismaClient.runtimeEnvironment.update({
|
||||
where: { id: environmentId },
|
||||
data: { archivedAt: new Date(), slug, shortcode },
|
||||
});
|
||||
|
||||
// archivedAt/slug/shortcode changed in the control-plane; drop any cached copy.
|
||||
controlPlaneResolver.invalidateEnvironment(environmentId);
|
||||
|
||||
return {
|
||||
success: true as const,
|
||||
branch: updatedBranch,
|
||||
organization: environment.organization,
|
||||
project: environment.project,
|
||||
};
|
||||
} catch (e) {
|
||||
logger.error("ArchiveBranchService error", { environmentId, error: e });
|
||||
return {
|
||||
success: false as const,
|
||||
error: "Failed to archive branch",
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user