Sources & Tree-v1 Structure
Sources & Tree-v1 Structure
Sources define where flwd discovers jobs. Each source uses the tree-v1 directory layout to organize jobs in a hierarchical structure.
What are Sources?
Sources are providers of jobs that flwd can discover and execute. They can be:
- Local filesystem directories
- Git repositories (local or remote)
- OCI images (add-ons)
Source Types
Filesystem Source
Points to a local directory containing jobs:
sources:
- name: "local-ops"
type: "fs"
path: "/opt/flwd/jobs"
mountPath: "ops"
watch: true # Auto-reload on changesFields:
name: Unique identifier for the sourcetype: Must be"fs"path: Absolute path to the jobs directorymountPath: Prefix for job IDs (e.g.,ops/backup)watch: Enable filesystem watching for auto-reload
Git Source
Clones and syncs jobs from a Git repository:
sources:
- name: "shared-tools"
type: "git"
url: "https://github.com/org/flwd-jobs.git"
ref: "main"
mountPath: "shared"
pull_policy: "on-run"
auto_sync: true
poll_interval: "5m"Fields:
name: Unique identifier for the sourcetype: Must be"git"url: Git repository URLref: Branch, tag, or commit SHAmountPath: Prefix for job IDspull_policy: When to pull updates (on-run,manual,disabled)auto_sync: Periodically sync to latest commit (for branches)poll_interval: How often to check for updates
OCI Source (Add-ons)
Loads jobs from OCI container images:
sources:
- name: "backup-addon"
type: "oci"
image: "ghcr.io/org/backup-tools:v1.0.0@sha256:..."
mountPath: "addons/backup"Fields:
name: Unique identifier for the sourcetype: Must be"oci"image: OCI image reference (must be digest-pinned)mountPath: Prefix for job IDs
See Add-on Manifests for details on OCI add-ons.
Tree-v1 Directory Layout
The tree-v1 layout organizes jobs in a hierarchical directory structure where each directory containing a config.yaml file defines a job.
Basic Structure
jobs/ # Source root
├── backup/ # Namespace
│ ├── daily/ # Job directory
│ │ ├── config.yaml # Job configuration (required)
│ │ └── run.sh # Job script
│ └── weekly/
│ ├── config.yaml
│ └── run.sh
└── deploy/
├── staging/
│ ├── config.yaml
│ └── deploy.sh
└── production/
├── config.yaml
└── deploy.shJob ID Resolution
Job IDs are derived from the directory path relative to the source root:
Source mountPath: "ops"
Directory path: backup/daily
Resulting job ID: ops/backup/dailyExamples:
| Source mountPath | Directory Path | Job ID |
|---|---|---|
ops | backup/daily | ops/backup/daily |
tools | deploy/staging | tools/deploy/staging |
shared | db/migrate | shared/db/migrate |
. | hello | hello |
Root Job
A job at the source root (.) is allowed:
jobs/
└── config.yaml # Root jobThis creates a job with ID equal to the mountPath (or empty string if mountPath is .).
Discovery Process
flwd discovers jobs using the following process:
- Mount sources: Each source is mounted at its
mountPathunder the tenant’s scripts root - Walk directories: Recursively walk the directory tree
- Identify jobs: Any directory containing
config.yamlis a job - Resolve IDs: Job ID =
mountPath+ relative directory path - Check collisions: Fail if multiple jobs resolve to the same ID
Discovery Example
Configuration:
sources:
- name: "local-ops"
type: "fs"
path: "/opt/flwd/jobs"
mountPath: "ops"
- name: "shared-tools"
type: "git"
url: "https://github.com/org/tools.git"
ref: "main"
mountPath: "shared"Directory Structure:
/opt/flwd/jobs/ # local-ops source
├── backup/
│ └── daily/
│ └── config.yaml
/tmp/flwd/git/tools/ # shared-tools source (cloned)
├── deploy/
│ └── app/
│ └── config.yamlDiscovered Jobs:
ops/backup/daily(from local-ops)shared/deploy/app(from shared-tools)
Job Collision Detection
If two or more jobs resolve to the same job ID, discovery fails with an error:
Error: Job ID collision detected
Job ID: ops/backup/daily
Sources:
- local-ops (mountPath: ops, path: backup/daily)
- remote-ops (mountPath: ops, path: backup/daily)Resolution:
- Change
mountPathfor one of the sources - Reorganize directory structure
- Remove duplicate job
Multi-Step Jobs
Jobs can include multiple script files for step-based execution:
jobs/
└── deploy/
├── config.yaml # composition: "steps"
└── scripts/
├── build.sh # Step 1
├── test.sh # Step 2
└── deploy.sh # Step 3config.yaml:
name: "Deploy Application"
composition: "steps"
steps:
- id: "build"
script: "./scripts/build.sh"
- id: "test"
script: "./scripts/test.sh"
needs: ["build"]
- id: "deploy"
script: "./scripts/deploy.sh"
needs: ["test"]Organizing Jobs
By Function
jobs/
├── backup/
│ ├── database/
│ ├── files/
│ └── logs/
├── deploy/
│ ├── frontend/
│ └── backend/
└── maintenance/
├── cleanup/
└── optimize/By Environment
jobs/
├── staging/
│ ├── deploy/
│ └── rollback/
└── production/
├── deploy/
└── rollback/By Team
jobs/
├── platform/
│ ├── infrastructure/
│ └── monitoring/
├── data/
│ ├── etl/
│ └── analytics/
└── security/
├── audit/
└── compliance/Source Management
Adding Sources
Add sources to flwd.yaml:
sources:
- name: "my-jobs"
type: "fs"
path: "/path/to/jobs"
mountPath: "custom"Reload configuration:
flwd sources reloadListing Sources
# List all sources
flwd sources list
# Show source details
flwd sources get my-jobsPulling Updates (Git Sources)
# Manual pull
flwd sources pull shared-tools
# Pull all sources
flwd sources pull --allWatching for Changes (Filesystem)
Enable watch: true for automatic reloading:
sources:
- name: "local-dev"
type: "fs"
path: "./jobs"
mountPath: "dev"
watch: true # Auto-reload on file changesPull Policies
Control when Git sources are updated:
sources:
- name: "shared-tools"
type: "git"
url: "https://github.com/org/tools.git"
ref: "main"
pull_policy: "on-run" # or "manual" or "disabled"Policies:
on-run: Pull before each job executionmanual: Only pull when explicitly requesteddisabled: Never pull (use initial clone only)
Auto-Sync (Git Sources)
Periodically sync to the latest commit:
sources:
- name: "shared-tools"
type: "git"
url: "https://github.com/org/tools.git"
ref: "main"
auto_sync: true
poll_interval: "5m" # Check every 5 minutesComplete Example
flwd.yaml:
instance:
name: "production"
data_dir: "/var/lib/flwd"
sources:
# Local development jobs
- name: "local-dev"
type: "fs"
path: "/opt/flwd/dev-jobs"
mountPath: "dev"
watch: true
# Shared team jobs from Git
- name: "platform-tools"
type: "git"
url: "https://github.com/org/platform-tools.git"
ref: "main"
mountPath: "platform"
pull_policy: "on-run"
auto_sync: true
poll_interval: "10m"
# Production-ready jobs from Git (pinned)
- name: "prod-ops"
type: "git"
url: "https://github.com/org/prod-ops.git"
ref: "v2.1.0" # Pinned tag
mountPath: "ops"
pull_policy: "manual"
# Backup tools add-on
- name: "backup-addon"
type: "oci"
image: "ghcr.io/org/backup-tools:v1.0.0@sha256:abc123..."
mountPath: "addons/backup"Directory Structure:
/opt/flwd/dev-jobs/ # local-dev
├── test/
│ └── hello/
│ ├── config.yaml
│ └── run.sh
/var/lib/flwd/git/platform-tools/ # platform-tools (cloned)
├── deploy/
│ └── app/
│ ├── config.yaml
│ └── deploy.sh
/var/lib/flwd/git/prod-ops/ # prod-ops (cloned)
├── backup/
│ └── database/
│ ├── config.yaml
│ └── backup.shDiscovered Jobs:
dev/test/helloplatform/deploy/appops/backup/databaseaddons/backup/backup(from OCI add-on)addons/backup/restore(from OCI add-on)
Validation
Validate source configuration:
# Validate sources in config
flwd config validate
# Test source discovery
flwd sources discover my-jobsNext Steps
- Job Configuration - Learn about config.yaml
- Add-on Manifests - Package jobs as OCI images
- Configuration - Configure sources in flwd.yaml