Skip to main content

actions type


def actions.anon_target(
rule: "function",
attrs: dict[str, typing.Any]
) -> anon_target

An anonymous target is defined by the hash of its attributes, rather than its name. During analysis, rules can define and access the providers of anonymous targets before producing their own providers. Two distinct rules might ask for the same anonymous target, sharing the work it performs.

For more details see


def actions.anon_targets(
rules: list[("function", dict[str, typing.Any])] | tuple[("function", dict[str, typing.Any]), ...]
) -> anon_targets

Generate a series of anonymous targets.


def actions.artifact_tag() -> artifact_tag

Allocate a new input tag. Used with the dep_files argument to run.


def actions.assert_short_path(artifact: artifact, short_path: str) -> artifact

Generate a promise artifact that has short path accessible on it. The short path's correctness will be asserted during analysis time.

TODO - we would prefer the API to be ctx.actions.anon_target(xxx).artifact("foo", short_path=yyy), but we cannot support this until we can get access to the AnalysisContext without passing it into this method.


def actions.cas_artifact(
output: artifact | output_artifact | str,
digest: str,
use_case: str,
expires_after_timestamp: int,
is_executable: bool = False,
is_tree: bool = False,
is_directory: bool = False
) -> artifact

Downloads a CAS artifact to an output

  • digest: must look like SHA1:SIZE
  • use_case: your RE use case
  • expires_after_timestamp: must be a UNIX timestamp. Your digest's TTL must exceed this timestamp. Your build will break once the digest expires, so make sure the expiry is long enough (preferably, in years).
  • is_executable (optional): indicates the resulting file should be marked with executable permissions


def actions.copied_dir(
output: artifact | output_artifact | str,
srcs: dict[str, artifact],
) -> artifact

Returns an artifact which is a directory containing copied files. The srcs must be a dictionary of path (as string, relative to the result directory) to the bound artifact, which will be laid out in the directory.


def actions.copy_dir(
dest: artifact | output_artifact | str,
src: artifact,
) -> artifact

Make a copy of a directory.


def actions.copy_file(
dest: artifact | output_artifact | str,
src: artifact,
) -> artifact

Copies the source artifact to the destination (which can be a string representing a filename or an output artifact) and returns the output artifact. The copy works for files or directories.


def actions.declare_output(
prefix: str,
filename: str = _,
dir: bool = False
) -> artifact

Returns an unbound artifact, representing where a file will go, which must be bound before analysis terminates. The usual way of binding an artifact is with As an example:

my_output = ctx.actions.declare_output("output.o")["gcc", "-c", my_source, "-o", my_output.as_output()], category = "compile")

This snippet declares an output with the filename output.o (it will be located in the output directory for this target). Note the use of as_output to tag this artifact as being an output in the action. After binding the artifact you can subsequently use my_output as either an input for subsequent actions, or as the result in a provider.

Artifacts from a single target may not have the same name, so if you then want a second artifact also named output.o you need to supply a prefix, e.g. ctx.actions.declare_output("directory", "output.o"). The artifact will still report having name output.o, but will be located at directory/output.o.

The dir argument should be set to True if the binding will be a directory.


def actions.digest_config() -> digest_config

Obtain this daemon's digest configuration. This allows rules to discover what digests the daemon may be able to e.g. defer download because they conform to its RE backend's expected digest format.


def actions.download_file(
output: artifact | output_artifact | str,
url: str,
vpnless_url: None | str = None,
sha1: None | str = None,
sha256: None | str = None,
is_executable: bool = False,
is_deferrable: bool = False
) -> artifact

Downloads a URL to an output (filename as string or output artifact). The file at the URL must have the given sha1 or the command will fail. The optional parameter is_executable indicates whether the resulting file should be marked with executable permissions. (Meta-internal) The optional parameter vpnless_url indicates a url from which this resource can be downloaded off VPN; this has the same restrictions as url above.


def actions.dynamic_output(
dynamic: list[artifact] | tuple[artifact, ...],
inputs: list[artifact] | tuple[artifact, ...],
outputs: list[artifact | output_artifact] | tuple[artifact | output_artifact, ...],
) -> None

dynamic_output allows a rule to use information that was not available when the rule was first run at analysis time. Examples include things like Distributed ThinLTO (where the index file is created by another action) or OCaml builds (where the dependencies are created by ocamldeps).

The arguments are:

  • dynamic - a list of artifacts whose values will be available in the function. These will be built before the function is run.
  • inputs - a container of artifacts (cmd_args, list of artifacts, and so on).
    • These inputs must include all the inputs that are referenced by the body of the function argument, apart from those listed in dynamic and outputs: extra inputs may be passed that are not used.
    • The inputs are used for buck2 aquery functionality, but do not cause speculative building. In fact, these inputs may form a cycle with other dynamic_output actions if they were all required.
    • In the future, it may be possible to not pass all the inputs if the repo is set to permissive mode, allowing a more powerful form of dynamic dependencies.
  • outputs - a list of unbound artifacts (created with declare_artifact) which will be bound by the function.
  • The function argument is given 3 arguments:
    • ctx (context) - which is the same as that passed to the initial rule analysis.
    • artifacts - using one of the artifacts from dynamic (example usage: artifacts[artifact_from_dynamic]) gives an artifact value containing the methods read_string, read_lines, and read_json to obtain the values from the disk in various formats. Anything too complex should be piped through a Python script for transformation to JSON.
    • outputs - using one of the artifacts from the dynamic_output's outputs (example usage: outputs[artifact_from_dynamic_output_outputs]) gives an unbounded artifact. The function argument must use its outputs argument to bind output artifacts, rather than reusing artifacts from the outputs passed into dynamic_output directly.
  • The function must call ctx.actions (probably to bind all outputs. It can examine the values of the dynamic variables and depends on the inputs.

category: str,
identifier: None | str = None,
env: dict[str, typing.Any] = _,
local_only: bool = False,
prefer_local: bool = False,
prefer_remote: bool = False,
low_pass_filter: bool = True,
always_print_stderr: bool = False,
weight: int = _,
weight_percentage: int = _,
dep_files: dict[str, artifact_tag] = _,
metadata_env_var: str = _,
metadata_path: str = _,
no_outputs_cleanup: bool = False,
allow_cache_upload: bool = False,
allow_dep_file_cache_upload: bool = False,
force_full_hybrid_if_capable: bool = False,
exe: RunInfo | WorkerRunInfo = _,
unique_input_inodes: bool = False,
error_handler = _
) -> None

Runs a command

  • arguments: must be of type cmd_args, or a type convertible to such (such as a list of strings and artifacts) and must contain at least one .as_output() artifact
  • category: category and identifier - when used together, identify the action in Buck2's event stream, and must be unique for a given target
  • weight: used to note how heavy the command is and will typically be set to a higher value to indicate that less such commands should be run in parallel (if running locally)
  • no_outputs_cleanup: if this flag is set then Buck2 won't clean the outputs of a previous build that might be present on a disk; in which case, command from arguments should be responsible for the cleanup (that is useful, for example, when an action is supporting incremental mode and its outputs are based on result from a previous build)
  • metadata_env_var and meadata_path should be used together: both set or both unset
    • metadata_path: defines a path relative to the result directory for a file with action metadata, which will be created right before the command will be run.
    • Metadata contains the path relative to the Buck2 project root and hash digest for every action input (this excludes symlinks as they could be resolved by a user script if needed). The resolved path relative to the Buck2 project for the metadata file will be passed to command from arguments, via the environment variable, with its name set by metadata_env_var
    • Both metadata_env_var and metadata_path are useful when making actions behave in an incremental manner (for details, see Incremental Actions)
  • The prefer_local, prefer_remote and local_only options allow selecting where the action should run if the executor selected for this target is a hybrid executor.
    * All those options disable concurrent execution: the action will run on the preferred
    platform first (concurrent execution only happens with a "full" hybrid executor).
    * Execution may be retried on the "non-preferred" platform if it fails due to a
    transient error, except for `local_only`, which does not allow this.
    * If the executor selected is a remote-only executor and you use `local_only`, that's an
    error. The other options will not raise errors.
    * Setting more than one of those options is an error.
    * Those flags behave the same way as the equivalent `--prefer-remote`, `--prefer-local`
    and `--local-only` CLI flags. The CLI flags take precedence.
    * The `force_full_hybrid_if_capable` option overrides the `use_limited_hybrid` hybrid.
    The options listed above take precedence if set.

When actions execute, they'll do so from the root of the repository. As they execute, actions have exclusive access to their output directory.

Actions also get exclusive access to a "scratch" path that is exposed via the environment variable BUCK_SCRATCH_PATH. This path is expressed as a path relative to the working directory (i.e. relative to the project). This path is guaranteed to exist when the action executes.

When actions run locally, the scratch path is also used as the TMPDIR.

def actions.symlink_dir(
dest: artifact | output_artifact | str,
src: artifact,
) -> artifact

Create a symlink to a directory.

def actions.symlink_file(
dest: artifact | output_artifact | str,
src: artifact,
) -> artifact

Creates a symlink to the source artifact at the destination (which can be a string representing a filename or an output artifact) and returns the output artifact. The symlink works for files or directories.


def actions.symlinked_dir(
output: artifact | output_artifact | str,
srcs: dict[str, artifact],
) -> artifact

Returns an artifact that is a directory containing symlinks. The srcs must be a dictionary of path (as string, relative to the result directory) to bound artifact, which will be laid out in the directory.


def actions.tset(
definition: transitive_set_definition,
value = _,
children: typing.Iterable = _
) -> transitive_set

Creates a new transitive set. For details, see


def actions.write(
output: artifact | output_artifact | str,
is_executable: bool = False,
allow_args: bool = False,
with_inputs: bool = False,
absolute: bool = False
) -> artifact | (artifact, list[artifact])

Returns an artifact whose contents are content

  • is_executable (optional): indicates whether the resulting file should be marked with executable permissions
  • allow_args (optional): must be set to True if you want to write parameter arguments to the file (in particular, macros that write to file)
    • If it is true, the result will be a pair of the artifact containing content and a list of artifact values that were written by macros, which should be used in hidden fields or similar
  • absolute (optional): if set, this action will produce absolute paths in its output when rendering artifact paths. You generally shouldn't use this if you plan to use this action as the input for anything else, as this would effectively result in losing all shared caching.

The content is often a string, but can be any ArgLike value. This is occasionally useful for generating scripts to run as a part of another action. cmd_args in the content are newline separated unless another delimiter is explicitly specified.


def actions.write_json(
output: artifact | output_artifact | str,
with_inputs: bool = False,
pretty: bool = False
) -> artifact | write_json_cli_args

Returns an artifact whose contents are content written as a JSON value.

  • output: can be a string, or an existing artifact created with declare_output
  • content: must be composed of the basic json types (boolean, number, string, list/tuple, dictionary) plus artifacts and command lines
    • An artifact will be written as a string containing the path
    • A command line will be written as a list of strings, unless joined=True is set, in which case it will be a string
  • If you pass with_inputs = True, you'll get back a cmd_args that expands to the JSON file but carries all the underlying inputs as dependencies (so you don't have to use, for example, hidden for them to be added to an action that already receives the JSON file)
  • pretty (optional): write formatted JSON (defaults to False)