068c024477
* Initial preview migrations * Modified the staging endpoint to create preview environments * Added isBranchableEnvironment to RuntimeEnvironment * Staging = yellow Preview = orange * Changed the env sort order * Set isBranchableEnvironment correctly. Create preview for new projects * Very basic branch menu * Creating branches from the dashboard * Fix for string icons on project delete page * Don’t show branch API keys * WIP on the manage branches page * RuntimeEnvironment added projectId index * Only create the parentEnvironmentId column if it doesn’t exist already * Improved the limit wording * Add search to the branch list * contains in both places * Many style improvements * Branch dropdown and v4 badge * Arching/unarchive branches working in the dashboard * Tidied imports * Change preview slug from `prev` to `preview` * Use correct color for side menu preview branch icon * Upsert the branch and use the shortcode as a unique constraint * Upserting working with nice messages in the dashboard * Better errors when upserting branches * Button shortcut, don’t allow event to propagate * Better duplicate error message * Filter out archived branches from the env selector * Archiving/creating tweaked some more * Add an archived banner to the app, fixes for archived branches and upsells * Fixed pagination * Disable editing schedules, pausing queues, testing tasks * Don’t allow replaying if the env is archived * When deploying detect the correct environment * Get the projectClient when there’s a branch * createGitMeta function, most code from the vercel CLI repo * Deploy, getting the correct environment client * Added git column to WorkerDeployment * Add GitMeta to core schemas * Create branch when deploying * WIP on branch support in the API * Delete old createTaskRunAttempt fn * apiAuth remove export from internal functions * Rename env var to “TRIGGER_PREVIEW_BRANCH” * Add TRIGGER_PREVIEW_BRANCH to resolved env vars for runs * First preview deploy and run working * Set the preview branch in the main SDK * Added git links to the preview branches table * Better errors when replaying/testing archived branches * Don’t dequeue archived environments * Env var resolution with parent environment * Hello world default machine small-2x to save my memory * Fix for more env var functions * Only return non-archived envs * Switch to controlled state for the checkboxes * Uncheck everything when PREVIEW is checked * WIP on branch UI * Show the preview branch label on the env vars list * Fix for overriding env vars * Adding preview branch env vars working * Progress on new env vars * Only allow selecting a single branch * Layout fix when there are errors * Set the defaultValue so there are some fields * Conform fix for team invite page * Archived environments don’t run scheduled tasks * Added Git data to deployments * Added git data to the deployment inspector * Don’t allow upserting schedules when archived * Deduplicate and blacklist some env vars * Fix for wrong conform function being used * Show a better error if all vars were blacklisted * Added environment variable search (by key and value) * Improved preview branch icon * Replay now supports branches * Schedule page render branches properly * Show the env icon in bottom-left of the test page * When editing older schedules (that have multi-env) show preview branches correctly * Fix for incorrect disallowed branch name character * Extract and improve the directory verification code * WIP for CLI preview archive command * Improved the preview branch action buttons * Redirect to the project if we don’t find a matching env * Archiving branch via the CLI working * Fix for archiving branches * Public access token test task * JWTs working are with preview branches * Add branch and git data to the Run ctx * Updated GitMeta functions to work in CI * Added pullRequestState * Archive when deploying if the PR is closed/merged * Fix for the changesets guide * Fix for CLI dev bug introduced * CLI promote now supports preview branches * Add PR title. Reordered them and added tooltips * syncEnvVars working with branches * Added preview branch support to syncVercelEnvVars() * Detect the branch from Vercel env var (set during build) * Allow passing a branch in * Use process.env.VERCEL_TOKEN as well… this used in Vercel CI * Temp delete * Improved regenerate api key modal * Added Accordion component (with styles) * Redesigned the API keys page * Revert "Temp delete" This reverts commit 177b92cd935a6161456bde65d01294e23ecfd47f. * Changeset * Fixed docs link * The new branch panel closes when a branch is created * Update apps/webapp/app/services/upsertBranch.server.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Removed findUniques from WorkerGroupTokenService * Made the parentEnvironmentId migrations safe * Latest lockfile * Update packages/cli-v3/src/commands/workers/build.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Move isValidGitBranchName to a separate file * Move the sanitize fn too * removeBlacklistedVariables moved to a separate file * Moved deduplicateVariableArray to a separate file… * Fix broken sanitizeBranchName import * Another import fix… * Improved blacklisted error message * SImplified migration to use `ADD COLUMN IF NOT EXISTS "parentEnvironmentId" TEXT` --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
278 lines
5.9 KiB
TypeScript
278 lines
5.9 KiB
TypeScript
import type { AuthenticatedEnvironment } from "@internal/run-engine";
|
|
import type { Prisma, PrismaClientOrTransaction, RuntimeEnvironment } from "@trigger.dev/database";
|
|
import { prisma } from "~/db.server";
|
|
import { logger } from "~/services/logger.server";
|
|
import { getUsername } from "~/utils/username";
|
|
import { sanitizeBranchName } from "~/v3/gitBranch";
|
|
|
|
export type { RuntimeEnvironment };
|
|
|
|
export async function findEnvironmentByApiKey(
|
|
apiKey: string,
|
|
branchName: string | undefined
|
|
): Promise<AuthenticatedEnvironment | null> {
|
|
const environment = await prisma.runtimeEnvironment.findFirst({
|
|
where: {
|
|
apiKey,
|
|
},
|
|
include: {
|
|
project: true,
|
|
organization: true,
|
|
orgMember: true,
|
|
childEnvironments: branchName
|
|
? {
|
|
where: {
|
|
branchName: sanitizeBranchName(branchName),
|
|
archivedAt: null,
|
|
},
|
|
}
|
|
: undefined,
|
|
},
|
|
});
|
|
|
|
//don't return deleted projects
|
|
if (environment?.project.deletedAt !== null) {
|
|
return null;
|
|
}
|
|
|
|
if (environment.type === "PREVIEW") {
|
|
if (!branchName) {
|
|
logger.error("findEnvironmentByApiKey(): Preview env with no branch name provided", {
|
|
environmentId: environment.id,
|
|
});
|
|
return null;
|
|
}
|
|
|
|
const childEnvironment = environment?.childEnvironments.at(0);
|
|
|
|
if (childEnvironment) {
|
|
return {
|
|
...childEnvironment,
|
|
apiKey: environment.apiKey,
|
|
orgMember: environment.orgMember,
|
|
organization: environment.organization,
|
|
project: environment.project,
|
|
};
|
|
}
|
|
|
|
//A branch was specified but no child environment was found
|
|
return null;
|
|
}
|
|
|
|
return environment;
|
|
}
|
|
|
|
/** @deprecated We don't use public api keys anymore */
|
|
export async function findEnvironmentByPublicApiKey(
|
|
apiKey: string,
|
|
branchName: string | undefined
|
|
): Promise<AuthenticatedEnvironment | null> {
|
|
const environment = await prisma.runtimeEnvironment.findFirst({
|
|
where: {
|
|
pkApiKey: apiKey,
|
|
},
|
|
include: {
|
|
project: true,
|
|
organization: true,
|
|
orgMember: true,
|
|
},
|
|
});
|
|
|
|
//don't return deleted projects
|
|
if (environment?.project.deletedAt !== null) {
|
|
return null;
|
|
}
|
|
|
|
return environment;
|
|
}
|
|
|
|
export async function findEnvironmentById(
|
|
id: string
|
|
): Promise<(AuthenticatedEnvironment & { parentEnvironment: { apiKey: string } | null }) | null> {
|
|
const environment = await prisma.runtimeEnvironment.findFirst({
|
|
where: {
|
|
id,
|
|
},
|
|
include: {
|
|
project: true,
|
|
organization: true,
|
|
orgMember: true,
|
|
parentEnvironment: {
|
|
select: {
|
|
apiKey: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
//don't return deleted projects
|
|
if (environment?.project.deletedAt !== null) {
|
|
return null;
|
|
}
|
|
|
|
return environment;
|
|
}
|
|
|
|
export async function findEnvironmentBySlug(
|
|
projectId: string,
|
|
envSlug: string,
|
|
userId: string
|
|
): Promise<AuthenticatedEnvironment | null> {
|
|
return prisma.runtimeEnvironment.findFirst({
|
|
where: {
|
|
projectId: projectId,
|
|
slug: envSlug,
|
|
OR: [
|
|
{
|
|
type: {
|
|
in: ["PREVIEW", "STAGING", "PRODUCTION"],
|
|
},
|
|
},
|
|
{
|
|
type: "DEVELOPMENT",
|
|
orgMember: {
|
|
userId,
|
|
},
|
|
},
|
|
],
|
|
},
|
|
include: {
|
|
project: true,
|
|
organization: true,
|
|
orgMember: true,
|
|
},
|
|
});
|
|
}
|
|
|
|
export async function findEnvironmentFromRun(
|
|
runId: string,
|
|
tx?: PrismaClientOrTransaction
|
|
): Promise<AuthenticatedEnvironment | null> {
|
|
const taskRun = await (tx ?? prisma).taskRun.findFirst({
|
|
where: {
|
|
id: runId,
|
|
},
|
|
include: {
|
|
runtimeEnvironment: {
|
|
include: {
|
|
project: true,
|
|
organization: true,
|
|
orgMember: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!taskRun) {
|
|
return null;
|
|
}
|
|
|
|
return taskRun?.runtimeEnvironment;
|
|
}
|
|
|
|
export async function createNewSession(environment: RuntimeEnvironment, ipAddress: string) {
|
|
const session = await prisma.runtimeEnvironmentSession.create({
|
|
data: {
|
|
environmentId: environment.id,
|
|
ipAddress,
|
|
},
|
|
});
|
|
|
|
await prisma.runtimeEnvironment.update({
|
|
where: {
|
|
id: environment.id,
|
|
},
|
|
data: {
|
|
currentSessionId: session.id,
|
|
},
|
|
});
|
|
|
|
return session;
|
|
}
|
|
|
|
export async function disconnectSession(environmentId: string) {
|
|
const environment = await prisma.runtimeEnvironment.findFirst({
|
|
where: {
|
|
id: environmentId,
|
|
},
|
|
});
|
|
|
|
if (!environment || !environment.currentSessionId) {
|
|
return null;
|
|
}
|
|
|
|
const session = await prisma.runtimeEnvironmentSession.update({
|
|
where: {
|
|
id: environment.currentSessionId,
|
|
},
|
|
data: {
|
|
disconnectedAt: new Date(),
|
|
},
|
|
});
|
|
|
|
await prisma.runtimeEnvironment.update({
|
|
where: {
|
|
id: environment.id,
|
|
},
|
|
data: {
|
|
currentSessionId: null,
|
|
},
|
|
});
|
|
|
|
return session;
|
|
}
|
|
|
|
export async function findLatestSession(environmentId: string) {
|
|
const session = await prisma.runtimeEnvironmentSession.findFirst({
|
|
where: {
|
|
environmentId,
|
|
},
|
|
orderBy: {
|
|
createdAt: "desc",
|
|
},
|
|
});
|
|
|
|
return session;
|
|
}
|
|
|
|
export type DisplayableInputEnvironment = Prisma.RuntimeEnvironmentGetPayload<{
|
|
select: {
|
|
id: true;
|
|
type: true;
|
|
slug: true;
|
|
orgMember: {
|
|
select: {
|
|
user: {
|
|
select: {
|
|
id: true;
|
|
name: true;
|
|
displayName: true;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}>;
|
|
|
|
export function displayableEnvironment(
|
|
environment: DisplayableInputEnvironment,
|
|
userId: string | undefined
|
|
) {
|
|
let userName: string | undefined = undefined;
|
|
|
|
if (environment.type === "DEVELOPMENT") {
|
|
if (!environment.orgMember) {
|
|
userName = "Deleted";
|
|
} else if (environment.orgMember.user.id !== userId) {
|
|
userName = getUsername(environment.orgMember.user);
|
|
}
|
|
}
|
|
|
|
return {
|
|
id: environment.id,
|
|
type: environment.type,
|
|
slug: environment.slug,
|
|
userName,
|
|
};
|
|
}
|