Skip to content

Commit 4d945b6

Browse files
authored
feat: import project (#636)
* Seed from file * Adjust get-project command to accept --expand * Rename to import
1 parent b236535 commit 4d945b6

6 files changed

Lines changed: 1103 additions & 6 deletions

File tree

cmd/dev_server/dev_server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ func NewDevServerCmd(client resources.Client, analyticsTrackerFn analytics.Track
7272
cmd.AddCommand(NewRemoveProjectCmd(client))
7373
cmd.AddCommand(NewAddProjectCmd(client))
7474
cmd.AddCommand(NewUpdateProjectCmd(client))
75+
cmd.AddCommand(NewImportProjectCmd())
7576

7677
cmd.AddGroup(&cobra.Group{ID: "overrides", Title: "Override commands:"})
7778
cmd.AddCommand(NewAddOverrideCmd(client))

cmd/dev_server/import_project.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package dev_server
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
8+
"github.com/adrg/xdg"
9+
"github.com/spf13/cobra"
10+
"github.com/spf13/viper"
11+
12+
"github.com/launchdarkly/ldcli/cmd/cliflags"
13+
resourcescmd "github.com/launchdarkly/ldcli/cmd/resources"
14+
"github.com/launchdarkly/ldcli/cmd/validators"
15+
"github.com/launchdarkly/ldcli/internal/dev_server/db"
16+
"github.com/launchdarkly/ldcli/internal/dev_server/model"
17+
)
18+
19+
const ImportFileFlag = "file"
20+
21+
func NewImportProjectCmd() *cobra.Command {
22+
cmd := &cobra.Command{
23+
GroupID: "projects",
24+
Args: validators.Validate(),
25+
Long: `Import a project into the dev server database from a JSON file.
26+
27+
The JSON file format matches the output from:
28+
ldcli dev-server get-project --project=<key> \
29+
--expand=overrides --expand=availableVariations
30+
31+
Examples:
32+
# Export project data (while dev server is running)
33+
ldcli dev-server get-project --project=my-project \
34+
--expand=overrides --expand=availableVariations > backup.json
35+
36+
# Later, import the project from backup
37+
ldcli dev-server import-project --project=my-project --file=backup.json`,
38+
RunE: importProject(),
39+
Short: "import project from file",
40+
Use: "import-project",
41+
}
42+
43+
cmd.SetUsageTemplate(resourcescmd.SubcommandUsageTemplate())
44+
45+
cmd.Flags().String(cliflags.ProjectFlag, "", "The project key to create")
46+
_ = cmd.MarkFlagRequired(cliflags.ProjectFlag)
47+
_ = cmd.Flags().SetAnnotation(cliflags.ProjectFlag, "required", []string{"true"})
48+
_ = viper.BindPFlag(cliflags.ProjectFlag, cmd.Flags().Lookup(cliflags.ProjectFlag))
49+
50+
cmd.Flags().String(ImportFileFlag, "", "Path to JSON file containing project data")
51+
_ = cmd.MarkFlagRequired(ImportFileFlag)
52+
_ = cmd.Flags().SetAnnotation(ImportFileFlag, "required", []string{"true"})
53+
_ = viper.BindPFlag(ImportFileFlag, cmd.Flags().Lookup(ImportFileFlag))
54+
55+
return cmd
56+
}
57+
58+
func importProject() func(*cobra.Command, []string) error {
59+
return func(cmd *cobra.Command, args []string) error {
60+
ctx := context.Background()
61+
projectKey := viper.GetString(cliflags.ProjectFlag)
62+
filepath := viper.GetString(ImportFileFlag)
63+
64+
// Get database path (same logic as dev_server.go)
65+
dbFilePath, err := xdg.StateFile("ldcli/dev_server.db")
66+
if err != nil {
67+
return fmt.Errorf("unable to get database path: %w", err)
68+
}
69+
70+
// Open database
71+
sqlStore, err := db.NewSqlite(ctx, dbFilePath)
72+
if err != nil {
73+
return fmt.Errorf("unable to open database: %w", err)
74+
}
75+
76+
// Set store on context
77+
ctx = model.ContextWithStore(ctx, sqlStore)
78+
79+
// Import project from file
80+
err = model.ImportProjectFromFile(ctx, projectKey, filepath)
81+
if err != nil {
82+
return fmt.Errorf("unable to import project: %w", err)
83+
}
84+
85+
log.Printf("Successfully imported project '%s' from %s", projectKey, filepath)
86+
fmt.Fprintf(cmd.OutOrStdout(), "Successfully imported project '%s' from %s\n", projectKey, filepath)
87+
88+
return nil
89+
}
90+
}

0 commit comments

Comments
 (0)