fluentcidocs
Website GitHub

Build pipelines

Host and transfer primitives

Compose host facts, digests, SSH, file transfers, and S3 operations in native task graphs.

Compose operations as tasks

Primitive constructors describe work. They do not connect to servers, install tools, or read files until their native plan executes. Combine these tasks with ordinary commands, dependencies, timeouts, environment bindings, and resources. Use a matching engine and SDK; these bindings are included in the bundled SDK sources and may precede the next published SDK release.

Operation Result or behavior
OS Rust host OS identifier, such as macos, linux, freebsd, netbsd, or openbsd
Architecture Rust host architecture identifier, such as aarch64 or x86_64
Digest Streaming SHA-256 or SHA-512 of UTF-8 text or a file
SSH Run an argument vector on a remote host through its POSIX shell
SCP / SFTP Upload or download files
rsync Synchronize a source and destination over SSH
FTP / FTPS Get, put, list, or delete; FTPS requires TLS
S3 Get, put, list, or delete through AWS CLI, including compatible endpoints

OS, architecture, and digest tasks write a newline-terminated value to stdout and expose the trimmed result as the named output value. Use the SDK's output environment binding to pass it to a dependent command. File paths resolve from the task's working directory. OS and architecture describe the executor host; they are not cross-compilation target selectors.

SDK entry points

All eight SDKs expose the same operation kinds. Use their native enums or unions for algorithms, actions, and transfer directions.

SDK Module Digest constructor
ClojureScript fluentci.remote digest-text / digest-file
PureScript FluentCI.Host.Remote digestText / digestFile
TypeScript src/remote.ts digestText / digestFile
Python fluentci.remote digest_text / digest_file
Gleam fluentci/host/remote digest_text / digest_file
Elixir FluentCI.Remote digest_text / digest_file
ReScript Remote digestText / digestFile
Rust fluentci_pdk::remote or native fluentci_executor::remote Operation::Digest

For example, describe a digest in each SDK:

(require '[fluentci.remote :as remote])
(remote/digest-text "checksum" :sha256 "hello" ".")
import FluentCI.Host.Remote as Remote

checksum = Remote.digestText "checksum" Remote.Sha256 "hello" "."
import { digestText } from "./.sdk/typescript/src/remote.ts";

const checksum = digestText("checksum", "sha256", "hello");
from fluentci.remote import digest_text

checksum = digest_text("checksum", "sha256", "hello")
import fluentci/host/remote

pub fn checksum() {
  remote.digest_text("checksum", remote.Sha256, "hello", ".")
}
checksum = FluentCI.Remote.digest_text("checksum", :sha256, "hello")
let checksum = Remote.digestText("checksum", Remote.Sha256, "hello", ".")
use fluentci_pdk::remote::{self, Algorithm, Input, Operation};

let checksum = remote::task(
    "checksum",
    Operation::Digest {
        algorithm: Algorithm::Sha256,
        input: Input::Text("hello".into()),
    },
    ".",
);

Add the resulting task to a native plan. Rust's PDK serializes typed requests at the Wasm host boundary; the native executor can compile and execute its Rust plan directly.

SSH and transfers

SSH connections specify host, optional user and identity, a port (default 22), and install (default true). SSH uses batch authentication and normal host key verification. Provision a key or agent and trusted host keys before the task runs. Password prompts are disabled.

import { ssh, scp } from "./.sdk/typescript/src/remote.ts";
import { after } from "./.sdk/typescript/src/matrix.ts";

const connection = {
  host: "deploy.example.com",
  user: "deploy",
  port: 22,
  install: false,
};
const upload = scp(
  "upload",
  connection,
  "upload",
  "dist/app.tar.gz",
  "/srv/app.tar.gz",
);
const inspect = after(
  [upload],
  ssh("inspect", connection, ["ls", "-lh", "/srv/app.tar.gz"]),
);

Commands are argument vectors. The executor quotes each SSH argument for the remote POSIX shell. Remote execution still requires the named program on the server. Local provisioning installs client tools only.

FTP and FTPS accept username_env and password_env: names of variables in the task environment. Credentials are supplied through a private temporary curl configuration and removed after execution. Do not embed credentials in URLs. S3 uses the AWS CLI credential chain from the task environment, with optional endpoint and region fields for services such as R2 or MinIO.

Tool provisioning

Digest and host detection need no external tools. Network primitives use OpenSSH, curl, rsync, or AWS CLI. rsync must support --protect-args (rsync 3+); older bundled clients are skipped so a suitable client can be provisioned. The executor first searches PATH and standard system/package-manager locations. When missing and install is true, it uses an available host package manager:

Platform Package managers
macOS Homebrew or MacPorts
Linux apt-get, dnf, yum, apk, pacman, or zypper
FreeBSD pkg
NetBSD pkgin
OpenBSD pkg_add

Installation needs package repository access and appropriate permissions. Non-root hosts use noninteractive sudo; unavailable managers or permissions produce an error. Set install: false for preprovisioned or locked CI images. Package availability depends on the OS repository. These POSIX backends do not imply that every BSD release has been tested.

Cache and lifecycle

Remote operations are side effects and cannot use the local action cache. Host facts and digests may be cached with an explicit cache policy. For a file digest, declare a safe relative path covered by the cache inputs. This lets changes to the source invalidate the action. Use dependencies and exclusive resources to order writes to a shared destination.

Native operations participate in task cancellation and timeouts. Cancelling a transfer stops its client process group; it does not roll back remote changes already accepted by the server. See caching and services for related lifecycle contracts.

Made with ♥ in Antananarivo, Madagascar.
Search documentation