Giter Club home page Giter Club logo

target-determinator's Introduction

Target Determinator

Target determinator is a binary (and Go API) used to determine which Bazel targets changed between two git commits.

target-determinator binary

For simple listing, the target-determinator binary is supplied:

Usage of target-determinator:
target-determinator <before-revision>
Where <before-revision> may be any commit revision - full commit hashes, short commit hashes, tags, branches, etc.
  -bazel string
    	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.
  -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
    	Working directory to query (default ".")

This binary lists targets to stdout, one-per-line, which were affected between and the currently checked-out revision.

driver binary

driver is a binary which implements a simple CI pipeline; it runs the same logic as target-determinator, then tests all identified targets.

Usage of driver:
  driver <before-revision>
Where <before-revision> may be any commit-like strings - full commit hashes, short commit hashes, tags, branches, etc.
Optional flags:
  -bazel string
    	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.
  -manual-test-mode string
    	How to handle affected tests tagged manual. Possible values: run|skip (default "skip")
  -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 ".")

WalkAffectedTargets API

Both of the above binaries are thin wrappers around a Go function called WalkAffectedTargets which calls a user-supplied callback for each affected target between two commits:

// WalkAffectedTargets computes which targets have changed between two commits, and calls
// 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, commitishBefore, commitishAfter LabelledGitRev, pattern label.Pattern, includeDifferences bool, callback WalkCallback) error { ... }

type WalkCallback func(label.Label, []Difference, *analysis.ConfiguredTarget)

This can be used to flexibly build your own logic handling the affected targets to drive whatever analysis you want.

How to get Target Determinator

Pre-built binary releases are published as GitHub Releases for most changes.

We recommend you download the latest release for your platform, and run it where needed (e.g. in your CI pipeline).

We avoid breaking changes where possible, but offer no formal compatibility guarantees release-to-release.

We do not recommend integrating Target Determinator into your Bazel build graph unless you have a compelling reason to do so.

Contributing

Contributions are very welcome!

We have an extensive integration testing suite in the tests/integration directory which has its own README. The test suite also runs against several other target determinator implementations which are pulled in as http_archives, to test compatibility. Please make sure any contributions are covered by a test.

When adding new dependencies to the Go code, please run scripts/update-dependencies.

In general, BUILD files in this repo are maintained by gazelle; to regenerate tem, please run bazel run //:gazelle.

Alongside each go_proto_library, there is a runnable copy_proto_output rule which can be used to generate the Go source for a protobuf, in case it's useful to inspect.

Supported Bazel versions

Target Determinator currently supports Bazel 4.0.0 up to and including the latest LTS release.

We are happy to support newer Bazel versions (as long as this doesn't break support for the current LTS), but only exhaustively test against the latest LTS release.

We have a small number of smoke tests which verify basic functionality on the oldest supported release, but do not regularly test against it.

target-determinator's People

Contributors

alokpr avatar duarten avatar illicitonion avatar jonmeow avatar kushalp avatar mark-thm avatar michaelboyd2 avatar mkosiba avatar purkhusid avatar shs96c avatar sitaktif avatar stevebarrau avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

target-determinator's Issues

In Bazel 7 diffs involving 3rd party deps seem to be ignored

I'm running Bazel 7 and rules_python 0.27.1 (via bzlmod, using rules_python's pip management).

Given a basic py_library that depends on a requirement, updating the underlying requirement's version no longer seems to cause target-determinator to indicate my target has changed.

bazel-opts are not passed to bazel-config command

According to bazel-config documentation:

Usage: bazel config [<config_id> | <config_id> <config_id>]

Displays the given configuration objects, if they can be found in the Skyframe cache. The best way
to use this command is to first run a build (or cquery), and then immediately run the config
command to view the configuration. Note that any flags passed to build (or cquery) must also be
passed to config, or else the Skyframe cache will be evicted and no configurations will be found.

Not sure if --dump_all overrides this. But may be a good idea to pass bazel-opts to the config command anyways.

--enforce-clean accepts a tri-state value but only has boolean behaviour

As far as I can tell, there is no code which differentiates between AllowIgnored and AllowDirty... @sitaktif do you remember any history here? AFAICT there has never been any code which differentiates between these, or any tests which set --enforce-clean=allow-dirty (or indeed which set --enforce-clean=allow-ignored)?

#86 is going to simplify this behaviour to be more boolean (but doesn't remove the three variants) - I think this is ok (and that we should just remove the extra unused variant), but figured I should file an issue to discuss...

Add --keep_going flag

While trying to use the target-determinator in our repo, I am seeing an error that is not letting me use the tool.

Can we please add support for --keep_going flag to the bazel query command, so we don't have to fix all the errors before this tool can actually be used?

target-determinator does not evaluate aliases as changed

In my project I have a setup akin to:

py_library(
  name = "foo"
  ...
)

alias(name = "bar", actual = ":foo")

When I've made changes that invalidate foo and running:

target-determinator -targets //foo HEAD~1

I observe, correctly that //foo has been identified as a changed target.

However, for the same changeset that invalidates foo and running:

target-determinator -targets //bar HEAD~1

//bar is not listed as changed.

Possible circular configurations?

I'm currently debugging an issue I'm having with target-determinator and it's seems like there is a cycle in the graphq that target determinator is processing. This sounds like it could be a possible bug in Bazel or target-determinator.

I'm working on a small repro but it's hard to figure out what is causing this. It seems like it's either caused by the heavy use of transitions in the rules I'm using or heavy use of aliases but I haven't been able to pin it down. The issue that this cycle is causing is that target-determinator freezes because there becomes a race condition for the lock in the hash cache for the label that has the cycle.

Just wanted to check if there are any known issue with cycles while I try to narrow this down.

TestDigestsSingleSourceFile fails in clean codespace

Steps to reproduce on d9d5911:

  1. Create a new codespace.
  2. Run npm install -g @bazel/bazelisk
  3. Run bazel test //...

Note that TestDigestsSingleSourceFile fails:

$ bazel test //...
INFO: Analyzed 36 targets (0 packages loaded, 0 targets configured).
INFO: Found 28 targets and 8 test targets...
FAIL: //pkg:pkg_test (see /home/codespace/.cache/bazel/_bazel_codespace/982569728e62b3340e5f2051314017bd/execroot/__main__/bazel-out/k8-fastbuild/testlogs/pkg/pkg_test/test.log)
INFO: From Testing //pkg:pkg_test:
==================== Test output for //pkg:pkg_test:
--- FAIL: TestDigestsSingleSourceFile (0.00s)
    hash_cache_test.go:117: Wrong hash: want 33e4ab761182518bbdaabdb916ecea5ad264778881dbe4ce93567f07ea89784b got 00da44523270e18ac5d8529b6f477cadd88dbd6326d6ea9fb7eeb7fc02faac97
FAIL
================================================================================
INFO: Elapsed time: 0.569s, Critical Path: 0.07s
INFO: 2 processes: 1 internal, 1 linux-sandbox.
INFO: Build completed, 1 test FAILED, 2 total actions

query for attr does not work

I have the following query

driver -targets 'attr(tags, "gov", "//...")' 3db60bbdd57d39ea1b8acd6d7d650f7100842c5b

but it reported the following error.

image

however the bazel query 'attr(tags, "gov", //...)') works.

[driver] bazel-opts are not passed to test command

bazel-opts are passed to the cquery command but not to the test command.

$ driver --bazel-opts="--config=asan" main

2023/02/13 13:17:21 Running cquery on deps(//...)
/usr/bin/bazel --output_base redacted cquery --config=asan --output=proto deps(//...)
2023/02/13 13:17:23 Running cquery on //...
/usr/bin/bazel --output_base redacted --config=asan --output=proto //...
2023/02/13 13:17:23 Matching labels to configurations
/usr/bin/bazel --output_base redacted config --output=json --dump_all
2023/02/13 13:17:24 Hashing targets
2023/02/13 13:17:28 Processing revision 'after' (current working directory state)
2023/02/13 13:17:28 Running cquery on deps(//...)
/usr/bin/bazel --output_base redacted cquery --config=asan --output=proto deps(//...)
2023/02/13 13:17:29 Running cquery on //...
/usr/bin/bazel --output_base redacted cquery --config=asan --output=proto //...
2023/02/13 13:17:30 Matching labels to configurations
/usr/bin/bazel --output_base redacted config --output=json --dump_all
2023/02/13 13:17:30 Hashing targets
2023/02/13 13:17:34 Discovered 1 affected targets
2023/02/13 13:17:34 Running test on 1 targets
/usr/bin/bazel test --target_pattern_file /tmp/3689943729

Note that --config=asan is not passed to the test command

Provide an option to override bazel command

The driver runs 'build' or 'test' depending on the target type. The 'test' command however does not make sense for some build configs like clang-tidy which only performs static analysis.

The driver should provide a 'command' option which can be set to either 'build' or 'auto' (current behavior)

When using with bzlmod rules_python encounter error with Bazel 6.4.0

After upgrading to Bazel 6.4.0 I encountered the following error while running target-determinator:

label parse error: repository has invalid characters: "@@rules_python~0.26.0~python~python_3_10_x86_64-unknown-linux-gnu//:python_runtimes"

Either Gazelle or target-determinator is going to need to strip one of the @s.

I filed bazelbuild/bazel-gazelle#1650 on Gazelle and proposed a fix in bazelbuild/bazel-gazelle#1651. If the fix is accepted, we can just upgrade the Gazelle dependency. If not, we can work around the issue in https://github.com/bazel-contrib/target-determinator/blob/c1521bb5deb6d8028c4ae6f3f5d57c5e5122abff/pkg/target_determinator.go#L922C1-L922C1.

Invalid options syntax error

Trying to run the command, but I get this:

/target-determinator.linux.amd64 -verbose -targets //src/... d2181321315c9864e1ec5c533c4b5f3f1d2008b2 
2023/08/24 00:27:38 Processing revision 'before' (sha: d2181321315c9864e1ec5c533c4b5f3f1d2008b2)
2023/08/24 00:27:38 Current working tree has 1 non-ignored untracked files:
2023/08/24 00:27:38  ?? src/openapi/
2023/08/24 00:27:38 Workspace is unclean, using git worktree. This will be slower the first time. You can avoid this by committing local changes and ignoring untracked files.
2023/08/24 00:27:38 Reusing git worktree in /home/joakim/.cache/target-determinator/td-worktree-crossplane-aab12449c40715569ff5e44d2da20f6d6c4c6d53
2023/08/24 00:27:39 Running cquery on deps(//src/...)
2023/08/24 00:27:56 Running cquery on //src/...
2023/08/24 00:27:58 Finding compatible targets under //src/...
Target Determinator invocation Error
2023/08/24 00:27:59 failed to process change: failed to load metadata at revision 'before' (sha: d2181321315c9864e1ec5c533c4b5f3f1d2008b2): failed to query at revision 'before' (sha: d2181321315c9864e1ec5c533c4b5f3f1d2008b2) in /home/joakim/.cache/target-determinator/td-worktree-crossplane-aab12449c40715569ff5e44d2da20f6d6c4c6d53: failed to find compatible targets: failed to run compatibility-filtering cquery on //src/...: exit status 2. Stderr:
INFO: Options provided by the client:
  Inherited 'common' options: --isatty=0 --terminal_columns=80
INFO: Reading rc options for 'cquery' from /home/joakim/.cache/target-determinator/td-worktree-crossplane-aab12449c40715569ff5e44d2da20f6d6c4c6d53/.bazelrc:
  Inherited 'build' options: --incompatible_enable_cc_toolchain_resolution --action_env BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
ERROR: - :: Invalid options syntax: -

I don't know if it's related to .bazelrc, which contains this:

build --incompatible_enable_cc_toolchain_resolution
build --action_env BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1

Enhancement: make it possible to print debug logs of what's being hashed

I recently had a user report that their build was stuck in the "Hashing targets" phase. The issue didn't reproduce for me locally and it was tricky to debug why that's the case.
For cases like this it would be useful to have a flag or environment variable that would print which file is being hashed.

CLI support base commit hash file as an input

We are considering trying out target-determinator in Diff CI, but we have some performance constraints.

Can we add CLI that supports taking in an already computed hash file from master to avoid git checkout base commit and perform a cquery on the base commit for comparison? This is a feature in https://github.com/Tinder/bazel-diff#get-impacted-targets-command

With this feature, we can compute hash file in master CI and reuse the result in diff CI and save us seconds to minutes.

TargetHashCache has already been frozen

version: target-determinator v0.26.0

When running target-determinator on a repo, I am seeing the error TargetHashCache has already been frozen

~/Downloads/target-determinator.darwin.arm64 -verbose main
2024/04/05 12:16:02 Processing revision 'before' (main, sha: a679f0f50ccc115fc3f50474af98cef947d3958e)
2024/04/05 12:16:02 Finding compatible targets under //...
2024/04/05 12:16:02 Running cquery on deps(//...)
2024/04/05 12:16:03 Running cquery on //...
2024/04/05 12:16:03 Finding compatible targets under //...
2024/04/05 12:16:03 Matching labels to configurations
2024/04/05 12:16:03 Hashing targets
2024/04/05 12:16:04 Processing revision 'after' (current working directory state)
2024/04/05 12:16:04 Finding compatible targets under //...
2024/04/05 12:16:04 Running cquery on deps(//...)
2024/04/05 12:16:05 Running cquery on //...
2024/04/05 12:16:05 Finding compatible targets under //...
2024/04/05 12:16:05 Matching labels to configurations
2024/04/05 12:16:05 Hashing targets
Target Determinator invocation Error
2024/04/05 12:16:06 TargetHashCache has already been frozen

There isn't much more information I can provide based on this limited output but happy to give anything requested if needed

Support -enforce-clean=enforce-clean for when the "before" location is unclean

The -enforce-clean=enforce-clean option only seems to fail when the "after" location is unclean (when it is checked in cli/flags.go). In particular, it is not used in EnsureGitRepositoryClean in pkg/target_determinator.go. I think it probably should be? Perhaps another option could be added to -enforce-clean to activate this behaviour?

It would be great to understand from someone more familiar with target_determinator whether this is a good idea - I could potentially submit a PR if the direction were clear.

The surfaced for us when target_determinator identified all targets as changed when the "before" location was unclean (due to a .gitignore change).

targets incompatible with the current platform are selected

$ cat .bazelrc
build --cxxopt -std=c++17
build:asan --compilation_mode dbg
build:asan --copt -fsanitize=address
build:asan --linkopt -fsanitize=address
$ cat BUILD.bazel
cc_test(
    name = "foo_test",
    srcs = ["foo_test.cc"],
    target_compatible_with = select({
        "//:asan_config": ["@platforms//:incompatible"],
        "//conditions:default": [],
    }),
)

config_setting(
    name = "asan_config",
    values = {
        "copt": "-fsanitize=address",
    },
)
$ target-determinator --bazel-opts="--config=asan" main
//:foo_test

Should driver rebuild non-test targets?

The driver tool works great for running tests that were affected by changes. However, targets that are not dependencies of any test target, will be skipped. If we were to gate using this driver, we would not catch compile errors on non-test targets.

Should the driver be extended to also build non-test targets? Non-test targets are correctly identified by target_determinator but appear skipped by the driver. For our CI, I'm thinking of using target_determinator to get all the targets, then writing our own driver that does both build / test (not just test).

The commandVerb does start out as build , but it seems like a single test target will turn the command to test? I wonder if it would be better to split the targets by build / test targets. Or in my case, I might try to run all the targets as build then all the targets as test.

Thoughts?

With Bazel 6 and bzlmod configured rules_python, target determinator complains of invalid characters

When running with Bazel 6 and bzlmod configured rules_python, target-determinator complains of invalid characters in the repository name. rules_python when configured with bzlmod in Bazel 6 generates repository names of the form @rules_python~\d+\.\d+\.\d+\~pip~[user-defined-str].

An example of the error with minor redactions:

failed to process change: failed to load metadata at revision 'before' (sha: <sha>): failed to query at revision 'before' (sha: <sha>) in /runner/_work/repo/repo: failed to parse cquery result: label parse error: repository has invalid characters: "@rules_python~0.21.0~pip~pip//:boto3_pkg"

It looks like this error comes from using Gazelle's label.Parse, which depends on this regex.

I suspect it's unrelated, but I should also mention that I'm running a custom target selection query to pick up py_tests tagged external:

"attr('tags', '\bexternal\b', kind(py_test, //...))"

Bazel errors with --transitions=lite

Looks like when we enable --transitions=lite, we get a bunch of Bazel errors spewed out which I suspect is related to bazelbuild/bazel#15797

For example:

ERROR: /home/jrodgers/tmp/build_output/fbda6e2d89ae38953fedf0d9ffd7a05c/external/io_bazel_rules_go/go/private/rules/transition.bzl:255:36: transition inputs [@@io_bazel_rules_go//go/config:debug, @@io_bazel_rules_go//go/config:linkmode, @@io_bazel_rules_go//go/config:msan, @@io_bazel_rules_go//go/config:pure, @@io_bazel_rules_go//go/config:race, @@io_bazel_rules_go//go/config:static, @@io_bazel_rules_go//go/config:strip, @@io_bazel_rules_go//go/config:tags, @@io_bazel_rules_go//go/private/rules:original_linkmode, @@io_bazel_rules_go//go/private/rules:original_msan, @@io_bazel_rules_go//go/private/rules:original_pure, @@io_bazel_rules_go//go/private/rules:original_race, @@io_bazel_rules_go//go/private/rules:original_static, @@io_bazel_rules_go//go/private/rules:original_tags, @@io_bazel_rules_go//go/private:bootstrap_nogo, @@io_bazel_rules_go//go/private:request_nogo] do not correspond to valid settings
ERROR: /home/jrodgers/tmp/build_output/fbda6e2d89ae38953fedf0d9ffd7a05c/external/io_bazel_rules_go/go/private/rules/transition.bzl:181:27: transition inputs [@@io_bazel_rules_go//go/config:linkmode, @@io_bazel_rules_go//go/config:msan, @@io_bazel_rules_go//go/config:pure, @@io_bazel_rules_go//go/config:race, @@io_bazel_rules_go//go/config:static, @@io_bazel_rules_go//go/config:tags] do not correspond to valid settings
ERROR: /home/jrodgers/tmp/build_output/fbda6e2d89ae38953fedf0d9ffd7a05c/external/io_bazel_rules_go/go/private/rules/transition.bzl:181:27: transition inputs [@@io_bazel_rules_go//go/config:linkmode, @@io_bazel_rules_go//go/config:msan, @@io_bazel_rules_go//go/config:pure, @@io_bazel_rules_go//go/config:race, @@io_bazel_rules_go//go/config:static, @@io_bazel_rules_go//go/config:tags] do not correspond to valid settings
ERROR: /home/jrodgers/tmp/build_output/fbda6e2d89ae38953fedf0d9ffd7a05c/external/io_bazel_rules_go/go/private/rules/transition.bzl:181:27: transition inputs [@@io_bazel_rules_go//go/config:linkmode, @@io_bazel_rules_go//go/config:msan, @@io_bazel_rules_go//go/config:pure, @@io_bazel_rules_go//go/config:race, @@io_bazel_rules_go//go/config:static, @@io_bazel_rules_go//go/config:tags] do not correspond to valid settings

Any ideas on how we can get these to go away? bazelbuild/bazel#15797 mentions explicitly defining all the flags, but that didn't seem to help ๐Ÿค”

deadlock in hashTarget -> build.Target_RULE -> hashRule

Haven't narrowed it down exactly yet but seems there is a deadlock somewhere in the following flow:

PrefillCache calls queryInfo.TargetHashCache.Hash which holds onto entry.hashLock.Lock() while it calls hashTarget.

hashTarget, in the case of build.Target_RULE, calls hashRule, which eventually calls thc.Hash again which blocks on entry.hashLock.Lock() indefinitely.

Trying to narrow down exactly what is going on but figured I'd surface this in case someone else can figure it out faster ๐Ÿ˜›

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.