55 "os"
66 "os/exec"
77 "strings"
8+ "time"
89)
910
1011// Deploy executes the deployment
@@ -165,4 +166,130 @@ func buildDeployParams(config *Config) string {
165166 params = append (params , fmt .Sprintf ("CLUSTER_NAME=%s" , clusterName ))
166167
167168 return strings .Join (params , "," )
169+ }
170+
171+ // triggerBuild triggers a Cloud Build for the specified environment
172+ func triggerBuild (config * Config , environment string ) error {
173+ fmt .Printf ("Triggering %s build...\n " , environment )
174+
175+ // Build substitutions
176+ substitutions := []string {
177+ fmt .Sprintf ("_PROJECT_ID=%s" , config .ProjectID ),
178+ fmt .Sprintf ("_REGION=%s" , config .Region ),
179+ fmt .Sprintf ("_IMAGE_REPO=%s-images" , config .AppConfig .App ),
180+ fmt .Sprintf ("_CACHE_REPO=%s-cache" , config .AppConfig .App ),
181+ fmt .Sprintf ("_IMAGE_NAME=%s" , config .AppConfig .App ),
182+ fmt .Sprintf ("_IMAGE_PREFIX=%s" , environment ),
183+ fmt .Sprintf ("COMMIT_SHA=%s" , config .CommitSHA ),
184+ fmt .Sprintf ("SHORT_SHA=%s" , config .ShortSHA ),
185+ }
186+
187+ // Build gcloud command
188+ triggerName := fmt .Sprintf ("%s-%s-trigger" , config .AppConfig .App , environment )
189+ args := []string {
190+ "builds" , "triggers" , "run" , triggerName ,
191+ "--region=" + config .Region ,
192+ "--project=" + config .ProjectID ,
193+ "--branch=master" ,
194+ }
195+
196+ // Add substitutions
197+ for _ , sub := range substitutions {
198+ args = append (args , "--substitutions=" + sub )
199+ }
200+
201+ cmd := exec .Command ("gcloud" , args ... )
202+ cmd .Stdout = os .Stdout
203+ cmd .Stderr = os .Stderr
204+
205+ if err := cmd .Run (); err != nil {
206+ return fmt .Errorf ("failed to trigger build: %w" , err )
207+ }
208+
209+ // Wait for build to complete
210+ fmt .Println ("Waiting for build to complete..." )
211+ return waitForBuild (config , triggerName )
212+ }
213+
214+ // triggerBuildWithTag triggers a Cloud Build for QA with tag
215+ func triggerBuildWithTag (config * Config , environment string , tagName string ) error {
216+ fmt .Printf ("Triggering %s build with tag %s...\n " , environment , tagName )
217+
218+ // Build substitutions
219+ substitutions := []string {
220+ fmt .Sprintf ("_PROJECT_ID=%s" , config .ProjectID ),
221+ fmt .Sprintf ("_REGION=%s" , config .Region ),
222+ fmt .Sprintf ("_IMAGE_REPO=%s-images" , config .AppConfig .App ),
223+ fmt .Sprintf ("_CACHE_REPO=%s-cache" , config .AppConfig .App ),
224+ fmt .Sprintf ("_IMAGE_NAME=%s" , config .AppConfig .App ),
225+ fmt .Sprintf ("_IMAGE_PREFIX=%s" , environment ),
226+ fmt .Sprintf ("COMMIT_SHA=%s" , config .CommitSHA ),
227+ fmt .Sprintf ("SHORT_SHA=%s" , config .ShortSHA ),
228+ fmt .Sprintf ("TAG_NAME=%s" , tagName ),
229+ }
230+
231+ // Build gcloud command for QA (uses tag trigger)
232+ triggerName := fmt .Sprintf ("%s-qa-deployment" , config .AppConfig .App )
233+ args := []string {
234+ "builds" , "triggers" , "run" , triggerName ,
235+ "--region=" + config .Region ,
236+ "--project=" + config .ProjectID ,
237+ "--tag=" + tagName ,
238+ }
239+
240+ // Add substitutions
241+ for _ , sub := range substitutions {
242+ args = append (args , "--substitutions=" + sub )
243+ }
244+
245+ cmd := exec .Command ("gcloud" , args ... )
246+ cmd .Stdout = os .Stdout
247+ cmd .Stderr = os .Stderr
248+
249+ if err := cmd .Run (); err != nil {
250+ return fmt .Errorf ("failed to trigger build: %w" , err )
251+ }
252+
253+ // Wait for build to complete
254+ fmt .Println ("Waiting for build to complete..." )
255+ return waitForBuild (config , triggerName )
256+ }
257+
258+ // waitForBuild waits for a Cloud Build to complete
259+ func waitForBuild (config * Config , triggerName string ) error {
260+ maxAttempts := 60 // 30 minutes with 30 second intervals
261+
262+ for i := 0 ; i < maxAttempts ; i ++ {
263+ // Get latest build status
264+ args := []string {
265+ "builds" , "list" ,
266+ "--region=" + config .Region ,
267+ "--project=" + config .ProjectID ,
268+ "--limit=1" ,
269+ "--filter=substitutions.TRIGGER_NAME:" + triggerName ,
270+ "--format=value(status)" ,
271+ }
272+
273+ cmd := exec .Command ("gcloud" , args ... )
274+ output , err := cmd .Output ()
275+ if err != nil {
276+ return fmt .Errorf ("failed to get build status: %w" , err )
277+ }
278+
279+ status := strings .TrimSpace (string (output ))
280+
281+ switch status {
282+ case "SUCCESS" :
283+ fmt .Println ("✅ Build completed successfully" )
284+ return nil
285+ case "FAILURE" , "TIMEOUT" , "CANCELLED" :
286+ return fmt .Errorf ("build failed with status: %s" , status )
287+ default :
288+ // Still running
289+ fmt .Printf ("Build status: %s - waiting...\n " , status )
290+ time .Sleep (30 * time .Second )
291+ }
292+ }
293+
294+ return fmt .Errorf ("build timed out after 30 minutes" )
168295}
0 commit comments