@@ -75,7 +75,9 @@ import {
7575import { GitBranchIcon } from "lucide-react" ;
7676import { env } from "~/env.server" ;
7777import { useEnvironment } from "~/hooks/useEnvironment" ;
78- import { DateTime , DateTimeShort } from "~/components/primitives/DateTime" ;
78+ import { DateTime } from "~/components/primitives/DateTime" ;
79+ import { checkGitHubBranchExists } from "~/services/gitHub.server" ;
80+ import { tryCatch } from "@trigger.dev/core" ;
7981
8082export const meta : MetaFunction = ( ) => {
8183 return [
@@ -163,7 +165,7 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
163165 // Most installations will only have a couple of repos so loading them here should be fine.
164166 // However, there might be outlier organizations so it's best to expose the installation repos
165167 // via a resource endpoint and filter on user input.
166- take : 100 ,
168+ take : 200 ,
167169 } ,
168170 } ,
169171 take : 20 ,
@@ -187,8 +189,8 @@ const ConnectGitHubRepoFormSchema = z.object({
187189
188190const UpdateGitSettingsFormSchema = z . object ( {
189191 action : z . literal ( "update-git-settings" ) ,
190- productionBranch : z . string ( ) . optional ( ) ,
191- stagingBranch : z . string ( ) . optional ( ) ,
192+ productionBranch : z . string ( ) . trim ( ) . optional ( ) ,
193+ stagingBranch : z . string ( ) . trim ( ) . optional ( ) ,
192194 previewDeploymentsEnabled : z
193195 . string ( )
194196 . optional ( )
@@ -333,12 +335,57 @@ export const action: ActionFunction = async ({ request, params }) => {
333335 where : {
334336 projectId : project . id ,
335337 } ,
338+ include : {
339+ repository : {
340+ include : {
341+ installation : true ,
342+ } ,
343+ } ,
344+ } ,
336345 } ) ;
337346
338347 if ( ! existingConnection ) {
339348 return redirectBackWithErrorMessage ( request , "No connected GitHub repository found" ) ;
340349 }
341350
351+ const [ owner , repo ] = existingConnection . repository . fullName . split ( "/" ) ;
352+ const installationId = Number ( existingConnection . repository . installation . appInstallationId ) ;
353+
354+ const existingBranchTracking = BranchTrackingConfigSchema . safeParse (
355+ existingConnection . branchTracking
356+ ) ;
357+
358+ const [ error , branchValidationsOrFail ] = await tryCatch (
359+ Promise . all ( [
360+ productionBranch && existingBranchTracking . data ?. production ?. branch !== productionBranch
361+ ? checkGitHubBranchExists ( installationId , owner , repo , productionBranch )
362+ : Promise . resolve ( true ) ,
363+ stagingBranch && existingBranchTracking . data ?. staging ?. branch !== stagingBranch
364+ ? checkGitHubBranchExists ( installationId , owner , repo , stagingBranch )
365+ : Promise . resolve ( true ) ,
366+ ] )
367+ ) ;
368+
369+ if ( error ) {
370+ return redirectBackWithErrorMessage ( request , "Failed to validate tracking branches" ) ;
371+ }
372+
373+ const [ productionBranchExists , stagingBranchExists ] = branchValidationsOrFail ;
374+
375+ if ( productionBranch && ! productionBranchExists ) {
376+ return redirectBackWithErrorMessage (
377+ request ,
378+ `Production tracking branch '${ productionBranch } ' does not exist in the repository`
379+ ) ;
380+ }
381+
382+ if ( stagingBranch && ! stagingBranchExists ) {
383+ return redirectBackWithErrorMessage (
384+ request ,
385+ `Staging tracking branch '${ stagingBranch } ' does not exist in the repository`
386+ ) ;
387+ }
388+
342389 await prisma . connectedGithubRepository . update ( {
343390 where : {
344391 projectId : project . id ,
0 commit comments