diff --git a/README.md b/README.md index 0abadd4b..90ad2973 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ Where may be any commit revision - full commit hashes, short c Bazel binary (basename on $PATH, or absolute or relative path) to run (default "bazel") -ignore-file value Files to ignore for git operations, relative to the working-directory. These files shan't affect the Bazel graph. - -target-pattern string - Target pattern to diff. (default "//...") + -targets bazel query + Targets to consider. Accepts any valid bazel query expression (see https://bazel.build/reference/query). (default "//...") -verbose Whether to explain (messily) why each target is getting run -working-directory string @@ -39,8 +39,8 @@ Optional flags: Files to ignore for git operations, relative to the working-directory. These files shan't affect the Bazel graph. -manual-test-mode string How to handle affected tests tagged manual. Possible values: run|skip (default "skip") - -target-pattern string - Target pattern to consider. (default "//...") + -targets bazel query + Targets to consider. Accepts any valid bazel query expression (see https://bazel.build/reference/query). (default "//...") -working-directory string Working directory to query (default ".") ``` diff --git a/WORKSPACE b/WORKSPACE index 5dc97d23..b0d7cb49 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -2,9 +2,6 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "bazel_gazelle", - patch_args = ["-p1"], - # Pull in https://github.com/bazelbuild/bazel-gazelle/pull/1227 - patches = ["@//:third_party/patches/bazel_gazelle/1227-label-pattern-matching.patch"], sha256 = "73bac497740e1a9583354ca36332cd48fd60803b1d0ed927ea3fcb3488565182", strip_prefix = "bazel-gazelle-a98769c9a26e312ac40d1f5b14f574fdcd4aa21a", urls = [ diff --git a/cli/BUILD.bazel b/cli/BUILD.bazel index f09241a5..0cf95049 100644 --- a/cli/BUILD.bazel +++ b/cli/BUILD.bazel @@ -11,6 +11,5 @@ go_library( deps = [ "//common", "//pkg", - "@bazel_gazelle//label:go_default_library", ], ) diff --git a/cli/flags.go b/cli/flags.go index 70364f99..e3257259 100644 --- a/cli/flags.go +++ b/cli/flags.go @@ -9,7 +9,6 @@ import ( "github.com/bazel-contrib/target-determinator/common" "github.com/bazel-contrib/target-determinator/pkg" - gazelle_label "github.com/bazelbuild/bazel-gazelle/label" ) type IgnoreFileFlag []common.RelPath @@ -71,7 +70,7 @@ type CommonFlags struct { EnforceCleanRepo EnforceCleanFlag DeleteCachedWorktree bool IgnoredFiles *IgnoreFileFlag - TargetPatternFlag *string + TargetsFlag *string } func StrPtr() *string { @@ -86,7 +85,7 @@ func RegisterCommonFlags() *CommonFlags { EnforceCleanRepo: AllowIgnored, DeleteCachedWorktree: false, IgnoredFiles: &IgnoreFileFlag{}, - TargetPatternFlag: StrPtr(), + TargetsFlag: StrPtr(), } flag.StringVar(commonFlags.WorkingDirectory, "working-directory", ".", "Working directory to query.") flag.StringVar(commonFlags.BazelPath, "bazel", "bazel", @@ -98,14 +97,15 @@ func RegisterCommonFlags() *CommonFlags { "Delete created worktrees after use when created. Keeping them can make subsequent invocations faster.") flag.Var(commonFlags.IgnoredFiles, "ignore-file", "Files to ignore for git operations, relative to the working-directory. These files shan't affect the Bazel graph.") - flag.StringVar(commonFlags.TargetPatternFlag, "target-pattern", "//...", "Target pattern to diff.") + flag.StringVar(commonFlags.TargetsFlag, "targets", "//...", + "Targets to consider. Accepts any valid `bazel query` expression (see https://bazel.build/reference/query).") return &commonFlags } type CommonConfig struct { Context *pkg.Context RevisionBefore pkg.LabelledGitRev - TargetPattern gazelle_label.Pattern + Targets pkg.TargetsList } // ValidateCommonFlags ensures that the argument follow the right format @@ -158,9 +158,9 @@ func ResolveCommonConfig(commonFlags *CommonFlags, beforeRevStr string) (*Common return nil, fmt.Errorf("failed to resolve the \"before\" git revision: %w", err) } - targetPattern, err := gazelle_label.ParsePattern(*commonFlags.TargetPatternFlag) + targetsList, err := pkg.ParseTargetsList(*commonFlags.TargetsFlag) if err != nil { - return nil, fmt.Errorf("failed to parse target pattern: %w", err) + return nil, fmt.Errorf("failed to parse targets: %w", err) } // Additional checks @@ -182,6 +182,6 @@ func ResolveCommonConfig(commonFlags *CommonFlags, beforeRevStr string) (*Common return &CommonConfig{ Context: context, RevisionBefore: beforeRev, - TargetPattern: targetPattern, + Targets: targetsList, }, nil } diff --git a/driver/BUILD.bazel b/driver/BUILD.bazel index a0f4c5cb..321359ab 100644 --- a/driver/BUILD.bazel +++ b/driver/BUILD.bazel @@ -1,4 +1,4 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "go_library") load("//rules:multi_platform_go_binary.bzl", "multi_platform_go_binary") go_library( diff --git a/driver/driver.go b/driver/driver.go index 544f4ceb..2a0f4fb3 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -33,7 +33,7 @@ type driverFlags struct { type config struct { Context *pkg.Context RevisionBefore pkg.LabelledGitRev - TargetPattern gazelle_label.Pattern + Targets pkg.TargetsList // One of "run" or "skip". ManualTestMode string } @@ -77,7 +77,7 @@ func main() { if err := pkg.WalkAffectedTargets(config.Context, config.RevisionBefore, - config.TargetPattern, + config.Targets, false, callback); err != nil { log.Fatal(err) @@ -161,7 +161,7 @@ func resolveConfig(flags driverFlags) (*config, error) { return &config{ Context: commonArgs.Context, RevisionBefore: commonArgs.RevisionBefore, - TargetPattern: commonArgs.TargetPattern, + Targets: commonArgs.Targets, ManualTestMode: flags.manualTestMode, }, nil } diff --git a/pkg/BUILD.bazel b/pkg/BUILD.bazel index 317bf56f..2abaa82b 100644 --- a/pkg/BUILD.bazel +++ b/pkg/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "hash_cache.go", "target_determinator.go", + "targets_list.go", "walker.go", ], importpath = "github.com/bazel-contrib/target-determinator/pkg", diff --git a/pkg/target_determinator.go b/pkg/target_determinator.go index 28da23ac..2ff8352d 100644 --- a/pkg/target_determinator.go +++ b/pkg/target_determinator.go @@ -111,16 +111,16 @@ type Context struct { } // FullyProcess returns the before and after metadata maps, with fully filled caches. -func FullyProcess(context *Context, revBefore LabelledGitRev, revAfter LabelledGitRev, pattern label.Pattern) (*QueryResults, *QueryResults, error) { +func FullyProcess(context *Context, revBefore LabelledGitRev, revAfter LabelledGitRev, targets TargetsList) (*QueryResults, *QueryResults, error) { log.Printf("Processing %s", revBefore) - queryInfoBefore, err := fullyProcessRevision(context, revBefore, pattern) + queryInfoBefore, err := fullyProcessRevision(context, revBefore, targets) if err != nil { return nil, nil, err } // At this point, we assume that the working directory is back to its pristine state. log.Printf("Processing %s", revAfter) - queryInfoAfter, err := fullyProcessRevision(context, revAfter, pattern) + queryInfoAfter, err := fullyProcessRevision(context, revAfter, targets) if err != nil { return nil, nil, err } @@ -128,14 +128,14 @@ func FullyProcess(context *Context, revBefore LabelledGitRev, revAfter LabelledG return queryInfoBefore, queryInfoAfter, nil } -func fullyProcessRevision(context *Context, rev LabelledGitRev, pattern label.Pattern) (queryInfo *QueryResults, err error) { +func fullyProcessRevision(context *Context, rev LabelledGitRev, targets TargetsList) (queryInfo *QueryResults, err error) { defer func() { innerErr := gitCheckout(context.WorkspacePath, context.OriginalRevision) if innerErr != nil && err == nil { err = fmt.Errorf("failed to check out original commit during cleanup: %v", err) } }() - queryInfo, loadMetadataCleanup, err := LoadIncompleteMetadata(context, rev, pattern) + queryInfo, loadMetadataCleanup, err := LoadIncompleteMetadata(context, rev, targets) defer loadMetadataCleanup() if err != nil { return nil, fmt.Errorf("failed to load metadata at %s: %w", rev, err) @@ -149,14 +149,13 @@ func fullyProcessRevision(context *Context, rev LabelledGitRev, pattern label.Pa } // LoadIncompleteMetadata loads the metadata about, but not hashes of, targets into a QueryResults. -// The (transitive) dependencies of the passed pattern will be loaded. For all targets, pass the -// pattern `//...`. +// The (transitive) dependencies of the passed targets will be loaded. For all targets, use `//...`. // // It may change the git revision of the workspace to rev, in which case it is the caller's // responsibility to check out the original commit. // // It returns a non-nil callback to clean up the worktree if it was created. -func LoadIncompleteMetadata(context *Context, rev LabelledGitRev, pattern label.Pattern) (*QueryResults, func(), error) { +func LoadIncompleteMetadata(context *Context, rev LabelledGitRev, targets TargetsList) (*QueryResults, func(), error) { // Create a temporary context to allow the workspace path to point to a git worktree if necessary. context = &Context{ WorkspacePath: context.WorkspacePath, @@ -195,7 +194,7 @@ func LoadIncompleteMetadata(context *Context, rev LabelledGitRev, pattern label. return nil, cleanupFunc, err } - queryInfo, err := doQueryDeps(context, pattern) + queryInfo, err := doQueryDeps(context, targets) if err != nil { return nil, cleanupFunc, fmt.Errorf("failed to query at %s in %v: %w", rev, context.WorkspacePath, err) } @@ -557,13 +556,13 @@ func bazelInfo(bazelPath string, workspacePath string, key string) (string, erro return strings.TrimRight(stdoutBuf.String(), "\n"), nil } -func doQueryDeps(context *Context, pattern label.Pattern) (*QueryResults, error) { +func doQueryDeps(context *Context, targets TargetsList) (*QueryResults, error) { bazelRelease, err := BazelRelease(context.BazelPath, context.WorkspacePath) if err != nil { return nil, fmt.Errorf("failed to resolve the bazel release: %w", err) } - depsPattern := fmt.Sprintf("deps(%s)", pattern.String()) + depsPattern := fmt.Sprintf("deps(%s)", targets.String()) transitiveResult, err := runToCqueryResult(context, depsPattern) if err != nil { return nil, fmt.Errorf("failed to cquery %v: %w", depsPattern, err) @@ -574,7 +573,7 @@ func doQueryDeps(context *Context, pattern label.Pattern) (*QueryResults, error) return nil, fmt.Errorf("failed to parse cquery result: %w", err) } - matchingTargetResults, err := runToCqueryResult(context, pattern.String()) + matchingTargetResults, err := runToCqueryResult(context, targets.String()) if err != nil { return nil, fmt.Errorf("failed to run top-level cquery: %w", err) } diff --git a/pkg/targets_list.go b/pkg/targets_list.go new file mode 100644 index 00000000..4193af5e --- /dev/null +++ b/pkg/targets_list.go @@ -0,0 +1,14 @@ +package pkg + +type TargetsList struct { + targets string +} + +func ParseTargetsList(targets string) (TargetsList, error) { + // TODO: validate against syntax in https://bazel.build/reference/query + return TargetsList{targets: targets}, nil +} + +func (tl *TargetsList) String() string { + return tl.targets +} diff --git a/pkg/walker.go b/pkg/walker.go index ba153fbf..1cc7beae 100644 --- a/pkg/walker.go +++ b/pkg/walker.go @@ -15,7 +15,7 @@ type WalkCallback func(label.Label, []Difference, *analysis.ConfiguredTarget) // callback once for each target which has changed. // Explanation of the differences may be expensive in both time and memory to compute, so if // includeDifferences is set to false, the []Difference parameter to the callback will always be nil. -func WalkAffectedTargets(context *Context, revBefore LabelledGitRev, pattern label.Pattern, includeDifferences bool, callback WalkCallback) error { +func WalkAffectedTargets(context *Context, revBefore LabelledGitRev, targets TargetsList, includeDifferences bool, callback WalkCallback) error { // The revAfter revision represents the current state of the working directory, which may contain local changes. // It is distinct from context.OriginalRevision, which represents the original commit that we want to reset to before exiting. revAfter, err := NewLabelledGitRev(context.WorkspacePath, "", "after") @@ -23,7 +23,7 @@ func WalkAffectedTargets(context *Context, revBefore LabelledGitRev, pattern lab return fmt.Errorf("could not create \"after\" revision: %w", err) } - beforeMetadata, afterMetadata, err := FullyProcess(context, revBefore, revAfter, pattern) + beforeMetadata, afterMetadata, err := FullyProcess(context, revBefore, revAfter, targets) if err != nil { return fmt.Errorf("failed to process change: %w", err) } diff --git a/target-determinator/target-determinator.go b/target-determinator/target-determinator.go index 1eb3ec03..980c94d8 100644 --- a/target-determinator/target-determinator.go +++ b/target-determinator/target-determinator.go @@ -30,7 +30,7 @@ type targetDeterminatorFlags struct { type config struct { Context *pkg.Context RevisionBefore pkg.LabelledGitRev - TargetPattern gazelle_label.Pattern + Targets pkg.TargetsList Verbose bool } @@ -79,7 +79,7 @@ func main() { if err := pkg.WalkAffectedTargets(config.Context, config.RevisionBefore, - config.TargetPattern, + config.Targets, config.Verbose, callback); err != nil { // Print something on stdout that will make bazel fail when passed as a target. @@ -112,7 +112,7 @@ func resolveConfig(flags targetDeterminatorFlags) (*config, error) { return &config{ Context: commonArgs.Context, RevisionBefore: commonArgs.RevisionBefore, - TargetPattern: commonArgs.TargetPattern, + Targets: commonArgs.Targets, Verbose: flags.verbose, }, nil } diff --git a/tests/integration/java/com/github/bazel_contrib/target_determinator/integration/TargetDeterminatorSpecificFlagsTest.java b/tests/integration/java/com/github/bazel_contrib/target_determinator/integration/TargetDeterminatorSpecificFlagsTest.java index f3a50804..736b8728 100644 --- a/tests/integration/java/com/github/bazel_contrib/target_determinator/integration/TargetDeterminatorSpecificFlagsTest.java +++ b/tests/integration/java/com/github/bazel_contrib/target_determinator/integration/TargetDeterminatorSpecificFlagsTest.java @@ -138,16 +138,16 @@ public void testWorktreeCreation() throws Exception { } - private Set