Effects

Effects provide a means to perform actions that affect real-world resources in a controlled manner.

This document serves as reference documentation. See also the Effects Introduction and the deployment guides in hercules-ci-effects.

Running effects

Effects run as part of a job, after all its builds have completed successfully and after preceding jobs for the same repository have completed effect execution.

Sandbox type

Currently, effects run in Linux containers only. Note that you can deploy to a macOS machine via SSH from a Linux agent using e.g. hercules-ci-effects runNixDarwin.

Paths

This container contains at least the Nix store and /dev, /proc, /sys, each filled as appropriate for a container.

The store and a nix-daemon socket are accessible.

It may further provide /etc/resolv.conf and other files that are required for network access.

An empty directory is created, to serve as the working directory and TMP.

The /bin/sh and /usr/bin/env executables are not provided by the sandbox and should be installed by the effect instead. Effects defined directly or indirectly through hercules-ci-effects mkEffect provide this by default.

Execution

The process started inside the container is the builder, similar to how the Nix sandbox starts the derivation, but in the effects sandbox, the process appears as uid 0 ("root"), allowing it to modify the root filesystem as necessary. This is possible via uid remapping. The process does not gain any real privileges from being uid 0 in the effects sandbox.

Environment

These are the notable environment variables set by the sandbox itself.

IN_HERCULES_CI_EFFECT

Value: true

HERCULES_CI_API_BASE_URL

The apiBaseUrl configuration value.

HERCULES_CI_SECRETS_JSON

A file path pointing to a file with secrets data.

See Secrets.

HERCULES_CI_PROJECT_ID

The id UUID of the project that created the job that contains the effect.

HERCULES_CI_PROJECT_PATH

A slash separated string containing in order: the site name (typically github), the owner (user or organization) and the repository name.

Example: github/hercules-ci/hercules-ci-agent

Secrets

The contents of $HERCULES_CI_SECRETS_JSON are computed by looking up the secretsMap values in the agent’s secrets.json, and filtering using the condition field. Its contents arise from roughly the following pseudocode:

agentSecrets = fromJSON (readFile secrets.json);
HERCULES_CI_SECRETS_JSON = writeSecureFile
  (
    (filterAttrs (k: secret: conditionHolds secret.condition)
      (mapAttrs (k: agentSecretName: agentSecrets.${agentSecretName})
        drv.secretsMap
      )
    ) // {
      hercules-ci = {
        data.token = ;
      };
    }
  );

API token

The hercules-ci secret is provided, containing a token string attribute in its data. This token can be used with the Hercules CI API and has appropriate permissions for the effect’s execution.

This is picked up automatically by the hci command and hercules-ci-effects bash functions like getStateFile.

Network

Network access is provided via the container runtime used.

The current implementation is based on runc and bind mounts /etc/resolv.conf. If your host setup demands a different approach, please open an issue describing your needs or contact mailto:[email protected] if you are hesitant to share any network information.