Evaluation

Project configuration for Hercules CI is written in the Nix language. Your agent will evaluate the herculesCI attribute of a flake, or, if a repository does not contain flake.nix, the agent will look for that attribute in nix/ci.nix, ci.nix or default.nix.

Inside this expression, Hercules CI looks for an optional but recommended herculesCI attribute. If this attribute is not present, the evaluator will either:

  • if it is a flake, evaluate a default onPush job with sensible defaults, or

  • if it is a ci.nix or default.nix, fall back to the pre-0.9 evaluation behavior.

A simple example of an herculesCI attribute looks as follows:

  herculesCI = { ... }: {
    onPush.default = {
      outputs = { ... }: {
        # Attributes here will be built for each push.
        hello = pkgs.hello;
      };
    };
  };

herculesCI Value

The herculesCI attribute can be a function producing an attribute set. If no parameters are needed, the attribute set can be provided directly instead.

herculesCI Parameters

When you define the herculesCI attribute as a function, it will receive the following arguments, providing context for your CI/CD configuration attributes

ref, branch, tag, rev, shortRev

These strings represent the version and origin of the source that contains the herculesCI attribute.

branch and tag may be null.

primaryRepo

Information about the repository and revision of the sources that led to the herculesCI attribute.

primaryRepo.outPath

A path containing the files of the checked out revision.

herculesCI

Information about the Hercules CI instance the agent is connected to. This is mostly for Hercules CI Enterprise users; who self-manage the entire stack.

herculesCI.apiBaseUrl

The base URL of the Hercules CI API. This can be used to differentiate behavior on Hercules CI Enterprise. On non-enterprise agents, the value is https://hercules-ci.com. This matches the configuration file.

herculesCI Attributes

The herculesCI value primarily defines handlers for what to build and run for various events, such as onPush.

onPush

This declares what to do when a Git ref is updated, such as when you push a commit or after you merge a pull request.

If onPush is omitted and your herculesCI attribute is in a flake, Hercules CI will use the flake to generate a default job.

If onPush is set to { }, no jobs will be created for the push event.

If onPush contains attributes, jobs will created for each.

The name will be used as part of the commit status for each resulting job.

onPush.<name>.extraInputs.<inputName> (beta)

Specifies a location to an unpinned dependency. The name chosen for the <inputName> placeholder will be used as an attribute argument for onPush.<name>.outputs Parameters.

onPush.<name>.extraInputs.<inputName>.project (beta)

The name of a repository in the same organization.

onPush.<name>.extraInputs.<inputName>.ref (beta)

A Git ref indicating the branch or tag to check out. Example: refs/heads/staging for a branch called staging.

onPush.<name>.outputs Parameters

The arguments to the outputs are sourced from onPush.<name>.extraInputs.<inputName> (beta), by resolving the inputs to pinned revisions before creating the job.

You can find the pinned revisions in the dashboard or by clicking a commit status.

Other information besides extraInputs can be retrieved from the herculesCI parameters.

onPush.<name>.outputs Attributes

These "output" attributes can be

  • derivations,

  • effects IF added in onPush.<name>.outputs.effects,

  • attribute sets containing further "outputs", in a nested manner,

  • other types, which will be ignored.

During the execution of the job, first, all derivations will be built. If the build went well, all effects will run, concurrently with effects in the same job, but only after preceding jobs have either completed or failed to build.

onPush.<name>.outputs.effects Attributes

This is this the only location in outputs where effects are allowed.

Derivations, shells and effects

All three are defined through derivations.

  • A derivation marked by the attribute isEffect = true is categorized as an effect and will be run in the effects sandbox. Effects must be defined below the outputs.effects attribute.

  • A derivation marked by the buildDependenciesOnly = true attribute will not be built, but its dependencies will.

  • A derivation with phases = ["noBuildPhase"] is treated as if it had buildDependenciesOnly = true. This includes Nixpkgs' mkShell.

  • A derivation with ignoreFailure = true will be built, but not included in the job status and commit status. This is only useful when a build is unpredictable and irrelevant to the development process. requireFailure may be a better option, to avoid regressions after repairs.

  • A derivation with requireFailure = true will be built and included in the job status and commit status, but with its build status reversed. This is useful during development to track for example which tests are known to fail. If during development a problem is solved, you are required to remove the attribute, which is necessary to avoid regressions.

Attribute sets

Unlike the legacy format and nix-build, nested attribute sets are traversed by default.

You can mark attribute sets not to be traversed by adding an attribute recurseForDerivations = false inside them, as is done by the function lib.dontRecurseIntoAttrs of type attrs → attrs.

Default onPush job

When the herculesCI.onPush attribute is omitted, Hercules CI will supply a default definition.

This will build the flake attributes:

  • packages

  • checks

  • devShell

  • devShells

  • apps

  • nixosConfigurations

  • darwinConfigurations

  • effects

If effects is a function, it will receive the same arguments as the herculesCI attribute.

Ignored attributes

The following attributes are silently ignored, because they do not have a well-defined or independently testable structure.

  • overlays

  • submodules

  • nixosModules

  • darwinModules

  • legacyPackages

Unknown attributes are also ignored and produce a trace line in the evaluation log.

Default systems

The herculesCI attribute, if it exists, is read for its ciSystems attribute; an optional list of "system" strings. If specified, it restricts the job to just the listed architecture-platform combinations.