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 ()
@@ -156,28 +142,22 @@ var RollbackResources = Task{
156142 return fmt .Errorf ("The following errors occurred:\n " + strings .Join (system .Context .CurrentDeployment .RollbackErrors , "\n " ))
157143 }
158144
159- // Delete deployment version
160- //if err := xfs.DeleteFolder("ssh://"+system.Context.CurrentDeployment.GetPath(), true); err != nil {
161- // return fmt.Errorf("unable to remove deployment folder: " + err.Error())
162- //}
163-
164145 return nil
165146 },
166147}
167148
168149var CreateResources = Task {
169150 Name : "Creating resources" ,
170151 Run : func (r * Task ) error {
171- var errors []error
152+ var errors []string
172153 var uncompletedSpinners []* ysmrr.Spinner
173154
174155 for _ , resourceGroup := range system .Context .CurrentDeployment .ResourceGroups {
175156 for _ , resource := range resourceGroup .Resources {
176157 spinner := r .TaskRunner .GetNewSubtaskSpinner (resource .ToString (false ))
177- processed , err := system .ApplyResourceOperation (resource )
158+ processed , err := system .ApplyResourceOperation (resource , false )
178159 if err != nil {
179160 rollback = true
180- errors = append (errors , err )
181161 if spinner != nil {
182162 spinner .UpdateMessage (err .Error ())
183163 spinner .Error ()
@@ -201,7 +181,7 @@ var CreateResources = Task{
201181 spinner .Error ()
202182 }
203183 rollback = true
204- errors = append (errors , fmt .Errorf ("Unable to complete resource creation: %s" , err ))
184+ errors = append (errors , fmt .Sprintf ("Unable to complete resource creation: %s" , err ))
205185 }
206186 }
207187 if ! rollback {
@@ -219,24 +199,80 @@ var CreateResources = Task{
219199 }
220200 errorMessages := []string {"The following errors occurred:" }
221201 for _ , err2 := range errors {
222- errorMessages = append (errorMessages , "- " + err2 . Error () )
202+ errorMessages = append (errorMessages , "- " + err2 )
223203 }
224204 return fmt .Errorf (strings .Join (errorMessages , "\n " ))
225205 },
226206}
227207
208+ func reverse [S ~ []E , E any ](s S ) {
209+ for i , j := 0 , len (s )- 1 ; i < j ; i , j = i + 1 , j - 1 {
210+ s [i ], s [j ] = s [j ], s [i ]
211+ }
212+ }
213+
214+ var RemoveResources = func (latestDeployment * system.Deployment ) Task {
215+ return Task {
216+ Name : "Removing project resources" ,
217+ Run : func (r * Task ) error {
218+ var uncompletedSpinners []* ysmrr.Spinner
219+
220+ reverse (latestDeployment .ResourceGroups )
221+ for _ , group := range latestDeployment .ResourceGroups {
222+ reverse (group .Resources )
223+ for _ , resource := range group .Resources {
224+ if resource .ExternalResource {
225+ resource .Operation = system .OperationDelete
226+ spinner := r .TaskRunner .GetNewSubtaskSpinner (resource .ToString (false ))
227+ if processed , err := system .PerformOperation (resource , true ); err != nil {
228+ if err != nil {
229+ if spinner != nil {
230+ spinner .UpdateMessage (err .Error ())
231+ spinner .Error ()
232+ }
233+ return err
234+ }
235+ if spinner != nil {
236+ if processed {
237+ spinner .Complete ()
238+ } else {
239+ // uncompleted spinners are resolved when resource group finishes
240+ uncompletedSpinners = append (uncompletedSpinners , spinner )
241+ }
242+ }
243+ }
244+ }
245+ }
246+ for _ , spinner := range uncompletedSpinners {
247+ spinner .Complete ()
248+ }
249+ }
250+ return nil
251+ },
252+ }
253+ }
254+
228255var FinalizeDeployment = Task {
229256 Name : "Finalizing deployment" ,
230257 Run : func (r * Task ) error {
258+ // set deployment end date
231259 system .Context .CurrentDeployment .DateEnd = time .Now ()
232- resourcesPath := path .Join (system .Context .CurrentDeployment .GetPath (), "deployment.yaml" )
260+
261+ // save deployment.yaml file
233262 yamlString , err := yaml .Marshal (system .Context .CurrentDeployment )
234263 if err != nil {
235264 return err
236265 }
237- if err = xfs .WriteFile ("ssh://" + resourcesPath , string (yamlString )); err != nil {
266+ if err = xfs .WriteFile ("ssh://" + path . Join ( system . Context . CurrentDeployment . GetPath (), "deployment.yaml" ) , string (yamlString )); err != nil {
238267 return err
239268 }
269+
270+ // update current symlink if deployment was successful
271+ if ! system .Context .CurrentDeployment .RolledBack {
272+ if _ , err := system .SimpleRemoteRun ("ln" , system.RemoteRunOpts {Args : []string {"-sfn " + system .Context .CurrentDeployment .GetPath () + " " + path .Join (system .Context .CurrentDeployment .Project .GetDeploymentsPath (), "current" )}}); err != nil {
273+ return fmt .Errorf ("Unable to symlink current deployment: " + err .Error ())
274+ }
275+ }
240276 return nil
241277 },
242278}
0 commit comments