package migration import ( "context" "fmt" "math/rand" "os" "os/exec" "strings" "time" "git.handmade.network/hmn/hmn/src/auth" "git.handmade.network/hmn/hmn/src/config" "git.handmade.network/hmn/hmn/src/db" "git.handmade.network/hmn/hmn/src/hmndata" "git.handmade.network/hmn/hmn/src/models" "git.handmade.network/hmn/hmn/src/oops" "git.handmade.network/hmn/hmn/src/parsing" "git.handmade.network/hmn/hmn/src/utils" lorem "github.com/HandmadeNetwork/golorem" "github.com/jackc/pgx/v4" ) // Applies a cloned db to the local db. // Applies the seed after the migration specified in `afterMigration`. // NOTE(asaf): The db role specified in the config must have the CREATEDB attribute! `ALTER ROLE hmn WITH CREATEDB;` func SeedFromFile(seedFile string) { file, err := os.Open(seedFile) if err != nil { panic(fmt.Errorf("couldn't open seed file %s: %w", seedFile, err)) } file.Close() fmt.Println("Executing seed...") cmd := exec.Command("pg_restore", "--single-transaction", "--dbname", config.Config.Postgres.DSN(), seedFile, ) fmt.Println("Running command:", cmd) if output, err := cmd.CombinedOutput(); err != nil { fmt.Print(string(output)) panic(fmt.Errorf("failed to execute seed: %w", err)) } fmt.Println("Done! You may want to migrate forward from here.") ListMigrations() } // Creates only what's necessary to get the site running. Not really very useful for // local dev on its own; sample data makes things a lot better. func BareMinimumSeed() *models.Project { Migrate(LatestVersion()) ctx := context.Background() conn := db.NewConnWithConfig(config.PostgresConfig{ LogLevel: pgx.LogLevelWarn, }) defer conn.Close(ctx) tx := utils.Must1(conn.Begin(ctx)) defer tx.Rollback(ctx) fmt.Println("Creating HMN project...") hmn := seedProject(ctx, tx, seedHMN, nil) utils.Must(tx.Commit(ctx)) return hmn } // Seeds the database with sample data for local dev. func SampleSeed() { hmn := BareMinimumSeed() ctx := context.Background() conn := db.NewConnWithConfig(config.PostgresConfig{ LogLevel: pgx.LogLevelWarn, }) defer conn.Close(ctx) tx := utils.Must1(conn.Begin(ctx)) defer tx.Rollback(ctx) fmt.Println("Creating admin user (\"admin\"/\"password\")...") admin := seedUser(ctx, tx, models.User{Username: "admin", Name: "Admin", Email: "admin@handmade.network", IsStaff: true}) fmt.Println("Creating normal users (all with password \"password\")...") alice := seedUser(ctx, tx, models.User{Username: "alice", Name: "Alice"}) bob := seedUser(ctx, tx, models.User{Username: "bob", Name: "Bob"}) charlie := seedUser(ctx, tx, models.User{Username: "charlie", Name: "Charlie"}) fmt.Println("Creating a spammer...") spammer := seedUser(ctx, tx, models.User{ Username: "spam", Status: models.UserStatusConfirmed, Name: "Hot singletons in your local area", Bio: "Howdy, everybody I go by Jarva seesharpe from Bangalore. In this way, assuming you need to partake in a shared global instance with me then, at that poi", }) users := []*models.User{alice, bob, charlie, spammer} fmt.Println("Creating starter projects...") hero := seedProject(ctx, tx, seedHandmadeHero, []*models.User{admin}) fourcoder := seedProject(ctx, tx, seed4coder, []*models.User{bob}) for i := 0; i < 5; i++ { name := fmt.Sprintf("%s %s", lorem.Word(1, 10), lorem.Word(1, 10)) slug := strings.ReplaceAll(strings.ToLower(name), " ", "-") possibleOwners := []*models.User{alice, bob, charlie} var owners []*models.User for ownerIdx, owner := range possibleOwners { mask := (i % ((1 << len(possibleOwners)) - 1)) + 1 if (1<