package gitops // source_config JSON keys this package can overlay. Kept as constants so the // apply, merge, and drift paths agree on the exact key strings. const ( keyPort = "port" keyHealthcheck = "healthcheck" keyDeployStrategy = "deploy_strategy" ) // Source kinds eligible for GitOps in v1 (git-backed sources only). const ( SourceDockerfile = "dockerfile" SourceStatic = "static" ) // supportedKeys returns the source_config keys a given source kind accepts // from a .tinyforge.yml overlay. A field declared in the file but not in this // set is ignored (not applied, not drift-compared) so a shared file can target // either source without producing dead keys or false drift. // // dockerfile: port + healthcheck + deploy_strategy (its real run knobs). // static: deploy_strategy only (a static site has no port/healthcheck). func supportedKeys(sourceKind string) map[string]bool { switch sourceKind { case SourceDockerfile: return map[string]bool{keyPort: true, keyHealthcheck: true, keyDeployStrategy: true} case SourceStatic: return map[string]bool{keyDeployStrategy: true} default: return nil } } // IsEligibleSource reports whether GitOps may be enabled for a source kind. func IsEligibleSource(sourceKind string) bool { return supportedKeys(sourceKind) != nil } // ApplyPlan is the typed, multi-target plan for applying an overlay. In v1 only // SourceConfigPatch is populated; EnvUpserts/Faces are reserved so env (the // workload_env table) and faces (the public_faces column) can be added later // without reshaping the apply path — they are NOT in v1 (env would re-open the // secrets-in-repo hole; faces live in a sibling store). type ApplyPlan struct { // SourceConfigPatch holds the source_config keys to overlay onto the live // config. Only keys supported by the target source are present. SourceConfigPatch map[string]any // reserved for future phases — see package doc. // EnvUpserts []store.WorkloadEnv // Faces []plugin.PublicFace } // declaredValues returns the present (non-nil) overlay fields keyed by their // source_config JSON key, before the per-source filter. Shared by BuildPlan and // Drift so they agree on what the file declared. func declaredValues(spec Spec) map[string]any { out := map[string]any{} if spec.Deploy.Port != nil { out[keyPort] = *spec.Deploy.Port } if spec.Deploy.Healthcheck != nil { out[keyHealthcheck] = *spec.Deploy.Healthcheck } if spec.Deploy.DeployStrategy != nil { out[keyDeployStrategy] = *spec.Deploy.DeployStrategy } return out } // BuildPlan maps the present, source-supported overlay fields to a patch for // the given source kind. Unsupported/absent fields are dropped. func BuildPlan(spec Spec, sourceKind string) ApplyPlan { allowed := supportedKeys(sourceKind) patch := map[string]any{} for k, v := range declaredValues(spec) { if allowed[k] { patch[k] = v } } return ApplyPlan{SourceConfigPatch: patch} }