From 5f2037a2cd5c539e7e054486024e218ef2e50462 Mon Sep 17 00:00:00 2001 From: Hunter Long Date: Thu, 5 Jul 2018 20:01:03 -0700 Subject: [PATCH] database migrations - gh updates - 29.6 --- .travis.yml | 2 +- Dockerfile | 2 +- cli.go | 120 ++++++++++++++++++++++++++++++-- core/core.go | 11 +++ core/database.go | 72 +++++++++---------- main.go | 1 + source/sql/mysql_up.sql | 4 +- source/sql/mysql_upgrade.sql | 4 ++ source/sql/postgres_up.sql | 4 +- source/sql/postgres_upgrade.sql | 4 ++ source/sql/sqlite_up.sql | 4 +- source/sql/sqlite_upgrade.sql | 4 ++ 12 files changed, 183 insertions(+), 49 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1ac9329ec..31fbade44 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,7 @@ services: env: global: - - VERSION=0.29.5 + - VERSION=0.29.6 - DB_HOST=localhost - DB_USER=travis - DB_PASS= diff --git a/Dockerfile b/Dockerfile index c4055eda9..4cb9b91da 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 && \ diff --git a/cli.go b/cli.go index 039f5177d..125438f82 100644 --- a/cli.go +++ b/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"` +} diff --git a/core/core.go b/core/core.go index 3569dd984..a4cc807d1 100644 --- a/core/core.go +++ b/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) diff --git a/core/database.go b/core/database.go index fb047a34e..58f5c2deb 100644 --- a/core/database.go +++ b/core/database.go @@ -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 } diff --git a/main.go b/main.go index 649d4f28d..4ef21d58e 100644 --- a/main.go +++ b/main.go @@ -65,6 +65,7 @@ func mainProcess() { if err != nil { utils.Log(3, err) } + core.RunDatabaseUpgrades() core.InitApp() diff --git a/source/sql/mysql_up.sql b/source/sql/mysql_up.sql index 7f5bdb796..f3ef7f706 100644 --- a/source/sql/mysql_up.sql +++ b/source/sql/mysql_up.sql @@ -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, diff --git a/source/sql/mysql_upgrade.sql b/source/sql/mysql_upgrade.sql index e69de29bb..2dc303ef5 100644 --- a/source/sql/mysql_upgrade.sql +++ b/source/sql/mysql_upgrade.sql @@ -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; \ No newline at end of file diff --git a/source/sql/postgres_up.sql b/source/sql/postgres_up.sql index 994dabd78..755835e78 100644 --- a/source/sql/postgres_up.sql +++ b/source/sql/postgres_up.sql @@ -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 ( diff --git a/source/sql/postgres_upgrade.sql b/source/sql/postgres_upgrade.sql index e69de29bb..1cf914f65 100644 --- a/source/sql/postgres_upgrade.sql +++ b/source/sql/postgres_upgrade.sql @@ -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; \ No newline at end of file diff --git a/source/sql/sqlite_up.sql b/source/sql/sqlite_up.sql index 82104d73b..2516e14d4 100644 --- a/source/sql/sqlite_up.sql +++ b/source/sql/sqlite_up.sql @@ -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 ( diff --git a/source/sql/sqlite_upgrade.sql b/source/sql/sqlite_upgrade.sql index e69de29bb..50acbd3af 100644 --- a/source/sql/sqlite_upgrade.sql +++ b/source/sql/sqlite_upgrade.sql @@ -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; \ No newline at end of file