When projects are created, conditionally create staging based on the plan
This commit is contained in:
@@ -77,7 +77,7 @@ export async function createOrganization(
|
||||
}
|
||||
|
||||
export async function createEnvironment(
|
||||
organization: Pick<Organization, "id">,
|
||||
organization: Pick<Organization, "id" | "maximumConcurrencyLimit">,
|
||||
project: Pick<Project, "id">,
|
||||
type: RuntimeEnvironment["type"],
|
||||
member?: OrgMember,
|
||||
@@ -95,7 +95,7 @@ export async function createEnvironment(
|
||||
pkApiKey,
|
||||
shortcode,
|
||||
autoEnableInternalSources: type !== "DEVELOPMENT",
|
||||
maximumConcurrencyLimit: env.DEFAULT_ENV_EXECUTION_CONCURRENCY_LIMIT,
|
||||
maximumConcurrencyLimit: organization.maximumConcurrencyLimit / 3,
|
||||
organization: {
|
||||
connect: {
|
||||
id: organization.id,
|
||||
|
||||
@@ -4,17 +4,21 @@ import { prisma } from "~/db.server";
|
||||
import type { Project } from "@trigger.dev/database";
|
||||
import { Organization, createEnvironment } from "./organization.server";
|
||||
import { env } from "~/env.server";
|
||||
import { BillingService } from "~/services/billing.v3.server";
|
||||
export type { Project } from "@trigger.dev/database";
|
||||
|
||||
const externalRefGenerator = customAlphabet("abcdefghijklmnopqrstuvwxyz", 20);
|
||||
|
||||
type Options = {
|
||||
organizationSlug: string;
|
||||
name: string;
|
||||
userId: string;
|
||||
version: "v2" | "v3";
|
||||
isManagedCloud: boolean;
|
||||
};
|
||||
|
||||
export async function createProject(
|
||||
{
|
||||
organizationSlug,
|
||||
name,
|
||||
userId,
|
||||
version,
|
||||
}: { organizationSlug: string; name: string; userId: string; version: "v2" | "v3" },
|
||||
{ organizationSlug, name, userId, version, isManagedCloud }: Options,
|
||||
attemptCount = 0
|
||||
): Promise<Project & { organization: Organization }> {
|
||||
//check the user has permissions to do this
|
||||
@@ -58,6 +62,7 @@ export async function createProject(
|
||||
name,
|
||||
userId,
|
||||
version,
|
||||
isManagedCloud,
|
||||
},
|
||||
attemptCount + 1
|
||||
);
|
||||
@@ -89,6 +94,13 @@ export async function createProject(
|
||||
|
||||
if (version === "v2") {
|
||||
await createEnvironment(organization, project, "STAGING");
|
||||
} else {
|
||||
//staging is only available on certain plans
|
||||
const billingService = new BillingService(isManagedCloud);
|
||||
const plan = await billingService.currentPlan(organization.id);
|
||||
if (plan?.v3Subscription.plan?.limits.hasStagingEnvironment) {
|
||||
await createEnvironment(organization, project, "STAGING");
|
||||
}
|
||||
}
|
||||
|
||||
for (const member of project.organization.members) {
|
||||
|
||||
+1
-67
@@ -57,73 +57,6 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const action = async ({ request, params }: ActionFunctionArgs) => {
|
||||
const userId = await requireUserId(request);
|
||||
const { organizationSlug, projectParam } = ProjectParamSchema.parse(params);
|
||||
|
||||
if (request.method.toUpperCase() !== "POST") {
|
||||
return { status: 405, body: "Method Not Allowed" };
|
||||
}
|
||||
|
||||
const project = await prisma.project.findUnique({
|
||||
where: {
|
||||
slug: params.projectParam,
|
||||
organization: {
|
||||
members: {
|
||||
some: {
|
||||
userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
organizationId: true,
|
||||
environments: {
|
||||
select: {
|
||||
type: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!project) {
|
||||
return redirectWithErrorMessage(
|
||||
v3ApiKeysPath({ slug: organizationSlug }, { slug: projectParam }),
|
||||
request,
|
||||
"Project not found"
|
||||
);
|
||||
}
|
||||
|
||||
if (project.environments.some((env) => env.type === "STAGING")) {
|
||||
return redirectWithErrorMessage(
|
||||
v3ApiKeysPath({ slug: organizationSlug }, { slug: projectParam }),
|
||||
request,
|
||||
"You already have a staging environment"
|
||||
);
|
||||
}
|
||||
|
||||
const environment = await createEnvironment(
|
||||
{ id: project.organizationId },
|
||||
{ id: project.id },
|
||||
"STAGING"
|
||||
);
|
||||
|
||||
if (!environment) {
|
||||
return redirectWithErrorMessage(
|
||||
v3ApiKeysPath({ slug: organizationSlug }, { slug: projectParam }),
|
||||
request,
|
||||
"Failed to create staging environment"
|
||||
);
|
||||
}
|
||||
|
||||
return redirectWithSuccessMessage(
|
||||
v3ApiKeysPath({ slug: organizationSlug }, { slug: projectParam }),
|
||||
request,
|
||||
"Staging environment created"
|
||||
);
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
const { environments, hasStaging } = useTypedLoaderData<typeof loader>();
|
||||
const { isManagedCloud } = useFeatures();
|
||||
@@ -216,6 +149,7 @@ export default function Page() {
|
||||
</Table>
|
||||
|
||||
{!hasStaging && (
|
||||
// todo take you to the plans page
|
||||
<Callout
|
||||
variant="info"
|
||||
cta={
|
||||
|
||||
@@ -101,11 +101,13 @@ export const action: ActionFunction = async ({ request, params }) => {
|
||||
}
|
||||
|
||||
try {
|
||||
const { isManagedCloud } = featuresForRequest(request);
|
||||
const project = await createProject({
|
||||
organizationSlug: organizationSlug,
|
||||
name: submission.value.projectName,
|
||||
userId,
|
||||
version: submission.value.projectVersion,
|
||||
isManagedCloud,
|
||||
});
|
||||
|
||||
return redirectWithSuccessMessage(
|
||||
|
||||
Reference in New Issue
Block a user