(Feat): Initial Commit
Some checks failed
Build & Test / build-test (push) Has been cancelled
Build & Test / swagger-codegen-cli (push) Has been cancelled
CodeQL / Analyze (go) (push) Has been cancelled

This commit is contained in:
2026-07-03 19:41:31 +05:30
commit 7e940c83a7
461 changed files with 45002 additions and 0 deletions

13
cmd/db/db.go Normal file
View File

@@ -0,0 +1,13 @@
package db
import (
"allaboutapps.dev/aw/go-starter/internal/util/command"
"github.com/spf13/cobra"
)
func New() *cobra.Command {
return command.NewSubcommandGroup("db",
newMigrate(),
newSeed(),
)
}

97
cmd/db/migrate.go Normal file
View File

@@ -0,0 +1,97 @@
package db
import (
"context"
"database/sql"
"fmt"
"allaboutapps.dev/aw/go-starter/internal/api"
"allaboutapps.dev/aw/go-starter/internal/config"
"allaboutapps.dev/aw/go-starter/internal/util"
"allaboutapps.dev/aw/go-starter/internal/util/command"
"github.com/rs/zerolog/log"
migrate "github.com/rubenv/sql-migrate"
"github.com/spf13/cobra"
)
func newMigrate() *cobra.Command {
return &cobra.Command{
Use: "migrate",
Short: "Executes all migrations which are not yet applied.",
Run: func(_ *cobra.Command, _ []string) {
migrateCmdFunc()
},
}
}
func migrateCmdFunc() {
err := command.WithServer(context.Background(), config.DefaultServiceConfigFromEnv(), func(ctx context.Context, s *api.Server) error {
log := util.LogFromContext(ctx)
n, err := ApplyMigrations(ctx, s.Config)
if err != nil {
log.Err(err).Msg("Error while applying migrations")
return err
}
log.Info().Int("appliedMigrationsCount", n).Msg("Successfully applied migrations")
return nil
})
if err != nil {
log.Fatal().Err(err).Msg("Failed to apply migrations")
}
}
func ApplyMigrations(ctx context.Context, serviceConfig config.Server) (int, error) {
log := util.LogFromContext(ctx)
// pin migrate to use the globally defined `migrations` table identifier
migrate.SetTable(config.DatabaseMigrationTable)
db, err := sql.Open("postgres", serviceConfig.Database.ConnectionString())
if err != nil {
return 0, fmt.Errorf("failed to open the database: %w", err)
}
defer db.Close()
if err := db.PingContext(ctx); err != nil {
return 0, fmt.Errorf("failed to ping the database: %w", err)
}
// In case an old default sql-migrate migration table (named "gorp_migrations") still exists we rename it to the new name equivalent
// in sync with the settings in dbconfig.yml and config.DatabaseMigrationTable.
if _, err := db.ExecContext(ctx, fmt.Sprintf("ALTER TABLE IF EXISTS gorp_migrations RENAME TO %s;", config.DatabaseMigrationTable)); err != nil {
return 0, fmt.Errorf("failed to rename migrations table: %w", err)
}
migrations := &migrate.FileMigrationSource{
Dir: config.DatabaseMigrationFolder,
}
missingMigrations, _, err := migrate.PlanMigration(db, "postgres", migrations, migrate.Up, 0)
if err != nil {
log.Err(err).Msg("Error while planning migrations")
return 0, fmt.Errorf("failed to plan migrations: %w", err)
}
var appliedMigrationsCount int
for i := 0; i < len(missingMigrations); i++ {
log.Info().Str("migrationId", missingMigrations[i].Id).Msg("Applying migration")
n, err := migrate.ExecMax(db, "postgres", migrations, migrate.Up, 1)
if err != nil {
log.Err(err).Msg("Error while applying migration")
return 0, fmt.Errorf("failed to apply migration: %w", err)
}
log.Info().Int("appliedMigrationsCount", n).Msg("Applied migration")
appliedMigrationsCount += n
if n == 0 {
break
}
}
return appliedMigrationsCount, nil
}

77
cmd/db/seed.go Normal file
View File

@@ -0,0 +1,77 @@
package db
import (
"context"
"database/sql"
"fmt"
"allaboutapps.dev/aw/go-starter/internal/api"
"allaboutapps.dev/aw/go-starter/internal/config"
data "allaboutapps.dev/aw/go-starter/internal/data/fixtures"
"allaboutapps.dev/aw/go-starter/internal/util"
"allaboutapps.dev/aw/go-starter/internal/util/command"
dbutil "allaboutapps.dev/aw/go-starter/internal/util/db"
"github.com/aarondl/sqlboiler/v4/boil"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
)
func newSeed() *cobra.Command {
return &cobra.Command{
Use: "seed",
Short: "Inserts or updates fixtures to the database.",
Long: `Uses upsert to add test data to the current environment.`,
Run: func(_ *cobra.Command, _ []string) {
seedCmdFunc()
},
}
}
func seedCmdFunc() {
err := command.WithServer(context.Background(), config.DefaultServiceConfigFromEnv(), func(ctx context.Context, s *api.Server) error {
log := util.LogFromContext(ctx)
err := ApplySeedFixtures(ctx, s.Config)
if err != nil {
log.Err(err).Msg("Error while applying seed fixtures")
return err
}
log.Info().Msg("Successfully applied seed fixtures")
return nil
})
if err != nil {
log.Fatal().Err(err).Msg("Failed to apply migrations")
}
}
func ApplySeedFixtures(ctx context.Context, config config.Server) error {
log := util.LogFromContext(ctx)
db, err := sql.Open("postgres", config.Database.ConnectionString())
if err != nil {
return fmt.Errorf("failed to open the database: %w", err)
}
defer db.Close()
if err := db.PingContext(ctx); err != nil {
return fmt.Errorf("failed to ping the database: %w", err)
}
// insert fixtures in an auto-managed db transaction
return dbutil.WithTransaction(ctx, db, func(tx boil.ContextExecutor) error {
fixtures := data.Upserts()
for _, fixture := range fixtures {
if err := fixture.Upsert(ctx, tx, true, nil, boil.Infer(), boil.Infer()); err != nil {
log.Error().Err(err).Msg("Failed to upsert fixture")
return err
}
}
log.Info().Int("fixturesCount", len(fixtures)).Msg("Successfully upserted fixtures")
return nil
})
}