fix(releaser): add MODULE.bazel boilerplate (#4225)

This will make the release easier.

We should also have the releaser add the MODULE.bazel boilerplate code.

This also adds tests to the modified function.

We also don't need require release notes, since we can just edit in the
UI.
diff --git a/go/tools/releaser/BUILD.bazel b/go/tools/releaser/BUILD.bazel
index e750c67..9908278 100644
--- a/go/tools/releaser/BUILD.bazel
+++ b/go/tools/releaser/BUILD.bazel
@@ -31,7 +31,14 @@
 
 go_test(
     name = "releaser_test",
-    srcs = ["upgradedep_test.go"],
+    srcs = [
+        "boilerplate_test.go",
+        "upgradedep_test.go",
+    ],
+    data = glob(["testdata/**"]),
     embed = [":releaser_lib"],
-    deps = ["@com_github_bazelbuild_buildtools//build:go_default_library"],
+    deps = [
+        "//go/runfiles",
+        "@com_github_bazelbuild_buildtools//build:go_default_library",
+    ],
 )
diff --git a/go/tools/releaser/boilerplate.go b/go/tools/releaser/boilerplate.go
index a686bc7..50fd0c1 100644
--- a/go/tools/releaser/boilerplate.go
+++ b/go/tools/releaser/boilerplate.go
@@ -21,19 +21,33 @@
 	"io"
 	"net/http"
 	"sort"
+	"strings"
 
 	"golang.org/x/mod/semver"
 )
 
 func genBoilerplate(version, shasum, goVersion string) string {
-	return fmt.Sprintf(`load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+	trimmedVersion := strings.TrimPrefix(version, "v")
+	return fmt.Sprintf(`## `+"`MODULE.bazel`"+` code
+
+`+"```"+`
+bazel_dep(name = "rules_go", version = "%[1]s")
+
+go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
+go_sdk.from_file(go_mod = "//:go.mod")
+`+"```"+`
+
+## `+"`WORKSPACE`"+` code
+
+`+"```"+`
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 http_archive(
     name = "io_bazel_rules_go",
     sha256 = "%[2]s",
     urls = [
-        "https://mirror.bazel.build/github.com/bazel-contrib/rules_go/releases/download/%[1]s/rules_go-%[1]s.zip",
-        "https://github.com/bazel-contrib/rules_go/releases/download/%[1]s/rules_go-%[1]s.zip",
+        "https://mirror.bazel.build/github.com/bazel-contrib/rules_go/releases/download/v%[1]s/rules_go-v%[1]s.zip",
+        "https://github.com/bazel-contrib/rules_go/releases/download/v%[1]s/rules_go-v%[1]s.zip",
     ],
 )
 
@@ -48,10 +62,10 @@
 load("@platforms//host:extension.bzl", "host_platform_repo")
 
 maybe(
-	host_platform_repo,
-	name = "host_platform",
+    host_platform_repo,
+    name = "host_platform",
 )
-`, version, shasum, goVersion)
+`+"```", trimmedVersion, shasum, goVersion)
 }
 
 func findLatestGoVersion() (v string, err error) {
diff --git a/go/tools/releaser/boilerplate_test.go b/go/tools/releaser/boilerplate_test.go
new file mode 100644
index 0000000..9941830
--- /dev/null
+++ b/go/tools/releaser/boilerplate_test.go
@@ -0,0 +1,32 @@
+package main
+
+import (
+	"os"
+	"strings"
+	"testing"
+
+	"github.com/bazelbuild/rules_go/go/runfiles"
+)
+
+func TestGenBoilerplate(t *testing.T) {
+	version := "v1.2.3"
+	shasum := "abcd1234"
+	goVersion := "1.23"
+
+	actual := genBoilerplate(version, shasum, goVersion)
+
+	expectedPath, err := runfiles.Rlocation("_main/go/tools/releaser/testdata/boilerplate.md")
+	if err != nil {
+		t.Fatalf("failed to locate test data: %v", err)
+	}
+	expectedBytes, err := os.ReadFile(expectedPath)
+	if err != nil {
+		t.Fatalf("failed to read expected boilerplate: %v", err)
+	}
+	expected := strings.TrimSpace(string(expectedBytes))
+	actual = strings.TrimSpace(actual)
+
+	if actual != expected {
+		t.Errorf("generated boilerplate does not match expected\nExpected:\n%s\nActual:\n%s", expected, actual)
+	}
+}
diff --git a/go/tools/releaser/prepare.go b/go/tools/releaser/prepare.go
index 1dba9a0..26694b3 100644
--- a/go/tools/releaser/prepare.go
+++ b/go/tools/releaser/prepare.go
@@ -15,7 +15,6 @@
 package main
 
 import (
-	"bytes"
 	"context"
 	"errors"
 	"flag"
@@ -65,12 +64,11 @@
 func runPrepare(ctx context.Context, stderr io.Writer, args []string) error {
 	// Parse arguments.
 	flags := flag.NewFlagSet("releaser prepare", flag.ContinueOnError)
-	var rnotesPath, version string
+	var version string
 	var githubToken githubTokenFlag
 	var uploadToMirror bool
 	flags.Var(&githubToken, "githubtoken", "GitHub personal access token or path to a file containing it")
 	flags.BoolVar(&uploadToMirror, "mirror", false, "whether to upload dependency archives to mirror.bazel.build")
-	flags.StringVar(&rnotesPath, "rnotes", "", "Name of file containing release notes in Markdown")
 	flags.StringVar(&version, "version", "", "Version to release")
 	if err := flags.Parse(args); err != nil {
 		return err
@@ -81,9 +79,6 @@
 	if githubToken == "" {
 		return usageErrorf(&prepareCmd, "-githubtoken must be set")
 	}
-	if rnotesPath == "" {
-		return usageErrorf(&prepareCmd, "-rnotes must be set")
-	}
 	if version == "" {
 		return usageErrorf(&prepareCmd, "-version must be set")
 	}
@@ -149,18 +144,11 @@
 		return err
 	}
 
-	// Read release notes, append boilerplate.
-	rnotesData, err := os.ReadFile(rnotesPath)
-	if err != nil {
-		return err
-	}
-	rnotesData = bytes.TrimSpace(rnotesData)
 	goVersion, err := findLatestGoVersion()
 	if err != nil {
 		return err
 	}
-	boilerplate := genBoilerplate(version, arcSum, goVersion)
-	rnotesStr := string(rnotesData) + "\n\n## `WORKSPACE` code\n\n```\n" + boilerplate + "\n```\n"
+	rnotesStr := genBoilerplate(version, arcSum, goVersion)
 
 	// Push the release branch.
 	fmt.Fprintf(stderr, "pushing branch %s to origin...\n", branchName)
diff --git a/go/tools/releaser/testdata/boilerplate.md b/go/tools/releaser/testdata/boilerplate.md
new file mode 100644
index 0000000..b41a1b9
--- /dev/null
+++ b/go/tools/releaser/testdata/boilerplate.md
@@ -0,0 +1,38 @@
+## `MODULE.bazel` code
+
+```
+bazel_dep(name = "rules_go", version = "1.2.3")
+
+go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
+go_sdk.from_file(go_mod = "//:go.mod")
+```
+
+## `WORKSPACE` code
+
+```
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+http_archive(
+    name = "io_bazel_rules_go",
+    sha256 = "abcd1234",
+    urls = [
+        "https://mirror.bazel.build/github.com/bazel-contrib/rules_go/releases/download/v1.2.3/rules_go-v1.2.3.zip",
+        "https://github.com/bazel-contrib/rules_go/releases/download/v1.2.3/rules_go-v1.2.3.zip",
+    ],
+)
+
+load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
+
+go_rules_dependencies()
+
+go_register_toolchains(version = "1.23")
+
+# Create the host platform repository transitively required by rules_go.
+load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
+load("@platforms//host:extension.bzl", "host_platform_repo")
+
+maybe(
+    host_platform_repo,
+    name = "host_platform",
+)
+```