Prerequisites

What You'll Learn

This codelab isn't exhaustive however it should give you an idea of the sort of things the Please CLI is capable of:

For this codelab we will be using the Please codelabs repo:

$ git clone https://github.com/thought-machine/please-codelabs
Cloning into 'please-examples'...
remote: Enumerating objects: 228, done.
remote: Total 228 (delta 0), reused 0 (delta 0), pack-reused 228
Receiving objects: 100% (228/228), 38.23 KiB | 543.00 KiB/s, done.
Resolving deltas: 100% (79/79), done.

We'll be using the getting started with go codelab for these examples:

$ cd please-codelabs/getting_started_go

Please has a strict build graph representing each built target and their dependencies on each other. Among many things, this graph can be interrogated to determine the dependencies of a target:

$ plz query deps //src/greetings:greetings_test 
  //src/greetings:greetings_test
        //src/greetings:greetings
        //third_party/go:assert
              //third_party/go:_assert-assert#download

This can be especially useful when trying to improve build performance. Unnecessary dependencies between targets can cause certain rules to be rebuilt when they don't need to be.

Internal rules

Woah what's that //third_party/go:_assert-assert#download target we just saw? That's an internal rule that was generated by the go_get() rule //third_party/go:assert. Internal rules can be identified by their leading _ in their name. We can view more information about this one with plz query print:

$ plz query print //third_party/go:_assert-assert#download
  # //third_party/go:_assert-assert#download:
  remote_file(
      name = '_assert-assert#download',
      srcs = ['https://github.com/go-playground/assert/archive/v1.2.1.zip'],
      outs = ['assert-assert.zip'],
      building_description = 'Fetching...',
      timeout = 600,
      config = 'None',
      visibility = ['PUBLIC'],
  )

As we can see, go_get() has generated a remote file rule to download the github archive of the sources for that go module! You shouldn't depend on these rules directly as they may change between minor releases of Please.

Most of the plz query sub-commands have a --hidden flag that can be used to include hidden targets:

$ plz query alltargets --hidden 
//src:_main#lib
//src:_main#lib_srcs
//src:main
//src/greetings:_greetings#import_config
//src/greetings:_greetings#srcs
//src/greetings:_greetings_test#lib
//src/greetings:_greetings_test#lib_srcs
//src/greetings:_greetings_test#main
//src/greetings:_greetings_test#main_lib
//src/greetings:_greetings_test#main_lib_srcs
//src/greetings:greetings
//src/greetings:greetings_test
//third_party/go:_assert#a_rule
//third_party/go:_assert#get
//third_party/go:_assert#import_config
//third_party/go:_assert-assert#download
//third_party/go:assert

If you're changing a build rule that you know has a wide reaching effect, it might be good to run all the tests that will be affected by that change. Let's find the reverse dependencies of our internal download rule:

$ plz query revdeps //third_party/go:_assert-assert#download
  //third_party/go:assert

Well that doesn't look quite right... We should see //src/greetings:greetings_test too.

Turns out finding reverse dependencies is quite a slow operation. Please limits this to just one level so you don't accidentally lock up your terminal trying to walk the whole build graph. You can set the level with --level=2 or if you want to get all reverse dependencies, you can set it to -1:

$ plz query revdeps --level=-1 //third_party/go:_assert-assert#download
//src/greetings:greetings_test
//third_party/go:assert

Be careful, this can be slow on larger build graphs. You can use --include=//src/foo/... to limit the search to a slice of your repository. More on this later in this codelab!

So we've managed to determine that targets that might be effected by our change. How do we run these tests? Please can be instructed to listen for targets on standard input:

$ plz query revdeps --level=-1 //third_party/go:_assert-assert#download | plz test -
//src/greetings:greetings_test 1 test run in 0s; 1 passed [cached]
1 test target and 1 test run; 1 passed.
Total time: 110ms real, 0s compute.

The - at the end of plz test - indicates to Please that we will be supplying the targets to build over standard input.

Almost all Please commands can take in the --include and --exclude arguments. These can be used to specifically exclude targets:

$ plz query revdeps --exclude //src/greetings:greetings_test --level=-1 //third_party/go:_assert-assert#download | plz test -
0 test targets and 0 tests run; 0 passed.
Total time: 40ms real, 0s compute.

As you can see, we excluded the test from earlier so plz test didn't run it. We can also exclude this on the test command:

$ plz query revdeps --level=-1 //third_party/go:_assert-assert#download | plz test --exclude //src/greetings:greetings_test -
0 test targets and 0 tests run; 0 passed.
Total time: 40ms real, 0s compute.

Including based on label

Targets can be labeled in Please. Most of the built-in rules apply some basic labels, e.g. the go rules apply the go label to their targets. These can be very useful to run all tests for a given language:

$ plz build --include go --exclude //third_party/go/...

This will build all Go targets but will only build targets under //third_party/go/... if they're a dependency of a target that needs to be built.

You may also add custom labels to your targets. Update srcs/greetings/BUILD as such:

src/greetings/BUILD

go_library(
    name = "greetings",
    srcs = ["greetings.go"],
    visibility = ["//src/..."],
    labels = ["my_label"], # Add a label to the library rule
)

go_test(
    name = "greetings_test",
    srcs = ["greetings_test.go"],
    deps = [
        ":greetings",
        "//third_party/go:assert",
    ],
    external = True,
)
$ plz query alltargets --include=my_label
//src/greetings:greetings

$ plz build --include=my_label
Build finished; total time 300ms, incrementality 100.0%. Outputs:
//src/greetings:greetings:
  plz-out/gen/src/greetings/greetings.a

This can be especially useful for separating out slow running tests:

$ plz test --exclude e2e

Hopefully this has given you a taster for what is possible with plz query, however there's so much more. See the cli for an idea of what's possible!