77 logger "github.com/sirupsen/logrus"
88 "gopkg.in/yaml.v3"
99 "path"
10- "sort "
10+ "strconv "
1111 "strings"
1212 "time"
1313
@@ -37,7 +37,7 @@ var ValidateStackHeadVersionTask = Task{
3737
3838var PrepareProjectTask = func (projectDefinition * project.Project ) Task {
3939 return Task {
40- Name : fmt .Sprintf ("Preparing project structure " ),
40+ Name : fmt .Sprintf ("Preparing deployment " ),
4141 Run : func (r * Task ) error {
4242 r .PrintLn ("Create project directory if not exists" )
4343 if err := xfs .CreateFolder ("ssh://" + projectDefinition .GetDirectoryPath ()); err != nil {
@@ -47,40 +47,25 @@ var PrepareProjectTask = func(projectDefinition *project.Project) Task {
4747 return err
4848 }
4949
50+ r .PrintLn ("Lookup previous deployments" )
5051 // Find latest deployment
51- files , err := xfs . ListFolders ( "ssh://" + projectDefinition . GetDeploymentsPath () )
52+ latestDeployment , err := system . GetLatestDeployment ( projectDefinition )
5253 if err != nil {
5354 return err
5455 }
55- if files != nil {
56- // newest files at the top
57- sort .Slice (files , func (i , j int ) bool {
58- return files [i ].ModTime ().After (files [j ].ModTime ())
59- })
60- for _ , file := range files {
61- if file .IsDir () && system .MatchDeploymentNaming (file .Name ()) {
62- fullPath := path .Join (projectDefinition .GetDeploymentsPath (), file .Name ())
63- latestDeployment , err := system .GetDeploymentByPath (fullPath )
64- if err != nil {
65- return err
66- }
67- if ! latestDeployment .RolledBack {
68- latestDeployment .Project = system .Context .Project
69- system .Context .LatestDeployment = latestDeployment
70- break
71- }
72- }
73- }
74- }
56+ system .Context .LatestDeployment = latestDeployment
57+ oldVersion := "N/A"
7558 newVersion := 1
7659 if system .Context .LatestDeployment != nil {
60+ oldVersion = "v" + strconv .Itoa (system .Context .LatestDeployment .Version )
7761 newVersion = system .Context .LatestDeployment .Version + 1
7862 }
7963 system .Context .CurrentDeployment = system.Deployment {
8064 Version : newVersion ,
8165 DateStart : time .Now (),
8266 Project : system .Context .Project ,
8367 }
68+ r .PrintLn (fmt .Sprintf ("Previous deployment: %s, new deployment: v%d" , oldVersion , newVersion ))
8469
8570 // Create folder for new deployment
8671 if err := xfs .CreateFolder ("ssh://" + system .Context .CurrentDeployment .GetPath ()); err != nil {
@@ -104,6 +89,7 @@ var CollectResourcesTask = func(projectDefinition *project.Project) Task {
10489 if module .GetConfig ().Type == "plugin" {
10590 continue
10691 }
92+ r .PrintLn ("Collecting from " + module .GetConfig ().Name )
10793 moduleSettings := system .GetModuleSettings (module .GetConfig ().Name )
10894 if err := module .Deploy (moduleSettings ); err != nil {
10995 return err
@@ -132,7 +118,7 @@ var RollbackResources = Task{
132118 }
133119 for _ , resource := range resourceGroup .Resources {
134120 spinner := r .TaskRunner .GetNewSubtaskSpinner (resource .ToString (true ))
135- matched , err := system .RollbackResourceOperation (resource )
121+ matched , err := system .RollbackResourceOperation (resource , false )
136122 if ! matched || err == nil {
137123 if spinner != nil {
138124 spinner .Complete ()
@@ -168,16 +154,16 @@ var RollbackResources = Task{
168154var CreateResources = Task {
169155 Name : "Creating resources" ,
170156 Run : func (r * Task ) error {
171- var errors []error
157+ var errors []string
172158 var uncompletedSpinners []* ysmrr.Spinner
173159
174160 for _ , resourceGroup := range system .Context .CurrentDeployment .ResourceGroups {
175161 for _ , resource := range resourceGroup .Resources {
176162 spinner := r .TaskRunner .GetNewSubtaskSpinner (resource .ToString (false ))
177- processed , err := system .ApplyResourceOperation (resource )
163+ processed , err := system .ApplyResourceOperation (resource , false )
178164 if err != nil {
179165 rollback = true
180- errors = append (errors , err )
166+ errors = append (errors , err . Error () )
181167 if spinner != nil {
182168 spinner .UpdateMessage (err .Error ())
183169 spinner .Error ()
@@ -201,7 +187,7 @@ var CreateResources = Task{
201187 spinner .Error ()
202188 }
203189 rollback = true
204- errors = append (errors , fmt .Errorf ("Unable to complete resource creation: %s" , err ))
190+ errors = append (errors , fmt .Sprintf ("Unable to complete resource creation: %s" , err ))
205191 }
206192 }
207193 if ! rollback {
@@ -219,24 +205,89 @@ var CreateResources = Task{
219205 }
220206 errorMessages := []string {"The following errors occurred:" }
221207 for _ , err2 := range errors {
222- errorMessages = append (errorMessages , "- " + err2 . Error () )
208+ errorMessages = append (errorMessages , "- " + err2 )
223209 }
224210 return fmt .Errorf (strings .Join (errorMessages , "\n " ))
225211 },
226212}
227213
214+ func reverse [S ~ []E , E any ](s S ) {
215+ for i , j := 0 , len (s )- 1 ; i < j ; i , j = i + 1 , j - 1 {
216+ s [i ], s [j ] = s [j ], s [i ]
217+ }
218+ }
219+
220+ var RemoveResources = func (latestDeployment * system.Deployment ) Task {
221+ return Task {
222+ Name : "Removing project resources" ,
223+ Run : func (r * Task ) error {
224+ var errors []string
225+ var uncompletedSpinners []* ysmrr.Spinner
226+
227+ reverse (latestDeployment .ResourceGroups )
228+ for _ , group := range latestDeployment .ResourceGroups {
229+ reverse (group .Resources )
230+ for _ , resource := range group .Resources {
231+ if resource .ExternalResource {
232+ resource .Operation = system .OperationDelete
233+ spinner := r .TaskRunner .GetNewSubtaskSpinner (resource .ToString (false ))
234+ if processed , err := system .PerformOperation (resource , true ); err != nil {
235+ if err != nil {
236+ errors = append (errors , err .Error ())
237+ if spinner != nil {
238+ spinner .UpdateMessage (err .Error ())
239+ spinner .Error ()
240+ }
241+ return err
242+ }
243+ if spinner != nil {
244+ if processed {
245+ spinner .Complete ()
246+ } else {
247+ // uncompleted spinners are resolved when resource group finishes
248+ uncompletedSpinners = append (uncompletedSpinners , spinner )
249+ }
250+ }
251+ }
252+ }
253+ }
254+ for _ , spinner := range uncompletedSpinners {
255+ spinner .Complete ()
256+ }
257+ }
258+ if len (errors ) == 0 {
259+ return nil
260+ }
261+ errorMessages := []string {"The following errors occurred:" }
262+ for _ , err2 := range errors {
263+ errorMessages = append (errorMessages , "- " + err2 )
264+ }
265+ return fmt .Errorf (strings .Join (errorMessages , "\n " ))
266+ },
267+ }
268+ }
269+
228270var FinalizeDeployment = Task {
229271 Name : "Finalizing deployment" ,
230272 Run : func (r * Task ) error {
273+ // set deployment end date
231274 system .Context .CurrentDeployment .DateEnd = time .Now ()
232- resourcesPath := path .Join (system .Context .CurrentDeployment .GetPath (), "deployment.yaml" )
275+
276+ // save deployment.yaml file
233277 yamlString , err := yaml .Marshal (system .Context .CurrentDeployment )
234278 if err != nil {
235279 return err
236280 }
237- if err = xfs .WriteFile ("ssh://" + resourcesPath , string (yamlString )); err != nil {
281+ if err = xfs .WriteFile ("ssh://" + path . Join ( system . Context . CurrentDeployment . GetPath (), "deployment.yaml" ) , string (yamlString )); err != nil {
238282 return err
239283 }
284+
285+ // update current symlink if deployment was successful
286+ if ! system .Context .CurrentDeployment .RolledBack {
287+ if _ , err := system .SimpleRemoteRun ("ln" , system.RemoteRunOpts {Args : []string {"-sfn " + system .Context .CurrentDeployment .GetPath () + " " + path .Join (system .Context .CurrentDeployment .Project .GetDeploymentsPath (), "current" )}}); err != nil {
288+ return fmt .Errorf ("Unable to symlink current deployment: " + err .Error ())
289+ }
290+ }
240291 return nil
241292 },
242293}
0 commit comments