With our app in a healthy place, we can add database seeding. This is going to be quick because all we’re going to have to do is write a handful of ent create methods. We can make this more advanced with environment specific config and/or external files that we can embed using embed.FS.

Since we don’t need anything too complicated just yet, let’s keep our seeding command simple. We can always expand on it later if we need additional functionality.

Create Skeleton Command

Let’s start with creating a skeleton for the Cobra command for our migrate command. It’s pretty standard boilerplate code from what we’ve seen before on Cobra:

package cmd

import (
  "fmt"

  "github.com/spf13/cobra"
)

var seedCmd = &cobra.Command{
  Use:   "seed",
  Short: "Seed the database with initial values",
  RunE:  runSeed,
}

func init() {
  rootCmd.AddCommand(seedCmd)
}

func runSeed(cmd *cobra.Command, args []string) error {
  return fmt.Errorf("not implemented")
}

Here we’re just creating a new seedCmd with the command name (Use) of seed and a short description (the Short field) and using our runE wrapper for the run command. Also, don’t forget to add this command to the rootCmd otherwise this command won’t ba available to us when we try to run the app.

With the boilerplate for it in place we can implement our runSeed func to seed our database:

func runSeed(cmd *cobra.Command, args []string) (err error) {
  cfg := config.GetApp()

  entClient, err := ent.Open(cfg.Database.Driver, cfg.Database.URL)
  if err != nil {
    return
  }
  defer entClient.Close()

  notes := []*ent.NoteCreate{
    entClient.Note.Create().
      SetTitle("My First Note").
      SetBody("## My First Note Section\n\nSome content for the note. With a [link](https://blog.miu.guru) to a cool site!"),
    entClient.Note.Create().
      SetTitle("My Second Note").
      SetBody("## My Other Note\n\nMore random note content...\n\n- with\n- a\n- list\n\nAll this formatting and no where to go."),
  }

  fmt.Println("Seeding notes...")
  err = entClient.Note.CreateBulk(notes...).Exec(cmd.Context())

  // create additional seeds here

  return
}

Here we are bulk creating notes with some basic Markdown to test our app with. Notice that we have NoteCreate structs being generated by using the ent client’s Create() method for the model but we don’t commit with Save(context.Context) or Exec(context.Context) when we’re done. Then when we are ready we can pass all of our builders into the CreateBulk() method of the ent client.

With this all in place, we can run our seed command:

go run . seed

You should just see the output:

output
Seeding notes...

We can also check out our new command in the Cobra help:

go run . -h

You should see the seed command and its description of what it does:

output
GentQL backend application services.

Usage:
  gentql [command]

Available Commands:
  api         Start the API services for gentql
  completion  Generate the autocompletion script for the specified shell
  help        Help about any command
  migrate     Migrate the database between versions
  seed        Seed the database with initial values

Flags:
  -h, --help   help for gentql

Use "gentql [command] --help" for more information about a command.

We can combine this with more advanced create options to ensure we don’t duplicate some records when they shouldn’t be added multiple times in a row. Typically, when I set up seeding I’ll use a testing user or some other unique data that can be checked against to ensure there isn’t duplicate data, in the case that’s not desirable.