Added seed command

This commit is contained in:
Asaf Gartner 2021-04-12 12:56:44 +03:00
parent 470a0e4932
commit cdfd558730
3 changed files with 151 additions and 0 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
src/config/config.go
.vscode
vendor/
dbclones/

View File

@ -5,11 +5,13 @@ import (
_ "embed"
"fmt"
"os"
"os/exec"
"path/filepath"
"sort"
"strings"
"time"
"git.handmade.network/hmn/hmn/src/config"
"git.handmade.network/hmn/hmn/src/db"
"git.handmade.network/hmn/hmn/src/migration/migrations"
"git.handmade.network/hmn/hmn/src/migration/types"
@ -61,8 +63,31 @@ func init() {
},
}
seedFromFileCommand := &cobra.Command{
Use: "seedfile <filename> <after migration id>",
Short: "Resets the db, runs migrations up to and including <after migration id>, and runs the seed file.",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 2 {
fmt.Printf("You must provide a seed file and migration id.\n\n")
cmd.Usage()
os.Exit(1)
}
seedFile := args[0]
afterMigration, err := time.Parse(time.RFC3339, args[1])
if err != nil {
fmt.Printf("ERROR: bad version string: %v", err)
os.Exit(1)
}
SeedFromFile(seedFile, types.MigrationVersion(afterMigration))
},
}
website.WebsiteCommand.AddCommand(migrateCommand)
website.WebsiteCommand.AddCommand(makeMigrationCommand)
website.WebsiteCommand.AddCommand(seedFromFileCommand)
}
func getSortedMigrationVersions() []types.MigrationVersion {
@ -257,3 +282,100 @@ func MakeMigration(name, description string) {
fmt.Println("Successfully created migration file:")
fmt.Println(path)
}
// Drops all tables
func ClearDatabase() {
conn := db.NewConn()
defer conn.Close(context.Background())
dbName := config.Config.Postgres.DbName
rows, err := conn.Query(context.Background(), "SELECT tablename FROM pg_tables WHERE tableowner = $1", dbName)
if err != nil {
panic(fmt.Errorf("couldn't fetch the list of tables owned by %s: %w", dbName, err))
}
tablesToDrop := []string{}
for rows.Next() {
var tableName string
err = rows.Scan(&tableName)
if err != nil {
panic(fmt.Errorf("failed to fetch row from pg_tables: %w", err))
}
tablesToDrop = append(tablesToDrop, tableName)
}
rows.Close()
for _, tableName := range tablesToDrop {
conn.Exec(context.Background(), "DROP TABLE $1", tableName)
}
}
// Applies a cloned db to the local db.
// Drops the db and runs migrations from scratch.
// Applies the seed after the migration specified in `afterMigration`, then runs the rest of the migrations.
func SeedFromFile(seedFile string, afterMigration types.MigrationVersion) {
file, err := os.Open(seedFile)
if err != nil {
panic(fmt.Errorf("couldn't open seed file %s: %w", seedFile, err))
}
file.Close()
migration := migrations.All[afterMigration]
if migration == nil {
panic(fmt.Errorf("could not find migration: %s", afterMigration))
}
fmt.Println("Clearing database...")
ClearDatabase()
fmt.Println("Running migrations...")
Migrate(afterMigration)
fmt.Println("Executing seed...")
cmd := exec.Command("psql",
"--single-transaction",
"--dbname",
config.Config.Postgres.DbName,
"--host",
config.Config.Postgres.Hostname,
"--username",
config.Config.Postgres.User,
"--password",
"-f",
seedFile,
)
fmt.Println("Running command:", cmd)
if err = cmd.Run(); err != nil {
exitError, isExit := err.(*exec.ExitError)
if isExit {
panic(fmt.Errorf("failed to execute seed: %w\n%s", err, string(exitError.Stderr)))
} else {
panic(fmt.Errorf("failed to execute seed: %w", err))
}
}
fmt.Println("Done! You may want to migrate forward from here.")
ListMigrations()
}
// NOTE(asaf): This will be useful for open-sourcing the website, but is not yet necessary.
// Creates only what's necessary for a fresh deployment with no data
func BareMinimumSeed() {
}
// NOTE(asaf): This will be useful for open-sourcing the website, but is not yet necessary.
// Creates enough data for development
func SampleSeed() {
// admin := CreateAdminUser("admin", "12345678")
// user := CreateUser("regular_user", "12345678")
// hmnProject := CreateProject("hmn", "Handmade Network")
// Create category
// Create thread
// Create accepted user project
// Create pending user project
// Create showcase items
// Create codelanguages
// Create library and library resources
}

28
src/migration/todo.txt Normal file
View File

@ -0,0 +1,28 @@
Clean this up once we get the website working
---------------------------------------------
TODO: Questionable db tables that we inherited from Django:
* auth_group
* auth_group_permissions
* auth_permission
* auth_user_groups
* auth_user_user_permissions
* django_admin_log
* django_content_type
* django_migrations
* django_session
* django_site
TODO: Questionable db tables that we inherited from the old website:
* handmade_blacklistemail
* handmade_blacklisthostname
* handmade_communicationchoice
* handmade_communicationchoicelist
* handmade_communicationsubcategory
* handmade_communicationsubthread
* handmade_kunenapost
* handmade_license
* handmade_license_texts
* handmade_memberextended.joomlaid
* handmade_onetimetoken // Is this for password resets??
* handmade_otherfile
* handmade_project_licenses