mirror of https://github.com/statping/statping
database migrations - gh updates - 29.6
parent
1f2991e765
commit
5f2037a2cd
|
@ -18,7 +18,7 @@ services:
|
|||
|
||||
env:
|
||||
global:
|
||||
- VERSION=0.29.5
|
||||
- VERSION=0.29.6
|
||||
- DB_HOST=localhost
|
||||
- DB_USER=travis
|
||||
- DB_PASS=
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
FROM alpine:latest
|
||||
|
||||
ENV VERSION=v0.29.5
|
||||
ENV VERSION=v0.29.6
|
||||
|
||||
RUN apk --no-cache add libstdc++ ca-certificates
|
||||
RUN wget -q https://github.com/hunterlong/statup/releases/download/$VERSION/statup-linux-alpine.tar.gz && \
|
||||
|
|
120
cli.go
120
cli.go
|
@ -1,13 +1,17 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/hunterlong/statup/core"
|
||||
"github.com/hunterlong/statup/plugin"
|
||||
"github.com/hunterlong/statup/types"
|
||||
"github.com/hunterlong/statup/utils"
|
||||
"github.com/joho/godotenv"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
"upper.io/db.v3/sqlite"
|
||||
|
@ -27,8 +31,18 @@ func CatchCLI(args []string) {
|
|||
core.CreateAllAssets()
|
||||
case "sass":
|
||||
core.CompileSASS()
|
||||
case "api":
|
||||
HelpEcho()
|
||||
case "update":
|
||||
gitCurrent, err := CheckGithubUpdates()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(2)
|
||||
}
|
||||
fmt.Printf("Statup Version: v%v\nLatest Version: %v\n", VERSION, gitCurrent.TagName)
|
||||
if VERSION != gitCurrent.TagName[1:] {
|
||||
fmt.Printf("You don't have the latest version v%v!\nDownload the latest release at: https://github.com/hunterlong/statup\n", gitCurrent.TagName[1:])
|
||||
} else {
|
||||
fmt.Printf("You have the latest version of Statup!\n")
|
||||
}
|
||||
case "test":
|
||||
cmd := args[2]
|
||||
switch cmd {
|
||||
|
@ -52,8 +66,6 @@ func CatchCLI(args []string) {
|
|||
utils.Log(1, "Exported Statup index page: 'index.html'")
|
||||
case "help":
|
||||
HelpEcho()
|
||||
case "update":
|
||||
fmt.Println("Sorry updating isn't available yet!")
|
||||
case "run":
|
||||
utils.Log(1, "Running 1 time and saving to database...")
|
||||
RunOnce()
|
||||
|
@ -72,6 +84,10 @@ func CatchCLI(args []string) {
|
|||
}
|
||||
}
|
||||
|
||||
func CheckUpdates() {
|
||||
|
||||
}
|
||||
|
||||
func RunOnce() {
|
||||
var err error
|
||||
core.Configs, err = core.LoadConfig()
|
||||
|
@ -265,3 +281,99 @@ func FakeSeed(plug plugin.PluginActions) {
|
|||
fmt.Println("Seeding example data is complete, running Plugin Tests")
|
||||
|
||||
}
|
||||
|
||||
func CheckGithubUpdates() (GithubResponse, error) {
|
||||
var gitResp GithubResponse
|
||||
response, err := http.Get("https://api.github.com/repos/hunterlong/statup/releases/latest")
|
||||
if err != nil {
|
||||
return GithubResponse{}, err
|
||||
} else {
|
||||
defer response.Body.Close()
|
||||
contents, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return GithubResponse{}, err
|
||||
}
|
||||
err = json.Unmarshal(contents, &gitResp)
|
||||
return gitResp, err
|
||||
}
|
||||
return gitResp, err
|
||||
}
|
||||
|
||||
type GithubResponse struct {
|
||||
URL string `json:"url"`
|
||||
AssetsURL string `json:"assets_url"`
|
||||
UploadURL string `json:"upload_url"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
ID int `json:"id"`
|
||||
NodeID string `json:"node_id"`
|
||||
TagName string `json:"tag_name"`
|
||||
TargetCommitish string `json:"target_commitish"`
|
||||
Name string `json:"name"`
|
||||
Draft bool `json:"draft"`
|
||||
Author GitAuthor `json:"author"`
|
||||
Prerelease bool `json:"prerelease"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
PublishedAt time.Time `json:"published_at"`
|
||||
Assets []GitAssets `json:"assets"`
|
||||
TarballURL string `json:"tarball_url"`
|
||||
ZipballURL string `json:"zipball_url"`
|
||||
Body string `json:"body"`
|
||||
}
|
||||
|
||||
type GitAuthor struct {
|
||||
Login string `json:"login"`
|
||||
ID int `json:"id"`
|
||||
NodeID string `json:"node_id"`
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
GravatarID string `json:"gravatar_id"`
|
||||
URL string `json:"url"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
FollowersURL string `json:"followers_url"`
|
||||
FollowingURL string `json:"following_url"`
|
||||
GistsURL string `json:"gists_url"`
|
||||
StarredURL string `json:"starred_url"`
|
||||
SubscriptionsURL string `json:"subscriptions_url"`
|
||||
OrganizationsURL string `json:"organizations_url"`
|
||||
ReposURL string `json:"repos_url"`
|
||||
EventsURL string `json:"events_url"`
|
||||
ReceivedEventsURL string `json:"received_events_url"`
|
||||
Type string `json:"type"`
|
||||
SiteAdmin bool `json:"site_admin"`
|
||||
}
|
||||
|
||||
type GitAssets struct {
|
||||
URL string `json:"url"`
|
||||
ID int `json:"id"`
|
||||
NodeID string `json:"node_id"`
|
||||
Name string `json:"name"`
|
||||
Label string `json:"label"`
|
||||
Uploader GitUploader `json:"uploader"`
|
||||
ContentType string `json:"content_type"`
|
||||
State string `json:"state"`
|
||||
Size int `json:"size"`
|
||||
DownloadCount int `json:"download_count"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
BrowserDownloadURL string `json:"browser_download_url"`
|
||||
}
|
||||
|
||||
type GitUploader struct {
|
||||
Login string `json:"login"`
|
||||
ID int `json:"id"`
|
||||
NodeID string `json:"node_id"`
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
GravatarID string `json:"gravatar_id"`
|
||||
URL string `json:"url"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
FollowersURL string `json:"followers_url"`
|
||||
FollowingURL string `json:"following_url"`
|
||||
GistsURL string `json:"gists_url"`
|
||||
StarredURL string `json:"starred_url"`
|
||||
SubscriptionsURL string `json:"subscriptions_url"`
|
||||
OrganizationsURL string `json:"organizations_url"`
|
||||
ReposURL string `json:"repos_url"`
|
||||
EventsURL string `json:"events_url"`
|
||||
ReceivedEventsURL string `json:"received_events_url"`
|
||||
Type string `json:"type"`
|
||||
SiteAdmin bool `json:"site_admin"`
|
||||
}
|
||||
|
|
11
core/core.go
11
core/core.go
|
@ -20,6 +20,8 @@ type Core struct {
|
|||
Footer string `db:"footer" json:"-"`
|
||||
Domain string `db:"domain" json:"domain,omitempty"`
|
||||
Version string `db:"version" json:"version,omitempty"`
|
||||
MigrationId int64 `db:"migration_id" json:"-"`
|
||||
UseCdn bool `db:"use_cdn" json:"-"`
|
||||
Services []*Service `json:"services,omitempty"`
|
||||
Plugins []plugin.Info
|
||||
Repos []PluginJSON
|
||||
|
@ -103,6 +105,15 @@ func (c Core) AllOnline() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func SelectLastMigration() (int64, error) {
|
||||
var c *Core
|
||||
err := DbSession.Collection("core").Find().One(&c)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return c.MigrationId, err
|
||||
}
|
||||
|
||||
func SelectCore() (*Core, error) {
|
||||
var c *Core
|
||||
err := DbSession.Collection("core").Find().One(&c)
|
||||
|
|
|
@ -20,6 +20,7 @@ var (
|
|||
postgresSettings postgresql.ConnectionURL
|
||||
mysqlSettings mysql.ConnectionURL
|
||||
DbSession sqlbuilder.Database
|
||||
currentMigration int64
|
||||
)
|
||||
|
||||
type DbConfig types.DbConfig
|
||||
|
@ -66,7 +67,10 @@ func DbConnection(dbType string) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
//dbSession.SetLogging(true)
|
||||
err = DbSession.Ping()
|
||||
if err == nil {
|
||||
utils.Log(1, fmt.Sprintf("Database connection to '%v' was successful.", DbSession.Name()))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -122,6 +126,7 @@ func (c *DbConfig) Save() error {
|
|||
ApiKey: utils.NewSHA1Hash(9),
|
||||
ApiSecret: utils.NewSHA1Hash(16),
|
||||
Domain: c.Domain,
|
||||
MigrationId: time.Now().Unix(),
|
||||
}
|
||||
col := DbSession.Collection("core")
|
||||
_, err = col.Insert(newCore)
|
||||
|
@ -135,78 +140,65 @@ func (c *DbConfig) Save() error {
|
|||
return err
|
||||
}
|
||||
|
||||
func versionSplit(v string) (int64, int64, int64) {
|
||||
currSplit := strings.Split(v, ".")
|
||||
if len(currSplit) < 2 {
|
||||
return 9999, 9999, 9999
|
||||
}
|
||||
var major, mid, minor string
|
||||
if len(currSplit) == 3 {
|
||||
major = currSplit[0]
|
||||
mid = currSplit[1]
|
||||
minor = currSplit[2]
|
||||
return utils.StringInt(major), utils.StringInt(mid), utils.StringInt(minor)
|
||||
}
|
||||
major = currSplit[0]
|
||||
mid = currSplit[1]
|
||||
return utils.StringInt(major), utils.StringInt(mid), 0
|
||||
}
|
||||
|
||||
func versionHigher(migrate string) bool {
|
||||
cM, cMi, cMn := versionSplit(CoreApp.Version)
|
||||
mM, mMi, mMn := versionSplit(migrate)
|
||||
if mM > cM {
|
||||
return true
|
||||
}
|
||||
if mMi > cMi {
|
||||
return true
|
||||
}
|
||||
if mMn > cMn {
|
||||
func versionHigher(migrate int64) bool {
|
||||
if CoreApp.MigrationId < migrate {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func reverseSlice(s []string) []string {
|
||||
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func RunDatabaseUpgrades() error {
|
||||
var err error
|
||||
utils.Log(1, fmt.Sprintf("Checking Database Upgrades from v%v in '%v_upgrade.sql'...", CoreApp.Version, CoreApp.DbConnection))
|
||||
currentMigration, err = SelectLastMigration()
|
||||
utils.Log(1, fmt.Sprintf("Checking for Database Upgrades since #%v", currentMigration))
|
||||
upgrade, _ := SqlBox.String(CoreApp.DbConnection + "_upgrade.sql")
|
||||
// parse db version and upgrade file
|
||||
ups := strings.Split(upgrade, "=========================================== ")
|
||||
ups = reverseSlice(ups)
|
||||
var ran int
|
||||
var lastMigration int64
|
||||
for _, v := range ups {
|
||||
if len(v) == 0 {
|
||||
continue
|
||||
}
|
||||
vers := strings.Split(v, "\n")
|
||||
version := vers[0]
|
||||
lastMigration = utils.StringInt(vers[0])
|
||||
data := vers[1:]
|
||||
|
||||
//fmt.Printf("Checking Migration from v%v to v%v - %v\n", CoreApp.Version, version, versionHigher(version))
|
||||
if !versionHigher(version) {
|
||||
//fmt.Printf("Already up-to-date with v%v\n", version)
|
||||
if currentMigration >= lastMigration {
|
||||
continue
|
||||
}
|
||||
fmt.Printf("Migration Database from v%v to v%v\n", CoreApp.Version, version)
|
||||
utils.Log(1, fmt.Sprintf("Migrating Database from #%v to #%v", currentMigration, lastMigration))
|
||||
for _, m := range data {
|
||||
if m == "" {
|
||||
continue
|
||||
}
|
||||
fmt.Printf("Running Migration: %v\n", m)
|
||||
utils.Log(1, fmt.Sprintf("Running Query: %v", m))
|
||||
_, err := DbSession.Exec(db.Raw(m + ";"))
|
||||
ran++
|
||||
if err != nil {
|
||||
utils.Log(2, err)
|
||||
continue
|
||||
}
|
||||
ran++
|
||||
CoreApp.Version = m
|
||||
}
|
||||
currentMigration = lastMigration
|
||||
}
|
||||
if ran > 0 {
|
||||
utils.Log(1, fmt.Sprintf("Database Upgraded, %v query ran", ran))
|
||||
CoreApp.Update()
|
||||
utils.Log(1, fmt.Sprintf("Database Upgraded %v queries ran, current #%v", ran, currentMigration))
|
||||
CoreApp, err = SelectCore()
|
||||
} else {
|
||||
utils.Log(1, fmt.Sprintf("Database is already up-to-date, latest v%v", CoreApp.Version))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
CoreApp.MigrationId = currentMigration
|
||||
CoreApp.Update()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
1
main.go
1
main.go
|
@ -65,6 +65,7 @@ func mainProcess() {
|
|||
if err != nil {
|
||||
utils.Log(3, err)
|
||||
}
|
||||
|
||||
core.RunDatabaseUpgrades()
|
||||
core.InitApp()
|
||||
|
||||
|
|
|
@ -7,7 +7,9 @@ CREATE TABLE core (
|
|||
style text,
|
||||
footer text,
|
||||
domain text,
|
||||
version VARCHAR(50)
|
||||
version VARCHAR(50),
|
||||
migration_id INT(6) NOT NULL DEFAULT 0,
|
||||
use_cdn BOOL NOT NULL DEFAULT '0'
|
||||
);
|
||||
CREATE TABLE users (
|
||||
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
=========================================== 1530841150
|
||||
ALTER TABLE core ADD COLUMN use_cdn BOOL NOT NULL DEFAULT '0';
|
||||
=========================================== 1
|
||||
ALTER TABLE core ADD COLUMN migration_id INT(6) NOT NULL DEFAULT 0;
|
|
@ -7,7 +7,9 @@ CREATE TABLE core (
|
|||
style text,
|
||||
footer text,
|
||||
domain text,
|
||||
version text
|
||||
version text,
|
||||
migration_id integer default 0,
|
||||
use_cdn bool default false
|
||||
);
|
||||
|
||||
CREATE TABLE users (
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
=========================================== 1530841150
|
||||
ALTER TABLE core ADD COLUMN use_cdn bool DEFAULT FALSE;
|
||||
=========================================== 1
|
||||
ALTER TABLE core ADD COLUMN migration_id integer default 0 NOT NULL;
|
|
@ -7,7 +7,9 @@ CREATE TABLE core (
|
|||
style text,
|
||||
footer text,
|
||||
domain text,
|
||||
version text
|
||||
version text,
|
||||
migration_id integer default 0,
|
||||
use_cdn bool default false
|
||||
);
|
||||
|
||||
CREATE TABLE users (
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
=========================================== 1530841150
|
||||
ALTER TABLE core ADD COLUMN use_cdn bool DEFAULT FALSE;
|
||||
=========================================== 1
|
||||
ALTER TABLE core ADD COLUMN migration_id integer NOT NULL DEFAULT 0;
|
Loading…
Reference in New Issue