Documentation
¶
Overview ¶
Package config defines flow's configuration schema, its defaults, and the precedence rules that merge them: flags beat environment, environment beats the file, the file beats built-in defaults. flow works with no config at all.
Index ¶
- Constants
- func DefaultPath(override string) string
- func ExpandPath(p string) string
- func Marshal(c Config) (string, error)
- func SetCluster(path, context string, cc ClusterConfig) error
- func SetRepoHelmRepo(path, repoKey, helmRepo, chartName string) error
- func WriteFileAtomic(path string, data []byte, perm os.FileMode) error
- type Assets
- type ClusterConfig
- type Config
- type Defaults
- type Editor
- type GitHub
- type Jira
- type Loaded
- type Naming
- type RepoConfig
- type Workspace
Constants ¶
const EnvPrefix = "FLOW_"
EnvPrefix is the prefix for environment overrides; "__" separates nesting levels, so FLOW_ASSETS__ROOT sets assets.root.
const Template = `# ~/.config/flow/config.yaml
#
# Every key below is optional: flow runs with no config file at all. Values
# shown are the built-in defaults. Precedence, highest first:
# command-line flags > FLOW_ environment variables > this file > defaults
# Environment variables use "__" for nesting, e.g. FLOW_ASSETS__ROOT.
defaults:
base_branch: main # branch to create new ticket branches from
remote: origin
fetch_before_branch: true # fetch the remote before branching
open_editor: true
create_workspace: true
create_assets: true
naming:
# {id} is the normalized ticket ID (RD-19471), {slug} the normalized
# description. Note the underscore in assets_dir and the hyphen elsewhere:
# that difference is deliberate and load-bearing.
branch: "{id}-{slug}" # also used for the worktree directory name
assets_dir: "{id}_{slug}"
workspace_label: "{id}"
worktrees_subdir: ".worktrees"
assets:
root: "~/Developer/assets"
editor:
command: "cursor"
args: ["{path}"] # {path} is substituted with the worktree path
detach: true # spawn detached; flow must not block on it
workspace:
provider: "herdr" # only "herdr" and "none" are supported in v1
command: "herdr"
jira:
browse_url: "https://scaleopscom.atlassian.net/browse/{id}"
github:
api_base: "https://api.github.com"
# Token resolution order: $GITHUB_TOKEN, $GH_TOKEN, github.token below,
# then the macOS keychain service named here.
token_keychain_service: "flow-github-token"
# Per-repository overrides. Keys are "owner/name" or an absolute repo path.
repos: {}
# scaleops-sh/scaleops:
# base_branch: main
# helm_repo: scaleops # local ` + "`helm repo`" + ` name for this project's charts
# chart_name: scaleops # chart within that repo
# build_workflow: go.yaml # workflow file that produces the chart
# chart_version_pattern: "alpha" # "alpha" for feature branches, "rc-main" for main
# # Jobs that must finish before the chart is installable. Matched by name
# # prefix; a "skipped" job counts as satisfied.
# wait_for_jobs:
# - "Pre Release Helm"
# - "Pre Release Images"
# Per-kube-context cluster settings, learned on first use and written back here.
# A context absent from this map is one flow will refuse to upgrade.
clusters: {}
# ido-saban-dev: # the kube context name
# release_name: scaleops
# namespace: scaleops-system
# values_file: "~/Developer/helm-values/ido-saban-dev.yaml"
# helm_repo: scaleops
# chart: scaleops/scaleops
# extra_args: ["--reset-then-reuse-values"]
# repo: scaleops-sh/scaleops # which source repo this cluster tracks
`
Template is the fully-commented default config file written by `flow config init`. It documents every key, and every value in it matches Default(), so writing it changes nothing about flow's behaviour.
Variables ¶
This section is empty.
Functions ¶
func DefaultPath ¶
DefaultPath returns the config path, honoring --config and FLOW_CONFIG.
func ExpandPath ¶
ExpandPath expands a leading ~ and returns an absolute path where possible. Every path-valued config field passes through here.
func SetCluster ¶
func SetCluster(path, context string, cc ClusterConfig) error
SetCluster writes a clusters.{context} block into the config file, creating the file if necessary. The edit is surgical — it walks the YAML node tree and replaces (or appends) one mapping entry — so the comments that `flow config init` wrote survive. The write itself is atomic: temp file, fsync, rename.
func SetRepoHelmRepo ¶
SetRepoHelmRepo records the helm repo learned for a source repository.
func WriteFileAtomic ¶
WriteFileAtomic writes data to path via a temp file in the same directory, fsyncs it, and renames it into place, so a crash mid-write cannot truncate the existing file.
The parent directory is deliberately not fsynced after the rename. That would be needed to guarantee the rename itself survives a power loss; for a CLI writing its own config and registry, the atomic-replace guarantee is what matters and the extra syscall on every write is not worth it.
Types ¶
type Assets ¶
type Assets struct {
Root string `koanf:"root" yaml:"root"`
}
Assets locates the per-ticket asset folders.
type ClusterConfig ¶
type ClusterConfig struct {
ReleaseName string `koanf:"release_name" yaml:"release_name"`
Namespace string `koanf:"namespace" yaml:"namespace"`
ValuesFile string `koanf:"values_file" yaml:"values_file,omitempty"`
HelmRepo string `koanf:"helm_repo" yaml:"helm_repo,omitempty"`
Chart string `koanf:"chart" yaml:"chart,omitempty"`
ExtraArgs []string `koanf:"extra_args" yaml:"extra_args,omitempty"`
Repo string `koanf:"repo" yaml:"repo,omitempty"`
}
ClusterConfig holds per-kube-context settings. An unknown context is never acted on silently: interactively flow asks for these and records them, and non-interactively it refuses rather than guessing.
type Config ¶
type Config struct {
Defaults Defaults `koanf:"defaults" yaml:"defaults"`
Naming Naming `koanf:"naming" yaml:"naming"`
Assets Assets `koanf:"assets" yaml:"assets"`
Editor Editor `koanf:"editor" yaml:"editor"`
Workspace Workspace `koanf:"workspace" yaml:"workspace"`
Jira Jira `koanf:"jira" yaml:"jira"`
GitHub GitHub `koanf:"github" yaml:"github"`
Repos map[string]RepoConfig `koanf:"repos" yaml:"repos,omitempty"`
Clusters map[string]ClusterConfig `koanf:"clusters" yaml:"clusters,omitempty"`
}
Config is the whole configuration tree.
func Default ¶
func Default() Config
Default returns the built-in configuration, which is a complete, usable configuration on its own.
func (Config) AssetsRoot ¶
AssetsRoot returns the assets root with ~ expanded.
func (Config) BaseBranchFor ¶
BaseBranchFor resolves the base branch for a repo, falling back to the global default.
func (Config) Cluster ¶
func (c Config) Cluster(ctx string) (ClusterConfig, bool)
Cluster returns the settings for a kube context and whether they exist. The boolean matters: absence is the signal to run first-use setup, or to refuse.
func (Config) Repo ¶
func (c Config) Repo(key string) RepoConfig
Repo returns the overrides for a repo key, or the zero value if there are none. It never returns nil, so callers can read fields unconditionally.
type Defaults ¶
type Defaults struct {
BaseBranch string `koanf:"base_branch" yaml:"base_branch"`
Remote string `koanf:"remote" yaml:"remote"`
FetchBeforeBranch bool `koanf:"fetch_before_branch" yaml:"fetch_before_branch"`
OpenEditor bool `koanf:"open_editor" yaml:"open_editor"`
CreateWorkspace bool `koanf:"create_workspace" yaml:"create_workspace"`
CreateAssets bool `koanf:"create_assets" yaml:"create_assets"`
}
Defaults control branch creation and which side effects flow init performs.
type Editor ¶
type Editor struct {
Command string `koanf:"command" yaml:"command"`
Args []string `koanf:"args" yaml:"args"`
Detach bool `koanf:"detach" yaml:"detach"`
}
Editor describes how to launch the editor for a worktree.
type GitHub ¶
type GitHub struct {
APIBase string `koanf:"api_base" yaml:"api_base"`
Token string `koanf:"token" yaml:"token,omitempty"`
TokenKeychainService string `koanf:"token_keychain_service" yaml:"token_keychain_service"`
}
GitHub holds API and token-resolution settings.
type Jira ¶
type Jira struct {
BrowseURL string `koanf:"browse_url" yaml:"browse_url"`
}
Jira holds the browse URL template. flow never calls the Jira API.
type Loaded ¶
type Loaded struct {
Config Config
// Path is the config file flow resolved, whether or not it exists.
Path string
// Exists reports whether that file was actually read.
Exists bool
}
Loaded is a Config plus the provenance a user needs to debug it.
type Naming ¶
type Naming struct {
Branch string `koanf:"branch" yaml:"branch"`
AssetsDir string `koanf:"assets_dir" yaml:"assets_dir"`
WorkspaceLabel string `koanf:"workspace_label" yaml:"workspace_label"`
WorktreesSubdir string `koanf:"worktrees_subdir" yaml:"worktrees_subdir"`
}
Naming holds the templates that derive every path and label from a ticket.
type RepoConfig ¶
type RepoConfig struct {
BaseBranch string `koanf:"base_branch" yaml:"base_branch,omitempty"`
HelmRepo string `koanf:"helm_repo" yaml:"helm_repo,omitempty"`
ChartName string `koanf:"chart_name" yaml:"chart_name,omitempty"`
BuildWorkflow string `koanf:"build_workflow" yaml:"build_workflow,omitempty"`
ChartVersionPattern string `koanf:"chart_version_pattern" yaml:"chart_version_pattern,omitempty"`
WaitForJobs []string `koanf:"wait_for_jobs" yaml:"wait_for_jobs,omitempty"`
}
RepoConfig holds per-repository overrides, keyed by "owner/name" or by absolute repo path when the origin remote cannot be parsed.