Files
ansiblings/packages/nopy/docs/API.md
T
Benjamin Diedrichsen fcc181700e
Release / release (push) Successful in 1m0s
test release nopy-alpha5
2026-07-27 17:07:18 +02:00

12 KiB

Nopy API Reference

This document describes the public API for the nopy package.


Table of Contents


Main Module

nopy(options?)

Main entry point for nopy deployments.

import { nopy } from '@bitsquare/nopy';

const result = await nopy({
  useDefaults: false,
  dryRun: true,
});

Parameters:

Name Type Default Description
useDefaults boolean false Skip variable prompts, use defaults
useAuthKey boolean false Force SSH key authentication
saveSession string - Path to save session file
loadSession string - Path to load session for replay
dryRun boolean false Show execution plan without running
parallel boolean false Execute independent cubes in parallel
continueOnError boolean false Continue after failures
jsonOutput boolean false Output results as JSON

Returns: Promise<NopyResult | undefined>

interface NopyResult {
  success: boolean;
  results: ExecutionResult[];
  summary: {
    total: number;
    successful: number;
    failed: number;
    totalDuration: number;
  };
}

Cubes Module

The cubes module provides types and functions for working with deployment units.

Types

Cube<Schema>

A fully loaded cube with filesystem location.

interface Cube<Schema extends z.AnyZodObject = z.AnyZodObject> {
  key: string;           // Unique identifier
  name: string;          // Human-readable name
  dir: string;           // Absolute path to cube directory
  dependencies: string[];
  schema: Schema;
  defaults: () => z.infer<Schema>;
  before: Hook<Schema>[];
  after: Hook<Schema>[];
}

Manifest<Schema>

Cube manifest (used in *.manifest.mjs files).

interface Manifest<Schema extends z.AnyZodObject = z.AnyZodObject> {
  name: string;
  key: string;
  dependencies: string[];
  schema: Schema;
  defaults: () => z.infer<Schema>;
  before: Hook<Schema>[];
  after: Hook<Schema>[];
}

Hook<Schema>

Hook function for before/after cube execution. See Cube Hooks for more details.

type Hook<Schema extends z.AnyZodObject> = (
  ctx: HookContext,
  params: z.infer<Schema>
) => void | Promise<void>;

interface HookContext {
  /**
   * Schedules another cube for execution.
   * @param key - The unique identifier or path of the cube.
   * @param params - Variables to pass to the cube.
   */
  exec: (key: string, params: CubeVariables) => Promise<void> | void;
}

Functions

loadCubes()

Loads all cubes from discovered cube directories.

const { cubes, errors } = await loadCubes();

Returns: Promise<LoadResult>

interface LoadResult {
  cubes: Record<string, Cube>;
  errors: string[];
}

resolveDependencies(cubes, selectedCubeNames)

Resolves all transitive dependencies for selected cubes.

const order = resolveDependencies(cubes, ['apt-all']);
// Returns: ['apt:essentials', 'apt-more', 'apt-all']

Parameters:

Name Type Description
cubes Record<string, Cube> Map of all available cubes
selectedCubeNames string[] Cubes to resolve

Returns: string[] - Cube names in execution order

Throws: Error if cube not found or circular dependency detected

buildExecutionStages(cubes, selectedCubeNames)

Groups cubes into stages for parallel execution.

const stages = buildExecutionStages(cubes, ['apt-all', 'docker']);
// Returns: [['apt:essentials'], ['apt-more', 'docker'], ['apt-all']]

Returns: string[][] - Array of stages

createManifest(options)

Factory function for creating cube manifests.

export default createManifest({
  name: 'My Cube',
  dependencies: () => [['apt:essentials']],
  schema: z.object({
    VERSION: z.string().default('1.0'),
  }),
});

uniqid(length?)

Generates a random alphanumeric string.

const id = uniqid();     // 'Kx7Pm'
const long = uniqid(10); // 'Kx7PmQr2Yw'

Executor Module

Handles pyinfra command execution.

Types

DeployCall

A deployment command ready for execution.

interface DeployCall {
  cube: string;
  host: string;
  cwd: string;
  command: string[];
  env: Record<string, unknown>;
  dependencies: string[];
}

ExecutionResult

Result of executing a deployment command.

interface ExecutionResult {
  cube: string;
  host: string;
  success: boolean;
  duration: number;
  stdout?: string;
  stderr?: string;
  error?: Error;
}

ExecutionOptions

Options for deployment execution.

interface ExecutionOptions {
  parallel?: boolean;
  concurrency?: number;
  continueOnError?: boolean;
  dryRun?: boolean;
  onProgress?: (result: ExecutionResult, completed: number, total: number) => void;
  onStart?: (cube: string, host: string) => void;
}

Functions

executeDeployCalls(calls, options?)

Executes an array of deployment calls.

const results = await executeDeployCalls(calls, {
  parallel: true,
  concurrency: 4,
  onProgress: (result, completed, total) => {
    console.log(`${completed}/${total}`);
  },
});

outputExecutionPlan(calls, asJson?)

Outputs the execution plan without running.

outputExecutionPlan(deployCalls);       // Text output
outputExecutionPlan(deployCalls, true); // JSON output

summarizeResults(results)

Generates a summary of execution results.

const summary = summarizeResults(results);
// {
//   total: 5,
//   successful: 4,
//   failed: 1,
//   totalDuration: 12345,
//   failures: [{ cube: 'docker', ... }]
// }

Builder Module

Constructs deployment commands.

buildDeployCalls(cubeNames, hosts, context)

Builds deployment calls for all cubes and hosts.

const result = await buildDeployCalls(
  ['apt:essentials', 'apt-more'],
  ['@docker/test'],
  {
    cubes,
    session,
    config,
    authMethod: 'ssh-key',
    useDefaults: true,
    isSessionReplay: false,
  }
);

Returns: Promise<BuildResult>

interface BuildResult {
  deployCalls: DeployCall[];
  cubeSessions: CubeSession[];
  sessionEnv: Record<string, unknown>;
}

Workflow Module

Manages interactive and replay workflows.

runWorkflow(sessionPath, cubes, config, options?)

Runs the appropriate workflow based on options.

const result = await runWorkflow(
  undefined,  // null for interactive, path for replay
  cubes,
  config,
  { useDefaults: false }
);

Returns: Promise<WorkflowResult>

interface WorkflowResult {
  session: NopySession;
  cubesWithDependencies: string[];
  authMethod: string;
  username?: string;
  password?: string;
  isReplay: boolean;
}

runInteractiveWorkflow(cubes, config, options?)

Runs the interactive cube selection workflow.

runReplayWorkflow(sessionPath, cubes, config)

Runs a replay from a saved session file.


Session Module

Manages session save/load operations.

Types

NopySession

Complete session configuration.

interface NopySession {
  name?: string;
  cubes: CubeSession[];
  hosts?: string[];
  auth: AuthSession;
  env?: SessionVariables;
}

CubeSession

Configuration for a single cube.

interface CubeSession {
  key: string;
  variables: SessionVariables;
}

AuthSession

Authentication configuration.

interface AuthSession {
  method: 'ssh-key' | 'password' | 'ssh';
  username?: string;
}

Functions

saveSession(session, filePath)

Saves a session to a JSON file.

saveSession(session, './my-deployment.nopysession.json');

loadSession(filePath)

Loads a session from a JSON or MJS file.

const session = await loadSession('./deployment.json');
const session = await loadSession('./deployment.mjs');

createSession(params)

Creates a session object from runtime data.

const session = createSession({
  cubes: [{ key: 'apt:essentials', variables: {} }],
  hosts: ['localhost'],
  auth: { method: 'ssh-key' },
});

listSessions(dirPath?)

Lists all session files in a directory.

const sessions = listSessions('./sessions');
// ['./sessions/deploy.session.json', './sessions/test.session.mjs']

Config Module

Manages nopy configuration.

Types

NopyConfig

Configuration file structure.

interface NopyConfig {
  hosts: string[];
  cubeDirs: string[];
  env: EnvConfig;
  log?: LogConfig;
}

LogConfig

Logging configuration.

interface LogConfig {
  verbosity?: 'silent' | 'info' | 'verbose' | 'trace';
  debug?: boolean;
}

Functions

loadConfig()

Loads configuration from .nopyrc.json.

const config = loadConfig();

Search order:

  1. ./nopyrc.json (local)
  2. ~/.nopyrc.json (home)

saveConfig(data, local?)

Saves configuration to a file.

saveConfig({ hosts: ['server.local'] });       // Local
saveConfig({ hosts: ['server.local'] }, false); // Home

logConfigToFlags(logConfig?)

Converts log config to pyinfra flags.

logConfigToFlags({ verbosity: 'verbose', debug: true });
// ['-vv', '--debug']

Prompts Module

Interactive prompts for user input.

CubeSelection(cubes)

Prompts user to select cubes to execute.

const { selectedCubes } = await CubeSelection(cubes);

HostSelection(hosts)

Prompts user to select a target host.

const host = await HostSelection(['server1', 'server2']);

AuthSelection(useAuthKey?)

Prompts user to select authentication method.

const { authMethod, username, password } = await AuthSelection();

VariableAssignment(cube, env)

Prompts user to customize cube variables.

const vars = await VariableAssignment(cube, { existing: 'value' });

PasswordSelection(username)

Prompts for password input.

const password = await PasswordSelection('admin');

CLI Usage

# Interactive deployment
nopy install

# With defaults (no prompts)
nopy install -D

# SSH key auth
nopy install -K

# Save session
nopy install -s ./my-session.json

# Replay session
nopy install -l ./my-session.json

# Dry run
nopy install -n

# Parallel execution
nopy install -p

# JSON output
nopy install -j

# Continue on error
nopy install -c

Creating a Cube

File Structure

cubes/
└── my-cube/
    ├── my-cube.manifest.mjs
    └── my-cube.deploy.py

Manifest Example

// my-cube.manifest.mjs
import { createManifest } from '@bitsquare/nopy';
import { z } from 'zod';

export default createManifest({
  name: 'My Cube',
  dependencies: () => [['apt:essentials']],
  schema: z.object({
    VERSION: z.string().default('1.0').describe('Version to install'),
    ENABLE_FEATURE: z.boolean().default(false),
  }),
  before: [
    (ctx, params) => {
      console.log('Before my-cube');
    },
  ],
  after: [
    (ctx, params) => {
      console.log('After my-cube');
    },
  ],
});

Deploy Script Example

# my-cube.deploy.py
from pyinfra import host
from pyinfra.operations import apt, server

VERSION = host.data.get('VERSION', '1.0')
ENABLE_FEATURE = host.data.get('ENABLE_FEATURE', False)

apt.packages(
    name='Install my-package',
    packages=[f'my-package={VERSION}'],
    update=True,
)

if ENABLE_FEATURE:
    server.shell(
        name='Enable feature',
        commands=['my-package --enable-feature'],
    )