From ee161715d50f286feef4c8cd03f307a38c5d07e7 Mon Sep 17 00:00:00 2001
From: William Martin <williammartin@github.com>
Date: Wed, 23 Oct 2024 13:46:22 +0200
Subject: [PATCH 1/4] Note fork purpose in README

---
 README.md | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/README.md b/README.md
index f670356..88bdab5 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,9 @@
+# Why is this forked?
+
+This repo is forked into the `cli` org to allow the `gh` maintainers to explore the use of `testscript` in `gh`, while providing the flexibility for us to share modifications and extensions. It is not intended to be a long-term maintained fork and you should not rely on it.
+
+## Original README
+
 This repository factors out an opinionated selection of internal packages and functionality from the Go standard
 library. Currently this consists mostly of packages and testing code from within the Go tool implementation.
 

From 7e305b22223eaed51fcbd0685fd7ef10d71c1011 Mon Sep 17 00:00:00 2001
From: William Martin <williammartin@github.com>
Date: Wed, 23 Oct 2024 13:47:40 +0200
Subject: [PATCH 2/4] Redact GH tokens from log

---
 testscript/testscript.go      | 18 ++++++++++-
 testscript/testscript_test.go | 57 +++++++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/testscript/testscript.go b/testscript/testscript.go
index e402483..9d162e6 100644
--- a/testscript/testscript.go
+++ b/testscript/testscript.go
@@ -581,7 +581,7 @@ func (ts *TestScript) run() {
 
 		markTime()
 		// Flush testScript log to testing.T log.
-		ts.t.Log(ts.abbrev(ts.log.String()))
+		ts.t.Log(ts.abbrev(redactTokens(ts.log.String())))
 	}()
 	defer func() {
 		ts.deferred()
@@ -883,6 +883,22 @@ func (ts *TestScript) condition(cond string) (bool, error) {
 
 // Helpers for command implementations.
 
+// redactTokens looks at the entire string looking for strings that start with
+// gho_ or ghp_, then it finds everything after _ until a whitespace separator,
+// and replaces those characters with asterisks (e.g. gho_abc123 -> gho_******).
+func redactTokens(s string) string {
+	// Regular expression to match "ghp_" or "gho_" followed by any sequence of non-whitespace characters
+	re := regexp.MustCompile(`(gh[op]_)\S+`)
+
+	// Replace matched strings with the prefix followed by asterisks
+	return re.ReplaceAllStringFunc(s, func(match string) string {
+		// Keep the "ghp_" or "gho_" prefix and replace the rest with asterisks
+		prefix := match[:4]                         // "ghp_" or "gho_"
+		length := len(match[4:])                    // Length of the remaining characters to be redacted
+		return prefix + strings.Repeat("*", length) // Replace the rest with asterisks
+	})
+}
+
 // abbrev abbreviates the actual work directory in the string s to the literal string "$WORK".
 func (ts *TestScript) abbrev(s string) string {
 	s = strings.Replace(s, ts.workdir, "$WORK", -1)
diff --git a/testscript/testscript_test.go b/testscript/testscript_test.go
index 9cbab8f..352f893 100644
--- a/testscript/testscript_test.go
+++ b/testscript/testscript_test.go
@@ -410,6 +410,63 @@ func TestBadDir(t *testing.T) {
 	}
 }
 
+func TestRedactTokens(t *testing.T) {
+	tests := []struct {
+		name  string
+		input string
+		want  string
+	}{
+		{
+			name:  "no token",
+			input: "no token",
+			want:  "no token",
+		},
+		{
+			name:  "oauth token at start",
+			input: "gho_1234567890",
+			want:  "gho_**********",
+		},
+		{
+			name:  "oauth token at end",
+			input: "this is a gho_1234567890",
+			want:  "this is a gho_**********",
+		},
+		{
+			name:  "oauth token in middle",
+			input: "this is a gho_1234567890 and this is redacted",
+			want:  "this is a gho_********** and this is redacted",
+		},
+		{
+			name:  "oauth token at start with newline",
+			input: "gho_1234567890\n",
+			want:  "gho_**********\n",
+		},
+		{
+			name:  "oauth token with no preceding word boundary",
+			input: "foogho_1234567890",
+			want:  "foogho_**********",
+		},
+		{
+			name:  "oauth token no word boundary (extends redaction into next word)",
+			input: "gho_1234567890x",
+			want:  "gho_***********",
+		},
+		{
+			name:  "pat token",
+			input: "ghp_1234567890",
+			want:  "ghp_**********",
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			if got := redactTokens(test.input); got != test.want {
+				t.Fatalf("redactTokens(%q) == %q, want %q", test.input, got, test.want)
+			}
+		})
+	}
+}
+
 // catchAbort catches the panic raised by fakeT.FailNow.
 func catchAbort() {
 	if err := recover(); err != nil && err != errAbort {

From fa3c22e38b9b2ff589e70fbe668214470defb60f Mon Sep 17 00:00:00 2001
From: William Martin <williammartin@github.com>
Date: Thu, 24 Oct 2024 15:02:15 +0200
Subject: [PATCH 3/4] Add redaction support for all token types

---
 testscript/testscript.go      | 20 ++++++----
 testscript/testscript_test.go | 73 +++++++++++++++++++----------------
 2 files changed, 51 insertions(+), 42 deletions(-)

diff --git a/testscript/testscript.go b/testscript/testscript.go
index 9d162e6..365167e 100644
--- a/testscript/testscript.go
+++ b/testscript/testscript.go
@@ -883,19 +883,23 @@ func (ts *TestScript) condition(cond string) (bool, error) {
 
 // Helpers for command implementations.
 
-// redactTokens looks at the entire string looking for strings that start with
-// gho_ or ghp_, then it finds everything after _ until a whitespace separator,
-// and replaces those characters with asterisks (e.g. gho_abc123 -> gho_******).
+// redactTokens looks at the entire string looking for strings that start with a known token prefix,
+// keeps the prefix that distinguishes the token type and masks the rest of the token with asterisks.
+// Note that it does not attempt to distinguish the end of a token from any suffixed characters so
+// gho_mytokenNOTATOKEN will mask the entirity of the string.
 func redactTokens(s string) string {
 	// Regular expression to match "ghp_" or "gho_" followed by any sequence of non-whitespace characters
-	re := regexp.MustCompile(`(gh[op]_)\S+`)
+	re := regexp.MustCompile(`(gh[pousr]_|github_pat_)\S+`)
 
 	// Replace matched strings with the prefix followed by asterisks
 	return re.ReplaceAllStringFunc(s, func(match string) string {
-		// Keep the "ghp_" or "gho_" prefix and replace the rest with asterisks
-		prefix := match[:4]                         // "ghp_" or "gho_"
-		length := len(match[4:])                    // Length of the remaining characters to be redacted
-		return prefix + strings.Repeat("*", length) // Replace the rest with asterisks
+		// If the match is gh then we want to keep the first 4 characters and redact everything else,
+		// otherwise, it must be a github_pat_ and then we keep the first 11 characters and redact everything else.
+		prefixLength := 4
+		if strings.HasPrefix(match, "github_pat_") {
+			prefixLength = 11
+		}
+		return match[:prefixLength] + strings.Repeat("*", len(match)-prefixLength)
 	})
 }
 
diff --git a/testscript/testscript_test.go b/testscript/testscript_test.go
index 352f893..e40b6fb 100644
--- a/testscript/testscript_test.go
+++ b/testscript/testscript_test.go
@@ -411,59 +411,64 @@ func TestBadDir(t *testing.T) {
 }
 
 func TestRedactTokens(t *testing.T) {
+	// https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-authentication-to-github#githubs-token-formats
+	tokensToRedacted := map[string]string{
+		"ghp_1234567890":        "ghp_**********",
+		"github_pat_1234567890": "github_pat_**********",
+		"gho_1234567890":        "gho_**********",
+		"ghu_1234567890":        "ghu_**********",
+		"ghs_1234567890":        "ghs_**********",
+		"ghr_1234567890":        "ghr_**********",
+	}
+
 	tests := []struct {
 		name  string
 		input string
 		want  string
 	}{
 		{
-			name:  "no token",
-			input: "no token",
-			want:  "no token",
-		},
-		{
-			name:  "oauth token at start",
-			input: "gho_1234567890",
-			want:  "gho_**********",
-		},
-		{
-			name:  "oauth token at end",
-			input: "this is a gho_1234567890",
-			want:  "this is a gho_**********",
+			name:  "token at start",
+			input: "%s",
+			want:  "%s",
 		},
 		{
-			name:  "oauth token in middle",
-			input: "this is a gho_1234567890 and this is redacted",
-			want:  "this is a gho_********** and this is redacted",
+			name:  "token at end",
+			input: "this is a %s",
+			want:  "this is a %s",
 		},
 		{
-			name:  "oauth token at start with newline",
-			input: "gho_1234567890\n",
-			want:  "gho_**********\n",
+			name:  "token in middle",
+			input: "this is a %s and this is redacted",
+			want:  "this is a %s and this is redacted",
 		},
 		{
-			name:  "oauth token with no preceding word boundary",
-			input: "foogho_1234567890",
-			want:  "foogho_**********",
+			name:  "token at start with newline",
+			input: "%s\n",
+			want:  "%s\n",
 		},
 		{
-			name:  "oauth token no word boundary (extends redaction into next word)",
-			input: "gho_1234567890x",
-			want:  "gho_***********",
+			name:  "token with no preceding word boundary",
+			input: "foo%s",
+			want:  "foo%s",
 		},
 		{
-			name:  "pat token",
-			input: "ghp_1234567890",
-			want:  "ghp_**********",
+			name:  "token no word boundary (extends redaction into next word)",
+			input: "%sx",
+			want:  "%s*",
 		},
 	}
 
-	for _, test := range tests {
-		t.Run(test.name, func(t *testing.T) {
-			if got := redactTokens(test.input); got != test.want {
-				t.Fatalf("redactTokens(%q) == %q, want %q", test.input, got, test.want)
-			}
-		})
+	for token, redacted := range tokensToRedacted {
+		for _, test := range tests {
+			t.Run(fmt.Sprintf("%s: %s", token, test.name), func(t *testing.T) {
+				unredacted := fmt.Sprintf(test.input, token)
+				expected := fmt.Sprintf(test.want, redacted)
+
+				if got := redactTokens(unredacted); got != expected {
+					t.Fatalf("redactTokens(%q) == %q, want %q", unredacted, got, expected)
+				}
+			})
+		}
 	}
 }
 

From 6c48bcd5ce24768590e572f4065590d9baddb275 Mon Sep 17 00:00:00 2001
From: William Martin <williammartin@github.com>
Date: Fri, 25 Oct 2024 16:13:32 +0200
Subject: [PATCH 4/4] Rewrite import paths to hard fork

This is an issue because this module is currently used via a replace directive in the
cli/cli go.mod, which prevents installation via go get@github.com/cli/cli/cmd/gh

https://github.com/cli/cli/issues/9818
---
 README.md                                        | 14 ++++++++------
 cache/cache.go                                   |  2 +-
 cmd/testscript/README.md                         |  8 ++++----
 cmd/testscript/help.go                           |  8 ++++----
 cmd/testscript/main.go                           |  8 ++++----
 cmd/testscript/main_test.go                      |  6 +++---
 cmd/txtar-addmod/addmod.go                       |  4 ++--
 cmd/txtar-addmod/script_test.go                  |  6 +++---
 cmd/txtar-c/savedir.go                           |  2 +-
 cmd/txtar-c/script_test.go                       |  2 +-
 cmd/txtar-goproxy/main.go                        |  2 +-
 cmd/txtar-x/extract.go                           |  2 +-
 cmd/txtar-x/extract_test.go                      |  2 +-
 fmtsort/sort_test.go                             |  2 +-
 go.mod                                           |  2 +-
 goproxytest/proxy.go                             |  2 +-
 goproxytest/proxy_test.go                        |  6 +++---
 gotooltest/script_test.go                        |  4 ++--
 gotooltest/setup.go                              |  2 +-
 gotooltest/testdata/cover.txt                    |  6 +++---
 imports/scan_test.go                             |  2 +-
 internal/syscall/windows/zsyscall_windows.go     |  2 +-
 lockedfile/internal/filelock/filelock_test.go    |  2 +-
 lockedfile/internal/filelock/filelock_windows.go |  2 +-
 lockedfile/lockedfile_filelock.go                |  2 +-
 lockedfile/lockedfile_test.go                    |  2 +-
 lockedfile/transform_test.go                     |  2 +-
 robustio/robustio_windows.go                     |  2 +-
 testscript/cmd.go                                |  6 +++---
 testscript/doc.go                                |  4 ++--
 testscript/testscript.go                         | 14 +++++++-------
 31 files changed, 66 insertions(+), 64 deletions(-)

diff --git a/README.md b/README.md
index 88bdab5..2821bf7 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,15 @@
 # Why is this forked?
 
-This repo is forked into the `cli` org to allow the `gh` maintainers to explore the use of `testscript` in `gh`, while providing the flexibility for us to share modifications and extensions. It is not intended to be a long-term maintained fork and you should not rely on it.
+This is hard forked from github.com/rogpeppe/testscript to allow the `gh` maintainers to explore the use of `testscript` in `gh`, while providing the flexibility for us to share modifications and extensions. It is not intended to be a long-term maintained fork and you should not rely on it.
 
-## Original README
+If we determine it is a good fit for the project, we will decide what to do next based on how our needs align with the preferences of the maintainers of rogpeppe/testscript.
+
+## Original README with minor tweaks to indicate upstream/fork relationship
 
 This repository factors out an opinionated selection of internal packages and functionality from the Go standard
 library. Currently this consists mostly of packages and testing code from within the Go tool implementation.
 
-This repo is [primarily maintained](https://github.com/rogpeppe/go-internal/graphs/contributors) by long-time
+The upstream repo is [primarily maintained](https://github.com/rogpeppe/go-internal/graphs/contributors) by long-time
 [Go contributors](https://github.com/golang/go/contributors) who are also currently
 [maintaining CUE](https://github.com/cue-lang/cue/graphs/contributors) (which is primarily written in Go
 and which relies upon several of the packages here).
@@ -31,7 +33,7 @@ Our package will be replaced by it once https://github.com/golang/go/issues/5926
 
 ### testscript
 
-The most popular package here is the [testscript](https://pkg.go.dev/github.com/rogpeppe/go-internal/testscript) package:
+The most popular package here is the [testscript](https://pkg.go.dev/github.com/cli/go-internal/testscript) package:
  * Provides a shell-like test environment that is very nicely tuned for testing Go CLI commands.
  * Extracted from the core Go team's internal testscript package ([cmd/go/internal/script](https://github.com/golang/go/tree/master/src/cmd/go/internal/script)),
  which is [heavily used](https://github.com/golang/go/tree/master/src/cmd/go/testdata/script) to test the `go` command.
@@ -39,10 +41,10 @@ The most popular package here is the [testscript](https://pkg.go.dev/github.com/
  * Integrates well with `go test`, including coverage support.
  * Inputs and sample output files can use the simple [txtar](https://pkg.go.dev/golang.org/x/tools/txtar)
  text archive format, also used by the Go playground.
- * Allows [automatically updating](https://pkg.go.dev/github.com/rogpeppe/go-internal/testscript#Params)
+ * Allows [automatically updating](https://pkg.go.dev/github.com/cli/go-internal/testscript#Params)
  golden files.
  * Built-in support for Go concepts like build tags.
- * Accompanied by a [testscript](https://github.com/rogpeppe/go-internal/tree/master/cmd/testscript) command
+ * Accompanied by a [testscript](https://github.com/cli/go-internal/tree/master/cmd/testscript) command
  for running standalone scripts with files embedded in txtar format.
  
  A nice introduction to using testscripts is this [blog post](https://bitfieldconsulting.com/golang/test-scripts) series.
diff --git a/cache/cache.go b/cache/cache.go
index 93c9053..5061a05 100644
--- a/cache/cache.go
+++ b/cache/cache.go
@@ -19,7 +19,7 @@ import (
 	"strings"
 	"time"
 
-	"github.com/rogpeppe/go-internal/lockedfile"
+	"github.com/cli/go-internal/lockedfile"
 )
 
 // An ActionID is a cache action key, the hash of a complete description of a
diff --git a/cmd/testscript/README.md b/cmd/testscript/README.md
index daf9930..40676a7 100644
--- a/cmd/testscript/README.md
+++ b/cmd/testscript/README.md
@@ -1,5 +1,5 @@
 ```
-The testscript command runs github.com/rogpeppe/go-internal/testscript scripts
+The testscript command runs github.com/cli/go-internal/testscript scripts
 in a fresh temporary work directory tree.
 
 Usage:
@@ -9,15 +9,15 @@ The testscript command is designed to make it easy to create self-contained
 reproductions of command sequences.
 
 Each file is opened as a script and run as described in the documentation for
-github.com/rogpeppe/go-internal/testscript. The special filename "-" is
+github.com/cli/go-internal/testscript. The special filename "-" is
 interpreted as the standard input.
 
 As a special case, supporting files/directories in the .gomodproxy subdirectory
-will be served via a github.com/rogpeppe/go-internal/goproxytest server which
+will be served via a github.com/cli/go-internal/goproxytest server which
 is available to each script via the GOPROXY environment variable. The contents
 of the .gomodproxy subdirectory are not available to the script except via the
 proxy server. See the documentation for
-github.com/rogpeppe/go-internal/goproxytest for details on the format of these
+github.com/cli/go-internal/goproxytest for details on the format of these
 files/directories.
 
 Environment variables can be passed through to each script with the -e flag,
diff --git a/cmd/testscript/help.go b/cmd/testscript/help.go
index 0b3975c..1845bc0 100644
--- a/cmd/testscript/help.go
+++ b/cmd/testscript/help.go
@@ -10,7 +10,7 @@ func mainUsage(f io.Writer) {
 }
 
 var mainHelp = `
-The testscript command runs github.com/rogpeppe/go-internal/testscript scripts
+The testscript command runs github.com/cli/go-internal/testscript scripts
 in a fresh temporary work directory tree.
 
 Usage:
@@ -20,15 +20,15 @@ The testscript command is designed to make it easy to create self-contained
 reproductions of command sequences.
 
 Each file is opened as a script and run as described in the documentation for
-github.com/rogpeppe/go-internal/testscript. The special filename "-" is
+github.com/cli/go-internal/testscript. The special filename "-" is
 interpreted as the standard input.
 
 As a special case, supporting files/directories in the .gomodproxy subdirectory
-will be served via a github.com/rogpeppe/go-internal/goproxytest server which
+will be served via a github.com/cli/go-internal/goproxytest server which
 is available to each script via the GOPROXY environment variable. The contents
 of the .gomodproxy subdirectory are not available to the script except via the
 proxy server. See the documentation for
-github.com/rogpeppe/go-internal/goproxytest for details on the format of these
+github.com/cli/go-internal/goproxytest for details on the format of these
 files/directories.
 
 Environment variables can be passed through to each script with the -e flag,
diff --git a/cmd/testscript/main.go b/cmd/testscript/main.go
index 65b340a..fa7e139 100644
--- a/cmd/testscript/main.go
+++ b/cmd/testscript/main.go
@@ -15,14 +15,14 @@ import (
 	"strings"
 	"sync/atomic"
 
-	"github.com/rogpeppe/go-internal/goproxytest"
-	"github.com/rogpeppe/go-internal/gotooltest"
-	"github.com/rogpeppe/go-internal/testscript"
+	"github.com/cli/go-internal/goproxytest"
+	"github.com/cli/go-internal/gotooltest"
+	"github.com/cli/go-internal/testscript"
 )
 
 const (
 	// goModProxyDir is the special subdirectory in a txtar script's supporting files
-	// within which we expect to find github.com/rogpeppe/go-internal/goproxytest
+	// within which we expect to find github.com/cli/go-internal/goproxytest
 	// directories.
 	goModProxyDir = ".gomodproxy"
 )
diff --git a/cmd/testscript/main_test.go b/cmd/testscript/main_test.go
index 7bc3902..5307b44 100644
--- a/cmd/testscript/main_test.go
+++ b/cmd/testscript/main_test.go
@@ -13,9 +13,9 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/rogpeppe/go-internal/gotooltest"
-	"github.com/rogpeppe/go-internal/internal/os/execpath"
-	"github.com/rogpeppe/go-internal/testscript"
+	"github.com/cli/go-internal/gotooltest"
+	"github.com/cli/go-internal/internal/os/execpath"
+	"github.com/cli/go-internal/testscript"
 )
 
 func TestMain(m *testing.M) {
diff --git a/cmd/txtar-addmod/addmod.go b/cmd/txtar-addmod/addmod.go
index e58514a..f9de5f4 100644
--- a/cmd/txtar-addmod/addmod.go
+++ b/cmd/txtar-addmod/addmod.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // The txtar-addmod command adds a module as a txtar archive to the a testdata module directory
-// as understood by the goproxytest package (see https://godoc.org/github.com/rogpeppe/go-internal/goproxytest).
+// as understood by the goproxytest package (see https://godoc.org/github.com/cli/go-internal/goproxytest).
 //
 // Usage:
 //
@@ -38,7 +38,7 @@ func usage() {
 	fmt.Fprintf(os.Stderr, `
 The txtar-addmod command adds a module as a txtar archive to the
 testdata module directory as understood by the goproxytest package
-(see https://godoc.org/github.com/rogpeppe/go-internal/goproxytest).
+(see https://godoc.org/github.com/cli/go-internal/goproxytest).
 
 The dir argument names to directory to add the module to. If dir is "-",
 the result will instead be written to the standard output in a form
diff --git a/cmd/txtar-addmod/script_test.go b/cmd/txtar-addmod/script_test.go
index b070ef0..cd93b8f 100644
--- a/cmd/txtar-addmod/script_test.go
+++ b/cmd/txtar-addmod/script_test.go
@@ -9,9 +9,9 @@ import (
 	"os"
 	"testing"
 
-	"github.com/rogpeppe/go-internal/goproxytest"
-	"github.com/rogpeppe/go-internal/gotooltest"
-	"github.com/rogpeppe/go-internal/testscript"
+	"github.com/cli/go-internal/goproxytest"
+	"github.com/cli/go-internal/gotooltest"
+	"github.com/cli/go-internal/testscript"
 )
 
 var proxyURL string
diff --git a/cmd/txtar-c/savedir.go b/cmd/txtar-c/savedir.go
index bc2f692..0d0ec5f 100644
--- a/cmd/txtar-c/savedir.go
+++ b/cmd/txtar-c/savedir.go
@@ -22,7 +22,7 @@ import (
 	"strings"
 	"unicode/utf8"
 
-	"github.com/rogpeppe/go-internal/txtar"
+	"github.com/cli/go-internal/txtar"
 )
 
 var flag = stdflag.NewFlagSet(os.Args[0], stdflag.ContinueOnError)
diff --git a/cmd/txtar-c/script_test.go b/cmd/txtar-c/script_test.go
index 94e7732..20a84ec 100644
--- a/cmd/txtar-c/script_test.go
+++ b/cmd/txtar-c/script_test.go
@@ -8,7 +8,7 @@ import (
 	"os"
 	"testing"
 
-	"github.com/rogpeppe/go-internal/testscript"
+	"github.com/cli/go-internal/testscript"
 )
 
 func TestMain(m *testing.M) {
diff --git a/cmd/txtar-goproxy/main.go b/cmd/txtar-goproxy/main.go
index c4f0553..c882a51 100644
--- a/cmd/txtar-goproxy/main.go
+++ b/cmd/txtar-goproxy/main.go
@@ -21,7 +21,7 @@ import (
 	"log"
 	"os"
 
-	"github.com/rogpeppe/go-internal/goproxytest"
+	"github.com/cli/go-internal/goproxytest"
 )
 
 var proxyAddr = flag.String("addr", "", "run proxy on this network address")
diff --git a/cmd/txtar-x/extract.go b/cmd/txtar-x/extract.go
index 713026e..3b5856b 100644
--- a/cmd/txtar-x/extract.go
+++ b/cmd/txtar-x/extract.go
@@ -19,7 +19,7 @@ import (
 	"log"
 	"os"
 
-	"github.com/rogpeppe/go-internal/txtar"
+	"github.com/cli/go-internal/txtar"
 )
 
 var (
diff --git a/cmd/txtar-x/extract_test.go b/cmd/txtar-x/extract_test.go
index 97e8e7e..1bb646d 100644
--- a/cmd/txtar-x/extract_test.go
+++ b/cmd/txtar-x/extract_test.go
@@ -9,7 +9,7 @@ import (
 	"os"
 	"testing"
 
-	"github.com/rogpeppe/go-internal/testscript"
+	"github.com/cli/go-internal/testscript"
 )
 
 func TestMain(m *testing.M) {
diff --git a/fmtsort/sort_test.go b/fmtsort/sort_test.go
index 88e5bb8..9ac7931 100644
--- a/fmtsort/sort_test.go
+++ b/fmtsort/sort_test.go
@@ -11,7 +11,7 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/rogpeppe/go-internal/fmtsort"
+	"github.com/cli/go-internal/fmtsort"
 )
 
 var compareTests = [][]reflect.Value{
diff --git a/go.mod b/go.mod
index 8a504e7..37f67b7 100644
--- a/go.mod
+++ b/go.mod
@@ -1,4 +1,4 @@
-module github.com/rogpeppe/go-internal
+module github.com/cli/go-internal
 
 go 1.22.0
 
diff --git a/goproxytest/proxy.go b/goproxytest/proxy.go
index e8fe8a7..3c5ea81 100644
--- a/goproxytest/proxy.go
+++ b/goproxytest/proxy.go
@@ -40,7 +40,7 @@ import (
 	"golang.org/x/mod/semver"
 	"golang.org/x/tools/txtar"
 
-	"github.com/rogpeppe/go-internal/par"
+	"github.com/cli/go-internal/par"
 )
 
 type Server struct {
diff --git a/goproxytest/proxy_test.go b/goproxytest/proxy_test.go
index 35a9452..fd16738 100644
--- a/goproxytest/proxy_test.go
+++ b/goproxytest/proxy_test.go
@@ -8,9 +8,9 @@ import (
 	"path/filepath"
 	"testing"
 
-	"github.com/rogpeppe/go-internal/goproxytest"
-	"github.com/rogpeppe/go-internal/gotooltest"
-	"github.com/rogpeppe/go-internal/testscript"
+	"github.com/cli/go-internal/goproxytest"
+	"github.com/cli/go-internal/gotooltest"
+	"github.com/cli/go-internal/testscript"
 )
 
 func TestScripts(t *testing.T) {
diff --git a/gotooltest/script_test.go b/gotooltest/script_test.go
index 5beb54a..78eac97 100644
--- a/gotooltest/script_test.go
+++ b/gotooltest/script_test.go
@@ -9,8 +9,8 @@ import (
 	"path/filepath"
 	"testing"
 
-	"github.com/rogpeppe/go-internal/gotooltest"
-	"github.com/rogpeppe/go-internal/testscript"
+	"github.com/cli/go-internal/gotooltest"
+	"github.com/cli/go-internal/testscript"
 )
 
 func TestSimple(t *testing.T) {
diff --git a/gotooltest/setup.go b/gotooltest/setup.go
index c8d9ec0..19d03f7 100644
--- a/gotooltest/setup.go
+++ b/gotooltest/setup.go
@@ -18,7 +18,7 @@ import (
 	"strings"
 	"sync"
 
-	"github.com/rogpeppe/go-internal/testscript"
+	"github.com/cli/go-internal/testscript"
 )
 
 var (
diff --git a/gotooltest/testdata/cover.txt b/gotooltest/testdata/cover.txt
index 815f4e6..96505a8 100644
--- a/gotooltest/testdata/cover.txt
+++ b/gotooltest/testdata/cover.txt
@@ -2,7 +2,7 @@ unquote scripts/exec.txt
 
 # The module uses testscript itself.
 # Use the checked out module, based on where the test binary ran.
-go mod edit -replace=github.com/rogpeppe/go-internal=${GOINTERNAL_MODULE}
+go mod edit -replace=github.com/cli/go-internal=${GOINTERNAL_MODULE}
 go mod tidy
 
 # First, a 'go test' run without coverage.
@@ -46,8 +46,8 @@ import (
 	"os"
 	"testing"
 
-	"github.com/rogpeppe/go-internal/gotooltest"
-	"github.com/rogpeppe/go-internal/testscript"
+	"github.com/cli/go-internal/gotooltest"
+	"github.com/cli/go-internal/testscript"
 )
 
 func TestMain(m *testing.M) {
diff --git a/imports/scan_test.go b/imports/scan_test.go
index 253bce1..4129fa9 100644
--- a/imports/scan_test.go
+++ b/imports/scan_test.go
@@ -10,7 +10,7 @@ import (
 	"runtime"
 	"testing"
 
-	"github.com/rogpeppe/go-internal/testenv"
+	"github.com/cli/go-internal/testenv"
 )
 
 func TestScan(t *testing.T) {
diff --git a/internal/syscall/windows/zsyscall_windows.go b/internal/syscall/windows/zsyscall_windows.go
index 3ed2d9f..d4efdf9 100644
--- a/internal/syscall/windows/zsyscall_windows.go
+++ b/internal/syscall/windows/zsyscall_windows.go
@@ -6,7 +6,7 @@ import (
 	"syscall"
 	"unsafe"
 
-	"github.com/rogpeppe/go-internal/internal/syscall/windows/sysdll"
+	"github.com/cli/go-internal/internal/syscall/windows/sysdll"
 )
 
 var _ unsafe.Pointer
diff --git a/lockedfile/internal/filelock/filelock_test.go b/lockedfile/internal/filelock/filelock_test.go
index 429969c..15436ca 100644
--- a/lockedfile/internal/filelock/filelock_test.go
+++ b/lockedfile/internal/filelock/filelock_test.go
@@ -15,7 +15,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/rogpeppe/go-internal/lockedfile/internal/filelock"
+	"github.com/cli/go-internal/lockedfile/internal/filelock"
 )
 
 func lock(t *testing.T, f *os.File) {
diff --git a/lockedfile/internal/filelock/filelock_windows.go b/lockedfile/internal/filelock/filelock_windows.go
index ceab65b..a6eeb1e 100644
--- a/lockedfile/internal/filelock/filelock_windows.go
+++ b/lockedfile/internal/filelock/filelock_windows.go
@@ -10,7 +10,7 @@ import (
 	"io/fs"
 	"syscall"
 
-	"github.com/rogpeppe/go-internal/internal/syscall/windows"
+	"github.com/cli/go-internal/internal/syscall/windows"
 )
 
 type lockType uint32
diff --git a/lockedfile/lockedfile_filelock.go b/lockedfile/lockedfile_filelock.go
index 454c3a4..8b2f429 100644
--- a/lockedfile/lockedfile_filelock.go
+++ b/lockedfile/lockedfile_filelock.go
@@ -10,7 +10,7 @@ import (
 	"io/fs"
 	"os"
 
-	"github.com/rogpeppe/go-internal/lockedfile/internal/filelock"
+	"github.com/cli/go-internal/lockedfile/internal/filelock"
 )
 
 func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
diff --git a/lockedfile/lockedfile_test.go b/lockedfile/lockedfile_test.go
index e4e01dc..7926488 100644
--- a/lockedfile/lockedfile_test.go
+++ b/lockedfile/lockedfile_test.go
@@ -16,7 +16,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/rogpeppe/go-internal/lockedfile"
+	"github.com/cli/go-internal/lockedfile"
 )
 
 func mustTempDir(t *testing.T) (dir string, remove func()) {
diff --git a/lockedfile/transform_test.go b/lockedfile/transform_test.go
index f7488fa..6bc0bee 100644
--- a/lockedfile/transform_test.go
+++ b/lockedfile/transform_test.go
@@ -16,7 +16,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/rogpeppe/go-internal/lockedfile"
+	"github.com/cli/go-internal/lockedfile"
 )
 
 func isPowerOf2(x int) bool {
diff --git a/robustio/robustio_windows.go b/robustio/robustio_windows.go
index 961de4e..b1ac9a0 100644
--- a/robustio/robustio_windows.go
+++ b/robustio/robustio_windows.go
@@ -8,7 +8,7 @@ import (
 	"errors"
 	"syscall"
 
-	"github.com/rogpeppe/go-internal/internal/syscall/windows"
+	"github.com/cli/go-internal/internal/syscall/windows"
 )
 
 const errFileNotFound = syscall.ERROR_FILE_NOT_FOUND
diff --git a/testscript/cmd.go b/testscript/cmd.go
index e04d26e..255e942 100644
--- a/testscript/cmd.go
+++ b/testscript/cmd.go
@@ -16,9 +16,9 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/rogpeppe/go-internal/diff"
-	"github.com/rogpeppe/go-internal/testscript/internal/pty"
-	"github.com/rogpeppe/go-internal/txtar"
+	"github.com/cli/go-internal/diff"
+	"github.com/cli/go-internal/testscript/internal/pty"
+	"github.com/cli/go-internal/txtar"
 )
 
 // scriptCmds are the script command implementations.
diff --git a/testscript/doc.go b/testscript/doc.go
index 8ccbb44..b0f1628 100644
--- a/testscript/doc.go
+++ b/testscript/doc.go
@@ -235,7 +235,7 @@ The predefined commands are:
     Rewrite each file by replacing any leading ">" characters from
     each line. This enables a file to contain substrings that look like
     txtar file markers.
-    See also https://godoc.org/github.com/rogpeppe/go-internal/txtar#Unquote
+    See also https://godoc.org/github.com/cli/go-internal/txtar#Unquote
 
   - wait [command]
     Wait for all 'exec' and 'go' commands started in the background (with the '&'
@@ -364,6 +364,6 @@ for manual debugging of failing tests:
 	func F() { p2.F() }
 	$
 
-See also: https://pkg.go.dev/github.com/rogpeppe/go-internal/gotooltest
+See also: https://pkg.go.dev/github.com/cli/go-internal/gotooltest
 */
 package testscript
diff --git a/testscript/testscript.go b/testscript/testscript.go
index 365167e..3c64fc2 100644
--- a/testscript/testscript.go
+++ b/testscript/testscript.go
@@ -29,13 +29,13 @@ import (
 	"testing"
 	"time"
 
-	"github.com/rogpeppe/go-internal/imports"
-	"github.com/rogpeppe/go-internal/internal/misspell"
-	"github.com/rogpeppe/go-internal/internal/os/execpath"
-	"github.com/rogpeppe/go-internal/par"
-	"github.com/rogpeppe/go-internal/testenv"
-	"github.com/rogpeppe/go-internal/testscript/internal/pty"
-	"github.com/rogpeppe/go-internal/txtar"
+	"github.com/cli/go-internal/imports"
+	"github.com/cli/go-internal/internal/misspell"
+	"github.com/cli/go-internal/internal/os/execpath"
+	"github.com/cli/go-internal/par"
+	"github.com/cli/go-internal/testenv"
+	"github.com/cli/go-internal/testscript/internal/pty"
+	"github.com/cli/go-internal/txtar"
 )
 
 var goVersionRegex = regexp.MustCompile(`^go([1-9][0-9]*)\.([1-9][0-9]*)$`)
