Add separate production, testserver, and demo deployments
CI / test (push) Failing after 10s

This commit is contained in:
2026-09-14 19:58:31 +02:00
parent b87aa0aa17
commit d06ff4a94a
37 changed files with 1293 additions and 121 deletions
+50
View File
@@ -92,11 +92,60 @@ func (app *application) run(ctx context.Context, args []string) error {
return app.runGardens(ctx, cfg, store, remaining[1:])
case "db":
return app.runDB(ctx, cfg, store, remaining[1:])
case "demo":
return app.runDemo(ctx, cfg, store, remaining[1:])
default:
return fmt.Errorf("unknown command %q; run gardomatic help", remaining[0])
}
}
func (app *application) runDemo(ctx context.Context, cfg config, store adminStore, args []string) error {
if len(args) == 0 || args[0] != "reset" {
return errors.New("usage: gardomatic --yes demo reset --password-stdin [--name NAME] [--email EMAIL]")
}
if !cfg.demoResetEnabled {
return errors.New("demo reset is disabled; set GARDOMATIC_DEMO_RESET_ENABLED=true only for a disposable demo database")
}
if !cfg.yes {
return errors.New("demo reset deletes all user and garden data; pass the global --yes flag")
}
fs := newFlagSet("demo reset", app.stderr)
var name, email string
var passwordStdin bool
fs.StringVar(&name, "name", "Demo-Besucher", "demo account display name")
fs.StringVar(&email, "email", "demo@example.com", "demo account email address")
fs.BoolVar(&passwordStdin, "password-stdin", false, "read the demo account password from standard input (required)")
if err := parseFlags(fs, args[1:]); err != nil {
return err
}
name, email = strings.TrimSpace(name), strings.TrimSpace(email)
if !passwordStdin {
return errors.New("--password-stdin is required so the demo password is not exposed in the process list")
}
if err := validateIdentity(name, email); err != nil {
return err
}
password, _, err := app.obtainPassword(false, true)
if err != nil {
return err
}
passwordHash, err := hashPassword(password)
if err != nil {
return err
}
result, err := store.ResetDemo(ctx, demoResetInput{Name: name, Email: email, PasswordHash: passwordHash})
if err != nil {
return fmt.Errorf("reset demo data: %w", err)
}
if cfg.json {
return writeJSON(app.stdout, result)
}
_, err = fmt.Fprintf(app.stdout, "Demo reset complete.\nLogin: %s\nGarden: %s\nImages: %d\nLocations: %d\nSpecies: %d\nPlants: %d\nTasks: %d\nJournal entries: %d\nAttachments: %d\n",
result.Email, result.Garden, result.Images, result.Locations, result.Species, result.Plants, result.Tasks, result.Journal, result.Attachments)
return err
}
func (app *application) runUsers(ctx context.Context, cfg config, store adminStore, args []string) error {
if len(args) == 0 {
return errors.New("missing users command: create, list, show, activate, deactivate, invite, reset-password, or set-role")
@@ -554,6 +603,7 @@ Usage:
gardomatic [global options] users set-role --email EMAIL --role ROLE
gardomatic [global options] gardens add-user --garden-id ID --email EMAIL [--role ROLE]
gardomatic [global options] db ping
gardomatic --yes demo reset --password-stdin [--name NAME] [--email EMAIL]
gardomatic [global options] version
Global options:`)