@@ -140,6 +140,14 @@ func (c *UpdaterClient) UpdateToNewVersion(version, edition, changelog string) e
140140 config .Logger ().Info ("Updating UTMStack to version %s-%s..." , version , edition )
141141 config .Updating = true
142142
143+ // Update installer binary first (only in prod branch)
144+ cnf := config .GetConfig ()
145+ if cnf .Branch == "prod" || cnf .Branch == "" {
146+ if err := c .UpdateInstaller (version ); err != nil {
147+ config .Logger ().ErrorF ("error updating installer: %v" , err )
148+ }
149+ }
150+
143151 err := docker .StackUP (version + "-" + edition )
144152 if err != nil {
145153 return fmt .Errorf ("error updating UTMStack: %v" , err )
@@ -153,9 +161,67 @@ func (c *UpdaterClient) UpdateToNewVersion(version, edition, changelog string) e
153161 config .Logger ().Info ("UTMStack updated to version %s-%s" , version , edition )
154162 config .Updating = false
155163
156- err = utils .RunCmd ("docker" , "system" , "prune" , "-f" )
164+ time .Sleep (3 * time .Minute )
165+
166+ err = utils .RunCmd ("docker" , "image" , "prune" , "-a" , "-f" )
167+ if err != nil {
168+ config .Logger ().ErrorF ("error cleaning up old Docker images after update: %v" , err )
169+ }
170+
171+ // Restart service to load new installer binary
172+ if cnf .Branch == "prod" || cnf .Branch == "" {
173+ go func () {
174+ time .Sleep (5 * time .Second )
175+ utils .RestartService ("UTMStackComponentsUpdater" )
176+ }()
177+ }
178+
179+ return nil
180+ }
181+
182+ func (c * UpdaterClient ) UpdateInstaller (version string ) error {
183+ execPath , err := os .Executable ()
184+ if err != nil {
185+ return fmt .Errorf ("error getting executable path: %v" , err )
186+ }
187+
188+ // Download new installer from GitHub
189+ url := fmt .Sprintf (config .GitHubReleasesURL , version )
190+ resp , err := http .Get (url )
191+ if err != nil {
192+ return fmt .Errorf ("error downloading installer from %s: %v" , url , err )
193+ }
194+ defer resp .Body .Close ()
195+
196+ if resp .StatusCode != http .StatusOK {
197+ return fmt .Errorf ("error downloading installer: status %d" , resp .StatusCode )
198+ }
199+
200+ // Create temp file
201+ tmpFile , err := os .CreateTemp ("" , "installer-*" )
157202 if err != nil {
158- config .Logger ().ErrorF ("error cleaning up Docker system after update: %v" , err )
203+ return fmt .Errorf ("error creating temp file: %v" , err )
204+ }
205+ tmpPath := tmpFile .Name ()
206+
207+ // Download to temp file
208+ _ , err = io .Copy (tmpFile , resp .Body )
209+ tmpFile .Close ()
210+ if err != nil {
211+ os .Remove (tmpPath )
212+ return fmt .Errorf ("error writing installer to temp file: %v" , err )
213+ }
214+
215+ // Make executable
216+ if err := os .Chmod (tmpPath , 0755 ); err != nil {
217+ os .Remove (tmpPath )
218+ return fmt .Errorf ("error making installer executable: %v" , err )
219+ }
220+
221+ // Replace current binary
222+ if err := os .Rename (tmpPath , execPath ); err != nil {
223+ os .Remove (tmpPath )
224+ return fmt .Errorf ("error replacing installer binary: %v" , err )
159225 }
160226
161227 return nil
0 commit comments