Skip to content

Commit f6e15d2

Browse files
julianknutsenclaude
andcommitted
Add GitHub PR shell via wl review --gh-pr
Create a real GitHub PR as a discussion venue for Dolt data reviews. The --gh-pr flag pushes the Dolt branch to the rig's GitHub fork, creates a git-native branch with a .wasteland/ marker file via the GitHub API, and opens a cross-fork PR against the upstream repo. Re-running updates the existing PR. wl merge auto-closes the PR. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4dfdc1b commit f6e15d2

8 files changed

Lines changed: 478 additions & 14 deletions

File tree

cmd/wl/cmd_config.go

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"fmt"
55
"io"
6+
"strings"
67

78
"github.com/spf13/cobra"
89
"github.com/steveyegge/wasteland/internal/federation"
@@ -18,7 +19,8 @@ Use 'wl config get <key>' to read a setting.
1819
Use 'wl config set <key> <value>' to change a setting.
1920
2021
Supported keys:
21-
mode Workflow mode: wild-west (default) or pr`,
22+
mode Workflow mode: wild-west (default) or pr
23+
github-repo Upstream GitHub repo for PR shells (owner/repo)`,
2224
Args: cobra.NoArgs,
2325
RunE: func(cmd *cobra.Command, _ []string) error {
2426
return cmd.Help()
@@ -57,34 +59,43 @@ func newConfigSetCmd(stdout, stderr io.Writer) *cobra.Command {
5759

5860
// validConfigKeys lists the keys that can be read/written via wl config.
5961
var validConfigKeys = map[string]bool{
60-
"mode": true,
62+
"mode": true,
63+
"github-repo": true,
6164
}
6265

6366
func runConfigGet(cmd *cobra.Command, stdout, _ io.Writer, key string) error {
6467
if !validConfigKeys[key] {
65-
return fmt.Errorf("unknown config key %q (supported: mode)", key)
68+
return fmt.Errorf("unknown config key %q (supported: mode, github-repo)", key)
6669
}
6770

6871
cfg, err := resolveWasteland(cmd)
6972
if err != nil {
7073
return fmt.Errorf("loading wasteland config: %w", err)
7174
}
7275

73-
if key == "mode" {
76+
switch key {
77+
case "mode":
7478
fmt.Fprintln(stdout, cfg.ResolveMode())
79+
case "github-repo":
80+
fmt.Fprintln(stdout, cfg.GitHubRepo)
7581
}
7682
return nil
7783
}
7884

7985
func runConfigSet(cmd *cobra.Command, stdout, _ io.Writer, key, value string) error {
8086
if !validConfigKeys[key] {
81-
return fmt.Errorf("unknown config key %q (supported: mode)", key)
87+
return fmt.Errorf("unknown config key %q (supported: mode, github-repo)", key)
8288
}
8389

84-
if key == "mode" {
90+
switch key {
91+
case "mode":
8592
if err := validateMode(value); err != nil {
8693
return err
8794
}
95+
case "github-repo":
96+
if err := validateGitHubRepo(value); err != nil {
97+
return err
98+
}
8899
}
89100

90101
explicit, _ := cmd.Flags().GetString("wasteland")
@@ -94,8 +105,11 @@ func runConfigSet(cmd *cobra.Command, stdout, _ io.Writer, key, value string) er
94105
return fmt.Errorf("loading wasteland config: %w", err)
95106
}
96107

97-
if key == "mode" {
108+
switch key {
109+
case "mode":
98110
cfg.Mode = value
111+
case "github-repo":
112+
cfg.GitHubRepo = value
99113
}
100114

101115
if err := store.Save(cfg); err != nil {
@@ -106,6 +120,14 @@ func runConfigSet(cmd *cobra.Command, stdout, _ io.Writer, key, value string) er
106120
return nil
107121
}
108122

123+
func validateGitHubRepo(value string) error {
124+
parts := strings.SplitN(value, "/", 2)
125+
if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
126+
return fmt.Errorf("invalid github-repo %q: expected format \"owner/repo\"", value)
127+
}
128+
return nil
129+
}
130+
109131
func validateMode(value string) error {
110132
switch value {
111133
case federation.ModeWildWest, federation.ModePR:

cmd/wl/cmd_config_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,25 @@ func TestValidConfigKeys(t *testing.T) {
3030
t.Error("'nonexistent' should not be a valid config key")
3131
}
3232
}
33+
34+
func TestValidConfigKeys_GitHubRepo(t *testing.T) {
35+
if !validConfigKeys["github-repo"] {
36+
t.Error("expected 'github-repo' to be a valid config key")
37+
}
38+
}
39+
40+
func TestValidateGitHubRepo_Valid(t *testing.T) {
41+
for _, repo := range []string{"owner/repo", "steveyegge/wl-commons", "a/b"} {
42+
if err := validateGitHubRepo(repo); err != nil {
43+
t.Errorf("validateGitHubRepo(%q) = %v, want nil", repo, err)
44+
}
45+
}
46+
}
47+
48+
func TestValidateGitHubRepo_Invalid(t *testing.T) {
49+
for _, repo := range []string{"", "noslash", "/bad", "bad/", "/"} {
50+
if err := validateGitHubRepo(repo); err == nil {
51+
t.Errorf("validateGitHubRepo(%q) = nil, want error", repo)
52+
}
53+
}
54+
}

cmd/wl/cmd_merge.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"fmt"
55
"io"
6+
"os/exec"
67

78
"github.com/spf13/cobra"
89
"github.com/steveyegge/wasteland/internal/commons"
@@ -71,5 +72,12 @@ func runMerge(cmd *cobra.Command, stdout, _ io.Writer, branch string, noPush, ke
7172
_ = commons.PushWithSync(cfg.LocalDir, stdout)
7273
}
7374

75+
// Best-effort: auto-close the corresponding GitHub PR shell.
76+
if cfg.GitHubRepo != "" {
77+
if ghPath, err := exec.LookPath("gh"); err == nil {
78+
closeGitHubPR(ghPath, cfg.GitHubRepo, cfg.ForkOrg, cfg.ForkDB, branch, stdout)
79+
}
80+
}
81+
7482
return nil
7583
}

0 commit comments

Comments
 (0)