@ticatec/omniflow
v2.0.0
Published
Unified CI/CD pipeline manager with centralized scheduling - manage all projects from one config file while keeping deployment scripts in their repositories
Downloads
332
Readme
Omniflow
A modern CI/CD pipeline manager for small teams: one configuration repository orchestrates everything, production-ready Recipes build and package, zero intrusion into project repositories!
┌─ config repository ────────────┐ ┌─ project repository ──────────┐
│ omniflow.yaml │ │ clean project source repo │
│ projects, environments, │ → │ (zero .omniflow intrusion) │
│ branches & variables │ │ │
│ built-in BaseCommand recipes │ │ src/ … │
│ plugins/*.ts shared commands │ │ │
└────────────────────────────────┘ └───────────────────────────────┘You manage environments, branches, and packaging centrally in your config repository, while project repositories remain clean and focused on application code.
Why
- Zero intrusion into project repositories. Built-in recipes cover standard workflows (TypeScript, Spring Boot, SPA apps, NPM & JAR libraries, container images) with a single line of configuration.
- Nothing fails silently. A failing step fails the run instead of quietly carrying on, and every command exits non-zero when it fails.
- You can see the decision before it happens.
omniflow planresolves every variable, branch, recipe, and artifact target and prints them without touching external infrastructure. - Every run is recorded. Plan, full log and per-step result land in
~/.omniflow/runs/<runId>/, so "what happened last night" is answerable after the CI console has scrolled away. - Extensible with escape hatches. Easily share custom commands via
plugins/or write inline project scripts when special customization is genuinely needed. --jsonon every command, so anything can drive it.
Install
npm install -g @ticatec/omniflow
omniflow --versionRequires Node.js 20.6 or newer.
Run it in five minutes
1. Point omniflow at a configuration file
omniflow init --config ~/projects/omniflow-config/omniflow.yamlOmniflow reads that file directly. Keep it in a git repository if you want history — git pull is how it stays current; there is nothing to sync.
2. Write omniflow.yaml using built-in recipes
omniflow:
env:
REGISTRY: registry.example.com
NAMESPACE: ticatec
projects:
- name: my-app
repos:
git: https://git.example.com/team/my-app.git
modules:
- name: backend
commands:
- name: build
run: image.build # built-in recipe: build the container image
environments:
- name: test
branch: main-testZero repository intrusion: No
.omniflow/pipeline.tsis needed inmy-app! It just contains your standard code andpackage.json.
3. Look at the plan before running anything
omniflow plan my-app -e test backend:build4. Run it
omniflow run my-app -e test backend:build
omniflow logs latest # if you want to read the output againFull walkthrough, including CI integration: Getting started.
Built-in Recipes (BaseCommand)
Omniflow's built-in recipes are BaseCommand classes, named in omniflow.yaml with run::
| Recipe | Description | Key Capabilities |
|---|---|---|
| package | Build and package an artifact | Detects the toolchain (Node, Maven, Gradle), packages one artifact (format: maven \| npm \| generic, packaging: tar.gz \| zip \| jar \| war) and uploads it; package.build / package.upload do either half |
| image.build | Container image builder | Assembles a build context with a Dockerfile from a template (e.g. node-dockerfile) and builds the image |
| image.publish | Container image publisher | Pushes the image to the configured registry |
Deployment is not built in — it is the kind of convention a plugin is for. Plugins live in the config repo and have the shell (ctx.actions.shell) at their disposal.
Commands
# Setup
omniflow init [--config <omniflow.yaml>] # point omniflow at a config file
# Plan and run
omniflow plan <project> -e <env> <cmd...> # resolve and print, execute nothing
omniflow run <project> -e <env> <cmd...> # run it
# History
omniflow runs # recorded runs, newest first
omniflow runs latest # one run in detail
omniflow logs latest # a run's recorded output
# Explore
omniflow list projects | environments | modules | commands [project] [module]
omniflow show <project> [environment]
# Maintenance
omniflow clean [project] -e <env> [--all]Useful flags on run:
| Flag | Effect |
|---|---|
| -d, --dry-run | The same as omniflow plan: prints the plan, runs nothing (no simulated lifecycle) |
| -v, --verbose | Resolved script paths, arguments, pre-flight details |
| -y, --yes | Skip the confirmation an environment asks for |
| --ref <sha> | Check out this exact commit (or tag) instead of the environment branch head; the checkout is detached. A ref that does not exist fails the run |
| --no-wait | Fail instead of waiting when another run holds the workspace |
| --wait <seconds> | How long to wait for a busy workspace (default 1800) |
| --json | Exactly one single-line JSON document on stdout, all human output on stderr |
Commands are module:command. A bare command searches every module, so a single-module
project can just say omniflow run my-app -e test build. plan takes --ref too.
Modular Architecture & Ecosystem
Omniflow core features are distributed across clean, decoupled SPI packages under the @ticatec namespace:
@ticatec/omniflow-core: Core execution context (AsyncLocalStorage), shell execution with masking, Docker primitives, and pluggable toolchain SPI (Node, Maven, Gradle).@ticatec/omniflow-command: AbstractBaseCommandlifecycle class and injectableCommandRegistry.@ticatec/omniflow-artifact: AbstractBasePublisherSPI, registry, Docker OCI, NPM, Maven, and Generic package upload coordinators.- Platform Drivers:
@ticatec/omniflow-github: GitHub artifact providers: container registry (ghcr.io), npm, maven, and releases.@ticatec/omniflow-gitlab: GitLab artifact providers: container registry, npm, maven, and generic packages.@ticatec/omniflow-forgejo: Forgejo & Gitea artifact providers: container registry, npm, maven, and generic packages.@ticatec/omniflow-aliyun: Alibaba Cloud ACR (Personal & Enterprise) and Apsara DevOps Package Registry.@ticatec/omniflow-nexus: Sonatype Nexus 3 Docker, Maven, NPM, and Raw package publishers.
Machine-readable output
--json puts exactly one single-line JSON document on stdout and sends all human output to stderr:
omniflow --json run my-app -e test backend:build | jq '.status, .steps[].fullName'
omniflow --json plan my-app -e test backend:build > plan.json
omniflow --json runs -n 10 | jq '.runs[] | select(.status == "failed")'Exit codes:
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Execution failure — a step failed, the fetch failed |
| 2 | Configuration, planning or pre-flight failure — unknown project / environment / command, invalid --ref, plan blockers, pre-flight validation. Nothing ran |
| 130 | Interrupted (Ctrl+C); the workspace lock is released |
| 143 | Terminated (SIGTERM) |
So omniflow run … && next-step behaves in CI.
Run records
Every run is written to $OMNIFLOW_HOME/runs/<runId>/:
20260909-142233-my-app-test-a1b2/
├── plan.json # the resolved plan — what was going to happen (no credentials; secret-looking vars masked)
├── log.txt # everything printed, including child-process output
└── result.json # outcome: status, ref, per-step results, errorresult.json fields: runId, planVersion, status (success | failed), project,
environment, startedAt, finishedAt, durationMs, ref? ({sha, branch};
no branch for a --ref run), steps[], artifacts?, error?,
failure? (preflight → exit 2, execution → exit 1), recordDir, logs (path to log.txt).
Documentation
| Guide | What it covers |
|---|---|
| Getting started | Install → configure → first run → CI integration |
| Configuration | Complete omniflow.yaml reference |
| Pipeline Commands | Command execution hierarchy, BaseCommand, and ctx API |
| Plugins | Shared commands, recipes, plugin format |
| Architecture | Modular SPI design, layers, execution lifecycle |
| Testing | Test suite organization and verification |
| LLM guide | Conventions for generating pipeline scripts with an AI assistant |
| Changelog | Releases and breaking changes |
Ready-to-copy plugins live in examples/plugins/, and a fully
annotated configuration in examples/config.yaml.
License
MIT © Henry Feng
