@ansible-flow/core 0.87.0 → 0.88.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/ai/describe.js +5 -5
- package/dist/ai/handlers.js +21 -20
- package/dist/ai/handlers.js.map +1 -1
- package/dist/ai/ops.js +4 -4
- package/dist/ai/reference.js +2 -2
- package/dist/ai/scenarios.js +8 -6
- package/dist/awx/import.js +3 -3
- package/dist/chunks/{chunk-IZJPLWDY.js → chunk-2KB3J3R5.js} +2 -2
- package/dist/chunks/{chunk-EAJFZKPB.js → chunk-37FKZNRN.js} +3 -3
- package/dist/chunks/{chunk-BNMW6KWK.js → chunk-57KJYXWA.js} +3 -3
- package/dist/chunks/{chunk-2P3JEHLH.js → chunk-7ALTNZCI.js} +3 -3
- package/dist/chunks/{chunk-WSARMPYU.js → chunk-APBEHKCF.js} +2 -2
- package/dist/chunks/{chunk-W2CSOAIB.js → chunk-BSX6G7QY.js} +5 -5
- package/dist/chunks/{chunk-3Z4WABFK.js → chunk-CATQHJS6.js} +4 -4
- package/dist/chunks/{chunk-HPRG2672.js → chunk-CCWUUVSG.js} +2 -2
- package/dist/chunks/{chunk-C6SQEXL5.js → chunk-CNQ7M7HA.js} +2 -2
- package/dist/chunks/{chunk-IXW7A4M7.js → chunk-CNYGDBID.js} +2 -2
- package/dist/chunks/{chunk-DL4LYODQ.js → chunk-J5LYSQ3L.js} +2 -2
- package/dist/chunks/{chunk-72LO6GQE.js → chunk-KXD6FX2Z.js} +2 -2
- package/dist/chunks/{chunk-4RMWFRWG.js → chunk-LELKMVJG.js} +45 -7
- package/dist/chunks/chunk-LELKMVJG.js.map +7 -0
- package/dist/chunks/{chunk-QMIXDOU6.js → chunk-OGNFHW5O.js} +4 -10
- package/dist/chunks/chunk-OGNFHW5O.js.map +7 -0
- package/dist/chunks/chunk-OJZSZBHW.js +45 -0
- package/dist/chunks/chunk-OJZSZBHW.js.map +7 -0
- package/dist/chunks/{chunk-R4MW3DRT.js → chunk-OW32YCZ6.js} +2 -2
- package/dist/chunks/{chunk-76T45V37.js → chunk-TBFB7A2Z.js} +5 -1
- package/dist/chunks/{chunk-76T45V37.js.map → chunk-TBFB7A2Z.js.map} +2 -2
- package/dist/chunks/{chunk-BXJOUAXV.js → chunk-TEJARYAE.js} +3 -3
- package/dist/chunks/{chunk-KZALUEFT.js → chunk-TPMACJFA.js} +3 -3
- package/dist/chunks/{chunk-2MJKBPGG.js → chunk-WTVGCMGV.js} +7 -3
- package/dist/chunks/chunk-WTVGCMGV.js.map +7 -0
- package/dist/chunks/{chunk-6MLYGFT6.js → chunk-XJAMBKE3.js} +6 -2
- package/dist/chunks/chunk-XJAMBKE3.js.map +7 -0
- package/dist/chunks/{chunk-FMCBTYUM.js → chunk-ZXUXX3YY.js} +2 -2
- package/dist/engine/binding.js +3 -1
- package/dist/engine/engines.js +5 -3
- package/dist/engine/files.js +5 -3
- package/dist/engine/optionA.js +4 -2
- package/dist/engine/preview.js +5 -3
- package/dist/engine/preview.js.map +1 -1
- package/dist/engine/writePlan.js +7 -5
- package/dist/export/drawio.js +3 -3
- package/dist/export/layoutCheck.js +3 -3
- package/dist/export/scene.js +2 -2
- package/dist/export/svg.js +4 -4
- package/dist/flow/findingCodes.js +1 -1
- package/dist/flow/localFiles.d.ts +17 -0
- package/dist/flow/localFiles.js +14 -0
- package/dist/flow/localFiles.js.map +7 -0
- package/dist/import/outline.js +5 -4
- package/dist/import/playbook.js +2 -2
- package/dist/import/source.js +2 -1
- package/dist/protocol.d.ts +12 -0
- package/dist/run/command.d.ts +13 -4
- package/dist/run/command.js +19 -0
- package/dist/run/command.js.map +3 -3
- package/dist/scenario/live.js +7 -5
- package/dist/scenario/simulate.js +6 -4
- package/dist/view/flowFacts.js +7 -5
- package/dist/view/flowFacts.js.map +1 -1
- package/dist/view/jinjaComplete.js +3 -3
- package/dist/view/route.d.ts +3 -1
- package/dist/view/route.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/chunk-2MJKBPGG.js.map +0 -7
- package/dist/chunks/chunk-4RMWFRWG.js.map +0 -7
- package/dist/chunks/chunk-6MLYGFT6.js.map +0 -7
- package/dist/chunks/chunk-QMIXDOU6.js.map +0 -7
- /package/dist/chunks/{chunk-IZJPLWDY.js.map → chunk-2KB3J3R5.js.map} +0 -0
- /package/dist/chunks/{chunk-EAJFZKPB.js.map → chunk-37FKZNRN.js.map} +0 -0
- /package/dist/chunks/{chunk-BNMW6KWK.js.map → chunk-57KJYXWA.js.map} +0 -0
- /package/dist/chunks/{chunk-2P3JEHLH.js.map → chunk-7ALTNZCI.js.map} +0 -0
- /package/dist/chunks/{chunk-WSARMPYU.js.map → chunk-APBEHKCF.js.map} +0 -0
- /package/dist/chunks/{chunk-W2CSOAIB.js.map → chunk-BSX6G7QY.js.map} +0 -0
- /package/dist/chunks/{chunk-3Z4WABFK.js.map → chunk-CATQHJS6.js.map} +0 -0
- /package/dist/chunks/{chunk-HPRG2672.js.map → chunk-CCWUUVSG.js.map} +0 -0
- /package/dist/chunks/{chunk-C6SQEXL5.js.map → chunk-CNQ7M7HA.js.map} +0 -0
- /package/dist/chunks/{chunk-IXW7A4M7.js.map → chunk-CNYGDBID.js.map} +0 -0
- /package/dist/chunks/{chunk-DL4LYODQ.js.map → chunk-J5LYSQ3L.js.map} +0 -0
- /package/dist/chunks/{chunk-72LO6GQE.js.map → chunk-KXD6FX2Z.js.map} +0 -0
- /package/dist/chunks/{chunk-R4MW3DRT.js.map → chunk-OW32YCZ6.js.map} +0 -0
- /package/dist/chunks/{chunk-BXJOUAXV.js.map → chunk-TEJARYAE.js.map} +0 -0
- /package/dist/chunks/{chunk-KZALUEFT.js.map → chunk-TPMACJFA.js.map} +0 -0
- /package/dist/chunks/{chunk-FMCBTYUM.js.map → chunk-ZXUXX3YY.js.map} +0 -0
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../src/core/engine/optionA.ts"],
|
|
4
|
-
"sourcesContent": ["// Option A code generation (handoff 05, ADR-0003, ADR-0009): one playbook per flow level, one play\n// per node, host sets routed between plays with group_by, and a final outcome play that fails the\n// hosts left on open ports or failed end nodes (no host ever fails inside a node play).\n\nimport {\n bubbles,\n type LevelTaken,\n levelTaken,\n portKey,\n unreachableBubbles,\n} from '../flow/bubbling';\nimport {\n capturedOutputs,\n captureTaskName,\n groupPart,\n outputVar,\n registerName,\n} from '../flow/dataNames';\nimport { portAccepted } from '../flow/decisions';\nimport { privilegeOf } from '../flow/inherit';\nimport { conditionExpr } from '../flow/jinja';\nimport { buildModel, type FlowModel, type Level, ROOT } from '../flow/model';\nimport { isFailPort, legalPorts, portsFor } from '../flow/ports';\nimport { rollingObstacles } from '../flow/rolling';\nimport { planSegments, type Segment } from '../flow/segments';\nimport type { Edge, FlowDocument, FlowNode, Ulid } from '../flow/types';\nimport type { Finding } from '../flow/validate';\nimport { plainText } from '../view/markdown';\nimport { bindingTask, inputVars, isIncludeTasks, stubFacts } from './binding';\nimport { withoutDisabled } from './bypass';\nimport { effectiveTargets } from './targets';\nimport type {\n Engine,\n GeneratedFile,\n GenerateOptions,\n GenerateResult,\n HostTerm,\n PlanStep,\n PlayRange,\n Route,\n RunPlan,\n SegmentFile,\n} from './types';\nimport { checksum, jinjaLiteral, timeoutValue } from './util';\nimport {\n Comment,\n comment,\n commentLine,\n flow,\n type Out,\n type OutMap,\n oneLine,\n writeBlock,\n} from './yamlWriter';\n\nexport const CHECKSUM_PREFIX = '# Checksum: ';\n\ninterface LevelCtx {\n level: Level;\n /** Keys of the enclosing subflow nodes, outermost first. */\n path: string[];\n file: string;\n /** Host pattern of a start node (root) or of the subflow's entry (inner levels). */\n entry: string;\n parent?: { node: FlowNode; ctx: LevelCtx };\n}\n\n/** Every line break YAML (1.1 and 1.2) knows: a Note's text is split on all of them (AFD-66). */\nconst LINE_BREAK = /\\r\\n|[\\r\\n\\u0085\\u2028\\u2029]/;\n\ninterface Chunk {\n node?: Ulid;\n lines: string[];\n}\n\ninterface OutcomeEntry {\n order: number;\n groups: string[];\n name: string;\n msg: string;\n}\n\n/** A segment build: the segment and the whole flow's outcome (failed only in leaf segments). */\ninterface SegmentRun {\n seg: Segment;\n outcome: OutcomeEntry[];\n}\n\nclass Generator {\n private readonly model: FlowModel;\n private readonly findings: Finding[] = [];\n private readonly routes: Record<string, Route> = {};\n private readonly outcome: OutcomeEntry[] = [];\n private readonly targets = new Map<string, string>();\n private readonly takenOf = new Map<Level, LevelTaken>();\n private readonly files: { ctx: LevelCtx; chunks: Chunk[] }[] = [];\n private order = 0;\n private todo = false;\n /** Approvals a local run passes unless afd_approvals says otherwise (AFD-21). */\n private approvals: string[] = [];\n /** Work nodes that run on an inventory_target (AFD-14). */\n private readonly overrides: Map<Ulid, string>;\n /** AFD-114: the plays of a scenario build, as the simulator runs them. */\n private readonly steps: PlanStep[] = [];\n private startInput?: string;\n /** The rolling subflow whose play the steps are blocks of (AFD-55): events land on it. */\n private rollingSub?: Ulid;\n\n constructor(\n private readonly doc: FlowDocument,\n private readonly opts: GenerateOptions,\n private readonly segment?: SegmentRun,\n ) {\n this.model = buildModel(doc);\n this.overrides = effectiveTargets(this.model);\n }\n\n /** become and become_user for a node's play (AFD-52: inherited from subflows in format 2). */\n private privilege(node: FlowNode): { become?: true; become_user?: string } {\n const p = privilegeOf(this.model, node);\n return {\n ...(p.become ? { become: true as const } : {}),\n ...(p.become_user ? { become_user: p.become_user } : {}),\n };\n }\n\n run(): GenerateResult {\n const root = this.model.levels.get(ROOT);\n const start = this.startPattern();\n if (!root || !start) return this.result(false);\n const ctx: LevelCtx = { level: root, path: [], file: `${this.doc.flow.key}.yml`, entry: start };\n if (!this.level(ctx)) return this.result(false);\n const outcome = this.outcomePlay();\n if (outcome) this.files[0]?.chunks.push({ lines: outcome });\n return this.result(true);\n }\n\n /** What the outcome play of the whole flow fails (segment builds reuse it). */\n outcomeEntries(): OutcomeEntry[] {\n return [...this.outcome];\n }\n\n // ---- AWX segments (AFD-11, ADR-0016) ---------------------------------------------------------\n\n /**\n * One segment's root playbook: restore the carried host sets (continuations), the segment's top-\n * level plays (subflow levels are the shared level files), then either carry the hosts waiting\n * at the gate and those bound for the outcome to the next segment, or, in a leaf, the outcome.\n */\n segmentRun(): GenerateResult {\n const { seg, outcome } = this.segment as SegmentRun;\n const root = this.model.levels.get(ROOT);\n const start = this.startPattern();\n if (!root || !start) return this.result(false);\n const ctx: LevelCtx = {\n level: root,\n path: [],\n file: `${this.doc.flow.key}.seg_${seg.name}.yml`,\n entry: start,\n };\n if (seg.finish) this.files.push({ ctx, chunks: [] });\n else if (!this.level(ctx)) return this.result(false);\n const chunks = this.files[0]?.chunks ?? [];\n chunks.unshift(...this.prelude(ctx, seg));\n // Segments never fail hosts themselves: the whole flow's outcome runs in the leaves.\n this.outcome.length = 0;\n this.outcome.push(...outcome);\n if (seg.gate) chunks.push({ lines: writeBlock([this.carry(seg.gate)], 0) });\n else {\n const play = this.outcomePlay();\n if (play) chunks.push({ lines: play });\n }\n return this.result(true);\n }\n\n private prelude(ctx: LevelCtx, seg: Segment): Chunk[] {\n if (!seg.entry && !seg.finish) return [];\n const tag = flow([`flow_${this.doc.flow.id}`]);\n const out: Chunk[] = [\n {\n lines: writeBlock(\n [\n {\n name: `[${this.doc.flow.key}] Segment ${seg.name}: restore host sets`,\n hosts: 'localhost',\n gather_facts: false,\n tags: tag,\n tasks: [\n {\n name: 'restore the host sets the previous segment carried',\n 'ansible.builtin.add_host': { name: '{{ item.1 }}', groups: '{{ item.0.key }}' },\n loop: \"{{ (afd_hostsets | default({})) | dict2items | subelements('value') }}\",\n loop_control: { label: '{{ item.0.key }}: {{ item.1 }}' },\n },\n ...(seg.finish\n ? [\n {\n name: 'only after an approval no host reached',\n 'ansible.builtin.fail': {\n msg: 'A segment before this one did not finish: see its AWX job',\n },\n when: 'not (afd_gate_empty | default(false) | bool)',\n },\n ]\n : []),\n ],\n },\n ],\n 0,\n ),\n },\n ];\n const gate = seg.entry ? this.model.nodes.get(seg.entry.approval)?.node : undefined;\n if (gate && seg.entry) {\n const port = seg.entry.outcome;\n const waiting = this.group([], gate.key, 'waiting');\n // AFD-272: AWX cannot tell a timeout from a rejection, so its rejected segment takes both;\n // a runner that can (runSegments) says which with afd_gate_outcome, and the hosts take the\n // timeout port when the approval has one.\n const timeout =\n port === 'rejected' && portsFor(gate).some((p) => p.name === 'timeout')\n ? [\n {\n test: \"(afd_gate_outcome | default('rejected')) == 'timeout'\",\n group: this.target(ctx, gate, 'timeout'),\n port: 'timeout',\n },\n ]\n : [];\n out.push({\n node: gate.id,\n lines: writeBlock(\n [\n {\n // The route suffix maps AWX events back to the approval node.\n name: `[${gate.key}] ${jinjaLiteral(oneLine(gate.title))}: route`,\n hosts: `{{ groups['${waiting}'] | default([]) | join(',') or 'afd_no_hosts' }}`,\n gather_facts: false,\n tags: flow([`node_${gate.id}`]),\n vars: { flow_node_id: gate.id },\n tasks: [choose(gate, timeout, { group: this.target(ctx, gate, port), port })],\n },\n ],\n 0,\n ),\n });\n }\n return out;\n }\n\n /** set_stats for the next segment, then stop this job when nobody waits at the gate. */\n private carry(gateId: Ulid): OutMap {\n const gate = this.model.nodes.get(gateId)?.node as FlowNode;\n const waiting = this.group([], gate.key, 'waiting');\n const groups = [...new Set([...this.outcome.flatMap((e) => e.groups), waiting])];\n const empty = `groups['${waiting}'] | default([]) | length == 0`;\n return {\n name: `[${this.doc.flow.key}] Segment ${this.segment?.seg.name}: carry host sets`,\n hosts: 'localhost',\n gather_facts: false,\n tags: flow([`flow_${this.doc.flow.id}`]),\n tasks: [\n {\n name: 'carry the hosts waiting for approval and those bound for the outcome',\n 'ansible.builtin.set_stats': {\n data: {\n afd_hostsets: Object.fromEntries(\n groups.map((g) => [g, `{{ groups['${g}'] | default([]) }}`]),\n ),\n afd_gate_empty: `{{ ${empty} }}`,\n },\n per_host: false,\n aggregate: false,\n },\n },\n {\n name: `[${gate.key}] no host reached ${jinjaLiteral(oneLine(gate.title))}`,\n 'ansible.builtin.fail': {\n msg: `No host reached [${gate.key}] ${jinjaLiteral(oneLine(gate.title))}: the approval is skipped and the flow finishes`,\n },\n when: empty,\n },\n ],\n };\n }\n\n // ---- inputs and routing -------------------------------------------------------------------\n\n /** The flow input that seeds start (decision 23): `targets: true`, else the first host_list. */\n private startPattern(): string | undefined {\n const inputs = Object.entries(this.doc.flow?.inputs ?? {});\n const hostLists = inputs.filter(([, f]) => f?.type === 'host_list');\n const chosen = hostLists.find(([, f]) => f.targets) ?? hostLists[0];\n if (!chosen) {\n this.finding('codegen-no-targets', 'error', 'The flow needs a host_list input to target', [\n 'flow',\n 'inputs',\n ]);\n return undefined;\n }\n // A list from the run inputs, or the comma-separated text an AWX survey answers (AFD-59).\n const name = chosen[0];\n this.startInput = name;\n return `{{ ${name} if ${name} is string else ${name} | join(',') }}`;\n }\n\n /** What takes the ports of the level's steps, once per level. */\n private taken(ctx: LevelCtx): LevelTaken {\n let taken = this.takenOf.get(ctx.level);\n if (!taken) {\n taken = levelTaken(ctx.level.edges, ctx.parent?.node);\n this.takenOf.set(ctx.level, taken);\n }\n return taken;\n }\n\n private group(path: string[], key: string, port: string): string {\n return `flow_${[...path, key].map(groupPart).join('__')}_${groupPart(port)}`;\n }\n\n /**\n * Group a node's output port routes into: its own group when wired (or open), the parent's port\n * group when the port leaves a subflow level through its boundary or bubbles up (ADR-0004).\n * An open fail port is recorded for the outcome play.\n */\n private target(ctx: LevelCtx, node: FlowNode, port: string): string {\n const memo = `${node.id}|${port}`;\n const known = this.targets.get(memo);\n if (known) return known;\n const own = this.group(ctx.path, node.key, port);\n let target = own;\n const taken = this.taken(ctx);\n const wired = taken.wired.has(portKey(node.id, port));\n const parent = ctx.parent;\n if (!wired && parent) {\n const exported = Object.entries(parent.node.subflow?.boundary?.outputs ?? {}).find(\n ([, refs]) => (refs ?? []).some((r) => r?.node === node.id && r.port === port),\n );\n if (exported) target = this.target(parent.ctx, parent.node, exported[0]);\n else if (bubbles(parent.node, node.id, port, taken))\n target = this.target(parent.ctx, parent.node, port);\n }\n if (target === own) {\n this.routes[own] = { node: node.id, port };\n if (!wired && isFailPort(port)) this.openPort(node, port, own);\n }\n this.targets.set(memo, target);\n return target;\n }\n\n private openPort(node: FlowNode, port: string, group: string): void {\n const decision = portAccepted(this.doc, node.id, port);\n const where = `[${node.key}] ${jinjaLiteral(oneLine(node.title))}`;\n this.outcome.push({\n order: this.order,\n groups: [group],\n name: decision ? `[${node.key}] ${port} open on purpose` : `[${node.key}] ${port} is open`,\n msg: decision\n ? `Stopped at ${where}: ${port} open on purpose (${jinjaLiteral(oneLine(decision.reason ?? 'no reason'))})`\n : `Stopped at ${where}: ${port} is not wired`,\n });\n }\n\n private sources(ctx: LevelCtx, node: FlowNode, edges: Edge[]): string[] {\n const out: string[] = [];\n for (const e of edges) {\n if (e.to.node !== node.id || e.to.port !== 'in') continue;\n const from = this.model.nodes.get(e.from.node)?.node;\n if (!from) continue;\n // A continuation segment starts at its approval, not at the flow targets.\n if (from.type === 'start' && this.segment?.seg.entry && !ctx.parent) continue;\n out.push(from.type === 'start' ? ctx.entry : this.target(ctx, from, e.from.port));\n }\n if (ctx.parent && ctx.parent.node.subflow?.boundary?.in === node.id) out.push(ctx.entry);\n return [...new Set(out)];\n }\n\n // ---- levels ----------------------------------------------------------------------------------\n\n private level(ctx: LevelCtx): boolean {\n const nodes = ctx.level.nodes.filter((n): n is FlowNode => !!n && typeof n === 'object');\n const ids = new Set(nodes.map((n) => n.id));\n const edges = ctx.level.edges.filter(\n (e): e is Edge => !!e?.from && !!e.to && ids.has(e.from.node) && ids.has(e.to.node),\n );\n const order = topoOrder(nodes, edges);\n if (!order) {\n const where = ctx.parent ? `level [${ctx.parent.node.key}]` : 'top level';\n this.finding('codegen-cycle', 'error', `The ${where} has a cycle; plays need an order`, []);\n return false;\n }\n const file = { ctx, chunks: [] as Chunk[] };\n this.files.push(file);\n for (const node of order) {\n this.order++;\n if (this.segment && !ctx.parent && !this.segment.seg.nodes.has(node.id)) continue;\n if (node.type === 'start') continue;\n if (node.type === 'end') {\n this.endNode(ctx, node, edges);\n continue;\n }\n const hosts = this.sources(ctx, node, edges);\n if (hosts.length === 0) {\n this.finding(\n 'codegen-no-input',\n 'warning',\n `Nothing leads to \"${node.title}\": no play is generated for it`,\n this.model.nodes.get(node.id)?.path ?? [],\n node.id,\n );\n continue;\n }\n if (node.type === 'subflow' && (node.subflow?.nodes?.length ?? 0) > 0) {\n if (!this.subflowLevel(ctx, node, hosts, file.chunks)) return false;\n continue;\n }\n // Its own target or an enclosing subflow's; decisions, approvals, parallels and joins\n // always run on the arriving hosts.\n const over = this.overrides.get(node.id);\n if (over) {\n // A blank line between the node's plays; a comment stays with the play it describes.\n const plays = this.overridePlays(ctx, node, hosts, over);\n file.chunks.push({\n node: node.id,\n lines: plays.flatMap((p, i) => [\n ...(i > 0 && !(plays[i - 1] instanceof Comment) ? [''] : []),\n ...writeBlock([p], 0),\n ]),\n });\n continue;\n }\n if (node.impl?.kind === 'playbook' && node.impl.ref && !this.opts.stubAll) {\n file.chunks.push({ node: node.id, lines: this.playbookNode(ctx, node, hosts) });\n continue;\n }\n const play = this.play(ctx, node, hosts, edges);\n file.chunks.push({ node: node.id, lines: writeBlock([play], 0) });\n }\n return true;\n }\n\n private subflowLevel(ctx: LevelCtx, node: FlowNode, hosts: string[], chunks: Chunk[]): boolean {\n const level = this.model.levels.get(node.id);\n if (!level) return true;\n const path = [...ctx.path, node.key];\n const file = `${this.doc.flow.key}.${path.join('.')}.yml`;\n chunks.push({\n node: node.id,\n lines: [\n commentLine(`[${node.key}] ${oneLine(node.title)}: subflow level, see ${file}`),\n ...writeBlock([{ import_playbook: file, tags: flow([`node_${node.id}`]) }], 0),\n ],\n });\n // Ports of the subflow node itself: wired ones feed this level, open ones reach the outcome.\n for (const p of portsFor(node)) if (p.direction === 'out') this.target(ctx, node, p.name);\n // A segment imports the level file the whole-flow build writes.\n if (this.segment) return true;\n const inner: LevelCtx = { level, path, file, entry: hosts.join(':'), parent: { node, ctx } };\n const rolling = node.settings?.rolling;\n if (rolling === undefined) return this.level(inner);\n const obstacles = rollingObstacles(this.model, node).map((o) => `${o.node.title}: ${o.why}`);\n for (const n of level.nodes)\n if (n && this.overrides.has(n.id) && !obstacles.some((o) => o.startsWith(`${n.title}:`)))\n obstacles.push(`${n.title}: it runs on an inventory_target, in plays of its own`);\n if (obstacles.length === 0) return this.rollingLevel(inner, rolling);\n this.finding(\n 'rolling-unsupported',\n 'error',\n `\"${node.title}\" cannot roll (${obstacles.join('; ')}): its steps run play by play`,\n this.model.nodes.get(node.id)?.path ?? [],\n node.id,\n );\n return this.level(inner);\n }\n\n /**\n * A rolling subflow's level (AFD-55): one play with `serial`, so each batch of hosts goes through\n * every step before the next batch starts. Each step is a block for the hosts that arrived at it\n * (its routing groups, as the play-per-step level uses), with the vars, tags and privilege its\n * own play would have; its routing, rescue and captures are the same tasks.\n */\n private rollingLevel(ctx: LevelCtx, batch: string | number): boolean {\n const sub = ctx.parent?.node as FlowNode;\n const nodes = ctx.level.nodes.filter((n): n is FlowNode => !!n && typeof n === 'object');\n const ids = new Set(nodes.map((n) => n.id));\n const edges = ctx.level.edges.filter(\n (e): e is Edge => !!e?.from && !!e.to && ids.has(e.from.node) && ids.has(e.to.node),\n );\n const order = topoOrder(nodes, edges);\n if (!order) {\n this.finding(\n 'codegen-cycle',\n 'error',\n `The level [${sub.key}] has a cycle; plays need an order`,\n [],\n );\n return false;\n }\n const blocks: Out[] = [];\n this.rollingSub = sub.id;\n for (const node of order) {\n this.order++;\n if (node.type === 'start') continue;\n if (node.type === 'end') {\n this.endNode(ctx, node, edges);\n continue;\n }\n const hosts = this.sources(ctx, node, edges);\n if (hosts.length === 0) {\n this.finding(\n 'codegen-no-input',\n 'warning',\n `Nothing leads to \"${node.title}\": no play is generated for it`,\n this.model.nodes.get(node.id)?.path ?? [],\n node.id,\n );\n continue;\n }\n const play = this.play(ctx, node, hosts, edges);\n for (const t of this.noteLines(node.id)) blocks.push(comment(t));\n // Every host of the play enters at the entry; the others arrive through their groups.\n const groups = hosts.filter((h) => h !== ctx.entry);\n blocks.push({\n name: play.name,\n block: play.tasks,\n vars: play.vars,\n become: play.become,\n become_user: play.become_user,\n tags: play.tags,\n when: hosts.includes(ctx.entry)\n ? undefined\n : `inventory_hostname in (${groups.map((g) => `groups['${g}'] | default([])`).join(' + ')})`,\n });\n }\n this.rollingSub = undefined;\n this.files.push({\n ctx,\n chunks: [\n {\n node: sub.id,\n lines: writeBlock(\n [\n {\n name: `[${sub.key}] ${jinjaLiteral(oneLine(sub.title))}: rolling, ${batch} at a time`,\n hosts: ctx.entry,\n gather_facts: false,\n serial: batch,\n tags: flow([`node_${sub.id}`]),\n vars: { flow_node_id: sub.id },\n tasks: blocks,\n },\n ],\n 0,\n ),\n },\n ],\n });\n return true;\n }\n\n private endNode(ctx: LevelCtx, node: FlowNode, edges: Edge[]): void {\n const groups = edges\n .filter((e) => e.to.node === node.id)\n .map((e) => {\n const from = this.model.nodes.get(e.from.node)?.node;\n return from && from.type !== 'start' ? this.target(ctx, from, e.from.port) : undefined;\n })\n .filter((g): g is string => !!g);\n if (node.outcome !== 'failed' || groups.length === 0) return;\n this.outcome.push({\n order: this.order,\n groups: [...new Set(groups)],\n name: `[${node.key}] ${jinjaLiteral(oneLine(node.title))}`,\n msg: `Ended at [${node.key}] ${jinjaLiteral(oneLine(node.title))} (outcome: failed)`,\n });\n }\n\n // ---- inventory_target (AFD-14) -------------------------------------------------------------\n\n /**\n * A node that runs on its inventory_target (AFD-14): the arriving hosts are marked, the binding\n * runs once on the target, and the arriving hosts leave together. They take ok_hosts when every\n * target host finished (or the failed share stays within max_fail_percentage), else failed_hosts\n * (timeout when a target host timed out and the port is enabled). A target that matches no host\n * fails them too: the work never ran.\n */\n private overridePlays(ctx: LevelCtx, node: FlowNode, hosts: string[], target: string): Out[] {\n const tag = `node_${node.id}`;\n // AFD-145: a play name is rendered too; Ansible stops the whole run on an undefined name.\n const title = `[${node.key}] ${jinjaLiteral(oneLine(node.title))}`;\n const settings = node.settings ?? {};\n const own = (part: string) => this.group(ctx.path, node.key, part);\n const arrived = own('arriving');\n const done = own('target_done');\n const timedOut = own('target_timeout');\n const failedOnTarget = own('target_failed');\n const enabled = new Set(portsFor(node).map((p) => p.name));\n const path = this.model.nodes.get(node.id)?.path ?? [];\n const impl = node.impl?.ref ? node.impl : undefined;\n const kind = this.opts.stubAll ? 'todo' : (impl?.kind ?? 'todo');\n const sim = this.opts.simulate && kind === 'todo';\n for (const p of portsFor(node)) if (p.direction === 'out') this.target(ctx, node, p.name);\n const never = ['unreachable', 'unchanged'].filter((p) => enabled.has(p));\n if (kind === 'playbook' && enabled.has('timeout')) never.push('timeout');\n if (never.length > 0)\n this.finding(\n 'codegen-target-ports',\n 'warning',\n `\"${node.title}\" runs on its inventory_target (${target}): arriving hosts never take ${never.join(', ')}`,\n path,\n node.id,\n );\n const timeoutPort = enabled.has('timeout') && kind !== 'playbook';\n const arriving = `{{ groups['${arrived}'] | default([]) }}`;\n const guard: OutMap = {\n name: `[${node.key}] no host arrived`,\n 'ansible.builtin.meta': 'end_play',\n when: 'afd_arriving | length == 0',\n };\n const plays: Out[] = [\n {\n name: `${title}: arriving hosts`,\n hosts: hosts.join(':'),\n gather_facts: false,\n tags: flow([tag]),\n vars: { flow_node_id: node.id },\n tasks: [{ name: `[${node.key}] arriving`, 'ansible.builtin.group_by': { key: arrived } }],\n },\n ];\n const inputs = inputVars(this.model, ctx.level.id, node, 'hostvars[afd_arriving | first]');\n\n if (kind === 'playbook') {\n const root = (this.opts.root ?? '../../..').replace(/\\/+$/, '');\n const ref = (impl?.ref ?? '').replace(/^\\.?\\//, '');\n plays.push(\n comment(\n `${title}: playbook ${ref} on ${target}; its plays should target \"{{ afd_hosts }}\"`,\n ),\n {\n import_playbook: `${root}/${ref}`,\n vars: {\n afd_target_pattern: target,\n afd_arriving: arriving,\n afd_hosts: `{{ (afd_arriving | length > 0) | ternary(afd_target_pattern, 'afd_no_hosts') }}`,\n ...((impl?.params ?? {}) as OutMap),\n ...inputs,\n },\n tags: flow([tag]),\n },\n {\n // Hosts that failed inside the playbook left the run; the rest finished.\n name: `${title}: target done`,\n hosts: target,\n gather_facts: false,\n tags: flow([tag]),\n vars: { flow_node_id: node.id, afd_arriving: arriving },\n tasks: [\n guard,\n ...this.captures(node),\n { name: `[${node.key}] target done`, 'ansible.builtin.group_by': { key: done } },\n ],\n },\n );\n } else {\n const vars: OutMap = {\n flow_node_id: node.id,\n afd_arriving: arriving,\n ...this.repoRoot(node),\n ...inputs,\n };\n if (this.opts.simulate) {\n const key = [...ctx.path, node.key].join('/');\n vars.afd_sim = `{{ (afd_simulate | default({}))['${key}'] | default({}) }}`;\n }\n const timeout = timeoutValue(settings.timeout);\n const reg = registerName(node, impl);\n const extra: Out[] = [];\n let body: OutMap;\n if (impl && kind !== 'todo') body = bindingTask(node, impl, timeout);\n else {\n const facts = stubFacts(node);\n if (facts) extra.push(facts);\n this.todo = true;\n const failing = ['failed', ...(enabled.has('timeout') ? ['timeout'] : [])];\n body = {\n name: `[${node.key}] TODO`,\n 'ansible.builtin.debug': {\n msg: `TODO: ${jinjaLiteral(oneLine(node.intent || node.title))}`,\n },\n failed_when: sim\n ? `inventory_hostname in ${failing.map((p) => `afd_sim.${p} | default([])`).join(' + ')}`\n : undefined,\n };\n }\n const finished: OutMap = {\n name: `[${node.key}] target done`,\n 'ansible.builtin.group_by': {\n key:\n kind === 'module'\n ? `{{ '${failedOnTarget}' if (${reg}.unreachable | default(false)) else '${done}' }}`\n : done,\n },\n };\n const timedTest = sim\n ? simIn('timeout')\n : '(ansible_failed_result.timedout | default(false))';\n plays.push({\n name: title,\n hosts: target,\n gather_facts: false,\n serial: settings.serial,\n ...this.privilege(node),\n tags: flow([tag, ...(settings.tags ?? [])]),\n vars,\n tasks: [\n guard,\n {\n block: [body, ...extra, ...this.captures(node), finished],\n rescue: [\n {\n name: `[${node.key}] target failed`,\n 'ansible.builtin.group_by': {\n key: timeoutPort\n ? `{{ '${timedOut}' if ${timedTest} else '${failedOnTarget}' }}`\n : failedOnTarget,\n },\n },\n failureRecord(node, [...ctx.path, node.key].join('/')),\n ],\n },\n ],\n });\n }\n\n // Route the arriving hosts on the target's result; outputs come from the first finished host.\n const limit = settings.max_fail_percentage;\n const failed =\n typeof limit === 'number'\n ? `afd_target | length == 0 or (afd_target_failed | length) * 100 > ${limit} * (afd_target | length)`\n : 'afd_target | length == 0 or afd_target_failed | length > 0';\n const failedGroup = this.target(ctx, node, 'failed_hosts');\n const failGroup = timeoutPort\n ? `('${this.target(ctx, node, 'timeout')}' if (groups['${timedOut}'] | default([]) | length > 0) else '${failedGroup}')`\n : `'${failedGroup}'`;\n const outputs = [\n ...new Set(\n Object.keys(node.outputs ?? {})\n .map((o) => outputVar(this.model, node, o).split(/[.[]/)[0] as string)\n .filter(Boolean),\n ),\n ];\n const failPorts = ['failed_hosts', ...(timeoutPort ? ['timeout'] : [])];\n const tasks: Out[] = [\n {\n name: `[${node.key}] target matched no host`,\n 'ansible.builtin.debug': {\n msg: 'inventory_target {{ afd_target_pattern }} matched no host: every arriving host takes failed_hosts',\n },\n when: 'afd_target | length == 0',\n run_once: true,\n },\n {\n name: `[${node.key}] target hosts that did not finish`,\n 'ansible.builtin.debug': { msg: \"{{ afd_target_failed | join(', ') }}\" },\n when: 'afd_target_failed | length > 0',\n run_once: true,\n },\n ];\n // One per variable, only when the target host set it, as a step's captures (AFD-53): a stub\n // registers nothing, and an unguarded read failed every arriving host (found by AFD-114).\n for (const o of outputs)\n tasks.push({\n name: `[${node.key}] outputs from the target (${o})`,\n 'ansible.builtin.set_fact': { [o]: `{{ hostvars[afd_target_done | first].${o} }}` },\n when: `afd_target_done | length > 0 and hostvars[afd_target_done | first].${o} is defined`,\n });\n // AFD-186: the arriving hosts take the target's failure, so the step on failed_hosts reads it.\n tasks.push({\n name: `[${node.key}] failure from the target`,\n 'ansible.builtin.set_fact': Object.fromEntries(\n FAILURE_FACTS.map((f) => [\n f,\n `{{ hostvars[afd_target_failed | first].${f} | default(none) }}`,\n ]),\n ),\n when: 'afd_target_failed | length > 0',\n });\n tasks.push(...failPorts.flatMap((p) => this.portComment(ctx, node, p)), {\n name: `[${node.key}] route ${['ok_hosts', ...failPorts].join(', ')}`,\n 'ansible.builtin.group_by': {\n key: `{{ ${failGroup} if (${failed}) else '${this.target(ctx, node, 'ok_hosts')}' }}`,\n },\n });\n if (enabled.has('always')) tasks.push(route(node, 'always', this.target(ctx, node, 'always')));\n plays.push({\n name: `${title}: route`,\n hosts: arrived,\n gather_facts: false,\n tags: flow([tag]),\n vars: {\n flow_node_id: node.id,\n afd_target_pattern: target,\n afd_target: \"{{ query('ansible.builtin.inventory_hostnames', afd_target_pattern) }}\",\n afd_target_done: `{{ groups['${done}'] | default([]) }}`,\n afd_target_failed: '{{ afd_target | difference(afd_target_done) }}',\n },\n tasks,\n });\n if (this.planning)\n this.steps.push({\n ...this.stepBase(ctx, node, hosts),\n kind: 'target',\n pattern: target,\n todo: `TODO: ${oneLine(node.intent || node.title)}`,\n ...(typeof limit === 'number' ? { maxFail: limit } : {}),\n });\n return plays;\n }\n\n // ---- the plan of a scenario build (AFD-114) ------------------------------------------------\n\n /** A scenario build (simulate, every step a stub) of the whole flow records its plan. */\n private get planning(): boolean {\n return !!this.opts.simulate && !!this.opts.stubAll && !this.segment;\n }\n\n /** The output ports of a node the generator routed, with their (resolved) groups. */\n private routedPorts(node: FlowNode): Record<string, string> {\n const out: Record<string, string> = {};\n const prefix = `${node.id}|`;\n for (const [memo, group] of this.targets)\n if (memo.startsWith(prefix)) out[memo.slice(prefix.length)] = group;\n return out;\n }\n\n private stepBase(ctx: LevelCtx, node: FlowNode, hosts: string[]) {\n const terms: HostTerm[] = hosts\n .flatMap((h) => h.split(':'))\n .filter(Boolean)\n .map((h) => (h.startsWith('{{') ? { start: true as const } : { group: h }));\n return {\n node: node.id,\n attribute: this.rollingSub ?? node.id,\n key: [...ctx.path, node.key].join('/'),\n label: `[${node.key}] ${oneLine(node.title)}`,\n hosts: terms,\n ports: this.routedPorts(node),\n serial: node.settings?.serial !== undefined,\n };\n }\n\n private record(ctx: LevelCtx, node: FlowNode, hosts: string[], edges: Edge[]): void {\n if (!this.planning) return;\n const base = this.stepBase(ctx, node, hosts);\n switch (node.type) {\n case 'decision':\n case 'approval':\n case 'parallel':\n this.steps.push({ ...base, kind: node.type });\n return;\n case 'join': {\n const members: string[] = [];\n for (const e of edges) {\n const from = e.to.node === node.id ? this.model.nodes.get(e.from.node)?.node : undefined;\n const group =\n from && from.type !== 'start' && this.targets.get(`${from.id}|${e.from.port}`);\n if (group) members.push(group);\n }\n this.steps.push({\n ...base,\n kind: 'join',\n mode: node.join_mode === 'any' ? 'any' : 'all',\n members,\n });\n return;\n }\n default: {\n const limit = node.settings?.max_fail_percentage;\n this.steps.push({\n ...base,\n kind: 'task',\n todo: `TODO: ${oneLine(node.intent || node.title)}`,\n // AFD-144: the hosts this step fails, as the generated code counts them.\n ...(typeof limit === 'number' ? { maxFail: { limit } } : {}),\n });\n }\n }\n }\n\n // ---- plays -----------------------------------------------------------------------------------\n\n /**\n * A playbook binding: `import_playbook` cannot sit inside a play, so the node is the import (its\n * plays target `afd_hosts`, the hosts arriving here) and a play that routes the hosts still\n * active to ok_hosts. Hosts that fail inside the playbook stop there (ADR-0011).\n */\n private playbookNode(ctx: LevelCtx, node: FlowNode, hosts: string[]): string[] {\n const tag = `node_${node.id}`;\n const root = (this.opts.root ?? '../../..').replace(/\\/+$/, '');\n const ref = (node.impl?.ref ?? '').replace(/^\\.?\\//, '');\n const pattern = hosts.join(':');\n if (\n portsFor(node).some(\n (p) => p.name !== 'failed_hosts' && p.direction === 'out' && p.name !== 'ok_hosts',\n )\n )\n this.finding(\n 'codegen-playbook-ports',\n 'warning',\n `\"${node.title}\" runs a playbook: only ok_hosts can be routed, other ports stay empty`,\n this.model.nodes.get(node.id)?.path ?? [],\n node.id,\n );\n for (const p of portsFor(node)) if (p.direction === 'out') this.target(ctx, node, p.name);\n return [\n commentLine(\n `[${node.key}] ${oneLine(node.title)}: playbook ${oneLine(ref)}; its plays should target \"{{ afd_hosts }}\"`,\n ),\n ...writeBlock(\n [\n {\n import_playbook: `${root}/${ref}`,\n vars: {\n afd_hosts: pattern,\n ...((node.impl?.params ?? {}) as OutMap),\n ...inputVars(this.model, ctx.level.id, node),\n },\n tags: flow([tag]),\n },\n {\n name: `[${node.key}] ${jinjaLiteral(oneLine(node.title))}: route`,\n hosts: pattern,\n gather_facts: false,\n tags: flow([tag]),\n tasks: [\n ...this.captures(node),\n route(node, 'ok_hosts', this.target(ctx, node, 'ok_hosts')),\n ],\n },\n ],\n 0,\n ),\n ];\n }\n\n private play(ctx: LevelCtx, node: FlowNode, hosts: string[], edges: Edge[]): OutMap {\n const tag = `node_${node.id}`;\n const vars: OutMap = {\n flow_node_id: node.id,\n ...this.repoRoot(node),\n ...inputVars(this.model, ctx.level.id, node),\n };\n if (this.opts.simulate) {\n const key = [...ctx.path, node.key].join('/');\n vars.afd_sim = `{{ (afd_simulate | default({}))['${key}'] | default({}) }}`;\n }\n const settings = node.settings ?? {};\n let tasks: Out[];\n switch (node.type) {\n case 'decision':\n tasks = this.decisionTasks(ctx, node);\n break;\n case 'approval':\n tasks =\n this.segment?.seg.gate === node.id && !ctx.parent\n ? [\n {\n name: `[${node.key}] wait for approval in AWX`,\n 'ansible.builtin.group_by': { key: this.group([], node.key, 'waiting') },\n },\n ]\n : this.approvalTasks(ctx, node, vars);\n break;\n case 'parallel':\n tasks = legalPorts(node)\n .filter((p) => p.enabled && p.name.startsWith('branch_'))\n .map((p) => route(node, p.name, this.target(ctx, node, p.name)));\n break;\n case 'join':\n tasks = this.joinTasks(ctx, node, edges);\n break;\n default:\n tasks = this.taskTasks(ctx, node);\n }\n this.record(ctx, node, hosts, edges);\n return {\n name: `[${node.key}] ${jinjaLiteral(oneLine(node.title))}`,\n hosts: hosts.join(':'),\n gather_facts: false,\n serial: settings.serial,\n ...this.privilege(node),\n tags: flow([tag, ...(settings.tags ?? [])]),\n vars,\n tasks,\n };\n }\n\n /**\n * A step's outputs that are not its register, copied into its own variables for the hosts that\n * finished it (AFD-53), so another step setting the same fact cannot change what readers get. An\n * output the code did not set stays unset, and its reader fails as it would have.\n */\n private captures(node: FlowNode): Out[] {\n return capturedOutputs(this.model, node).map(([out, name]) => ({\n name: captureTaskName(node.key, out),\n 'ansible.builtin.set_fact': { [name]: `{{ ${out} }}` },\n when: `${out} is defined`,\n }));\n }\n\n /**\n * AFD-177: `afd_repo_root`, the repository as an absolute path, for a step whose code reads it\n * or runs files the flow cannot see (a task file, a role). playbook_dir is generated/ and Ansible\n * does not let a play change it; shared files use `{{ afd_repo_root | default(playbook_dir) }}`.\n */\n private repoRoot(node: FlowNode): OutMap {\n const impl = node.impl;\n if (!impl?.ref || impl.kind === 'playbook') return {};\n const reads =\n impl.kind === 'role' ||\n isIncludeTasks(impl.ref) ||\n JSON.stringify([impl.params ?? null, impl.keywords ?? null]).includes('afd_repo_root');\n if (!reads) return {};\n const root = (this.opts.root ?? '../../..').replace(/\\/+$/, '');\n return { afd_repo_root: `{{ (playbook_dir ~ '/${root}') | ansible.builtin.realpath }}` };\n }\n\n private taskTasks(ctx: LevelCtx, node: FlowNode): Out[] {\n const enabled = new Set(portsFor(node).map((p) => p.name));\n const impl = node.impl?.ref ? node.impl : undefined;\n const kind =\n !this.opts.stubAll && (impl?.kind === 'module' || impl?.kind === 'role') ? impl.kind : 'todo';\n const sim = this.opts.simulate && kind === 'todo';\n const timeout = timeoutValue(node.settings?.timeout);\n const reg = registerName(node, impl);\n const on = (port: string) => this.target(ctx, node, port);\n\n let body: OutMap;\n const extra: Out[] = [];\n if (kind !== 'todo' && impl) {\n body = bindingTask(node, impl, timeout);\n } else {\n const facts = stubFacts(node);\n if (facts) extra.push(facts);\n this.todo = true;\n const failing = ['failed', ...(enabled.has('timeout') ? ['timeout'] : [])];\n body = {\n name: `[${node.key}] TODO`,\n 'ansible.builtin.debug': {\n msg: `TODO: ${jinjaLiteral(oneLine(node.intent || node.title))}`,\n },\n failed_when: sim\n ? `inventory_hostname in ${failing.map((p) => `afd_sim.${p} | default([])`).join(' + ')}`\n : undefined,\n };\n }\n\n // ok_hosts, refined by unchanged (module results or simulation) and unreachable (module\n // results ignore unreachable so the host stays routable, ADR-0009).\n const okChoices: Choice[] = [];\n if (kind === 'module') {\n const group = enabled.has('unreachable')\n ? on('unreachable')\n : this.unreachableNotEnabled(ctx, node);\n okChoices.push({ test: `(${reg}.unreachable | default(false))`, group, port: 'unreachable' });\n if (enabled.has('unchanged'))\n okChoices.push({ test: `not ${reg}.changed`, group: on('unchanged'), port: 'unchanged' });\n } else if (sim) {\n for (const port of ['unreachable', 'unchanged'])\n if (enabled.has(port)) okChoices.push({ test: simIn(port), group: on(port), port });\n }\n const okRoute = choose(node, okChoices, { group: on('ok_hosts'), port: 'ok_hosts' });\n\n const failChoices: Choice[] = [];\n if (enabled.has('timeout')) {\n const test = sim ? simIn('timeout') : '(ansible_failed_result.timedout | default(false))';\n failChoices.push({ test, group: on('timeout'), port: 'timeout' });\n }\n // AFD-144: max_fail_percentage counts the hosts this step failed, in a group of its own. The\n // port groups can be a parent subflow's, which already hold the hosts other steps failed.\n const limit = node.settings?.max_fail_percentage;\n const failedHere =\n typeof limit === 'number' ? this.group(ctx.path, node.key, 'failed_here') : undefined;\n const unreachableHere = okChoices.find((c) => c.port === 'unreachable');\n const counted: Out[] = failedHere\n ? [\n {\n name: `[${node.key}] count the failure`,\n 'ansible.builtin.group_by': { key: failedHere },\n },\n ]\n : [];\n const rescue: Out[] = [\n ...['failed_hosts', ...failChoices.map((c) => c.port)].flatMap((p) =>\n this.portComment(ctx, node, p),\n ),\n ...counted,\n choose(node, failChoices, { group: on('failed_hosts'), port: 'failed_hosts' }),\n failureRecord(node, [...ctx.path, node.key].join('/')),\n ];\n const countUnreachable: Out[] =\n failedHere && unreachableHere\n ? [\n {\n name: `[${node.key}] count the unreachable`,\n 'ansible.builtin.group_by': { key: failedHere },\n when: unreachableHere.test,\n },\n ]\n : [];\n const block: OutMap = {\n block: [body, ...extra, ...this.captures(node), okRoute, ...countUnreachable],\n rescue,\n };\n if (enabled.has('always')) block.always = [route(node, 'always', on('always'))];\n const tasks: Out[] = [block];\n\n if (typeof limit === 'number' && failedHere) {\n const count = `groups['${failedHere}'] | default([]) | length`;\n tasks.push({\n name: `[${node.key}] max_fail_percentage ${limit} exceeded`,\n 'ansible.builtin.fail': {\n msg: `Flow stopped at [${node.key}]: {{ ${count} }} of {{ ansible_play_hosts_all | length }} hosts failed`,\n },\n when: `(${count}) * 100 > ${limit} * (ansible_play_hosts_all | length)`,\n });\n }\n return tasks;\n }\n\n /**\n * Module hosts that turn unreachable on a node without the port: they bubble to an enclosing\n * subflow's `unreachable` when it has one, else they fail in the outcome play.\n */\n private unreachableNotEnabled(ctx: LevelCtx, node: FlowNode): string {\n const parent = ctx.parent;\n if (parent && unreachableBubbles(parent.node))\n return this.target(parent.ctx, parent.node, 'unreachable');\n const group = this.group(ctx.path, node.key, 'unreachable');\n if (!this.routes[group]) {\n this.routes[group] = { node: node.id, port: 'unreachable' };\n this.outcome.push({\n order: this.order,\n groups: [group],\n name: `[${node.key}] unreachable`,\n msg: `Stopped at [${node.key}] ${jinjaLiteral(oneLine(node.title))}: host unreachable (the unreachable port is not enabled)`,\n });\n }\n return group;\n }\n\n /** Comment in the rescue saying where an open, decided or bubbling fail port leads. */\n private portComment(ctx: LevelCtx, node: FlowNode, port: string): Out[] {\n const target = this.target(ctx, node, port);\n const own = this.group(ctx.path, node.key, port);\n if (target !== own) {\n const r = this.routes[target];\n const owner = r ? this.model.nodes.get(r.node)?.node : undefined;\n return owner ? [comment(`${port} leaves this level as [${owner.key}] ${r?.port}`)] : [];\n }\n if (this.taken(ctx).wired.has(portKey(node.id, port))) return [];\n const decided = !!portAccepted(this.doc, node.id, port);\n return [\n comment(\n decided\n ? `${port} is open on purpose: these hosts stop in the outcome play`\n : `${port} is open: these hosts fail in the outcome play`,\n ),\n ];\n }\n\n private decisionTasks(ctx: LevelCtx, node: FlowNode): Out[] {\n const yes = this.target(ctx, node, 'true');\n const no = this.target(ctx, node, 'false');\n const condition = node.condition?.trim();\n if (!condition || this.opts.stubAll) {\n this.todo = true;\n const choices = this.opts.simulate\n ? [{ test: simIn('false'), group: no, port: 'false' }]\n : [];\n const pick = choose(node, choices, { group: yes, port: 'true' });\n return [\n {\n name: `[${node.key}] TODO`,\n 'ansible.builtin.debug': {\n msg: condition\n ? `Scenario: ${jinjaLiteral(oneLine(node.title))} takes true unless afd_simulate sends a host to false`\n : `TODO: ${jinjaLiteral(oneLine(node.title))} has no condition yet, so every host takes true`,\n },\n },\n pick,\n ];\n }\n const error = this.group(ctx.path, node.key, 'condition_error');\n this.routes[error] = { node: node.id, port: 'condition_error' };\n this.outcome.push({\n order: this.order,\n groups: [error],\n name: `[${node.key}] condition error`,\n msg: `Stopped at [${node.key}] ${jinjaLiteral(oneLine(node.title))}: the condition could not be evaluated`,\n });\n return [\n {\n block: [\n choose(node, [{ test: `not (${conditionExpr(condition)})`, group: no, port: 'false' }], {\n group: yes,\n port: 'true',\n }),\n ],\n rescue: [\n {\n name: `[${node.key}] condition could not be evaluated`,\n 'ansible.builtin.group_by': { key: error },\n },\n ],\n },\n ];\n }\n\n private approvalTasks(ctx: LevelCtx, node: FlowNode, vars: OutMap): Out[] {\n const enabled = new Set(portsFor(node).map((p) => p.name));\n const ports = ['approved', ...['rejected', 'timeout'].filter((p) => enabled.has(p))];\n // A local run approves unless the extra var afd_approvals names another outcome for this\n // approval (AFD-21); AWX workflow runs wait in a real approval node (AFD-11).\n const key = [...ctx.path, node.key].join('/');\n this.approvals.push(key);\n vars.afd_approval = `{{ (afd_approvals | default({}))['${key}'] | default('approved') }}`;\n const pick = 'afd_approval';\n const choices: Choice[] = ports\n .slice(1)\n .map((port) => ({ test: `${pick} == '${port}'`, group: this.target(ctx, node, port), port }));\n if (this.opts.simulate) {\n for (const port of ['rejected', 'timeout'])\n if (enabled.has(port))\n choices.push({ test: simIn(port), group: this.target(ctx, node, port), port });\n }\n return [\n {\n name: `[${node.key}] local approval`,\n 'ansible.builtin.debug': {\n msg: `${jinjaLiteral(oneLine(node.title))}: {{ afd_approval }} in this local run (afd_approvals chooses; AWX workflow runs wait in an approval node)`,\n },\n run_once: true,\n },\n {\n name: `[${node.key}] afd_approvals outcome`,\n 'ansible.builtin.fail': {\n msg: `afd_approvals['${key}'] must be one of ${ports.join(', ')}`,\n },\n when: `${pick} not in [${ports.map((p) => `'${p}'`).join(', ')}]`,\n },\n choose(node, choices, { group: this.target(ctx, node, 'approved'), port: 'approved' }),\n ];\n }\n\n private joinTasks(ctx: LevelCtx, node: FlowNode, edges: Edge[]): Out[] {\n const ok = this.target(ctx, node, 'ok_hosts');\n if (node.join_mode === 'any') return [route(node, 'ok_hosts', ok)];\n const member: string[] = [];\n for (const e of edges) {\n const from = e.to.node === node.id ? this.model.nodes.get(e.from.node)?.node : undefined;\n if (from && from.type !== 'start')\n member.push(\n `inventory_hostname in groups['${this.target(ctx, from, e.from.port)}'] | default([])`,\n );\n }\n const all = member.join(' and ') || 'true';\n if (portsFor(node).some((p) => p.name === 'failed_hosts')) {\n const failed = this.target(ctx, node, 'failed_hosts');\n return [\n choose(node, [{ test: `not (${all})`, group: failed, port: 'failed_hosts' }], {\n group: ok,\n port: 'ok_hosts',\n }),\n ];\n }\n return [{ ...route(node, 'ok_hosts', ok), when: all }];\n }\n\n // ---- outcome and files -------------------------------------------------------------------------\n\n private outcomePlay(): string[] | undefined {\n if (this.outcome.length === 0) return undefined;\n const entries = [...this.outcome].sort((a, b) => a.order - b.order);\n const groups = [...new Set(entries.flatMap((e) => e.groups))];\n const play: OutMap = {\n name: `[${this.doc.flow.key}] Outcome`,\n hosts: groups.join(':'),\n gather_facts: false,\n tags: flow([`flow_${this.doc.flow.id}`]),\n tasks: entries.map((e) => ({\n name: e.name,\n 'ansible.builtin.fail': { msg: e.msg },\n when: e.groups\n .map((g) => `inventory_hostname in groups['${g}'] | default([])`)\n .join(' or '),\n })),\n };\n return [\n '# Hosts left on open ports or failed end nodes fail here, after every branch ran (ADR-0009).',\n ...writeBlock([play], 0),\n ];\n }\n\n /**\n * The Notes on a node as comment text (AFD-66): Markdown made plain, one line per line. Every\n * YAML line break is a split, so no text can end the comment and become code.\n */\n private noteLines(id: Ulid): string[] {\n const level = this.model.levels.get(this.model.nodes.get(id)?.level ?? '');\n const out: string[] = [];\n for (const a of level?.annotations ?? []) {\n if (!a || (a.kind ?? 'note') !== 'note' || a.on !== id) continue;\n const lines = plainText(String(a.text ?? ''))\n .split(LINE_BREAK)\n .map((l) => l.trimEnd())\n .filter((l, i, all) => l !== '' || (i > 0 && i < all.length - 1));\n lines.forEach((l, i) => {\n out.push(i === 0 ? `Note: ${l}` : ` ${l}`.trimEnd());\n });\n }\n return out;\n }\n\n private result(ok: boolean): GenerateResult {\n const eol = this.opts.eol ?? '\\n';\n const files: GeneratedFile[] = [];\n const plays: Record<Ulid, PlayRange> = {};\n if (ok) {\n for (const { ctx, chunks } of this.files) {\n const header = this.header(ctx);\n const body: string[] = [];\n for (const chunk of chunks) {\n body.push('');\n // AFD-66: the Notes on the node, above its code (outside its play range).\n if (chunk.node) body.push(...this.noteLines(chunk.node).map(commentLine));\n const start = header.length + 1 + body.length;\n body.push(...chunk.lines);\n if (chunk.node)\n plays[chunk.node] = { file: ctx.file, start, end: start + chunk.lines.length };\n }\n const bodyText = body.map((l) => `${l}\\n`).join('');\n const lines = [...header, `${CHECKSUM_PREFIX}${checksum(bodyText)}`, ...body];\n files.push({ name: ctx.file, text: lines.join(eol) + eol, level: ctx.level.id });\n }\n }\n const plan: RunPlan | undefined =\n ok && this.planning\n ? {\n ...(this.startInput ? { start: this.startInput } : {}),\n steps: this.steps,\n outcome: [...this.outcome]\n .sort((a, b) => a.order - b.order)\n .map(({ groups, name, msg }) => ({ groups, name, msg })),\n }\n : undefined;\n return {\n ok,\n files,\n findings: this.findings,\n routes: this.routes,\n plays,\n ...(plan ? { plan } : {}),\n };\n }\n\n private header(ctx: LevelCtx): string[] {\n const f = this.doc.flow;\n const level = ctx.parent\n ? `, level [${ctx.parent.node.key}] ${oneLine(ctx.parent.node.title)}`\n : '';\n const lines = [\n commentLine(\n `GENERATED by Ansible Flow Designer from ../${oneLine(this.opts.source)} (flow ${oneLine(String(f.key))}, version ${oneLine(String(f.version))}${level}).`,\n ),\n '# Do not edit by hand: change the flow and save it. Option A engine (ADR-0009).',\n ];\n if (this.segment)\n lines.push(\n commentLine(\n `AWX workflow segment \"${oneLine(this.segment.seg.name)}\" (ADR-0016): the workflow runs it, with the host sets of the segment before it.`,\n ),\n );\n else if (!ctx.parent && this.todo)\n lines.push('# Unbound nodes run TODO messages: run with --check until every node is bound.');\n if (!this.segment && !ctx.parent && this.approvals.length > 0)\n lines.push(\n `# Local runs pass approvals ${this.approvals.map((k) => `[${k}]`).join(', ')} automatically; choose another outcome with -e '{\"afd_approvals\": {\"${this.approvals[0]}\": \"rejected\"}}'.`,\n );\n if (this.opts.simulate)\n lines.push('# SIMULATION build: afd_simulate sends chosen hosts down other ports.');\n if (this.opts.stubAll)\n lines.push('# SCENARIO build: every step runs as its stub; no binding runs (AFD-58).');\n return lines;\n }\n\n private finding(\n code: string,\n severity: Finding['severity'],\n message: string,\n path: Finding['path'],\n node?: Ulid,\n ): void {\n this.findings.push({ code, severity, message, path, node });\n }\n}\n\n/** Kahn's algorithm; ties keep document order. Undefined when the level has a cycle. */\nfunction topoOrder(nodes: FlowNode[], edges: Edge[]): FlowNode[] | undefined {\n const index = new Map(nodes.map((n, i) => [n.id, i]));\n const indegree = new Map(nodes.map((n) => [n.id, 0]));\n for (const e of edges) indegree.set(e.to.node, (indegree.get(e.to.node) ?? 0) + 1);\n const ready = nodes.filter((n) => indegree.get(n.id) === 0);\n const out: FlowNode[] = [];\n while (ready.length > 0) {\n ready.sort((a, b) => (index.get(a.id) ?? 0) - (index.get(b.id) ?? 0));\n const n = ready.shift() as FlowNode;\n out.push(n);\n for (const e of edges) {\n if (e.from.node !== n.id) continue;\n const left = (indegree.get(e.to.node) ?? 0) - 1;\n indegree.set(e.to.node, left);\n if (left === 0) ready.push(nodes[index.get(e.to.node) ?? 0] as FlowNode);\n }\n }\n return out.length === nodes.length ? out : undefined;\n}\n\nfunction simIn(port: string): string {\n return `inventory_hostname in afd_sim.${port} | default([])`;\n}\n\ninterface Choice {\n test: string;\n group: string;\n port: string;\n}\n\n/** AFD-186: what a step's rescue keeps of a failure, as host facts later plays can read. */\nconst FAILURE_FACTS = ['afd_failed_result', 'afd_failed_task', 'afd_failed_node'] as const;\n\n/**\n * The failure as host facts (AFD-186): every step is its own play, so the step its failed_hosts\n * lead to cannot see ansible_failed_result. Written after the routing, and never fails the rescue.\n */\nfunction failureRecord(node: FlowNode, keyPath: string): OutMap {\n return {\n name: `[${node.key}] keep the failure`,\n 'ansible.builtin.set_fact': {\n afd_failed_result: '{{ ansible_failed_result | default({}) }}',\n afd_failed_task: \"{{ ansible_failed_task.name | default('') }}\",\n afd_failed_node: keyPath,\n },\n ignore_errors: true,\n };\n}\n\nfunction route(node: FlowNode, port: string, group: string): OutMap {\n return { name: `[${node.key}] route ${port}`, 'ansible.builtin.group_by': { key: group } };\n}\n\n/** A group_by whose key picks the first matching choice, else the fallback port's group. */\nfunction choose(\n node: FlowNode,\n choices: Choice[],\n fallback: { group: string; port: string },\n): OutMap {\n if (choices.length === 0) return route(node, fallback.port, fallback.group);\n const expr = choices.reduceRight(\n (rest, c) => `'${c.group}' if ${c.test} else ${rest}`,\n `'${fallback.group}'`,\n );\n const ports = [fallback.port, ...choices.map((c) => c.port)];\n return {\n name: `[${node.key}] route ${[...new Set(ports)].join(', ')}`,\n 'ansible.builtin.group_by': { key: `{{ ${expr} }}` },\n };\n}\n\nexport const optionA: Engine = {\n id: 'option-a',\n generate: (asWritten, options) => {\n // AFD-242: disabled nodes are not generated; the path closes over them (engine/bypass).\n const doc = withoutDisabled(asWritten);\n const whole = new Generator(doc, options);\n const result = whole.run();\n if (!result.ok) return result;\n const plan = planSegments(buildModel(doc));\n if (!plan) return result;\n if (plan.problems.length > 0 || plan.segments.length === 0)\n return {\n ...result,\n findings: [\n ...result.findings,\n ...plan.problems.map((p) => ({\n code: 'codegen-segments',\n severity: 'warning' as const,\n message: `${p.message}; local and skeleton runs approve automatically`,\n path: [],\n node: p.node,\n })),\n ],\n };\n const outcome = whole.outcomeEntries();\n const files = [...result.files];\n const segments: SegmentFile[] = [];\n for (const seg of plan.segments) {\n const r = new Generator(doc, options, { seg, outcome }).segmentRun();\n const file = r.files[0];\n if (!r.ok || !file) return { ...result, findings: [...result.findings, ...r.findings] };\n files.push(file);\n segments.push({\n name: seg.name,\n file: file.name,\n gate: seg.gate,\n entry: seg.entry,\n parent: seg.parent,\n finish: seg.finish,\n });\n }\n return { ...result, files, segments };\n },\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../src/core/view/route.ts"],
|
|
4
|
-
"sourcesContent": ["// Wires that step round nodes (AFD-70). A wire is React Flow's smooth step from port to port, as\n// before, wherever that clears every node box. Where it would run through one (a wire that skips a\n// step, or one back up the flow), it takes an orthogonal route round the boxes instead: short, few\n// turns, clear of the boxes, drawn with the same stubs and rounded corners. The canvas edge, the\n// export scenes and the layout check all route here, so every picture of a level shows the same\n// wires.\nimport { getSmoothStepPath, Position as Side } from '@xyflow/system';\nimport type { Position } from '../flow/types';\n\nexport interface Box {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface Route {\n /** SVG path in canvas pixels. */\n path: string;\n /** Where the wire's label sits. */\n label: Position;\n /** A route round boxes: its corners between the two ends (draw.io waypoints). */\n bends?: Position[];\n}\n\n/** getSmoothStepPath's defaults: the stub out of a port and the corner radius. */\nconst OFFSET = 20;\nconst RADIUS = 5;\n/** A wire that only grazes a box edge is not through it: boxes shrink by this much first. */\nexport const INSET = 2;\n/** Routes keep as far from a box as a stub keeps from its node (handle face 5 + stub 20)... */\nconst CLEAR = 25;\n/** ...and, in a narrow gap, never come closer than this. */\nconst GAP = 8;\n/** A bend costs as much as this much more wire... */\nconst BEND = 40;\n/** ...and wire closer to a box than CLEAR costs this much more again... */\nconst NEAR = 1;\n/**\n * ...and wire off the two lines through its stub ends a little more, so of equal routes it takes\n * the one that turns onto its stubs: wires into one port then share their last stretch.\n */\nconst DRIFT = 0.01;\n\n/** Directions of travel, clockwise from up; a port's side is the way its stub leaves. */\nconst DIRS: Position[] = [\n { x: 0, y: -1 },\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: -1, y: 0 },\n];\nconst DIR_OF: Record<Side, number> = {\n [Side.Top]: 0,\n [Side.Right]: 1,\n [Side.Bottom]: 2,\n [Side.Left]: 3,\n};\n\n// ---- geometry shared with the layout check ------------------------------------------------------\n\n/** The corners a stepped path passes: its M, L and Q points in order (Q's control is a corner). */\nexport function pointsOf(path: string): Position[] {\n const n = path.match(/-?\\d+(\\.\\d+)?(e-?\\d+)?/g)?.map(Number) ?? [];\n const out: Position[] = [];\n for (let i = 0; i + 1 < n.length; i += 2) out.push({ x: n[i] as number, y: n[i + 1] as number });\n return out;\n}\n\nexport const overlaps = (a: Box, b: Box) =>\n a.x < b.x + b.width && b.x < a.x + a.width && a.y < b.y + b.height && b.y < a.y + a.height;\n\n/** The box shrunk by `by` on every side (grown when negative). */\nexport const inset = (b: Box, by: number): Box => ({\n x: b.x + by,\n y: b.y + by,\n width: Math.max(0, b.width - 2 * by),\n height: Math.max(0, b.height - 2 * by),\n});\n\n/** Whether segment a\u2013b passes through the box (Liang\u2013Barsky clipping). */\nexport function segmentHits(a: Position, b: Position, r: Box): boolean {\n let t0 = 0;\n let t1 = 1;\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const edges: [number, number][] = [\n [-dx, a.x - r.x],\n [dx, r.x + r.width - a.x],\n [-dy, a.y - r.y],\n [dy, r.y + r.height - a.y],\n ];\n for (const [p, q] of edges) {\n if (p === 0) {\n if (q < 0) return false;\n continue;\n }\n const t = q / p;\n if (p < 0) t0 = Math.max(t0, t);\n else t1 = Math.min(t1, t);\n if (t0 > t1) return false;\n }\n return true;\n}\n\n/** Whether a polyline runs through any of the boxes. */\nexport function runsThrough(points: Position[], boxes: readonly Box[]): boolean {\n for (const box of boxes) {\n const r = inset(box, INSET);\n for (let i = 0; i + 1 < points.length; i++)\n if (segmentHits(points[i] as Position, points[i + 1] as Position, r)) return true;\n }\n return false;\n}\n\n/** A wire label as the canvas draws it: 10 px mono text (6 px a character) on a padded background. */\nexport function labelBox(text: string, at: Position): Box {\n const w = [...text].length * 6 + 8;\n return { x: at.x - w / 2, y: at.y - 8, width: w, height: 16 };\n}\n\n// ---- routing ------------------------------------------------------------------------------------\n\n/**\n * The wire from `a` (leaving by side `from`) to `b` (entered by side `to`) among the node boxes of\n * its level, its own two included. `label` is the text it shows, kept off the boxes on a route.\n */\nexport function routeWire(\n a: Position,\n from: Side,\n b: Position,\n to: Side,\n boxes: readonly Box[],\n label?: string,\n): Route {\n const [path, x, y] = getSmoothStepPath({\n sourceX: a.x,\n sourceY: a.y,\n sourcePosition: from,\n targetX: b.x,\n targetY: b.y,\n targetPosition: to,\n });\n const step = { path, label: { x, y } };\n if (!runsThrough(pointsOf(path), boxes)) return step;\n // Boxed in (a node on a port, or no gap wide enough): the smooth step, as before.\n const points = roundBoxes(a, DIR_OF[from], b, DIR_OF[to], boxes);\n if (!points) return step;\n return { path: pathOf(points), label: labelOn(points, boxes, label), bends: points.slice(1, -1) };\n}\n\n/** Grid lines: the stub ends, the lines CLEAR off each box edge, and the middle of a gap too narrow for those. */\nfunction lines(s: number, t: number, edges: [number, number][]): number[] {\n const all = edges.flat().sort((p, q) => p - q);\n const out = [s, t];\n for (const [lo, hi] of edges) out.push(lo - CLEAR, hi + CLEAR);\n for (let i = 0; i + 1 < all.length; i++) {\n const gap = (all[i + 1] as number) - (all[i] as number);\n if (gap > 2 * GAP && gap < 2 * CLEAR)\n out.push(((all[i] as number) + (all[i + 1] as number)) / 2);\n }\n return [...new Set(out)].sort((p, q) => p - q);\n}\n\n/**\n * The route's corners, from `a` to `b`, keeping the smooth step's stubs: it leaves the source stub\n * heading out and enters the target stub heading in. Nodes far off the two ends are left out of\n * the search; when that finds nothing, it runs again with every node.\n */\nfunction roundBoxes(\n a: Position,\n from: number,\n b: Position,\n to: number,\n boxes: readonly Box[],\n): Position[] | undefined {\n const out = DIRS[from] as Position;\n const back = DIRS[to] as Position;\n const s = { x: a.x + out.x * OFFSET, y: a.y + out.y * OFFSET };\n const t = { x: b.x + back.x * OFFSET, y: b.y + back.y * OFFSET };\n if (runsThrough([a, s], boxes) || runsThrough([t, b], boxes)) return undefined;\n for (const reach of [REACH, Number.POSITIVE_INFINITY]) {\n const near = nearby(s, t, boxes, reach);\n const found = search(s, from, t, (to + 2) % 4, near);\n if (found) return corners([a, ...found, b]);\n if (near.length === boxes.length) break;\n }\n return undefined;\n}\n\n/** How far round the two ends a first search looks: about two node widths. */\nconst REACH = 400;\n\n/**\n * The boxes within `reach` of the box spanning s and t, and then every box the search grid they\n * make would reach, so a grid segment can never jump a box it does not know.\n */\nfunction nearby(s: Position, t: Position, boxes: readonly Box[], reach: number): readonly Box[] {\n if (!Number.isFinite(reach)) return boxes;\n const span = (pts: Position[], pad: number): Box => {\n const xs = pts.map((p) => p.x);\n const ys = pts.map((p) => p.y);\n const [x, y] = [Math.min(...xs) - pad, Math.min(...ys) - pad];\n return { x, y, width: Math.max(...xs) + pad - x, height: Math.max(...ys) + pad - y };\n };\n let near = boxes.filter((r) => overlaps(r, span([s, t], reach)));\n for (;;) {\n const grid = span(\n [s, t, ...near.flatMap((r) => [r, { x: r.x + r.width, y: r.y + r.height }])],\n CLEAR + GAP,\n );\n const more = boxes.filter((r) => near.includes(r) || overlaps(r, grid));\n if (more.length === near.length) return near;\n near = more;\n }\n}\n\n/**\n * A* over a grid of lines in (point, direction) states: cost is length (more near a box) plus\n * BEND a turn, and no U-turns. A stretch into a box is not taken. From s heading `from` to t heading `into`; the grid points passed.\n */\nfunction search(\n s: Position,\n from: number,\n t: Position,\n into: number,\n boxes: readonly Box[],\n): Position[] | undefined {\n const xs = lines(\n s.x,\n t.x,\n boxes.map((r) => [r.x, r.x + r.width]),\n );\n const ys = lines(\n s.y,\n t.y,\n boxes.map((r) => [r.y, r.y + r.height]),\n );\n const nx = xs.length;\n const ny = ys.length;\n // Per stretch between neighbouring grid points, across (i,j)-(i+1,j) and down (i,j)-(i,j+1):\n // -1 when it enters a box grown by GAP, else how much of it runs closer to a box than CLEAR.\n const across = new Float32Array(nx * ny);\n const down = new Float32Array(nx * ny);\n const mark = (\n to: Float32Array,\n k: number,\n lo: number,\n hi: number,\n g0: number,\n g1: number,\n c0: number,\n c1: number,\n inside: boolean,\n ) => {\n if (hi <= c0 || lo >= c1 || (to[k] as number) < 0) return;\n if (inside && hi > g0 && lo < g1) to[k] = -1;\n else to[k] = Math.max(to[k] as number, Math.min(hi, c1) - Math.max(lo, c0));\n };\n for (const r of boxes) {\n const [gx0, gx1, gy0, gy1] = [r.x - GAP, r.x + r.width + GAP, r.y - GAP, r.y + r.height + GAP];\n const [cx0, cx1, cy0, cy1] = [\n r.x - CLEAR,\n r.x + r.width + CLEAR,\n r.y - CLEAR,\n r.y + r.height + CLEAR,\n ];\n for (let j = 0; j < ny; j++) {\n const y = ys[j] as number;\n if (y <= cy0 || y >= cy1) continue;\n for (let i = 0; i + 1 < nx; i++)\n mark(\n across,\n i * ny + j,\n xs[i] as number,\n xs[i + 1] as number,\n gx0,\n gx1,\n cx0,\n cx1,\n y > gy0 && y < gy1,\n );\n }\n for (let i = 0; i < nx; i++) {\n const x = xs[i] as number;\n if (x <= cx0 || x >= cx1) continue;\n for (let j = 0; j + 1 < ny; j++)\n mark(\n down,\n i * ny + j,\n ys[j] as number,\n ys[j + 1] as number,\n gy0,\n gy1,\n cy0,\n cy1,\n x > gx0 && x < gx1,\n );\n }\n }\n const inBox = (p: Position) =>\n boxes.some(\n (r) =>\n p.x > r.x - GAP &&\n p.x < r.x + r.width + GAP &&\n p.y > r.y - GAP &&\n p.y < r.y + r.height + GAP,\n );\n if (inBox(s) || inBox(t)) return undefined;\n const si = xs.indexOf(s.x);\n const sj = ys.indexOf(s.y);\n const ti = xs.indexOf(t.x);\n const tj = ys.indexOf(t.y);\n const states = nx * ny * 4;\n const cost = new Float64Array(states).fill(Number.POSITIVE_INFINITY);\n const prev = new Int32Array(states).fill(-1);\n // Distance left, plus the turns any route from here must still make (a lower bound, so A*\n // stays exact): none straight ahead in the right heading, one from a heading across it, else two.\n // At t itself none: the step onto t paid for its last turn.\n const h = (i: number, j: number, d: number) => {\n const dx = t.x - (xs[i] as number);\n const dy = t.y - (ys[j] as number);\n if (dx === 0 && dy === 0) return 0;\n const step = DIRS[d] as Position;\n const turns =\n d === into\n ? dx * step.y === dy * step.x && dx * step.x + dy * step.y >= 0\n ? 0\n : 2\n : d === (into + 2) % 4\n ? 2\n : 1;\n return Math.abs(dx) + Math.abs(dy) + turns * BEND;\n };\n const heap = new Heap();\n const start = (si * ny + sj) * 4 + from;\n cost[start] = 0;\n heap.push(h(si, sj, from), 0, start);\n let goal = -1;\n while (heap.size > 0) {\n const { key: f, value: k } = heap.pop();\n const d = k % 4;\n const p = (k - d) / 4;\n const i = Math.floor(p / ny);\n const j = p % ny;\n if (f > (cost[k] as number) + h(i, j, d)) continue;\n if (i === ti && j === tj) {\n goal = k;\n break;\n }\n for (let nd = 0; nd < 4; nd++) {\n if (nd === (d + 2) % 4) continue;\n const step = DIRS[nd] as Position;\n const ni = i + step.x;\n const nj = j + step.y;\n if (ni < 0 || nj < 0 || ni >= nx || nj >= ny) continue;\n const flat = nd % 2 === 1;\n const near = flat\n ? (across[Math.min(i, ni) * ny + j] as number)\n : (down[i * ny + Math.min(j, nj)] as number);\n if (near < 0) continue;\n const x = xs[i] as number;\n const y = ys[j] as number;\n const len = flat ? Math.abs((xs[ni] as number) - x) : Math.abs((ys[nj] as number) - y);\n const stub = flat ? y === s.y || y === t.y : x === s.x || x === t.x;\n let c =\n (cost[k] as number) + len * (stub ? 1 : 1 + DRIFT) + near * NEAR + (nd === d ? 0 : BEND);\n const nk = (ni * ny + nj) * 4 + nd;\n if (ni === ti && nj === tj) {\n if (nd === (into + 2) % 4) continue;\n if (nd !== into) c += BEND;\n }\n if (c < (cost[nk] as number)) {\n cost[nk] = c;\n prev[nk] = k;\n heap.push(c + h(ni, nj, nd), c, nk);\n }\n }\n }\n if (goal < 0) return undefined;\n const path: Position[] = [];\n for (let k = goal; k >= 0; k = prev[k] as number) {\n const p = (k - (k % 4)) / 4;\n path.push({ x: xs[Math.floor(p / ny)] as number, y: ys[p % ny] as number });\n }\n return path.reverse();\n}\n\n/** The points where the route turns, with its two ends. */\nfunction corners(points: Position[]): Position[] {\n const out: Position[] = [];\n for (const p of points) {\n const q = out.at(-1);\n if (q && q.x === p.x && q.y === p.y) continue;\n const o = out.at(-2);\n if (o && q && ((o.x === q.x && q.x === p.x) || (o.y === q.y && q.y === p.y))) out.pop();\n out.push(p);\n }\n return out;\n}\n\n/** The route as getSmoothStepPath draws its own points: rounded corners of radius RADIUS. */\nfunction pathOf(points: Position[]): string {\n const first = points[0] as Position;\n const last = points.at(-1) as Position;\n let path = `M${first.x} ${first.y}`;\n for (let i = 1; i < points.length - 1; i++)\n path += bendAt(points[i - 1] as Position, points[i] as Position, points[i + 1] as Position);\n return `${path}L${last.x} ${last.y}`;\n}\n\n/** @xyflow/system's getBend (not exported), so a route's corners match a smooth step's. */\nfunction bendAt(a: Position, b: Position, c: Position): string {\n const size = Math.min(\n Math.hypot(a.x - b.x, a.y - b.y) / 2,\n Math.hypot(b.x - c.x, b.y - c.y) / 2,\n RADIUS,\n );\n const { x, y } = b;\n if ((a.x === x && x === c.x) || (a.y === y && y === c.y)) return `L${x} ${y}`;\n if (a.y === y) {\n const xDir = a.x < c.x ? -1 : 1;\n const yDir = a.y < c.y ? 1 : -1;\n return `L ${x + size * xDir},${y}Q ${x},${y} ${x},${y + size * yDir}`;\n }\n const xDir = a.x < c.x ? 1 : -1;\n const yDir = a.y < c.y ? -1 : 1;\n return `L ${x},${y + size * yDir}Q ${x},${y} ${x + size * xDir},${y}`;\n}\n\n/** Length of a straight stretch. */\nconst length = (p: Position, q: Position) => Math.abs(q.x - p.x) + Math.abs(q.y - p.y);\n\n/**\n * Where a route's label goes: on the first stretch from the source that holds it clear of every\n * box, as near that stretch's middle as it can, so a label names the port its wire leaves by.\n * Without a clear spot, half way along.\n */\nfunction labelOn(points: Position[], boxes: readonly Box[], text: string | undefined): Position {\n for (let i = 0; text && i + 1 < points.length; i++) {\n const p = points[i] as Position;\n const q = points[i + 1] as Position;\n const len = length(p, q);\n const along = p.y === q.y ? labelBox(text, p).width : 16;\n const room = (len - along - 8) / 2;\n const ux = Math.sign(q.x - p.x);\n const uy = Math.sign(q.y - p.y);\n for (let k = 0; k <= room; k += 8)\n for (const sign of k ? [-1, 1] : [1]) {\n const o = len / 2 + sign * k;\n const at = { x: p.x + ux * o, y: p.y + uy * o };\n const box = labelBox(text, at);\n if (!boxes.some((r) => overlaps(box, r))) return at;\n }\n }\n const legs = points.slice(1).map((q, i) => length(points[i] as Position, q));\n let rest = legs.reduce((sum, len) => sum + len, 0) / 2;\n for (let i = 0; i + 1 < points.length; i++) {\n const p = points[i] as Position;\n const q = points[i + 1] as Position;\n const len = legs[i] as number;\n if (rest <= len)\n return { x: p.x + Math.sign(q.x - p.x) * rest, y: p.y + Math.sign(q.y - p.y) * rest };\n rest -= len;\n }\n return points[0] as Position;\n}\n\n/**\n * A binary min-heap of states by priority. Of equal priorities the one furthest along goes first\n * (else A* widens over every equally short path on a grid), then the first pushed, so a route is\n * the same wherever it is drawn. The heap holds entry numbers; an entry's fields are stored once.\n */\nclass Heap {\n private heap: number[] = [];\n private keys: number[] = [];\n private depths: number[] = [];\n private values: number[] = [];\n\n get size(): number {\n return this.heap.length;\n }\n\n push(key: number, depth: number, value: number): void {\n const e = this.keys.length;\n this.keys.push(key);\n this.depths.push(depth);\n this.values.push(value);\n const h = this.heap;\n let i = h.length;\n h.push(e);\n while (i > 0) {\n const up = (i - 1) >> 1;\n if (!this.before(e, h[up] as number)) break;\n h[i] = h[up] as number;\n i = up;\n }\n h[i] = e;\n }\n\n /** Takes the first entry off: its priority and value. */\n pop(): { key: number; value: number } {\n const h = this.heap;\n const top = h[0] as number;\n const last = h.pop() as number;\n if (h.length > 0) {\n let i = 0;\n for (;;) {\n const l = 2 * i + 1;\n if (l >= h.length) break;\n const r = l + 1;\n const c = r < h.length && this.before(h[r] as number, h[l] as number) ? r : l;\n if (!this.before(h[c] as number, last)) break;\n h[i] = h[c] as number;\n i = c;\n }\n h[i] = last;\n }\n return { key: this.keys[top] as number, value: this.values[top] as number };\n }\n\n private before(a: number, b: number): boolean {\n const ka = this.keys[a] as number;\n const kb = this.keys[b] as number;\n if (ka !== kb) return ka < kb;\n const da = this.depths[a] as number;\n const db = this.depths[b] as number;\n return da !== db ? da > db : a < b;\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["xDir", "yDir"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../src/core/engine/binding.ts"],
|
|
4
|
-
"sourcesContent": ["// What a bound node runs and how data reaches it (M5, ADR-0011): the module task or include_role\n// Option A emits, the play vars that pass upstream outputs in as node inputs, and set_fact\n// placeholders that let an unbound node's outputs flow through a skeleton run.\n\nimport { outputVar, registerName } from '../flow/dataNames';\nimport { resolveFrom } from '../flow/dataRefs';\nimport { ROLE_TASK_KEYWORDS, WITH } from '../flow/keywords';\nimport type { FlowModel } from '../flow/model';\nimport type { ContractType, FlowNode, ImplBinding } from '../flow/types';\nimport { jinjaLiteral } from './util';\nimport { flow, type Out, type OutMap, oneLine, writeBlock } from './yamlWriter';\n\n/** include_role options; every other role param becomes a role var. */\nexport const INCLUDE_OPTIONS = new Set([\n 'tasks_from',\n 'vars_from',\n 'defaults_from',\n 'handlers_from',\n 'public',\n 'allow_duplicates',\n 'rolespec_validate',\n]);\n\n/** Keywords ansible-core accepts on include_tasks itself; the others go into its apply. */\nconst INCLUDE_TASK_KEYWORDS: ReadonlySet<string> = new Set([\n 'when',\n 'loop',\n 'loop_control',\n 'vars',\n 'ignore_errors',\n 'no_log',\n 'run_once',\n 'debugger',\n]);\n\n/** A binding that runs a task file at run time (its tasks are not known to the flow). */\nexport function isIncludeTasks(ref: string | undefined): boolean {\n return /^(ansible\\.(builtin|legacy)\\.)?include_tasks$/.test(ref ?? '');\n}\n\n/** The module task or include_role of a bound node (without Option A's routing around it). */\nexport function bindingTask(node: FlowNode, impl: ImplBinding, timeout?: number | string): OutMap {\n const tag = `node_${node.id}`;\n const keywords = Object.entries(impl.keywords ?? {});\n if (impl.kind === 'role') {\n const options: OutMap = { name: impl.ref };\n const roleVars: OutMap = {};\n for (const [k, v] of Object.entries(impl.params ?? {}))\n (INCLUDE_OPTIONS.has(k) ? options : roleVars)[k] = v as Out;\n // Task keywords (AFD-26): conditions and loops stay on include_role; the rest reach every task\n // of the role through apply, as a static roles: entry would. Role variables live in params.\n const onTask: OutMap = {};\n const applied: OutMap = {};\n for (const [k, v] of keywords) {\n if (k === 'vars') continue;\n (ROLE_TASK_KEYWORDS.has(k) || WITH.test(k) ? onTask : applied)[k] = v as Out;\n }\n options.apply = { tags: flow([tag]), timeout, ...applied };\n return {\n name: `[${node.key}] Apply role`,\n 'ansible.builtin.include_role': options,\n ...onTask,\n vars: Object.keys(roleVars).length > 0 ? roleVars : undefined,\n };\n }\n const reg = registerName(node, impl);\n if (isIncludeTasks(impl.ref)) {\n // AFD-179: ansible-core refuses keywords outside its include list on include_tasks (no\n // ignore_unreachable, retries or until). Conditions, loops and vars stay on the include; the\n // rest reach every included task through apply, with the node's tag, as for a role.\n const onTask: OutMap = {};\n const applied: OutMap = {};\n for (const [k, v] of keywords)\n (INCLUDE_TASK_KEYWORDS.has(k) || WITH.test(k) ? onTask : applied)[k] = v as Out;\n const params = typeof impl.params === 'string' ? { file: impl.params } : (impl.params ?? {});\n return {\n name: `[${node.key}] ${jinjaLiteral(oneLine(node.title))}`,\n [impl.ref]: { ...(params as OutMap), apply: { tags: flow([tag]), timeout, ...applied } },\n ...onTask,\n register: reg,\n };\n }\n const { retries, delay, until } = node.settings ?? {};\n // A polling step stops when `until` holds (AFD-21); plain retries stop on the first success.\n const condition = until?.trim() || (retries ? `${reg} is succeeded` : undefined);\n return {\n name: `[${node.key}] ${jinjaLiteral(oneLine(node.title))}`,\n [impl.ref]: (impl.params ?? {}) as Out,\n ...(Object.fromEntries(keywords) as OutMap),\n register: reg,\n ignore_unreachable: true,\n timeout,\n retries,\n delay: condition ? delay : undefined,\n until: condition,\n };\n}\n\n/** The generated task as text, for the properties view (\"Generated task\", mockup 11). */\nexport function bindingTaskText(node: FlowNode, impl: ImplBinding): string {\n if (impl.kind === 'playbook')\n return writeBlock(\n [{ import_playbook: impl.ref, vars: { afd_hosts: '<hosts arriving here>' } }],\n 0,\n ).join('\\n');\n const task = bindingTask(node, impl);\n if (impl.kind === 'module') {\n // The preview shows what the user configured; Option A adds ignore_unreachable for routing.\n delete task.ignore_unreachable;\n task.tags = flow([`node_${node.id}`]);\n }\n return writeBlock([task], 0).join('\\n');\n}\n\n/**\n * The expression a `from:` reads, and whether it is a host variable of the producing host (an\n * output) rather than an extra var. Inside a subflow, `<subflow>.<input>` follows the subflow's\n * input to where it comes from (AFD-21); an input without `from` is read by its own name.\n */\nexport function sourceExpr(\n model: FlowModel,\n node: FlowNode,\n level: string,\n from: string,\n depth = 0,\n): { expr: string; host: boolean } | undefined {\n const src = resolveFrom(model, node, level, 'inputs', from);\n switch (src.kind) {\n case 'flow':\n return { expr: [src.name, ...src.path].join('.'), host: false };\n case 'output':\n return src.name\n ? { expr: [outputVar(model, src.node, src.name), ...src.path].join('.'), host: true }\n : undefined;\n case 'subflowInput': {\n const up = src.field.from?.trim();\n const at = model.nodes.get(src.node.id)?.level;\n const inner =\n up && at && depth < 16 ? sourceExpr(model, src.node, at, up, depth + 1) : undefined;\n if (!inner) return { expr: [src.name, ...src.path].join('.'), host: false };\n return { expr: [inner.expr, ...src.path].join('.'), host: inner.host };\n }\n case 'unresolved': {\n // The validator reports it; the code reads the name, as it did before AFD-21.\n const [head, name = '', ...path] = from.split('.');\n if (src.target && name)\n return { expr: [outputVar(model, src.target, name), ...path].join('.'), host: true };\n return head === 'flow' && name ? { expr: [name, ...path].join('.'), host: false } : undefined;\n }\n default:\n return undefined;\n }\n}\n\n/**\n * Play vars for a node's inputs (05 \u00A74): `from: <key>.<output>[.path]` reads the upstream node's\n * output variable (hostvars persist across plays and imported levels in one run), `from:\n * flow.<input>` reads the extra var. Same-name references need no var (and `x: \"{{ x }}\"` would\n * recurse). `via` reads upstream outputs from another host's hostvars: a node that runs on its\n * inventory_target reads them from the first arriving host (AFD-14).\n */\nexport function inputVars(model: FlowModel, level: string, node: FlowNode, via?: string): OutMap {\n const vars: OutMap = {};\n for (const [name, field] of Object.entries(node.inputs ?? {})) {\n const from = field?.from?.trim();\n // AFD-187: an input's default is what the step gets when its source left nothing; before, the\n // checker counted it as fed while the code never saw it.\n const fallback = field?.default;\n if (!from) {\n if (fallback !== undefined) vars[name] = fallback as Out;\n continue;\n }\n const src = sourceExpr(model, node, level, from);\n const expr = src && (src.host && via ? `${via}.${src.expr}` : src.expr);\n if (!expr || expr === name) continue;\n vars[name] =\n fallback === undefined ? `{{ ${expr} }}` : `{{ ${expr} | default(${jinjaValue(fallback)}) }}`;\n }\n return vars;\n}\n\n/** A YAML value as a Jinja literal: strings quoted, null as none, lists and dicts element-wise. */\nexport function jinjaValue(value: unknown): string {\n if (value === null || value === undefined) return 'none';\n if (typeof value === 'string')\n return `'${value.replaceAll('\\\\', '\\\\\\\\').replaceAll(\"'\", \"\\\\'\")}'`;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n if (Array.isArray(value)) return `[${value.map(jinjaValue).join(', ')}]`;\n if (typeof value === 'object')\n return `{${Object.entries(value as Record<string, unknown>)\n .map(([k, v]) => `${jinjaValue(k)}: ${jinjaValue(v)}`)\n .join(', ')}}`;\n return 'none';\n}\n\nconst PLACEHOLDER: Record<ContractType, Out> = {\n string: 'TODO',\n integer: 0,\n boolean: false,\n list: [],\n dict: {},\n host_list: [],\n any: 'TODO',\n};\n\n/** set_fact placeholders for the outputs of an unbound node, so downstream inputs resolve. */\nexport function stubFacts(node: FlowNode): OutMap | undefined {\n const outputs = Object.entries(node.outputs ?? {});\n if (outputs.length === 0) return undefined;\n const facts: OutMap = {};\n for (const [name, field] of outputs) {\n const value = field?.default ?? PLACEHOLDER[field?.type ?? 'any'] ?? 'TODO';\n facts[name] = value as Out;\n }\n return { name: `[${node.key}] TODO outputs`, 'ansible.builtin.set_fact': facts };\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../src/core/import/source.ts"],
|
|
4
|
-
"sourcesContent": ["// Playbooks, task files and roles as import sources (AFD-26): one normalized tree per playbook.\n// Tasks take their module and arguments apart (action:, local_action:, free-form and k=v forms),\n// inherit their play's and blocks' keywords as Ansible does, and literal includes and imports are\n// read in. What a flow cannot hold is listed per item, so the mapper can say so.\n// Ansible's own loader (the probe, ADR-0012) needs an environment, flattens blocks and drops\n// arguments, conditions and loops; this reader works anywhere and keeps them.\nimport { templated } from '../flow/jinja';\nimport { isAllowedKeyword } from '../flow/keywords';\nimport { builtinFqcn, shortName } from './builtins';\nimport {\n type AnsibleConfig,\n basename,\n dirname,\n exists,\n isMapping,\n isTemplated,\n isVaultFile,\n join,\n lineOf,\n normalize,\n type Plain,\n type PlainMap,\n parseAnsible,\n parseConfig,\n type SourceIO,\n toValue,\n} from './read';\n\nexport interface Origin {\n path: string;\n line?: number;\n}\n\nexport interface TaskForm {\n kind: 'task';\n name: string;\n /** As written (`copy`, `cisco.ios.ios_config`). */\n module: string;\n /** Fully qualified when known. */\n fqcn?: string;\n params: Record<string, unknown>;\n /** Task keywords a binding carries (impl.keywords), inherited ones included. */\n keywords: Record<string, unknown>;\n register?: string;\n notify: string[];\n /** Handlers: the topics they listen to besides their name. */\n listen: string[];\n tags: string[];\n become?: boolean;\n /** Whole seconds, or a template given at run time (AFD-112). */\n timeout?: number | string;\n retries?: number | string;\n delay?: number | string;\n until?: string;\n ignoreUnreachable?: boolean;\n /** Keywords with no place in a flow. */\n dropped: string[];\n /** Local files the task reads (template src, ...): where Ansible finds them, or missing. */\n files: LocalFile[];\n origin: Origin;\n}\n\nexport interface LocalFile {\n /** The parameter, or `cmd` for a script's first word. */\n param: string;\n written: string;\n /** Repository path, when found. */\n path?: string;\n}\n\nexport interface VarsFile {\n file: string;\n path?: string;\n /** Top-level variable names in it (none when encrypted or missing). */\n keys: string[];\n}\n\nexport interface BlockForm {\n kind: 'block';\n name: string;\n items: Item[];\n rescue: Item[];\n always: Item[];\n origin: Origin;\n}\n\nexport interface IncludeForm {\n kind: 'include';\n name: string;\n /** The file as written. */\n file: string;\n /** Read in: the file's items (a literal path that exists). */\n path?: string;\n items?: Item[];\n /** Why it is not read in (a templated path, a loop, missing). */\n dynamic?: string;\n /**\n * AFD-149: an include_tasks' own `when`, which Ansible checks once for the include (not on each\n * task in the file, as for import_tasks). Its parts are ANDed.\n */\n when?: unknown[];\n keywords: Record<string, unknown>;\n tags: string[];\n /** AFD-187: the include's own vars (they also reach every task read in). */\n vars?: Record<string, unknown>;\n /**\n * AFD-177: what keeps a file that runs as include_tasks from working in generated/ (it reads\n * playbook_dir, or includes files found only next to the playbook).\n */\n portability?: string[];\n origin: Origin;\n}\n\n/** A task file of a split role: one step per file (decision 2). */\nexport interface RoleStep {\n /** include_role tasks_from: the file under tasks/ without its extension. */\n tasksFrom: string;\n name: string;\n keywords: Record<string, unknown>;\n tags: string[];\n}\n\nexport interface RoleForm {\n kind: 'role';\n name: string;\n /** What include_role names: the role name, or an FQCN for a collection role. */\n ref: string;\n /** Folder of the role, when found. */\n dir?: string;\n /** Whether generated plays find it (roles_path of the repository's ansible.cfg, collections). */\n onRolesPath: boolean;\n /** Role variables and include options (tasks_from, vars_from, ...). */\n params: Record<string, unknown>;\n keywords: Record<string, unknown>;\n tags: string[];\n become?: boolean;\n split?: RoleStep[];\n /** Variables the role registers or sets (read statically), so later steps can read them. */\n outputs: string[];\n dropped: string[];\n origin: Origin;\n}\n\nexport interface MetaForm {\n kind: 'meta';\n name: string;\n action: string;\n keywords: Record<string, unknown>;\n origin: Origin;\n}\n\nexport type Item = TaskForm | BlockForm | IncludeForm | RoleForm | MetaForm;\n\nexport interface VarPrompt {\n name: string;\n private: boolean;\n default?: unknown;\n prompt?: string;\n}\n\nexport interface PlayForm {\n kind: 'play';\n name: string;\n hosts: string;\n gatherFacts: boolean;\n gatherParams: Record<string, unknown>;\n become?: boolean;\n serial?: string | number;\n maxFailPercentage?: number;\n anyErrorsFatal?: boolean;\n collections: string[];\n vars: Record<string, unknown>;\n varsFiles: VarsFile[];\n varsPrompt: VarPrompt[];\n preTasks: Item[];\n roles: Item[];\n tasks: Item[];\n postTasks: Item[];\n handlers: Item[];\n dropped: string[];\n origin: Origin;\n}\n\nexport interface ImportPlaybookForm {\n kind: 'import_playbook';\n name: string;\n file: string;\n playbook?: PlaybookForm;\n /** Why it is not read in. */\n missing?: string;\n keywords: Record<string, unknown>;\n origin: Origin;\n}\n\nexport interface PlaybookForm {\n path: string;\n plays: (PlayForm | ImportPlaybookForm)[];\n}\n\nexport interface ReadOptions {\n /** Short module name + the play's collections \u2192 FQCN (the catalog, when the host has one). */\n resolveModule?(name: string, collections: string[]): string | undefined;\n}\n\nexport interface ReadResult {\n playbook?: PlaybookForm;\n /** What did not read one to one, for the user. */\n notes: string[];\n /** Every file read, repository paths. */\n files: string[];\n config?: AnsibleConfig;\n}\n\n// ---- keywords ------------------------------------------------------------------------------------\n\n/** Every key a task may have besides its module (Ansible's Task attributes). */\nconst TASK_KEYS = new Set([\n 'name',\n 'action',\n 'local_action',\n 'args',\n 'async',\n 'poll',\n 'become',\n 'become_exe',\n 'become_flags',\n 'become_method',\n 'become_user',\n 'changed_when',\n 'check_mode',\n 'collections',\n 'connection',\n 'debugger',\n 'delay',\n 'delegate_facts',\n 'delegate_to',\n 'diff',\n 'environment',\n 'failed_when',\n 'ignore_errors',\n 'ignore_unreachable',\n 'loop',\n 'loop_control',\n 'module_defaults',\n 'no_log',\n 'notify',\n 'listen',\n 'port',\n 'register',\n 'remote_user',\n 'retries',\n 'run_once',\n 'tags',\n 'throttle',\n 'timeout',\n 'until',\n 'vars',\n 'when',\n 'any_errors_fatal',\n 'block',\n 'rescue',\n 'always',\n]);\n\nconst isTaskKey = (k: string) => TASK_KEYS.has(k) || /^with_[a-z_]+$/.test(k);\n\n/** What blocks and plays hand down to their tasks. */\ninterface Scope {\n keywords: Record<string, unknown>;\n when: unknown[];\n tags: string[];\n become?: boolean;\n ignoreUnreachable?: boolean;\n /** Keywords that have no place, inherited. */\n dropped: string[];\n}\n\nconst EMPTY_SCOPE: Scope = { keywords: {}, when: [], tags: [], dropped: [] };\n\n/** Keywords a block or play hands down (their own `when`, tags and become are kept apart). */\nconst INHERITED = new Set([\n 'become_user',\n 'become_method',\n 'become_flags',\n 'become_exe',\n 'environment',\n 'connection',\n 'remote_user',\n 'port',\n 'ignore_errors',\n 'no_log',\n 'check_mode',\n 'diff',\n 'delegate_to',\n 'delegate_facts',\n 'run_once',\n 'throttle',\n 'module_defaults',\n 'debugger',\n 'vars',\n]);\n\nconst asList = (v: unknown): string[] =>\n v === undefined || v === null\n ? []\n : (Array.isArray(v) ? v : String(v).split(',')).map((x) => String(x).trim()).filter(Boolean);\n\nconst asBool = (v: unknown): boolean | undefined =>\n typeof v === 'boolean'\n ? v\n : typeof v === 'string' && /^(yes|true|on|1)$/i.test(v)\n ? true\n : typeof v === 'string' && /^(no|false|off|0)$/i.test(v)\n ? false\n : undefined;\n\nconst asInt = (v: unknown): number | undefined =>\n typeof v === 'number' && Number.isInteger(v)\n ? v\n : typeof v === 'string' && /^[0-9]+$/.test(v.trim())\n ? Number(v)\n : undefined;\n\n/**\n * A number, or a whole template the flow keeps as a value given at run time (AFD-112: a templated\n * retries, delay or timeout used to be dropped on import).\n */\nconst asIntOrTemplate = (v: unknown): number | string | undefined =>\n asInt(v) ?? (templated(v) ? v.trim() : undefined);\n\n/** A block's or play's own keys added to what its parent handed down. */\nfunction narrow(parent: Scope, raw: PlainMap, own: 'block' | 'play'): Scope {\n const keywords = { ...parent.keywords };\n // A play's vars become flow inputs; a block's vars reach its tasks.\n for (const k of INHERITED)\n if (raw[k] !== undefined && !(own === 'play' && k === 'vars')) {\n const v = toValue(raw[k] as Plain);\n keywords[k] =\n k === 'vars' && isMapping(keywords.vars) && isMapping(v) ? { ...keywords.vars, ...v } : v;\n }\n const dropped = [...parent.dropped];\n if (own === 'block' && raw.any_errors_fatal !== undefined) dropped.push('any_errors_fatal');\n return {\n keywords,\n when: own === 'block' && raw.when !== undefined ? [...parent.when, raw.when] : parent.when,\n tags: [...parent.tags, ...asList(raw.tags)],\n become: asBool(raw.become) ?? parent.become,\n ignoreUnreachable: asBool(raw.ignore_unreachable) ?? parent.ignoreUnreachable,\n dropped,\n };\n}\n\n/** A task's keywords over what it inherits; `when` lists are ANDed in order. */\nfunction taskKeywords(\n scope: Scope,\n raw: PlainMap,\n): { keywords: Record<string, unknown>; dropped: string[] } {\n const keywords: Record<string, unknown> = { ...scope.keywords };\n const dropped = [...scope.dropped];\n for (const [k, v] of Object.entries(raw)) {\n if (!isTaskKey(k) || k === 'when') continue;\n if (\n [\n 'name',\n 'action',\n 'local_action',\n 'args',\n 'register',\n 'notify',\n 'listen',\n 'tags',\n 'become',\n 'timeout',\n 'retries',\n 'delay',\n 'until',\n 'ignore_unreachable',\n 'block',\n 'rescue',\n 'always',\n 'collections',\n ].includes(k)\n )\n continue;\n if (k === 'with_items' || k === 'with_list') keywords.loop = toValue(v);\n else if (k === 'vars' && isMapping(keywords.vars) && isMapping(v))\n keywords.vars = { ...keywords.vars, ...(toValue(v) as Record<string, unknown>) };\n else if (isAllowedKeyword(k)) keywords[k] = toValue(v);\n else dropped.push(k);\n }\n const when = [...scope.when, ...(raw.when !== undefined ? [raw.when] : [])]\n .flatMap((w) => (Array.isArray(w) ? w : [w]))\n .map((w) => toValue(w as Plain));\n if (when.length === 1) keywords.when = when[0];\n else if (when.length > 1) keywords.when = when;\n return { keywords, dropped: [...new Set(dropped)] };\n}\n\n// ---- module arguments ----------------------------------------------------------------------------\n\n/** `src=a dest=\"b c\" mode=0644` \u2192 {src, dest, mode}; quotes and `{{ }}` keep their spaces. */\nexport function parseKv(text: string): { args: Record<string, string>; rest: string } {\n const args: Record<string, string> = {};\n const rest: string[] = [];\n const tokens: string[] = [];\n let cur = '';\n let quote = '';\n let depth = 0;\n for (let i = 0; i < text.length; i++) {\n const c = text[i] as string;\n if (quote) {\n cur += c;\n if (c === quote && text[i - 1] !== '\\\\') quote = '';\n } else if (c === '\"' || c === \"'\") {\n quote = c;\n cur += c;\n } else if (text.startsWith('{{', i) || text.startsWith('{%', i)) {\n depth++;\n cur += text.slice(i, i + 2);\n i++;\n } else if ((text.startsWith('}}', i) || text.startsWith('%}', i)) && depth > 0) {\n depth--;\n cur += text.slice(i, i + 2);\n i++;\n } else if (/\\s/.test(c) && depth === 0) {\n if (cur) tokens.push(cur);\n cur = '';\n } else cur += c;\n }\n if (cur) tokens.push(cur);\n // Ansible's parse_kv drops the quotes and decodes escapes (`content=\"done\\n\"` ends in a newline).\n const ESC: Record<string, string> = { n: '\\n', t: '\\t', r: '\\r', '\\\\': '\\\\', '\"': '\"', \"'\": \"'\" };\n const unquote = (s: string) =>\n (/^([\"']).*\\1$/s.test(s) ? s.slice(1, -1) : s).replace(\n /\\\\([ntr\\\\\"'])/g,\n (_, c: string) => ESC[c] ?? c,\n );\n for (const t of tokens) {\n const m = /^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/s.exec(t);\n if (m?.[1]) args[m[1]] = unquote(m[2] ?? '');\n else rest.push(t);\n }\n return { args, rest: rest.join(' ') };\n}\n\n/** Modules whose arguments are a command line, and the options Ansible takes out of it. */\nconst FREE_FORM: Record<string, string> = {\n command: 'cmd',\n shell: 'cmd',\n script: 'cmd',\n raw: '_raw_params',\n win_command: '_raw_params',\n win_shell: '_raw_params',\n};\nconst FREE_OPTIONS = new Set(['chdir', 'creates', 'removes', 'executable', 'stdin', 'warn']);\n\n/** Module arguments from the task value: a map, k=v text, or a free-form command line. */\nfunction moduleArgs(module: string, value: unknown, extra: unknown): Record<string, unknown> {\n const short = shortName(module).replace(/^ansible\\.windows\\./, '');\n let params: Record<string, unknown> = {};\n if (isMapping(value)) params = toValue(value) as Record<string, unknown>;\n else if (typeof value === 'string' && value.trim()) {\n const free = FREE_FORM[short];\n if (free) {\n const { args, rest } = parseKv(value);\n const options = Object.fromEntries(Object.entries(args).filter(([k]) => FREE_OPTIONS.has(k)));\n const kept = Object.entries(args)\n .filter(([k]) => !FREE_OPTIONS.has(k))\n .map(([k, v]) => `${k}=${v}`);\n params = { [free]: [rest, ...kept].filter(Boolean).join(' '), ...options };\n } else if (short === 'include_vars') params = { file: value.trim() };\n else {\n const { args, rest } = parseKv(value);\n params = rest ? { ...args, _raw_params: rest } : args;\n }\n }\n if (isMapping(extra)) params = { ...params, ...(toValue(extra) as Record<string, unknown>) };\n return params;\n}\n\n/** The module key and its value: a lone non-keyword key, or action / local_action. */\nfunction moduleOf(raw: PlainMap): { module: string; value: unknown; local: boolean } | undefined {\n for (const key of ['action', 'local_action'] as const) {\n const a = raw[key];\n if (a === undefined) continue;\n if (typeof a === 'string') {\n const [module = '', ...rest] = a.trim().split(/\\s+/);\n return { module, value: rest.join(' '), local: key === 'local_action' };\n }\n if (isMapping(a) && typeof a.module === 'string') {\n const { module, ...rest } = a;\n return { module: module as string, value: rest, local: key === 'local_action' };\n }\n }\n const keys = Object.keys(raw).filter((k) => !isTaskKey(k));\n if (!keys[0]) return undefined;\n return { module: keys[0], value: raw[keys[0]], local: false };\n}\n\nconst INCLUDES = new Set(['include_tasks', 'import_tasks', 'include']);\n\n/** Modules that read a local file, the parameter naming it and the subfolder Ansible looks in. */\nconst LOCAL_FILES: Record<string, { param: string; sub: string }> = {\n template: { param: 'src', sub: 'templates' },\n win_template: { param: 'src', sub: 'templates' },\n copy: { param: 'src', sub: 'files' },\n win_copy: { param: 'src', sub: 'files' },\n unarchive: { param: 'src', sub: 'files' },\n script: { param: 'cmd', sub: 'files' },\n include_vars: { param: 'file', sub: 'vars' },\n};\nconst ROLE_INCLUDES = new Set(['include_role', 'import_role']);\n// ---- the reader ----------------------------------------------------------------------------------\n\ninterface RoleInfo {\n dir?: string;\n onRolesPath: boolean;\n split?: RoleStep[];\n outputs: string[];\n}\n\nclass Reader {\n readonly notes: string[] = [];\n readonly files = new Set<string>();\n private readonly roles = new Map<string, Promise<RoleInfo>>();\n /** Task files being read in, to stop an include cycle. */\n private readonly including: string[] = [];\n /** AFD-179: task files that include themselves, at any depth; they run as include_tasks. */\n private readonly cyclic = new Set<string>();\n private config?: AnsibleConfig;\n private collections: string[] = [];\n\n constructor(\n private readonly io: SourceIO,\n private readonly opts: ReadOptions,\n ) {}\n\n /** The repository's ansible.cfg (the one runs use, ADR-0005). */\n async loadConfig(): Promise<AnsibleConfig | undefined> {\n const text = await this.io.read('ansible.cfg');\n if (text !== undefined) this.config = parseConfig(text, '');\n return this.config;\n }\n\n private async readYaml(path: string): Promise<Plain | undefined> {\n const text = await this.io.read(path);\n if (text === undefined) return undefined;\n this.files.add(path);\n if (isVaultFile(text)) {\n this.notes.push(`${path} is encrypted with Ansible Vault as a whole: not read.`);\n return undefined;\n }\n const { value, error } = parseAnsible(text);\n if (error) {\n this.notes.push(`${path} is not valid YAML (${error}): not read.`);\n return undefined;\n }\n return value;\n }\n\n async playbook(path: string, stack: string[] = []): Promise<PlaybookForm | undefined> {\n const data = await this.readYaml(path);\n if (data === undefined) return undefined;\n if (!Array.isArray(data)) {\n this.notes.push(`${path} is not a playbook (no list of plays).`);\n return undefined;\n }\n const plays: PlaybookForm['plays'] = [];\n for (const raw of data) {\n if (!isMapping(raw)) continue;\n const origin = { path, line: lineOf(raw) };\n const imp = raw.import_playbook ?? raw['ansible.builtin.import_playbook'];\n if (imp !== undefined) {\n plays.push(await this.importPlaybook(raw, String(imp), path, origin, stack));\n continue;\n }\n if (raw.hosts === undefined) {\n this.notes.push(`${path}:${origin.line ?? '?'}: a play without hosts was skipped.`);\n continue;\n }\n plays.push(await this.play(raw, path, origin));\n }\n return { path, plays };\n }\n\n private async importPlaybook(\n raw: PlainMap,\n file: string,\n from: string,\n origin: Origin,\n stack: string[],\n ): Promise<ImportPlaybookForm> {\n const keywords: Record<string, unknown> = {};\n if (raw.vars !== undefined) keywords.vars = toValue(raw.vars);\n if (raw.when !== undefined) keywords.when = toValue(raw.when);\n const form: ImportPlaybookForm = {\n kind: 'import_playbook',\n name: typeof raw.name === 'string' ? raw.name : basename(file).replace(/\\.ya?ml$/, ''),\n file,\n keywords,\n origin,\n };\n if (isTemplated(file)) {\n form.missing = 'its path is templated';\n return form;\n }\n const path = join(dirname(from), file);\n if (stack.includes(path) || stack.length >= 8) {\n form.missing = stack.includes(path) ? 'it imports itself' : 'imports nest deeper than 8';\n return form;\n }\n form.playbook = await this.playbook(path, [...stack, from]);\n if (!form.playbook) form.missing = `${path} was not found or not read`;\n return form;\n }\n\n private async play(raw: PlainMap, path: string, origin: Origin): Promise<PlayForm> {\n this.collections = asList(raw.collections);\n const scope = narrow(EMPTY_SCOPE, raw, 'play');\n const dropped = ['strategy', 'order', 'force_handlers'].filter((k) => raw[k] !== undefined);\n const gather = asBool(raw.gather_facts);\n const gatherParams: Record<string, unknown> = {};\n if (raw.gather_subset !== undefined) gatherParams.gather_subset = toValue(raw.gather_subset);\n if (raw.gather_timeout !== undefined) gatherParams.gather_timeout = toValue(raw.gather_timeout);\n const dir = dirname(path);\n const section = async (key: string) =>\n this.items(Array.isArray(raw[key]) ? (raw[key] as Plain[]) : [], scope, dir, dir, path);\n const prompts = Array.isArray(raw.vars_prompt) ? raw.vars_prompt : [];\n return {\n kind: 'play',\n name: typeof raw.name === 'string' ? raw.name : '',\n hosts: Array.isArray(raw.hosts)\n ? raw.hosts.map(String).join(',')\n : String(raw.hosts ?? 'all'),\n gatherFacts: gather ?? this.config?.gathering !== 'explicit',\n gatherParams,\n become: scope.become,\n serial:\n typeof raw.serial === 'number' || typeof raw.serial === 'string' ? raw.serial : undefined,\n maxFailPercentage: asInt(raw.max_fail_percentage),\n anyErrorsFatal: asBool(raw.any_errors_fatal),\n collections: this.collections,\n vars: isMapping(raw.vars) ? (toValue(raw.vars) as Record<string, unknown>) : {},\n varsFiles: await this.varsFiles(raw.vars_files, dir),\n varsPrompt: prompts.filter(isMapping).map((p) => ({\n name: String(p.name ?? ''),\n private: asBool(p.private) ?? true,\n ...(p.default !== undefined ? { default: toValue(p.default) } : {}),\n ...(typeof p.prompt === 'string' ? { prompt: p.prompt } : {}),\n })),\n preTasks: await section('pre_tasks'),\n roles: await this.playRoles(raw.roles, scope, path),\n tasks: await section('tasks'),\n postTasks: await section('post_tasks'),\n handlers: await section('handlers'),\n dropped: [...new Set([...dropped, ...scope.dropped])],\n origin,\n };\n }\n\n /** The `roles:` section: strings or maps with role/name, vars, keywords and old-style vars. */\n private async playRoles(value: Plain | undefined, scope: Scope, path: string): Promise<Item[]> {\n const out: Item[] = [];\n for (const entry of Array.isArray(value) ? value : []) {\n const raw: PlainMap = isMapping(entry) ? entry : { role: entry as Plain };\n const name = String(raw.role ?? raw.name ?? '');\n if (!name) continue;\n const params: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(raw))\n if (!['role', 'name'].includes(k) && !isTaskKey(k)) params[k] = toValue(v);\n if (isMapping(raw.vars)) Object.assign(params, toValue(raw.vars));\n out.push(\n await this.role(name, params, { ...raw, vars: null } as PlainMap, scope, path, {\n path,\n line: lineOf(entry),\n }),\n );\n }\n return out;\n }\n\n async items(\n list: Plain[],\n scope: Scope,\n dir: string,\n playDir: string,\n file: string,\n depth = 0,\n ): Promise<Item[]> {\n const out: Item[] = [];\n for (const raw of list) {\n if (!isMapping(raw)) continue;\n const item = await this.item(raw, scope, dir, playDir, file, depth);\n if (item) out.push(item);\n }\n return out;\n }\n\n private async item(\n raw: PlainMap,\n scope: Scope,\n dir: string,\n playDir: string,\n file: string,\n depth: number,\n ): Promise<Item | undefined> {\n const origin = { path: file, line: lineOf(raw) };\n const name = typeof raw.name === 'string' ? raw.name : '';\n if (Array.isArray(raw.block)) {\n const inner = narrow(scope, raw, 'block');\n const list = async (key: string) =>\n this.items(\n Array.isArray(raw[key]) ? (raw[key] as Plain[]) : [],\n inner,\n dir,\n playDir,\n file,\n depth,\n );\n return {\n kind: 'block',\n name,\n items: await list('block'),\n rescue: await list('rescue'),\n always: await list('always'),\n origin,\n };\n }\n const found = moduleOf(raw);\n if (!found) {\n this.notes.push(`${file}:${origin.line ?? '?'}: a task without a module was skipped.`);\n return undefined;\n }\n const short = shortName(found.module);\n const { keywords, dropped } = taskKeywords(scope, raw);\n if (found.local) keywords.delegate_to = 'localhost';\n const tags = [...scope.tags, ...asList(raw.tags)];\n if (INCLUDES.has(short))\n return this.include(\n raw,\n found.value,\n name,\n keywords,\n tags,\n dir,\n playDir,\n origin,\n scope,\n depth,\n short === 'import_tasks',\n );\n if (ROLE_INCLUDES.has(short)) {\n const args = moduleArgs(found.module, found.value, raw.args);\n const roleName = String(args.name ?? '');\n const params: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(args)) if (k !== 'name' && k !== 'apply') params[k] = v;\n if (isMapping(raw.vars)) Object.assign(params, toValue(raw.vars));\n const apply = isMapping(args.apply) ? (args.apply as PlainMap) : {};\n const role = await this.role(\n roleName,\n params,\n { ...raw, ...apply, vars: null } as PlainMap,\n scope,\n file,\n origin,\n );\n role.name = name || role.name;\n return role;\n }\n if (short === 'meta') {\n return { kind: 'meta', name, action: String(found.value ?? '').trim(), keywords, origin };\n }\n const params = moduleArgs(found.module, found.value, raw.args);\n const fqcn =\n builtinFqcn(found.module) ?? this.opts.resolveModule?.(found.module, this.collections);\n const become = asBool(raw.become) ?? scope.become;\n return {\n kind: 'task',\n name,\n module: found.module,\n ...(fqcn ? { fqcn } : {}),\n params,\n keywords,\n ...(typeof raw.register === 'string' && raw.register ? { register: raw.register } : {}),\n notify: asList(raw.notify),\n listen: asList(raw.listen),\n tags,\n ...(become !== undefined ? { become } : {}),\n ...(asIntOrTemplate(raw.timeout) ? { timeout: asIntOrTemplate(raw.timeout) } : {}),\n ...(asIntOrTemplate(raw.retries) !== undefined\n ? { retries: asIntOrTemplate(raw.retries) }\n : {}),\n ...(asIntOrTemplate(raw.delay) !== undefined ? { delay: asIntOrTemplate(raw.delay) } : {}),\n ...(typeof raw.until === 'string' ? { until: raw.until } : {}),\n ...((asBool(raw.ignore_unreachable) ?? scope.ignoreUnreachable)\n ? { ignoreUnreachable: true }\n : {}),\n dropped: [\n ...dropped,\n ...(raw.retries !== undefined && asIntOrTemplate(raw.retries) === undefined\n ? ['retries']\n : []),\n ...(raw.delay !== undefined && asIntOrTemplate(raw.delay) === undefined ? ['delay'] : []),\n ...(raw.timeout !== undefined && !asIntOrTemplate(raw.timeout) ? ['timeout'] : []),\n ],\n files: await this.localFiles(found.module, params, dir, playDir),\n origin,\n };\n }\n\n /** Where Ansible would find the local files a task names, searched as it does. */\n private async localFiles(\n module: string,\n params: Record<string, unknown>,\n dir: string,\n playDir: string,\n ): Promise<LocalFile[]> {\n const short = shortName(module).replace(/^ansible\\.windows\\./, '');\n const spec = LOCAL_FILES[short];\n if (!spec || asBool(params.remote_src)) return [];\n let written = params[spec.param];\n if (short === 'script' && typeof written === 'string') written = written.trim().split(/\\s+/)[0];\n if (typeof written !== 'string' || !written || isTemplated(written) || written.startsWith('/'))\n return [];\n const bases = [...new Set([dir, playDir])];\n const candidates = bases.flatMap((b) => [join(b, spec.sub, written), join(b, written)]);\n for (const path of candidates)\n if (await exists(this.io, path)) return [{ param: spec.param, written, path }];\n return [{ param: spec.param, written }];\n }\n\n private async varsFiles(value: Plain | undefined, dir: string): Promise<VarsFile[]> {\n const out: VarsFile[] = [];\n for (const entry of Array.isArray(value) ? value : []) {\n const file = Array.isArray(entry) ? entry[0] : entry;\n if (typeof file !== 'string') continue;\n if (isTemplated(file) || file.startsWith('/')) {\n out.push({ file, keys: [] });\n continue;\n }\n const path = join(dir, file);\n const data = (await exists(this.io, path)) ? await this.readYaml(path) : undefined;\n out.push({\n file,\n ...(data !== undefined ? { path } : {}),\n keys: isMapping(data) ? Object.keys(data) : [],\n });\n }\n return out;\n }\n\n private async include(\n raw: PlainMap,\n value: unknown,\n name: string,\n keywords: Record<string, unknown>,\n tags: string[],\n dir: string,\n playDir: string,\n origin: Origin,\n scope: Scope,\n depth: number,\n /** import_tasks: static; include_tasks (and the old include): dynamic (AFD-149). */\n isStatic = false,\n ): Promise<IncludeForm> {\n const args = isMapping(value) ? (toValue(value) as Record<string, unknown>) : {};\n const target =\n typeof value === 'string' ? value.trim() : String(args.file ?? args._raw_params ?? '');\n const form: IncludeForm = { kind: 'include', name, file: target, keywords, tags, origin };\n if (isMapping(raw.vars)) form.vars = toValue(raw.vars) as Record<string, unknown>;\n if (!target || isTemplated(target)) {\n form.dynamic = 'its file name is templated';\n return form;\n }\n // AFD-179: the file is found first, so an include that cannot be read in can still run it.\n const candidates = [...new Set([join(dir, target), join(playDir, target)])];\n let path: string | undefined;\n for (const c of candidates)\n if (await exists(this.io, c)) {\n path = c;\n break;\n }\n const runAsIs = async (why: string) => {\n form.dynamic = why;\n if (path) {\n form.path = path;\n form.portability = await this.portability(path, playDir);\n }\n return form;\n };\n if (keywords.loop !== undefined || Object.keys(keywords).some((k) => k.startsWith('with_')))\n return runAsIs('it runs in a loop');\n if (depth >= 8) return runAsIs('includes nest deeper than 8');\n if (path && this.including.includes(path)) {\n this.cyclic.add(path);\n return runAsIs(`${path} includes itself`);\n }\n for (const p of path ? [path] : []) {\n const data = await this.readYaml(p);\n if (data === undefined) break;\n form.path = p;\n // import_tasks: its keywords reach every task in the file. include_tasks (AFD-149): its own\n // `when` is checked once and its tags select the include itself; only its vars and `apply`\n // (keywords for the tasks inside) reach them.\n let inner: Scope;\n if (isStatic) inner = narrow(scope, raw, 'block');\n else {\n const base = narrow(\n scope,\n (raw.vars !== undefined ? { vars: raw.vars } : {}) as PlainMap,\n 'block',\n );\n inner = isMapping(args.apply) ? narrow(base, args.apply as PlainMap, 'block') : base;\n if (raw.when !== undefined)\n form.when = (Array.isArray(raw.when) ? raw.when : [raw.when]).map((w) =>\n toValue(w as Plain),\n );\n }\n this.including.push(p);\n const items = await this.items(\n Array.isArray(data) ? data : [],\n inner,\n dirname(p),\n playDir,\n p,\n depth + 1,\n );\n this.including.pop();\n // A file that includes itself, here or deeper, runs as include_tasks: a copy read in one\n // level deep would not run as the source does.\n if (this.cyclic.has(p)) return runAsIs(`${p} includes itself`);\n form.items = items;\n form.keywords = {};\n return form;\n }\n form.dynamic = `${candidates[0]} was not found`;\n return form;\n }\n\n /**\n * AFD-177: why a task file would not work from generated/: it reads playbook_dir, or includes a\n * file Ansible finds only next to the playbook (not next to the file itself).\n */\n private async portability(path: string, playDir: string): Promise<string[]> {\n const text = (await this.io.read(path)) ?? '';\n const found: string[] = [];\n if (/\\bplaybook_dir\\b/.test(text)) found.push('reads playbook_dir');\n const data = await this.readYaml(path);\n const nested = new Set<string>();\n const walk = (v: unknown) => {\n if (Array.isArray(v)) v.forEach(walk);\n else if (isMapping(v))\n for (const [k, x] of Object.entries(v)) {\n if (INCLUDES.has(shortName(k))) {\n const f = typeof x === 'string' ? x : isMapping(x) ? (x.file ?? x._raw_params) : '';\n if (typeof f === 'string' && f && !isTemplated(f) && !f.startsWith('/'))\n nested.add(f.trim());\n } else walk(x);\n }\n };\n walk(data);\n for (const f of nested)\n if (\n !(await exists(this.io, join(dirname(path), f))) &&\n (await exists(this.io, join(playDir, f)))\n )\n found.push(`includes ${f} relative to the playbook`);\n return found;\n }\n\n private async role(\n name: string,\n params: Record<string, unknown>,\n raw: PlainMap,\n scope: Scope,\n file: string,\n origin: Origin,\n ): Promise<RoleForm> {\n // Role variables are params; every other keyword applies to the role's tasks.\n const { keywords, dropped } = taskKeywords(scope, raw);\n delete keywords.vars;\n const info = await this.roleInfo(name, dirname(file));\n const tags = [...scope.tags, ...asList(raw.tags)];\n const become = asBool(raw.become) ?? scope.become;\n return {\n kind: 'role',\n name: name.includes('/') ? basename(name) : name,\n ref: name.includes('/') && info.dir ? basename(info.dir) : name,\n ...(info.dir ? { dir: info.dir } : {}),\n onRolesPath: info.onRolesPath,\n params,\n keywords,\n tags,\n ...(become !== undefined ? { become } : {}),\n ...(info.split && !params.tasks_from ? { split: info.split } : {}),\n outputs: info.outputs,\n dropped,\n origin,\n };\n }\n\n /** Where a role lives, whether runs find it, its split and what it registers. */\n roleInfo(name: string, fromDir: string): Promise<RoleInfo> {\n const key = `${fromDir}|${name}`;\n let found = this.roles.get(key);\n if (!found) {\n found = this.findRole(name, fromDir);\n this.roles.set(key, found);\n }\n return found;\n }\n\n private async findRole(name: string, fromDir: string): Promise<RoleInfo> {\n const parts = name.split('.');\n const cfgRoles = this.config?.rolesPath ?? [];\n let candidates: { dir: string; onRolesPath: boolean }[];\n if (!name.includes('/') && parts.length === 3) {\n const [ns, coll, role] = parts;\n const bases = [\n 'collections',\n ...(this.config?.collectionsPath ?? []).map((p) => normalize(p)),\n ];\n candidates = [...new Set([...bases, join(fromDir, 'collections')])].map((b) => ({\n dir: join(b, 'ansible_collections', ns ?? '', coll ?? '', 'roles', role ?? ''),\n onRolesPath: true,\n }));\n } else {\n // Ansible's order: roles/ next to the playbook, then roles_path, then the playbook's folder.\n candidates = [\n { dir: join(fromDir, 'roles', name), onRolesPath: false },\n ...cfgRoles.map((p) => ({ dir: join(p, name), onRolesPath: true })),\n { dir: join('roles', name), onRolesPath: false },\n { dir: join(fromDir, name), onRolesPath: false },\n ];\n }\n for (const c of candidates) {\n for (const main of ['tasks/main.yml', 'tasks/main.yaml', 'meta/main.yml'])\n if (await exists(this.io, join(c.dir, main))) {\n const onRolesPath = c.onRolesPath || cfgRoles.includes(dirname(c.dir));\n return { dir: c.dir, onRolesPath, ...(await this.roleTasks(c.dir)) };\n }\n }\n // A collection role not in the repository is still bound by name: the EE may have it.\n return { onRolesPath: parts.length === 3, outputs: [] };\n }\n\n /** A split role (main only includes literal files) and the variables its tasks set. */\n private async roleTasks(dir: string): Promise<{ split?: RoleStep[]; outputs: string[] }> {\n const tasksDir = join(dir, 'tasks');\n const outputs = new Set<string>();\n const seen = new Set<string>();\n const walk = async (path: string, depth: number): Promise<Plain[] | undefined> => {\n if (seen.has(path) || depth > 4) return undefined;\n seen.add(path);\n const text = await this.io.read(path);\n if (text === undefined || isVaultFile(text)) return undefined;\n const { value } = parseAnsible(text);\n if (!Array.isArray(value)) return undefined;\n const visit = async (list: Plain[]) => {\n for (const t of list) {\n if (!isMapping(t)) continue;\n if (typeof t.register === 'string') outputs.add(t.register);\n for (const b of ['block', 'rescue', 'always'])\n if (Array.isArray(t[b])) await visit(t[b] as Plain[]);\n const m = moduleOf(t);\n const short = m ? shortName(m.module) : '';\n if (short === 'set_fact' && isMapping(m?.value))\n for (const k of Object.keys(m.value)) if (k !== 'cacheable') outputs.add(k);\n const target = INCLUDES.has(short)\n ? typeof m?.value === 'string'\n ? m.value\n : (m?.value as PlainMap)?.file\n : undefined;\n if (typeof target === 'string' && !isTemplated(target))\n await walk(join(dirname(path), target), depth + 1);\n }\n };\n await visit(value);\n return value;\n };\n let mainPath = join(tasksDir, 'main.yml');\n if (!(await exists(this.io, mainPath))) mainPath = join(tasksDir, 'main.yaml');\n const main = await walk(mainPath, 0);\n let split: RoleStep[] | undefined;\n if (main && main.length >= 2) {\n split = [];\n for (const t of main) {\n const m = isMapping(t) ? moduleOf(t) : undefined;\n const short = m ? shortName(m.module) : '';\n const target =\n typeof m?.value === 'string' ? m.value.trim() : (m?.value as PlainMap | undefined)?.file;\n const extra = isMapping(t)\n ? Object.keys(t).filter((k) => isTaskKey(k) && !['name', 'tags', 'when'].includes(k))\n : ['?'];\n if (\n !m ||\n !INCLUDES.has(short) ||\n typeof target !== 'string' ||\n isTemplated(target) ||\n extra.length\n ) {\n split = undefined;\n break;\n }\n const rel = normalize(join(dirname(mainPath.slice(tasksDir.length + 1)), target));\n split.push({\n tasksFrom: rel.replace(/\\.ya?ml$/, ''),\n name:\n typeof (t as PlainMap).name === 'string'\n ? ((t as PlainMap).name as string)\n : basename(rel).replace(/\\.ya?ml$/, ''),\n keywords:\n (t as PlainMap).when !== undefined\n ? { when: toValue((t as PlainMap).when as Plain) }\n : {},\n tags: asList((t as PlainMap).tags),\n });\n }\n }\n return { ...(split ? { split } : {}), outputs: [...outputs].sort() };\n }\n}\n\n/** Reads a playbook with everything it imports and includes. */\nexport async function readPlaybook(\n io: SourceIO,\n path: string,\n opts: ReadOptions = {},\n): Promise<ReadResult> {\n const reader = new Reader(io, opts);\n const config = await reader.loadConfig();\n const playbook = await reader.playbook(normalize(path));\n return { playbook, notes: reader.notes, files: [...reader.files], ...(config ? { config } : {}) };\n}\n\n// ---- folders -------------------------------------------------------------------------------------\n\n/** Folders a scan never enters: tooling, generated code, and Ansible content that is not a playbook. */\nconst SKIP_DIRS = new Set([\n 'node_modules',\n 'generated',\n 'out',\n 'dist',\n 'venv',\n 'roles',\n 'group_vars',\n 'host_vars',\n 'collections',\n 'flows',\n 'molecule',\n '__pycache__',\n]);\n\nconst PLAY_HINT = /^[ \\t]*-?[ \\t]*(hosts|(ansible\\.builtin\\.)?import_playbook)[ \\t]*:/m;\n\nexport interface FolderPlaybook {\n path: string;\n /** The first play's name, else the file name. */\n title: string;\n /** Not imported by another playbook in the folder: offered first. */\n entry: boolean;\n /** Who imports it, when not an entry. */\n importedBy?: string;\n}\n\nexport interface FolderScan {\n playbooks: FolderPlaybook[];\n /** Roles under roles/ (and roles_path) with whether each is split. */\n roles: { name: string; dir: string; split: boolean }[];\n truncated: boolean;\n}\n\n/** The playbooks of a folder (and below), which ones are entries, and its roles. */\nexport async function scanFolder(io: SourceIO, dir: string, maxFiles = 2000): Promise<FolderScan> {\n const files: string[] = [];\n let truncated = false;\n const walk = async (d: string, depth: number) => {\n if (depth > 6) return;\n for (const e of await io.list(d)) {\n if (files.length >= maxFiles) {\n truncated = true;\n return;\n }\n if (e.name.startsWith('.')) continue;\n const path = join(d, e.name);\n if (e.dir) {\n if (!SKIP_DIRS.has(e.name)) await walk(path, depth + 1);\n } else if (/\\.ya?ml$/.test(e.name) && !e.name.endsWith('.flow.yaml')) files.push(path);\n }\n };\n await walk(normalize(dir), 0);\n const playbooks: FolderPlaybook[] = [];\n const imports = new Map<string, string>();\n for (const path of files) {\n const text = await io.read(path);\n if (text === undefined || !PLAY_HINT.test(text) || isVaultFile(text)) continue;\n const { value } = parseAnsible(text);\n if (!Array.isArray(value)) continue;\n const items = value.filter(isMapping);\n const plays = items.filter((p) => p.hosts !== undefined);\n const imported = items\n .map((p) => p.import_playbook ?? p['ansible.builtin.import_playbook'])\n .filter((f): f is string => typeof f === 'string' && !isTemplated(f));\n if (!plays.length && !imported.length) continue;\n for (const f of imported) imports.set(join(dirname(path), f), path);\n const first = plays.find((p) => typeof p.name === 'string');\n playbooks.push({\n path,\n title: typeof first?.name === 'string' ? first.name : basename(path),\n entry: true,\n });\n }\n for (const p of playbooks) {\n const by = imports.get(p.path);\n if (by) {\n p.entry = false;\n p.importedBy = by;\n }\n }\n const roles: FolderScan['roles'] = [];\n const reader = new Reader(io, {});\n const config = await reader.loadConfig();\n const roleDirs = [...new Set([join(dir, 'roles'), 'roles', ...(config?.rolesPath ?? [])])];\n for (const base of roleDirs)\n for (const e of await io.list(base))\n if (e.dir && !e.name.startsWith('.') && !roles.some((r) => r.dir === join(base, e.name))) {\n const r = await reader.roleInfo(e.name, dirname(base));\n if (r.dir) roles.push({ name: e.name, dir: r.dir, split: !!r.split });\n }\n playbooks.sort((a, b) => Number(b.entry) - Number(a.entry) || a.path.localeCompare(b.path));\n return { playbooks, roles, truncated };\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["params"]
|
|
7
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|