tenseleyflow/shithub / 5dacf0e

Browse files

actions/workflow: bracket-quote non-ident keys in diagnostic paths (S41a-L6)

Pre-L6, an env entry with a dotted key (e.g. {"weird.key": ...}) produced
diagnostic paths like 'env.weird.key' — ambiguous between the
single key 'weird.key' and a nested env.weird.key. Authors reading
admin-actions-parse output had to deduce the boundary.

joinPath helper renders identifier-shaped keys unbracketed
(parent.child) and bracket-quotes anything else
(parent["weird.key"]). Wired into parseEnv where env names are
unconstrained YAML — the worst offender. Other callers can adopt
incrementally.

Local pathIdentRe rather than reusing the L2 polish-bundle's
canonical identRe so this cleanup PR is independent of #67. Once
both land we can dedupe.
Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
5dacf0eecc3e1f952a0cf6dd80489dd908335647
Parents
d1dddaf
Tree
e6dba5a

1 changed file

StatusFile+-
M internal/actions/workflow/parse.go 20 1
internal/actions/workflow/parse.gomodified
@@ -427,7 +427,7 @@ func parseEnv(n *yaml.Node, path string) (map[string]Value, []Diagnostic) {
427427
 		k := n.Content[i]
428428
 		v := n.Content[i+1]
429429
 		if v.Kind != yaml.ScalarNode {
430
-			diags = append(diags, errAt(path+"."+k.Value, "env values must be scalars"))
430
+			diags = append(diags, errAt(joinPath(path, k.Value), "env values must be scalars"))
431431
 			continue
432432
 		}
433433
 		// We tag env values literal-trusted here. The expression
@@ -663,6 +663,25 @@ func parseBool(n *yaml.Node, path string, diags *[]Diagnostic) bool {
663663
 	return b
664664
 }
665665
 
666
+// joinPath builds a dot-separated diagnostic path with bracket-quoting
667
+// for keys that aren't identifier-shaped. Identifier-shaped keys
668
+// appear as `parent.child`; anything else (keys containing dots,
669
+// spaces, quotes, brackets, or starting with a digit) appears as
670
+// `parent["weird key"]` so the path is unambiguous.
671
+//
672
+// Pre-L6, env-bag keys with dots produced ambiguous diagnostic paths
673
+// like `env.foo.bar.baz` for the entry `foo.bar` → `baz`. Authors
674
+// reading admin-actions-parse output had to deduce the boundary.
675
+//
676
+// Reuses identRe (defined at the top of this file by the L2 polish
677
+// bundle) so we have one canonical identifier-shape regex.
678
+func joinPath(parent, key string) string {
679
+	if identRe.MatchString(key) {
680
+		return parent + "." + key
681
+	}
682
+	return parent + "[" + strconv.Quote(key) + "]"
683
+}
684
+
666685
 // triggerSetIsNonEmpty reports whether at least one trigger is declared.
667686
 // TriggerSet contains slices, so it isn't comparable; this helper avoids
668687
 // per-call boilerplate at the parse-validate site.