2023-01-12 05:11:26 +00:00
|
|
|
package forge
|
|
|
|
|
2023-01-13 05:07:57 +00:00
|
|
|
import (
|
2023-01-13 23:04:41 +00:00
|
|
|
"errors"
|
2023-01-13 05:07:57 +00:00
|
|
|
"fmt"
|
|
|
|
"net/url"
|
2023-01-13 23:04:41 +00:00
|
|
|
"regexp"
|
|
|
|
"runtime"
|
2023-01-13 05:07:57 +00:00
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2023-01-13 23:04:41 +00:00
|
|
|
var (
|
2023-01-18 19:18:23 +00:00
|
|
|
amd64Re = regexp.MustCompile(`amd64|x86_64|64-bit|[^mhv]64`)
|
|
|
|
linuxRe = regexp.MustCompile(`linux`)
|
|
|
|
windowsRe = regexp.MustCompile(`windows|\Awin`)
|
|
|
|
installerRe = regexp.MustCompile(`\.deb|\.msi`)
|
2023-01-12 05:11:26 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type Release struct {
|
|
|
|
Name string
|
|
|
|
Assets []Asset
|
|
|
|
}
|
|
|
|
|
|
|
|
type Asset struct {
|
|
|
|
Name string
|
|
|
|
DownloadURL string
|
2023-01-15 03:31:58 +00:00
|
|
|
Version string // Release.Name
|
2023-01-12 05:11:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Forger interface {
|
2023-01-13 05:07:57 +00:00
|
|
|
Name() string
|
2023-01-15 03:31:58 +00:00
|
|
|
latestRelease() (Release, error)
|
|
|
|
tagRelease(tag string) (Release, error)
|
2023-01-12 05:11:26 +00:00
|
|
|
}
|
2023-01-13 05:07:57 +00:00
|
|
|
|
|
|
|
func splitURI(uri string) (string, []string, error) {
|
2023-01-13 23:04:41 +00:00
|
|
|
if !strings.HasPrefix(uri, "http") {
|
|
|
|
uri = "https://" + uri
|
|
|
|
}
|
2023-01-13 05:07:57 +00:00
|
|
|
u, err := url.ParseRequestURI(uri)
|
|
|
|
if err != nil {
|
|
|
|
return "", nil, fmt.Errorf("could not parse URI: %w", err)
|
|
|
|
}
|
|
|
|
u.Scheme = "https"
|
|
|
|
paths := strings.FieldsFunc(u.Path, func(r rune) bool { return r == '/' })
|
|
|
|
u.Path = ""
|
|
|
|
return u.String(), paths, nil
|
|
|
|
}
|
2023-01-13 23:04:41 +00:00
|
|
|
|
2023-01-15 03:31:58 +00:00
|
|
|
func TagRelease(f Forger, tag string) (Asset, error) {
|
2023-01-13 23:04:41 +00:00
|
|
|
var asset Asset
|
|
|
|
|
|
|
|
var re *regexp.Regexp
|
|
|
|
switch runtime.GOOS {
|
|
|
|
case "linux":
|
|
|
|
re = linuxRe
|
|
|
|
case "windows":
|
|
|
|
re = windowsRe
|
|
|
|
default:
|
|
|
|
return asset, fmt.Errorf("%q is not a supported OS", runtime.GOOS)
|
|
|
|
}
|
|
|
|
|
2023-01-15 03:31:58 +00:00
|
|
|
release, err := f.tagRelease(tag)
|
|
|
|
if err != nil {
|
|
|
|
return asset, fmt.Errorf("could not get %q release: %w", tag, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, a := range release.Assets {
|
|
|
|
if amd64Re.MatchString(a.Name) && re.MatchString(a.Name) {
|
|
|
|
fmt.Printf("found %q\n", a.Name)
|
|
|
|
asset = a
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if asset.Name == "" {
|
|
|
|
return asset, errors.New("no release found for this OS")
|
|
|
|
}
|
|
|
|
|
|
|
|
asset.Version = release.Name
|
|
|
|
return asset, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func LatestRelease(f Forger) (Asset, error) {
|
|
|
|
var asset Asset
|
|
|
|
|
|
|
|
var re *regexp.Regexp
|
|
|
|
switch runtime.GOOS {
|
|
|
|
case "linux":
|
|
|
|
re = linuxRe
|
|
|
|
case "windows":
|
|
|
|
re = windowsRe
|
|
|
|
default:
|
|
|
|
return asset, fmt.Errorf("%q is not a supported OS", runtime.GOOS)
|
|
|
|
}
|
|
|
|
|
|
|
|
release, err := f.latestRelease()
|
2023-01-13 23:04:41 +00:00
|
|
|
if err != nil {
|
|
|
|
return asset, fmt.Errorf("could not get latest release: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, a := range release.Assets {
|
2023-01-18 19:18:23 +00:00
|
|
|
if amd64Re.MatchString(a.Name) && re.MatchString(a.Name) && !installerRe.MatchString(a.Name) {
|
2023-01-13 23:04:41 +00:00
|
|
|
fmt.Printf("found %q\n", a.Name)
|
|
|
|
asset = a
|
2023-01-14 06:02:25 +00:00
|
|
|
break
|
2023-01-13 23:04:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if asset.Name == "" {
|
|
|
|
return asset, errors.New("no release found for this OS")
|
|
|
|
}
|
|
|
|
|
2023-01-15 03:31:58 +00:00
|
|
|
asset.Version = release.Name
|
2023-01-13 23:04:41 +00:00
|
|
|
return asset, nil
|
|
|
|
}
|