mirror of
https://github.com/ddworken/hishtory.git
synced 2025-08-17 18:31:43 +02:00
break down release versions and fix server tests
This commit is contained in:
@ -2,21 +2,16 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/ddworken/hishtory/internal/release"
|
||||
"github.com/ddworken/hishtory/internal/server"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/DataDog/datadog-go/statsd"
|
||||
"github.com/ddworken/hishtory/internal/database"
|
||||
"github.com/ddworken/hishtory/shared"
|
||||
_ "github.com/lib/pq"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
@ -28,9 +23,8 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
GLOBAL_DB *database.DB
|
||||
GLOBAL_STATSD *statsd.Client
|
||||
ReleaseVersion string = "UNKNOWN"
|
||||
GLOBAL_DB *database.DB
|
||||
GLOBAL_STATSD *statsd.Client
|
||||
)
|
||||
|
||||
func isTestEnvironment() bool {
|
||||
@ -102,15 +96,14 @@ func OpenDB() (*database.DB, error) {
|
||||
}
|
||||
|
||||
func init() {
|
||||
if ReleaseVersion == "UNKNOWN" && !isTestEnvironment() {
|
||||
if release.Version == "UNKNOWN" && !isTestEnvironment() {
|
||||
panic("server.go was built without a ReleaseVersion!")
|
||||
}
|
||||
InitDB()
|
||||
go runBackgroundJobs(context.Background())
|
||||
}
|
||||
|
||||
func cron(ctx context.Context, db *database.DB, stats *statsd.Client) error {
|
||||
if err := updateReleaseVersion(); err != nil {
|
||||
if err := release.UpdateReleaseVersion(); err != nil {
|
||||
return fmt.Errorf("updateReleaseVersion: %w", err)
|
||||
}
|
||||
|
||||
@ -125,7 +118,7 @@ func cron(ctx context.Context, db *database.DB, stats *statsd.Client) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runBackgroundJobs(ctx context.Context) {
|
||||
func runBackgroundJobs(ctx context.Context, srv *server.Server) {
|
||||
time.Sleep(5 * time.Second)
|
||||
for {
|
||||
err := cron(ctx, GLOBAL_DB, GLOBAL_STATSD)
|
||||
@ -135,80 +128,12 @@ func runBackgroundJobs(ctx context.Context) {
|
||||
// cron no longer panics, panicking here.
|
||||
panic(err)
|
||||
}
|
||||
srv.UpdateReleaseVersion(release.Version, release.BuildUpdateInfo(release.Version))
|
||||
time.Sleep(10 * time.Minute)
|
||||
}
|
||||
}
|
||||
|
||||
type releaseInfo struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func updateReleaseVersion() error {
|
||||
resp, err := http.Get("https://api.github.com/repos/ddworken/hishtory/releases/latest")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get latest release version: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read github API response body: %w", err)
|
||||
}
|
||||
if resp.StatusCode == 403 && strings.Contains(string(respBody), "API rate limit exceeded for ") {
|
||||
return nil
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("failed to call github API, status_code=%d, body=%#v", resp.StatusCode, string(respBody))
|
||||
}
|
||||
var info releaseInfo
|
||||
err = json.Unmarshal(respBody, &info)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse github API response: %w", err)
|
||||
}
|
||||
latestVersionTag := info.Name
|
||||
ReleaseVersion = decrementVersionIfInvalid(latestVersionTag)
|
||||
return nil
|
||||
}
|
||||
|
||||
func decrementVersionIfInvalid(initialVersion string) string {
|
||||
// Decrements the version up to 5 times if the version doesn't have valid binaries yet.
|
||||
version := initialVersion
|
||||
for i := 0; i < 5; i++ {
|
||||
updateInfo := buildUpdateInfo(version)
|
||||
err := assertValidUpdate(updateInfo)
|
||||
if err == nil {
|
||||
fmt.Printf("Found a valid version: %v\n", version)
|
||||
return version
|
||||
}
|
||||
fmt.Printf("Found %s to be an invalid version: %v\n", version, err)
|
||||
version, err = decrementVersion(version)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to decrement version after finding the latest version was invalid: %v\n", err)
|
||||
return initialVersion
|
||||
}
|
||||
}
|
||||
fmt.Printf("Decremented the version 5 times and failed to find a valid version version number, initial version number: %v, last checked version number: %v\n", initialVersion, version)
|
||||
return initialVersion
|
||||
}
|
||||
|
||||
func assertValidUpdate(updateInfo shared.UpdateInfo) error {
|
||||
urls := []string{updateInfo.LinuxAmd64Url, updateInfo.LinuxAmd64AttestationUrl, updateInfo.LinuxArm64Url, updateInfo.LinuxArm64AttestationUrl,
|
||||
updateInfo.LinuxArm7Url, updateInfo.LinuxArm7AttestationUrl,
|
||||
updateInfo.DarwinAmd64Url, updateInfo.DarwinAmd64UnsignedUrl, updateInfo.DarwinAmd64AttestationUrl,
|
||||
updateInfo.DarwinArm64Url, updateInfo.DarwinArm64UnsignedUrl, updateInfo.DarwinArm64AttestationUrl}
|
||||
for _, url := range urls {
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to retrieve URL %#v: %w", url, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode == 404 {
|
||||
return fmt.Errorf("URL %#v returned 404", url)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func InitDB() {
|
||||
func InitDB() *database.DB {
|
||||
var err error
|
||||
GLOBAL_DB, err = OpenDB()
|
||||
if err != nil {
|
||||
@ -228,39 +153,8 @@ func InitDB() {
|
||||
panic(fmt.Errorf("failed to set max idle conns: %w", err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func decrementVersion(version string) (string, error) {
|
||||
if version == "UNKNOWN" {
|
||||
return "", fmt.Errorf("cannot decrement UNKNOWN")
|
||||
}
|
||||
parts := strings.Split(version, ".")
|
||||
if len(parts) != 2 {
|
||||
return "", fmt.Errorf("invalid version: %s", version)
|
||||
}
|
||||
versionNumber, err := strconv.Atoi(parts[1])
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid version: %s", version)
|
||||
}
|
||||
return parts[0] + "." + strconv.Itoa(versionNumber-1), nil
|
||||
}
|
||||
|
||||
func buildUpdateInfo(version string) shared.UpdateInfo {
|
||||
return shared.UpdateInfo{
|
||||
LinuxAmd64Url: fmt.Sprintf("https://github.com/ddworken/hishtory/releases/download/%s/hishtory-linux-amd64", version),
|
||||
LinuxAmd64AttestationUrl: fmt.Sprintf("https://github.com/ddworken/hishtory/releases/download/%s/hishtory-linux-amd64.intoto.jsonl", version),
|
||||
LinuxArm64Url: fmt.Sprintf("https://github.com/ddworken/hishtory/releases/download/%s/hishtory-linux-arm64", version),
|
||||
LinuxArm64AttestationUrl: fmt.Sprintf("https://github.com/ddworken/hishtory/releases/download/%s/hishtory-linux-arm64.intoto.jsonl", version),
|
||||
LinuxArm7Url: fmt.Sprintf("https://github.com/ddworken/hishtory/releases/download/%s/hishtory-linux-arm", version),
|
||||
LinuxArm7AttestationUrl: fmt.Sprintf("https://github.com/ddworken/hishtory/releases/download/%s/hishtory-linux-arm.intoto.jsonl", version),
|
||||
DarwinAmd64Url: fmt.Sprintf("https://github.com/ddworken/hishtory/releases/download/%s/hishtory-darwin-amd64", version),
|
||||
DarwinAmd64UnsignedUrl: fmt.Sprintf("https://github.com/ddworken/hishtory/releases/download/%s/hishtory-darwin-amd64-unsigned", version),
|
||||
DarwinAmd64AttestationUrl: fmt.Sprintf("https://github.com/ddworken/hishtory/releases/download/%s/hishtory-darwin-amd64.intoto.jsonl", version),
|
||||
DarwinArm64Url: fmt.Sprintf("https://github.com/ddworken/hishtory/releases/download/%s/hishtory-darwin-arm64", version),
|
||||
DarwinArm64UnsignedUrl: fmt.Sprintf("https://github.com/ddworken/hishtory/releases/download/%s/hishtory-darwin-arm64-unsigned", version),
|
||||
DarwinArm64AttestationUrl: fmt.Sprintf("https://github.com/ddworken/hishtory/releases/download/%s/hishtory-darwin-arm64.intoto.jsonl", version),
|
||||
Version: version,
|
||||
}
|
||||
return GLOBAL_DB
|
||||
}
|
||||
|
||||
func main() {
|
||||
@ -275,13 +169,15 @@ func main() {
|
||||
srv := server.NewServer(
|
||||
GLOBAL_DB,
|
||||
server.WithStatsd(s),
|
||||
server.WithReleaseVersion(ReleaseVersion),
|
||||
server.WithReleaseVersion(release.Version),
|
||||
server.IsTestEnvironment(isTestEnvironment()),
|
||||
server.IsProductionEnvironment(isProductionEnvironment()),
|
||||
server.WithCron(cron),
|
||||
server.WithUpdateInfo(buildUpdateInfo(ReleaseVersion)),
|
||||
server.WithUpdateInfo(release.BuildUpdateInfo(release.Version)),
|
||||
)
|
||||
|
||||
go runBackgroundJobs(context.Background(), srv)
|
||||
|
||||
if err := srv.Run(context.Background(), ":8080"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
Reference in New Issue
Block a user