Skip to content

Preview branches #2086

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 98 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
7ae56e6
Initial preview migrations
matt-aitken May 11, 2025
b65e88b
Modified the staging endpoint to create preview environments
matt-aitken May 11, 2025
99e8130
Added isBranchableEnvironment to RuntimeEnvironment
matt-aitken May 11, 2025
9a57df2
Staging = yellow Preview = orange
matt-aitken May 11, 2025
406ce5d
Changed the env sort order
matt-aitken May 11, 2025
e1b1735
Set isBranchableEnvironment correctly. Create preview for new projects
matt-aitken May 11, 2025
7a04b97
Very basic branch menu
matt-aitken May 11, 2025
7de28ce
Creating branches from the dashboard
matt-aitken May 11, 2025
18941bf
Fix for string icons on project delete page
matt-aitken May 11, 2025
3b1dd91
Don’t show branch API keys
matt-aitken May 11, 2025
288cb7c
WIP on the manage branches page
matt-aitken May 13, 2025
05cff35
RuntimeEnvironment added projectId index
matt-aitken May 13, 2025
e741997
Only create the parentEnvironmentId column if it doesn’t exist already
matt-aitken May 13, 2025
79ce9a0
Improved the limit wording
matt-aitken May 13, 2025
2f79398
Add search to the branch list
matt-aitken May 13, 2025
8074fa3
contains in both places
matt-aitken May 13, 2025
9209607
Many style improvements
matt-aitken May 13, 2025
00ac0f7
Branch dropdown and v4 badge
matt-aitken May 13, 2025
65fc70a
Arching/unarchive branches working in the dashboard
matt-aitken May 13, 2025
b637ec1
Tidied imports
matt-aitken May 14, 2025
6efa232
Change preview slug from `prev` to `preview`
matt-aitken May 14, 2025
4e97a8c
Use correct color for side menu preview branch icon
matt-aitken May 14, 2025
0579f0e
Upsert the branch and use the shortcode as a unique constraint
matt-aitken May 14, 2025
17b5a40
Upserting working with nice messages in the dashboard
matt-aitken May 14, 2025
8b80cf2
Better errors when upserting branches
matt-aitken May 14, 2025
705b375
Button shortcut, don’t allow event to propagate
matt-aitken May 14, 2025
8719fb0
Better duplicate error message
matt-aitken May 14, 2025
9635408
Filter out archived branches from the env selector
matt-aitken May 14, 2025
e7e821a
Archiving/creating tweaked some more
matt-aitken May 14, 2025
865691e
Add an archived banner to the app, fixes for archived branches and up…
matt-aitken May 14, 2025
ff352ae
Fixed pagination
matt-aitken May 14, 2025
ac47c57
Disable editing schedules, pausing queues, testing tasks
matt-aitken May 14, 2025
66ee041
Don’t allow replaying if the env is archived
matt-aitken May 15, 2025
1dd75f8
When deploying detect the correct environment
matt-aitken May 15, 2025
1ed453c
Get the projectClient when there’s a branch
matt-aitken May 15, 2025
fdf3a86
createGitMeta function, most code from the vercel CLI repo
matt-aitken May 15, 2025
af5970d
Deploy, getting the correct environment client
matt-aitken May 15, 2025
162f922
Added git column to WorkerDeployment
matt-aitken May 15, 2025
199110b
Add GitMeta to core schemas
matt-aitken May 15, 2025
b5be9b4
Create branch when deploying
matt-aitken May 15, 2025
06720bb
WIP on branch support in the API
matt-aitken May 16, 2025
ba57574
Merge remote-tracking branch 'origin/main' into preview-branches
matt-aitken May 16, 2025
69c3cd9
Merge remote-tracking branch 'origin/main' into preview-branches
matt-aitken May 16, 2025
152963a
Delete old createTaskRunAttempt fn
matt-aitken May 16, 2025
7d92eba
apiAuth remove export from internal functions
matt-aitken May 16, 2025
8758961
Rename env var to “TRIGGER_PREVIEW_BRANCH”
matt-aitken May 16, 2025
f5c47d1
Add TRIGGER_PREVIEW_BRANCH to resolved env vars for runs
matt-aitken May 16, 2025
efbaf6c
First preview deploy and run working
matt-aitken May 19, 2025
6430da6
Set the preview branch in the main SDK
matt-aitken May 19, 2025
fc0e4a7
Added git links to the preview branches table
matt-aitken May 19, 2025
e80177e
Better errors when replaying/testing archived branches
matt-aitken May 19, 2025
862af37
Don’t dequeue archived environments
matt-aitken May 19, 2025
5de8317
Env var resolution with parent environment
matt-aitken May 20, 2025
43dd223
Hello world default machine small-2x to save my memory
matt-aitken May 20, 2025
082bdad
Fix for more env var functions
matt-aitken May 20, 2025
03e69c4
Merge remote-tracking branch 'origin/main' into preview-branches
matt-aitken May 20, 2025
e203f3c
Only return non-archived envs
matt-aitken May 20, 2025
932a4eb
Switch to controlled state for the checkboxes
matt-aitken May 20, 2025
615080f
Uncheck everything when PREVIEW is checked
matt-aitken May 20, 2025
184835b
WIP on branch UI
matt-aitken May 20, 2025
ff62192
Show the preview branch label on the env vars list
matt-aitken May 20, 2025
a1a3c44
Fix for overriding env vars
matt-aitken May 20, 2025
8ec543b
Adding preview branch env vars working
matt-aitken May 20, 2025
5d0d0ae
Progress on new env vars
matt-aitken May 20, 2025
25372d6
Only allow selecting a single branch
matt-aitken May 20, 2025
74d9923
Layout fix when there are errors
matt-aitken May 20, 2025
32e9950
Set the defaultValue so there are some fields
matt-aitken May 20, 2025
e21d65d
Conform fix for team invite page
matt-aitken May 20, 2025
ed30009
Archived environments don’t run scheduled tasks
matt-aitken May 21, 2025
7be7c30
Added Git data to deployments
matt-aitken May 21, 2025
9da2768
Added git data to the deployment inspector
matt-aitken May 21, 2025
e338061
Don’t allow upserting schedules when archived
matt-aitken May 21, 2025
e39eeeb
Deduplicate and blacklist some env vars
matt-aitken May 21, 2025
c24af91
Fix for wrong conform function being used
matt-aitken May 21, 2025
17b50c7
Show a better error if all vars were blacklisted
matt-aitken May 21, 2025
35ed095
Added environment variable search (by key and value)
matt-aitken May 21, 2025
236f3ff
Improved preview branch icon
matt-aitken May 21, 2025
81932bc
Replay now supports branches
matt-aitken May 21, 2025
2e3944d
Schedule page render branches properly
matt-aitken May 21, 2025
a2f324e
Show the env icon in bottom-left of the test page
matt-aitken May 21, 2025
c69cb2a
When editing older schedules (that have multi-env) show preview branc…
matt-aitken May 21, 2025
352c84d
Fix for incorrect disallowed branch name character
matt-aitken May 21, 2025
b3873f1
Extract and improve the directory verification code
matt-aitken May 21, 2025
8dbf504
WIP for CLI preview archive command
matt-aitken May 21, 2025
77bd001
Improved the preview branch action buttons
matt-aitken May 22, 2025
b8bdd60
Redirect to the project if we don’t find a matching env
matt-aitken May 22, 2025
4bb22d6
Archiving branch via the CLI working
matt-aitken May 22, 2025
351ee53
Fix for archiving branches
matt-aitken May 22, 2025
46498bb
Public access token test task
matt-aitken May 22, 2025
c7dcf57
JWTs working are with preview branches
matt-aitken May 22, 2025
527c632
Add branch and git data to the Run ctx
matt-aitken May 22, 2025
1b645e2
Updated GitMeta functions to work in CI
matt-aitken May 23, 2025
704deed
Added pullRequestState
matt-aitken May 23, 2025
052b63c
Archive when deploying if the PR is closed/merged
matt-aitken May 23, 2025
53de51b
Fix for the changesets guide
matt-aitken May 23, 2025
8b9efbc
Fix for CLI dev bug introduced
matt-aitken May 23, 2025
d8a71b5
CLI promote now supports preview branches
matt-aitken May 23, 2025
3ccb6d6
Add PR title. Reordered them and added tooltips
matt-aitken May 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 6 additions & 20 deletions CHANGESETS.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,28 +30,14 @@ Please follow the best-practice of adding changesets in the same commit as the c

## Snapshot instructions

!MAKE SURE TO UPDATE THE TAG IN THE INSTRUCTIONS BELOW!
1. Delete the `.changeset/pre.json` file (if it exists)

1. Add changesets as usual
2. Do a temporary commit (do NOT push this, you should undo it after)

```sh
pnpm run changeset:add
```
3. Copy the `GITHUB_TOKEN` line from the .env file

2. Create a snapshot version (replace "prerelease" with your tag)
4. Run `GITHUB_TOKEN=github_pat_12345 ./scripts/publish-prerelease.sh re2`

```sh
pnpm exec changeset version --snapshot prerelease
```
Make sure to replace the token with yours. `re2` is the tag that will be used for the pre-release.

3. Build the packages:

```sh
pnpm run build --filter "@trigger.dev/*" --filter "trigger.dev"
```

4. Publish the snapshot (replace "dev" with your tag)

```sh
pnpm exec changeset publish --no-git-tag --snapshot --tag prerelease
```
5. Undo the commit where you deleted the pre.json file.
44 changes: 44 additions & 0 deletions apps/webapp/app/assets/icons/ArchiveIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
export function ArchiveIcon({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clipPath="url(#clip0_17398_782)">
<path
d="M19.2293 9C20.1562 9.00001 20.8612 9.83278 20.7088 10.7471L19.2781 19.3291C19.1173 20.2933 18.283 21 17.3055 21H6.69416C5.71662 21 4.88235 20.2933 4.7215 19.3291L3.29084 10.7471C3.13848 9.83289 3.8436 9.00021 4.77033 9H19.2293ZM9.95002 12.5C9.12179 12.5002 8.45002 13.1717 8.45002 14C8.45002 14.8283 9.12179 15.4998 9.95002 15.5H13.95L14.1033 15.4922C14.8597 15.4154 15.45 14.7767 15.45 14C15.45 13.2233 14.8597 12.5846 14.1033 12.5078L13.95 12.5H9.95002Z"
fill="currentColor"
/>
<rect x="2" y="3" width="20" height="4" rx="1" fill="currentColor" />
</g>
<defs>
<clipPath id="clip0_17398_782">
<rect width="24" height="24" fill="currentColor" />
</clipPath>
</defs>
</svg>
);
}

export function UnarchiveIcon({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clipPath="url(#clip0_17398_66731)">
<path
d="M19.2027 10C20.1385 10 20.8456 10.8478 20.6782 11.7686L19.2984 19.3574C19.1254 20.3084 18.2972 21 17.3306 21H6.66945C5.70287 21 4.87458 20.3084 4.70167 19.3574L3.32179 11.7686C3.15438 10.8478 3.86152 10 4.79738 10H10.9995V16C10.9995 16.5521 11.4475 16.9997 11.9995 17C12.5518 17 12.9995 16.5523 12.9995 16V10H19.2027Z"
fill="currentColor"
/>
<rect x="11" y="4" width="2" height="6" fill="currentColor" />
<path
d="M15.5 6.5L12 3L8.5 6.5"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
<defs>
<clipPath id="clip0_17398_66731">
<rect width="24" height="24" fill="currentColor" />
</clipPath>
</defs>
</svg>
);
}
27 changes: 26 additions & 1 deletion apps/webapp/app/assets/icons/EnvironmentIcons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export function ProdEnvironmentIcon({ className }: { className?: string }) {
<svg className={className} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M12.5037 7.33603C12.3174 6.88799 11.6827 6.88799 11.4963 7.33603L10.4338 9.89064L7.6759 10.1117C7.1922 10.1505 6.99606 10.7542 7.36459 11.0698L9.46583 12.8698L8.82387 15.561C8.71128 16.033 9.22477 16.4061 9.63888 16.1532L12 14.711L14.3612 16.1532C14.7753 16.4061 15.2888 16.0331 15.1762 15.561L14.5343 12.8698L16.6355 11.0698C17.004 10.7542 16.8079 10.1505 16.3242 10.1117L13.5663 9.89064L12.5037 7.33603Z"
fill="white"
fill="currentColor"
/>
<rect
x="3"
Expand Down Expand Up @@ -151,3 +151,28 @@ export function DeployedEnvironmentIconSmall({ className }: { className?: string
</svg>
);
}

export function PreviewEnvironmentIconSmall({ className }: { className?: string }) {
return <BranchEnvironmentIconSmall className={className} />;
}

export function BranchEnvironmentIconSmall({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M2.23059 7C1.65409 6.99967 1.30545 6.36259 1.61634 5.87695L3.88489 2.33301C4.17195 1.88466 4.82727 1.88472 5.11438 2.33301L7.38294 5.87695C7.69386 6.36265 7.34531 6.99982 6.76868 7L2.23059 7Z"
fill="currentColor"
/>
<path
d="M3.5 6H5.5V15C5.5 15.5523 5.05228 16 4.5 16C3.94772 16 3.5 15.5523 3.5 15V6Z"
fill="currentColor"
/>
<path
d="M13.5 7V7.5C13.5 9.15685 12.1569 10.5 10.5 10.5H7.5C5.84315 10.5 4.5 11.8431 4.5 13.5V15"
stroke="currentColor"
strokeWidth="2"
/>
<circle cx="13.5" cy="5" r="2" stroke="currentColor" strokeWidth="2" />
</svg>
);
}
5 changes: 0 additions & 5 deletions apps/webapp/app/assets/icons/IntegrationIcon.tsx

This file was deleted.

120 changes: 120 additions & 0 deletions apps/webapp/app/components/BlankStatePanels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { useProject } from "~/hooks/useProject";
import { type MinimumEnvironment } from "~/presenters/SelectBestEnvironmentPresenter.server";
import {
docsPath,
v3BillingPath,
v3EnvironmentPath,
v3EnvironmentVariablesPath,
v3NewProjectAlertPath,
Expand All @@ -36,6 +37,11 @@ import { TextLink } from "./primitives/TextLink";
import { InitCommandV3, PackageManagerProvider, TriggerDevStepV3 } from "./SetupCommands";
import { StepContentContainer } from "./StepContentContainer";
import { WaitpointTokenIcon } from "~/assets/icons/WaitpointTokenIcon";
import { BranchEnvironmentIconSmall } from "~/assets/icons/EnvironmentIcons";
import { useFeatures } from "~/hooks/useFeatures";
import { DialogContent, DialogTrigger, Dialog } from "./primitives/Dialog";
import { V4Badge } from "./V4Badge";
import { NewBranchPanel } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route";

export function HasNoTasksDev() {
return (
Expand Down Expand Up @@ -431,6 +437,120 @@ export function NoWaitpointTokens() {
);
}

export function BranchesNoBranchableEnvironment() {
const { isManagedCloud } = useFeatures();
const organization = useOrganization();

if (!isManagedCloud) {
return (
<InfoPanel
title="Create a preview environment"
icon={BranchEnvironmentIconSmall}
iconClassName="text-preview"
panelClassName="max-w-full"
>
<Paragraph spacing variant="small">
To add branches you need to have a <InlineCode>RuntimeEnvironment</InlineCode> where{" "}
<InlineCode>isBranchableEnvironment</InlineCode> is true. We recommend creating a
dedicated one using the "PREVIEW" type.
</Paragraph>
</InfoPanel>
);
}

return (
<InfoPanel
title="Upgrade to get preview branches"
icon={BranchEnvironmentIconSmall}
iconClassName="text-preview"
panelClassName="max-w-full"
accessory={
<LinkButton variant="primary/small" to={v3BillingPath(organization)}>
Upgrade
</LinkButton>
}
>
<Paragraph spacing variant="small">
Preview branches in Trigger.dev create isolated environments for testing new features before
production.
</Paragraph>
</InfoPanel>
);
}

export function BranchesNoBranches({
parentEnvironment,
limits,
canUpgrade,
}: {
parentEnvironment: { id: string };
limits: { used: number; limit: number };
canUpgrade: boolean;
}) {
const organization = useOrganization();
if (limits.used >= limits.limit) {
return (
<InfoPanel
title="Upgrade to get preview branches"
icon={BranchEnvironmentIconSmall}
iconClassName="text-preview"
panelClassName="max-w-full"
accessory={
canUpgrade ? (
<LinkButton variant="primary/small" to={v3BillingPath(organization)}>
Upgrade
</LinkButton>
) : (
<Feedback
button={<Button variant="primary/small">Request more</Button>}
defaultValue="help"
/>
)
}
>
<Paragraph spacing variant="small">
You've reached the limit ({limits.used}/{limits.limit}) of branches for your plan. Upgrade
to get branches.
</Paragraph>
</InfoPanel>
);
}

return (
<InfoPanel
title="Create your first branch"
icon={BranchEnvironmentIconSmall}
iconClassName="text-preview"
panelClassName="max-w-full"
accessory={
<Dialog>
<DialogTrigger asChild>
<Button
variant="primary/small"
LeadingIcon={PlusIcon}
leadingIconClassName="text-white"
>
New branch
</Button>
</DialogTrigger>
<DialogContent>
<NewBranchPanel parentEnvironment={parentEnvironment} />
</DialogContent>
</Dialog>
}
>
<Paragraph spacing variant="small">
Branches are a way to test new features in isolation before merging them into the main
environment.
</Paragraph>
<Paragraph spacing variant="small">
Branches are only available when using <V4Badge inline /> or above. Read our{" "}
<TextLink to={docsPath("upgrade-to-v4")}>v4 upgrade guide</TextLink> to learn more.
</Paragraph>
</InfoPanel>
);
}

function SwitcherPanel() {
const organization = useOrganization();
const project = useProject();
Expand Down
86 changes: 86 additions & 0 deletions apps/webapp/app/components/GitMetadata.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { GitPullRequestIcon, GitCommitIcon, GitBranchIcon } from "lucide-react";
import { type GitMetaLinks } from "~/presenters/v3/BranchesPresenter.server";
import { LinkButton } from "./primitives/Buttons";
import { SimpleTooltip } from "./primitives/Tooltip";

export function GitMetadata({ git }: { git?: GitMetaLinks | null }) {
if (!git) return null;
return (
<>
{git.pullRequestUrl && git.pullRequestNumber && <GitMetadataPullRequest git={git} />}
{git.shortSha && <GitMetadataCommit git={git} />}
{git.branchUrl && <GitMetadataBranch git={git} />}
</>
);
}

export function GitMetadataBranch({
git,
}: {
git: Pick<GitMetaLinks, "branchUrl" | "branchName">;
}) {
return (
<SimpleTooltip
button={
<LinkButton
variant="minimal/small"
LeadingIcon={<GitBranchIcon className="size-4" />}
iconSpacing="gap-x-1"
to={git.branchUrl}
className="pl-1"
>
{git.branchName}
</LinkButton>
}
content="Jump to GitHub branch"
/>
);
}

export function GitMetadataCommit({
git,
}: {
git: Pick<GitMetaLinks, "commitUrl" | "shortSha" | "commitMessage">;
}) {
return (
<SimpleTooltip
button={
<LinkButton
variant="minimal/small"
to={git.commitUrl}
LeadingIcon={<GitCommitIcon className="size-4" />}
iconSpacing="gap-x-1"
className="pl-1"
>
{`${git.shortSha} / ${git.commitMessage}`}
</LinkButton>
}
content="Jump to GitHub commit"
/>
);
}

export function GitMetadataPullRequest({
git,
}: {
git: Pick<GitMetaLinks, "pullRequestUrl" | "pullRequestNumber" | "pullRequestTitle">;
}) {
if (!git.pullRequestUrl || !git.pullRequestNumber) return null;

return (
<SimpleTooltip
button={
<LinkButton
variant="minimal/small"
to={git.pullRequestUrl}
LeadingIcon={<GitPullRequestIcon className="size-4" />}
iconSpacing="gap-x-1"
className="pl-1"
>
#{git.pullRequestNumber} {git.pullRequestTitle}
</LinkButton>
}
content="Jump to GitHub pull request"
/>
);
}
26 changes: 26 additions & 0 deletions apps/webapp/app/components/V4Badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { cn } from "~/utils/cn";
import { Badge } from "./primitives/Badge";
import { SimpleTooltip } from "./primitives/Tooltip";

export function V4Badge({ inline = false, className }: { inline?: boolean; className?: string }) {
return (
<SimpleTooltip
button={
<Badge variant="extra-small" className={cn(inline ? "inline-grid" : "", className)}>
V4
</Badge>
}
content="This feature is only available in V4 and above."
disableHoverableContent
/>
);
}

export function V4Title({ children }: { children: React.ReactNode }) {
return (
<>
<span>{children}</span>
<V4Badge />
</>
);
}
Loading