Skip to main content
Version: Next

Targets

A target identifies the result of a task. It is declared using the target keyword and can be part of a task description.

There are three types of targets:

  • file
  • directory
  • docker image

Targets live inside a repository and are usually in your .gitignore. It's good practice to gather targets in a build directory, but it's not rquired. Bob does not allow to define filesystem targets outside of the repository you're currently working on. Something like ../ is not allowed.

Targets are archived on your local machine at ~/.bobcache/artifacts which is referred to as the cache.

Each time you see a task finishing with the status cached,

โ— โ— โ— โ—
Ran 1 tasks in 0s
build cached

you can be sure your targets are up-to-date and no rebuild was necessary.

Bob decides if a target needs a rebuild by computing a hash of the tasks inputs and additionally considering the task description itself. The integrity of the target is also considered by looking at its checksum.

This enables bob to reuse targets when switching back and forth between branches. Additionally, with the upcoming remote caching options you can greatly speed up CI builds saving valuable time and computing power.

File Targets

Bellow we have a Bobfile where the build task is running the command go build -o hello. This command is compiling the code of main.go and creating an executable with the name hello which is made available to bob declaring it using the target keyword.

# app/bob.yaml
dependencies: [ go ]
build:
build:
input: main.go
cmd: go build -o hello
target: hello

If you specify a different name than the one of the file being created you will get a Target does not exist for task [build]. error.

If you want to run the above Bobfile you need to have main.go and the go.mod file in your working directory:

// app/bob.yaml
package main

import "fmt"

func main() {
fmt.Println("Hello World!")
}
// app/go.mod
module example/hello

go 1.19

After running bob build you will notice a hello executable in your directory:

$ ls
bob.yaml go.mod hello main.go

Try to run rm hello and bob build again and see that build is marked as cached:

$ rm hello
$ bob build
Building nix dependencies...
Succeeded building nix dependencies
Running task build with 0 dependencies

โ— โ— โ— โ—
Ran 1 tasks in 0s
build cached

After running those commands the hello binary is back in the working directory. It was fetched from the cache.

Directory Targets

Here's an example with a build command that creates a new directory called hello

build:
build:
cmd: mkdir hello && touch ./hello/some-file
target: hello

The same rules apply to directory targets as the one from file targets with one caveat: empty directories, as opposed to empty files, will not be cached in the artifact store.

This means that having a build task creating an empty directory the directory will not be recreated from the cache next time you run bob build:

build:
build:
cmd: mkdir hello
target: hello

Mixing File and Directory Targets

If you have a task which is creating both files and directories you can define the targets in a multiline format using |-:

build:
build:
cmd: touch hello && mkdir hello-dir && touch ./hello-dir/some-file
target: |-
hello
hello-dir/

Docker Image Targets

If you have Docker running and a Dockerfile in your current working directory you can build a Docker image and specify it as a target as well:

dependencies: [ docker ]
build:
build:
cmd: docker build -t my-image:latest .
target:
image: my-image:latest

To have a target image you need to specify the full name:tag format.

Shallow Target Validation

For local performance optimization the size of the target is used for validation. We call this "shallow target validation". Bob assures that shallow targets never reach an artifact store.