Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion go/tools/releaser/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
load("//go:def.bzl", "go_binary", "go_library")
load("//go:def.bzl", "go_binary", "go_library", "go_test")

go_binary(
name = "releaser",
Expand Down Expand Up @@ -28,3 +28,10 @@ go_library(
"@org_golang_x_sync//errgroup",
],
)

go_test(
name = "releaser_test",
srcs = ["upgradedep_test.go"],
embed = [":releaser_lib"],
deps = ["@com_github_bazelbuild_buildtools//build:go_default_library"],
)
43 changes: 36 additions & 7 deletions go/tools/releaser/upgradedep.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,19 +433,20 @@ func upgradeDepDecl(ctx context.Context, gh *githubClient, workDir, name string,
return fmt.Errorf("\"patches\" attribute is not a list")
}
for patchIndex, patchLabelExpr := range patchesList.List {
patchLabel, ok := patchLabelExpr.(*bzl.StringExpr)
if !ok {
return fmt.Errorf("not all patches are string literals")
patchLabelValue, comments, err := parsePatchesItem(patchLabelExpr)
if err != nil {
return fmt.Errorf("parsing expr %#v : %w", patchLabelExpr, err)
}
if !strings.HasPrefix(patchLabel.Value, "@io_bazel_rules_go//third_party:") {
return fmt.Errorf("patch does not start with '@io_bazel_rules_go//third_party:': %s", patchLabel)

if !strings.HasPrefix(patchLabelValue, "//third_party:") {
return fmt.Errorf("patch does not start with '//third_party:': %q", patchLabelValue)
}
patchName := patchLabel.Value[len("@io_bazel_rules_go//third_party:"):]
patchName := patchLabelValue[len("//third_party:"):]
patchPath := filepath.Join(rootDir, "third_party", patchName)
prevDir := filepath.Join(workDir, name, string('a'+patchIndex))
patchDir := filepath.Join(workDir, name, string('a'+patchIndex+1))
var patchCmd []string
for _, c := range patchLabel.Comment().Before {
for _, c := range comments.Before {
words := strings.Fields(strings.TrimPrefix(c.Token, "#"))
if len(words) > 0 && words[0] == "releaser:patch-cmd" {
patchCmd = words[1:]
Expand Down Expand Up @@ -488,6 +489,34 @@ func upgradeDepDecl(ctx context.Context, gh *githubClient, workDir, name string,
return nil
}

func parsePatchesItem(patchLabelExpr bzl.Expr) (value string, comments *bzl.Comments, err error) {
switch patchLabel := patchLabelExpr.(type) {
case *bzl.CallExpr:
// Verify the identifier, should be Label
Comment thread
JamyDev marked this conversation as resolved.
if ident, ok := patchLabel.X.(*bzl.Ident); !ok {
return "", nil, fmt.Errorf("invalid identifier while parsing patch label")
} else if ident.Name != "Label" {
return "", nil, fmt.Errorf("invalid patch function: %q", ident.Name)
}

// Expect 1 String argument with the patch
if len(patchLabel.List) != 1 {
return "", nil, fmt.Errorf("Label expr should have 1 argument, found %d", len(patchLabel.List))
}

// Parse patch as a string
patchLabelStr, ok := patchLabel.List[0].(*bzl.StringExpr)
if !ok {
return "", nil, fmt.Errorf("Label expr does not contain a string literal")
}
return patchLabelStr.Value, patchLabel.Comment(), nil
case *bzl.StringExpr:
return strings.TrimPrefix(patchLabel.Value, "@io_bazel_rules_go"), patchLabel.Comment(), nil
default:
return "", nil, fmt.Errorf("not all patches are string literals or Label()")
}
}

// parseUpgradeDepDirective parses a '# releaser:upgrade-dep org repo' directive
// and returns the organization and repository name or an error if the directive
// was not found or malformed.
Expand Down
89 changes: 89 additions & 0 deletions go/tools/releaser/upgradedep_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package main

import (
"fmt"
"testing"

bzl "github.com/bazelbuild/buildtools/build"
)

func TestPatchItemParser(t *testing.T) {
Comment thread
JamyDev marked this conversation as resolved.
Outdated
tests := []struct {
expression []byte
result string
error string
}{
{
expression: []byte(`# releaser:patch-cmd gazelle -repo_root . -go_prefix golang.org/x/tools -go_naming_convention import_alias
Label("//third_party:org_golang_x_tools-gazelle.patch")`),
result: "//third_party:org_golang_x_tools-gazelle.patch",
},
{
expression: []byte(`# releaser:patch-cmd gazelle -repo_root . -go_prefix golang.org/x/tools -go_naming_convention import_alias
"@io_bazel_rules_go//third_party:org_golang_x_tools-gazelle.patch"`),
result: "//third_party:org_golang_x_tools-gazelle.patch",
},
{
expression: []byte(`# releaser:patch-cmd gazelle -repo_root . -go_prefix golang.org/x/tools -go_naming_convention import_alias
"//third_party:org_golang_x_tools-gazelle.patch"`),
result: "//third_party:org_golang_x_tools-gazelle.patch",
},
{
expression: []byte(`# releaser:patch-cmd gazelle -repo_root . -go_prefix golang.org/x/tools -go_naming_convention import_alias
Label("@io_bazel_rules_go//third_party:org_golang_x_tools-gazelle.patch")`),
result: "@io_bazel_rules_go//third_party:org_golang_x_tools-gazelle.patch",
},
{
expression: []byte(`# releaser:patch-cmd gazelle -repo_root . -go_prefix golang.org/x/tools -go_naming_convention import_alias
NotLabel("//third_party:org_golang_x_tools-gazelle.patch")`),
result: "",
error: `invalid patch function: "NotLabel"`,
},
{
expression: []byte(`# releaser:patch-cmd gazelle -repo_root . -go_prefix golang.org/x/tools -go_naming_convention import_alias
NotLabel(True)`),
error: `invalid patch function: "NotLabel"`,
},
{
expression: []byte(`# releaser:patch-cmd gazelle -repo_root . -go_prefix golang.org/x/tools -go_naming_convention import_alias
True`),
error: "not all patches are string literals or Label()",
},
{
expression: []byte(`# releaser:patch-cmd gazelle -repo_root . -go_prefix golang.org/x/tools -go_naming_convention import_alias
Label("//third_party:org_golang_x_tools-gazelle.patch", True)`),
error: "Label expr should have 1 argument, found 2",
},
{
expression: []byte(`# releaser:patch-cmd gazelle -repo_root . -go_prefix golang.org/x/tools -go_naming_convention import_alias
Label(True)`),
error: "Label expr does not contain a string literal",
},
}

for _, tt := range tests {
t.Run(fmt.Sprintf("%v", tt.expression), func(t *testing.T) {
patchExpr, err := bzl.Parse("repos.bzl", tt.expression)
if err != nil {
t.Fatalf(err.Error())
}

patchLabelStr, _, err := parsePatchesItem(patchExpr.Stmt[0])
if err != nil && err.Error() != tt.error {
Comment thread
JamyDev marked this conversation as resolved.
Outdated
if tt.error != "" {
t.Errorf("expected error %q, but got error %q instead", tt.error, err.Error())
} else {
t.Errorf("unexpected error while parsing expression: %s", err.Error())
}
}

if err == nil && patchLabelStr != tt.result {
if tt.error != "" {
t.Errorf("expected error %q, but got result %q instead", tt.error, patchLabelStr)
} else {
t.Errorf("expected result %q, but got result %q instead", tt.result, patchLabelStr)
}
}
})
}
}