From e842094c854ef4957082ea22a704c4c474f981de Mon Sep 17 00:00:00 2001 From: dawn Date: Tue, 22 Sep 2026 21:01:51 +0300 Subject: [PATCH] cmd/sites-migrate: single-source table list, dedupe wrangler calls Signed-off-by: dawn --- cmd/sites-migrate/main.go | 105 ++++++++++++-------------------------- 1 file changed, 33 insertions(+), 72 deletions(-) diff --git a/cmd/sites-migrate/main.go b/cmd/sites-migrate/main.go index 059052072..dd7c604e2 100644 --- a/cmd/sites-migrate/main.go +++ b/cmd/sites-migrate/main.go @@ -29,16 +29,15 @@ var ( wranglerDir = flag.String("wrangler-dir", "", "directory that owns the wrangler config; empty resolves to /sites") ) -// One insert head per table: the emitted script and the row counts -validate -// reads back out of it come from the same list. var inserts = []struct { table string head string + read func(context.Context, *appviewdb.DB) ([][]emit.Cell, error) }{ - {"domain_claims", "INSERT INTO domain_claims (did, domain, deleted) VALUES "}, - {"site_repos", "INSERT INTO site_repos (repo_did, owner_did, name, rkey, knot) VALUES "}, - {"repo_sites", "INSERT INTO repo_sites (repo_did, branch, dir, is_index, created, updated) VALUES "}, - {"site_deploys", "INSERT INTO site_deploys (repo_did, branch, dir, commit_sha, status, trigger, error, created_at) VALUES "}, + {"domain_claims", "INSERT INTO domain_claims (did, domain, deleted) VALUES ", readClaims}, + {"site_repos", "INSERT INTO site_repos (repo_did, owner_did, name, rkey, knot) VALUES ", readSiteRepos}, + {"repo_sites", "INSERT INTO repo_sites (repo_did, branch, dir, is_index, created, updated) VALUES ", readRepoSites}, + {"site_deploys", "INSERT INTO site_deploys (repo_did, branch, dir, commit_sha, status, trigger, error, created_at) VALUES ", readSiteDeploys}, } func main() { @@ -100,30 +99,6 @@ func main() { } func buildSQL(ctx context.Context, db *appviewdb.DB) (string, map[string]int, error) { - claims, err := readClaims(ctx, db) - if err != nil { - return "", nil, err - } - repos, err := readSiteRepos(ctx, db) - if err != nil { - return "", nil, err - } - siteConfigs, err := readRepoSites(ctx, db) - if err != nil { - return "", nil, err - } - deploys, err := readSiteDeploys(ctx, db) - if err != nil { - return "", nil, err - } - - rows := map[string][][]emit.Cell{ - "domain_claims": claims, - "site_repos": repos, - "repo_sites": siteConfigs, - "site_deploys": deploys, - } - var b strings.Builder b.WriteString("-- WARNING: deletes every row of domain_claims, site_repos, repo_sites\n") b.WriteString("-- and site_deploys before loading the appview snapshot below.\n") @@ -135,8 +110,12 @@ func buildSQL(ctx context.Context, db *appviewdb.DB) (string, map[string]int, er counts := make(map[string]int, len(inserts)) for _, in := range inserts { - emit.Insert(&b, in.head, rows[in.table]) - counts[in.table] = len(rows[in.table]) + rows, err := in.read(ctx, db) + if err != nil { + return "", nil, err + } + emit.Insert(&b, in.head, rows) + counts[in.table] = len(rows) } return b.String(), counts, nil } @@ -227,9 +206,7 @@ func readSiteDeploys(ctx context.Context, db *appviewdb.DB) ([][]emit.Cell, erro return out, rows.Err() } -// countEmitted re-reads the written script and counts the rows each table's -// INSERT statements carry, so -validate has a source for the row counts that -// does not come from the slices it is meant to check. +// countEmitted re-reads the script so -validate checks the file, not the slices. func countEmitted(path string) (map[string]int, error) { content, err := os.ReadFile(path) if err != nil { @@ -247,55 +224,45 @@ func countEmitted(path string) (map[string]int, error) { return counts, nil } -// applySQL hands the emitted script to `wrangler d1 execute --file`, which D1 -// runs as one transaction: the local path splits the file and passes the -// statements to D1's batch API, and --remote uploads the file to the D1 import -// endpoint, which rolls the database back if the load fails. --command gets -// neither treatment, so the load must never go that way. +// wrangler d1 --file: one transaction, and the trimmer strips bare BEGIN/COMMIT func applySQL(ctx context.Context, path, d1Name, dir string, remote bool) error { - cmdDir, err := sitesDir(dir) - if err != nil { - return err - } - - args := []string{"wrangler", "d1", "execute", d1Name, "--file", path, "--yes"} + target := "--local" if remote { - args = append(args, "--remote") - } else { - args = append(args, "--local") + target = "--remote" } + _, err := wranglerD1(ctx, dir, d1Name, "--file", path, "--yes", target) + return err +} - cmd := exec.CommandContext(ctx, "npx", args...) +func wranglerD1(ctx context.Context, dir string, args ...string) ([]byte, error) { + cmdDir, err := sitesDir(dir) + if err != nil { + return nil, err + } + cmd := exec.CommandContext(ctx, "npx", append([]string{"wrangler", "d1", "execute"}, args...)...) cmd.Dir = cmdDir out, err := cmd.CombinedOutput() if err != nil { - return fmt.Errorf("wrangler d1 execute failed: %v: %s", err, strings.TrimSpace(string(out))) + return nil, fmt.Errorf("wrangler d1 execute failed: %v: %s", err, strings.TrimSpace(string(out))) } - return nil + return out, nil } -// sitesDir resolves the directory that owns the wrangler config. func sitesDir(dir string) (string, error) { if dir != "" { return dir, nil } - return resolveSitesDir() -} - -func resolveSitesDir() (string, error) { - dir, err := os.Getwd() + cwd, err := os.Getwd() if err != nil { return "", err } - for { - if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { - return filepath.Join(dir, "sites"), nil + for root := cwd; ; root = filepath.Dir(root) { + if _, err := os.Stat(filepath.Join(root, "go.mod")); err == nil { + return filepath.Join(root, "sites"), nil } - parent := filepath.Dir(dir) - if parent == dir { + if filepath.Dir(root) == root { return "", fmt.Errorf("no go.mod found above the working directory") } - dir = parent } } @@ -322,16 +289,10 @@ func checkParity(ctx context.Context, src, emitted map[string]int, d1Name, dir s } func d1Count(ctx context.Context, d1Name, table, dir string) (int, error) { - cmdDir, err := sitesDir(dir) - if err != nil { - return 0, err - } - cmd := exec.CommandContext(ctx, "npx", "wrangler", "d1", "execute", d1Name, "--remote", "--json", "--yes", + out, err := wranglerD1(ctx, dir, d1Name, "--remote", "--json", "--yes", "--command", "SELECT COUNT(*) AS n FROM "+table) - cmd.Dir = cmdDir - out, err := cmd.CombinedOutput() if err != nil { - return 0, fmt.Errorf("wrangler d1 execute failed: %v: %s", err, strings.TrimSpace(string(out))) + return 0, err } var results []struct { -- 2.51.2