Add the STAGING environment by default
🚀 Publish Trigger.dev Docker / ʦ TypeScript (push) Has been cancelled
🚀 Publish Trigger.dev Docker / Unit Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / e2e Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / publish (push) Has been cancelled

This commit is contained in:
Eric Allam
2023-09-27 18:17:15 +01:00
parent bc757c8ddb
commit a42e94c75f
9 changed files with 144 additions and 9 deletions
@@ -272,6 +272,21 @@ export function HowToUseApiKeysAndEndpoints() {
you should use the Test feature to trigger any scheduled Jobs.
</Callout>
</StepContentContainer>
<StepNumber
stepNumber="→"
title={
<span className="flex items-center gap-x-2">
<span>Staging</span>
<EnvironmentLabel environment={{ type: "STAGING" }} />
</span>
}
/>
<StepContentContainer>
<Paragraph spacing>
The <InlineCode>STAGING</InlineCode> environment is where your Jobs will run in a staging
environment, meant to mirror your production environment.
</Paragraph>
</StepContentContainer>
<StepNumber
stepNumber="→"
title={
@@ -8,7 +8,6 @@ import type {
import { customAlphabet } from "nanoid";
import slug from "slug";
import { prisma, PrismaClientOrTransaction } from "~/db.server";
import { workerQueue } from "~/services/worker.server";
import { createProject } from "./project.server";
export type { Organization };
@@ -176,10 +175,10 @@ function envSlug(environmentType: RuntimeEnvironment["type"]) {
return "prod";
}
case "STAGING": {
return "staging";
return "stg";
}
case "PREVIEW": {
return "preview";
return "prev";
}
}
}
+1
View File
@@ -65,6 +65,7 @@ export async function createProject(
// Create the dev and prod environments
await createEnvironment(organization, project, "PRODUCTION");
await createEnvironment(organization, project, "STAGING");
for (const member of project.organization.members) {
await createEnvironment(organization, project, "DEVELOPMENT", member);
@@ -2,19 +2,19 @@ import { PrismaClient, prisma } from "~/db.server";
import { IndexEndpointStats, parseEndpointIndexStats } from "~/models/indexEndpoint.server";
import { Project } from "~/models/project.server";
import { User } from "~/models/user.server";
import {
import type {
Endpoint,
EndpointIndex,
RuntimeEnvironment,
RuntimeEnvironmentType,
} from "../../../../packages/database/src";
import { env } from "~/env.server";
} from "@trigger.dev/database";
export type Client = {
slug: string;
endpoints: {
DEVELOPMENT: ClientEndpoint;
PRODUCTION: ClientEndpoint;
STAGING?: ClientEndpoint;
};
};
@@ -133,6 +133,8 @@ export class EnvironmentsPresenter {
throw new Error("Development environment not found, this should not happen");
}
const stagingEnvironment = filtered.find((environment) => environment.type === "STAGING");
const productionEnvironment = filtered.find(
(environment) => environment.type === "PRODUCTION"
);
@@ -151,6 +153,9 @@ export class EnvironmentsPresenter {
state: "unconfigured",
environment: productionEnvironment,
},
STAGING: stagingEnvironment
? { state: "unconfigured", environment: stagingEnvironment }
: undefined,
},
};
@@ -161,6 +166,16 @@ export class EnvironmentsPresenter {
client.endpoints.DEVELOPMENT = endpointClient(devEndpoint, developmentEnvironment, baseUrl);
}
if (stagingEnvironment) {
const stagingEndpoint = stagingEnvironment.endpoints.find(
(endpoint) => endpoint.slug === slug
);
if (stagingEndpoint) {
client.endpoints.STAGING = endpointClient(stagingEndpoint, stagingEnvironment, baseUrl);
}
}
const prodEndpoint = productionEnvironment.endpoints.find(
(endpoint) => endpoint.slug === slug
);
@@ -85,8 +85,8 @@ export default function Page() {
const client = clients.find((c) => c.slug === selected.client);
if (!client) return undefined;
if (selected.type === "PREVIEW" || selected.type === "STAGING") {
throw new Error("PREVIEW/STAGING is not yet supported");
if (selected.type === "PREVIEW") {
throw new Error("PREVIEW is not yet supported");
}
return {
@@ -195,6 +195,18 @@ export default function Page() {
})
}
/>
{client.endpoints.STAGING && (
<EndpointRow
endpoint={client.endpoints.STAGING}
type="STAGING"
onClick={() =>
setSelected({
client: client.slug,
type: "STAGING",
})
}
/>
)}
<EndpointRow
endpoint={client.endpoints.PRODUCTION}
type="PRODUCTION"
@@ -218,7 +230,7 @@ export default function Page() {
</>
)}
</div>
{selectedEndpoint && (
{selectedEndpoint && selectedEndpoint.endpoint && (
<ConfigureEndpointSheet
slug={selectedEndpoint.clientSlug}
endpoint={selectedEndpoint.endpoint}
+67
View File
@@ -3,6 +3,7 @@
import { integrationCatalog } from "../app/services/externalApis/integrationCatalog.server";
import { seedCloud } from "./seedCloud";
import { prisma } from "../app/db.server";
import { createEnvironment } from "~/models/organization.server";
async function seedIntegrationAuthMethods() {
for (const [_, integration] of Object.entries(integrationCatalog.getIntegrations())) {
@@ -67,12 +68,78 @@ async function seedIntegrationAuthMethods() {
}
}
async function runDataMigrations() {
await runStagingEnvironmentMigration();
}
async function runStagingEnvironmentMigration() {
try {
await prisma.$transaction(async (tx) => {
const existingDataMigration = await tx.dataMigration.findUnique({
where: {
name: "2023-09-27-AddStagingEnvironments",
},
});
if (existingDataMigration) {
return;
}
await tx.dataMigration.create({
data: {
name: "2023-09-27-AddStagingEnvironments",
},
});
console.log("Running data migration 2023-09-27-AddStagingEnvironments");
const projectsWithoutStagingEnvironments = await tx.project.findMany({
where: {
environments: {
none: {
type: "STAGING",
},
},
},
include: {
organization: true,
},
});
for (const project of projectsWithoutStagingEnvironments) {
try {
console.log(
`Creating staging environment for project ${project.slug} on org ${project.organization.slug}`
);
await createEnvironment(project.organization, project, "STAGING", undefined, tx);
} catch (error) {
console.error(error);
}
}
await tx.dataMigration.update({
where: {
name: "2023-09-27-AddStagingEnvironments",
},
data: {
completedAt: new Date(),
},
});
});
} catch (error) {
console.error(error);
}
}
async function seed() {
await seedIntegrationAuthMethods();
if (process.env.NODE_ENV === "development" && process.env.SEED_CLOUD === "enabled") {
await seedCloud(prisma);
}
await runDataMigrations();
}
seed()
@@ -27,6 +27,10 @@ The `DEV` environment should only be used for local development. It's where you
<Snippet file="scheduled-dev-warning.mdx" />
### Staging
The `STAGING` environment is useful for testing your Jobs against your staging server, if you have one. STAGING works identically to PROD.
### Production
The `PROD` environment is where your Jobs will run in production. It's where you can run your Jobs against real data.
@@ -0,0 +1,13 @@
-- CreateTable
CREATE TABLE "DataMigration" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"completedAt" TIMESTAMP(3),
CONSTRAINT "DataMigration_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "DataMigration_name_key" ON "DataMigration"("name");
+9
View File
@@ -1091,3 +1091,12 @@ model ApiIntegrationVote {
@@unique([apiIdentifier, userId])
}
model DataMigration {
id String @id @default(cuid())
name String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
completedAt DateTime?
}