@@ -7,18 +7,24 @@ import (
77 "flag"
88 "fmt"
99
10+ "encoding/json"
1011 "log"
1112 "net"
1213 "net/http"
1314 _ "net/http/pprof"
1415 "os"
16+ "os/exec"
1517 "os/signal"
1618 "path"
19+ "path/filepath"
1720 "runtime"
1821 "runtime/pprof"
22+
1923 "strings"
2024 "time"
2125
26+ "github.com/hashicorp/go-version"
27+
2228 adj_module "github.com/HyperloopUPV-H8/h9-backend/internal/adj"
2329 "github.com/HyperloopUPV-H8/h9-backend/internal/common"
2430 "github.com/HyperloopUPV-H8/h9-backend/internal/pod_data"
@@ -76,9 +82,25 @@ var enableSNTP = flag.Bool("sntp", false, "enables a simple SNTP server on port
7682var networkDevice = flag .Int ("dev" , - 1 , "index of the network device to use, overrides device prompt" )
7783var blockprofile = flag .Int ("blockprofile" , 0 , "number of block profiles to include" )
7884var playbackFile = flag .String ("playback" , "" , "" )
85+ var currentVersion string
7986
8087func main () {
88+
89+ versionFile := "VERSION.md"
90+ versionData , err := os .ReadFile (versionFile )
91+ if err != nil {
92+ fmt .Fprintf (os .Stderr , "Error reading version file (%s): %v\n " , versionFile , err )
93+ os .Exit (1 )
94+ }
95+ currentVersion = strings .TrimSpace (string (versionData ))
96+
97+ versionFlag := flag .Bool ("version" , false , "Show the backend version" )
8198 flag .Parse ()
99+ if * versionFlag {
100+ fmt .Println ("Hyperloop UPV Backend Version:" , currentVersion )
101+ os .Exit (0 )
102+ }
103+
82104 traceFile := initTrace (* traceLevel , * traceFile )
83105 defer traceFile .Close ()
84106
@@ -99,6 +121,89 @@ func main() {
99121 runtime .SetBlockProfileRate (* blockprofile )
100122
101123 config := getConfig ("./config.toml" )
124+ latestVersionStr , err := getLatestVersionFromGitHub ()
125+ if err != nil {
126+ fmt .Println ("Warning:" , err )
127+ fmt .Println ("Skipping version check. Proceeding with the current version:" , currentVersion )
128+ } else {
129+ current , err := version .NewVersion (currentVersion )
130+ if err != nil {
131+ fmt .Println ("Invalid current version:" , err )
132+ return
133+ }
134+
135+ latest , err := version .NewVersion (latestVersionStr )
136+ if err != nil {
137+ fmt .Println ("Invalid latest version:" , err )
138+ return
139+ }
140+
141+ if latest .GreaterThan (current ) {
142+ fmt .Printf ("There is a new version available: %s (current version: %s)\n " , latest , current )
143+ fmt .Print ("Do you want to update? (y/n): " )
144+
145+ var response string
146+ fmt .Scanln (& response )
147+
148+ if strings .ToLower (response ) == "y" {
149+ fmt .Println ("Launching updater to update the backend..." )
150+
151+ // Get the directory of the current executable
152+ execPath , err := os .Executable ()
153+ if err != nil {
154+ fmt .Fprintf (os .Stderr , "Error getting executable path: %v\n " , err )
155+ os .Exit (1 )
156+ }
157+ execDir := filepath .Dir (execPath )
158+
159+ backendPath := filepath .Join (execDir , ".." , ".." , "backend" )
160+
161+ if _ , err := os .Stat (backendPath ); err == nil {
162+
163+ fmt .Println ("Backend folder detected. Building and launching updater..." )
164+
165+ updaterPath := filepath .Join (execDir , ".." , ".." , "updater" )
166+
167+ cmd := exec .Command ("go" , "build" , "-o" , filepath .Join (updaterPath , "updater.exe" ), updaterPath )
168+ cmd .Stdout = os .Stdout
169+ cmd .Stderr = os .Stderr
170+ if err := cmd .Run (); err != nil {
171+ fmt .Fprintf (os .Stderr , "Error building updater: %v\n " , err )
172+ os .Exit (1 )
173+ }
174+
175+ updaterExe := filepath .Join (updaterPath , "updater.exe" )
176+ cmd = exec .Command (updaterExe )
177+ cmd .Dir = updaterPath
178+ cmd .Stdout = os .Stdout
179+ cmd .Stderr = os .Stderr
180+ if err := cmd .Run (); err != nil {
181+ fmt .Fprintf (os .Stderr , "Error launching updater: %v\n " , err )
182+ os .Exit (1 )
183+ }
184+ } else {
185+
186+ fmt .Println ("Backend folder not detected. Launching existing updater..." )
187+
188+ updaterExe := filepath .Join (execDir , "updater.exe" )
189+ cmd := exec .Command (updaterExe )
190+ cmd .Dir = filepath .Dir (updaterExe )
191+ cmd .Stdout = os .Stdout
192+ cmd .Stderr = os .Stderr
193+ if err := cmd .Run (); err != nil {
194+ fmt .Fprintf (os .Stderr , "Error launching updater: %v\n " , err )
195+ os .Exit (1 )
196+ }
197+ }
198+
199+ os .Exit (0 )
200+ } else {
201+ fmt .Println ("Skipping update. Proceeding with the current version." )
202+ }
203+ } else {
204+ fmt .Printf ("You are using the latest version: %s\n " , current )
205+ }
206+ }
102207
103208 // <--- ADJ --->
104209
@@ -590,3 +695,23 @@ func getUDPFilter(addrs []net.IP, backendAddr net.IP, port uint16) string {
590695
591696 return fmt .Sprintf ("(%s) and (%s) and (%s or (dst host %s))" , udpPort , srcUdpAddrsStr , dstUdpAddrsStr , backendAddr )
592697}
698+
699+ type GitHubRelease struct {
700+ TagName string `json:"tag_name"`
701+ }
702+
703+ func getLatestVersionFromGitHub () (string , error ) {
704+ resp , err := http .Get ("https://api.github.com/repos/HyperloopUPV-H8/software/releases/latest" )
705+ if err != nil {
706+ return "" , fmt .Errorf ("unable to connect to the internet: %w" , err )
707+ }
708+ defer resp .Body .Close ()
709+
710+ var release GitHubRelease
711+ if err := json .NewDecoder (resp .Body ).Decode (& release ); err != nil {
712+ return "" , fmt .Errorf ("error decoding GitHub response: %w" , err )
713+ }
714+
715+ version := strings .TrimPrefix (release .TagName , "v" )
716+ return version , nil
717+ }
0 commit comments