@@ -2,17 +2,13 @@ package deployment
22
33import (
44 "context"
5- "database/sql"
65 "fmt"
7- "time"
86
97 "connectrpc.com/connect"
108 ctrlv1 "github.com/unkeyed/unkey/gen/proto/ctrl/v1"
11- hydrav1 "github.com/unkeyed/unkey/gen/proto/hydra/v1"
129 "github.com/unkeyed/unkey/pkg/db"
1310 "github.com/unkeyed/unkey/pkg/logger"
14- "github.com/unkeyed/unkey/pkg/uid"
15- "google.golang.org/protobuf/encoding/protojson"
11+ "github.com/unkeyed/unkey/svc/ctrl/internal/deployutil"
1612)
1713
1814// AuthorizeDeployment authorizes a deployment for an external contributor's push.
@@ -26,7 +22,6 @@ func (s *Service) AuthorizeDeployment(ctx context.Context, req *connect.Request[
2622 return nil , connect .NewError (connect .CodeInvalidArgument , fmt .Errorf ("project_id and branch are required" ))
2723 }
2824
29- // Find repo connection for this project
3025 repoConn , err := db .Query .FindGithubRepoConnectionByProjectId (ctx , s .db .RO (), projectID )
3126 if err != nil {
3227 if db .IsNotFound (err ) {
@@ -35,13 +30,11 @@ func (s *Service) AuthorizeDeployment(ctx context.Context, req *connect.Request[
3530 return nil , connect .NewError (connect .CodeInternal , fmt .Errorf ("failed to find repo connection: %w" , err ))
3631 }
3732
38- // Fetch current HEAD of the branch from GitHub — this is the SHA we deploy
3933 headCommit , err := s .github .GetBranchHeadCommit (repoConn .InstallationID , repoConn .RepositoryFullName , branch )
4034 if err != nil {
4135 return nil , connect .NewError (connect .CodeInternal , fmt .Errorf ("failed to fetch branch HEAD from GitHub: %w" , err ))
4236 }
4337
44- // Find all deploy contexts for this branch
4538 contexts , err := db .Query .ListRepoConnectionDeployContexts (ctx , s .db .RO (), db.ListRepoConnectionDeployContextsParams {
4639 InstallationID : repoConn .InstallationID ,
4740 RepositoryID : repoConn .RepositoryID ,
@@ -55,7 +48,6 @@ func (s *Service) AuthorizeDeployment(ctx context.Context, req *connect.Request[
5548 return nil , connect .NewError (connect .CodeNotFound , fmt .Errorf ("no deploy contexts found for project %s branch %s" , projectID , branch ))
5649 }
5750
58- // Fetch env vars for all matched apps
5951 allEnvVars , err := db .Query .ListEnvVarsForRepoConnections (ctx , s .db .RO (), db.ListEnvVarsForRepoConnectionsParams {
6052 InstallationID : repoConn .InstallationID ,
6153 RepositoryID : repoConn .RepositoryID ,
@@ -65,102 +57,32 @@ func (s *Service) AuthorizeDeployment(ctx context.Context, req *connect.Request[
6557 return nil , connect .NewError (connect .CodeInternal , fmt .Errorf ("failed to list env vars: %w" , err ))
6658 }
6759
68- envVarsByApp := make (map [string ][]db.ListEnvVarsForRepoConnectionsRow )
69- for _ , ev := range allEnvVars {
70- envVarsByApp [ev .AppID ] = append (envVarsByApp [ev .AppID ], ev )
71- }
60+ envVarsByApp := deployutil .GroupEnvVarsByApp (allEnvVars )
7261
73- commitTimestamp := headCommit .Timestamp .UnixMilli ()
62+ commit := deployutil.GitCommitInfo {
63+ SHA : headCommit .SHA ,
64+ Branch : branch ,
65+ Message : headCommit .Message ,
66+ AuthorHandle : headCommit .AuthorHandle ,
67+ AuthorAvatarURL : headCommit .AuthorAvatarURL ,
68+ Timestamp : headCommit .Timestamp .UnixMilli (),
69+ }
7470
7571 for _ , row := range contexts {
76- project := row .Project
77- env := row .Environment
78- app := row .App
79- runtimeSettings := row .AppRuntimeSetting
80- buildSettings := row .AppBuildSetting
81- repo := row .GithubRepoConnection
82-
83- // Build secrets blob from env vars
84- appEnvVars := envVarsByApp [app .ID ]
85- secretsBlob := []byte {}
86- if len (appEnvVars ) > 0 {
87- secretsConfig := & ctrlv1.SecretsConfig {
88- Secrets : make (map [string ]string , len (appEnvVars )),
89- }
90- for _ , ev := range appEnvVars {
91- secretsConfig .Secrets [ev .Key ] = ev .Value
92- }
93- var marshalErr error
94- secretsBlob , marshalErr = protojson .Marshal (secretsConfig )
95- if marshalErr != nil {
96- logger .Error ("failed to marshal secrets config" , "appId" , app .ID , "error" , marshalErr )
97- continue
98- }
72+ secretsBlob , marshalErr := deployutil .BuildSecretsBlob (envVarsByApp [row .App .ID ])
73+ if marshalErr != nil {
74+ logger .Error ("failed to marshal secrets config" , "appId" , row .App .ID , "error" , marshalErr )
75+ continue
9976 }
10077
101- deploymentID := uid .New (uid .DeploymentPrefix )
102- now := time .Now ().UnixMilli ()
103-
104- err = db .Tx (ctx , s .db .RW (), func (txCtx context.Context , tx db.DBTX ) error {
105- if txErr := db .Query .InsertDeployment (txCtx , tx , db.InsertDeploymentParams {
106- ID : deploymentID ,
107- K8sName : uid .DNS1035 (12 ),
108- WorkspaceID : project .WorkspaceID ,
109- ProjectID : project .ID ,
110- AppID : app .ID ,
111- EnvironmentID : env .ID ,
112- SentinelConfig : runtimeSettings .SentinelConfig ,
113- EncryptedEnvironmentVariables : secretsBlob ,
114- Command : runtimeSettings .Command ,
115- Status : db .DeploymentsStatusPending ,
116- CreatedAt : now ,
117- UpdatedAt : sql.NullInt64 {Valid : false },
118- GitCommitSha : sql.NullString {String : headCommit .SHA , Valid : true },
119- GitBranch : sql.NullString {String : branch , Valid : true },
120- GitCommitMessage : sql.NullString {String : headCommit .Message , Valid : headCommit .Message != "" },
121- GitCommitAuthorHandle : sql.NullString {String : headCommit .AuthorHandle , Valid : headCommit .AuthorHandle != "" },
122- GitCommitAuthorAvatarUrl : sql.NullString {String : headCommit .AuthorAvatarURL , Valid : headCommit .AuthorAvatarURL != "" },
123- GitCommitTimestamp : sql.NullInt64 {Int64 : commitTimestamp , Valid : true },
124- OpenapiSpec : sql.NullString {Valid : false },
125- CpuMillicores : runtimeSettings .CpuMillicores ,
126- MemoryMib : runtimeSettings .MemoryMib ,
127- Port : runtimeSettings .Port ,
128- ShutdownSignal : db .DeploymentsShutdownSignal (runtimeSettings .ShutdownSignal ),
129- Healthcheck : runtimeSettings .Healthcheck ,
130- }); txErr != nil {
131- return txErr
132- }
133-
134- return db .Query .InsertDeploymentStep (txCtx , tx , db.InsertDeploymentStepParams {
135- WorkspaceID : app .WorkspaceID ,
136- ProjectID : app .ProjectID ,
137- AppID : app .ID ,
138- EnvironmentID : env .ID ,
139- DeploymentID : deploymentID ,
140- Step : db .DeploymentStepsStepQueued ,
141- StartedAt : uint64 (now ),
142- })
143- })
144- if err != nil {
145- logger .Error ("failed to insert deployment for authorization" , "appId" , app .ID , "error" , err )
78+ deploymentID , insertErr := deployutil .InsertDeploymentRecord (ctx , s .db .RW (), row , commit , secretsBlob , db .DeploymentsStatusPending )
79+ if insertErr != nil {
80+ logger .Error ("failed to insert deployment for authorization" , "appId" , row .App .ID , "error" , insertErr )
14681 continue
14782 }
14883
149- // Fire deploy workflow via Restate
150- _ , sendErr := s .deploymentClient (project .ID ).
151- Deploy ().
152- Send (ctx , & hydrav1.DeployRequest {
153- DeploymentId : deploymentID ,
154- Source : & hydrav1.DeployRequest_Git {
155- Git : & hydrav1.GitSource {
156- InstallationId : repo .InstallationID ,
157- Repository : repo .RepositoryFullName ,
158- CommitSha : headCommit .SHA ,
159- ContextPath : buildSettings .DockerContext ,
160- DockerfilePath : buildSettings .Dockerfile ,
161- },
162- },
163- })
84+ deployReq := deployutil .BuildDeployRequest (deploymentID , row , headCommit .SHA )
85+ _ , sendErr := s .deploymentClient (row .Project .ID ).Deploy ().Send (ctx , deployReq )
16486 if sendErr != nil {
16587 logger .Error ("failed to trigger deploy workflow after authorization" ,
16688 "deployment_id" , deploymentID ,
@@ -171,8 +93,8 @@ func (s *Service) AuthorizeDeployment(ctx context.Context, req *connect.Request[
17193
17294 logger .Info ("deployment authorized and workflow triggered" ,
17395 "deployment_id" , deploymentID ,
174- "project_id" , project .ID ,
175- "app_id" , app .ID ,
96+ "project_id" , row . Project .ID ,
97+ "app_id" , row . App .ID ,
17698 "branch" , branch ,
17799 "commit_sha" , headCommit .SHA ,
178100 )
0 commit comments