chore(templater): migrate the template engine from slim-sprig to sprout - #2968
Draft
vmaerten wants to merge 4 commits into
Draft
chore(templater): migrate the template engine from slim-sprig to sprout#2968vmaerten wants to merge 4 commits into
vmaerten wants to merge 4 commits into
Conversation
Golden tests capturing the sorted list of template function names and the rendered output of a representative expression per function. Generated against the current slim-sprig implementation so that any change of templating library produces an auditable diff.
slim-sprig is a fork of the unmaintained Masterminds/sprig that Task keeps alive itself. sprout is its maintained successor, and its registry system gives the same trimmed function set without a fork to maintain. Task's own functions move into a sprout registry. Ten functions changed argument order between the two libraries, and dig lost its default-value argument; wrappers accept both forms so existing Taskfiles keep working. merge and fromYaml/toYaml are re-applied after the handler is built, because sprout's namesakes have different semantics. Closes #1638.
sprout logs its deprecation notices to stdout by default, which would corrupt the JSON and group output styles. Route them to the Executor's logger at verbose level instead, deduplicated so that a single deprecated call is not reported once per compilation pass.
Add a migration section listing the renamed functions, the ten argument order changes and the behaviour differences, extend the template function deprecation page with the new aliases, and point the sprig links at the sprout documentation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Task's template functions came from
slim-sprig, a fork of the unmaintainedMasterminds/sprigthat we keep alive ourselves. This migrates the engine to sprout, sprig's maintained successor, whose registry system gives the same trimmed function set without a fork to maintain —cryptoandnetworkare left out, so the exposed surface stays at slim-sprig parity. Task's own functions move into a sprout registry, every slim-sprig name still resolves through an alias table, and wrappers accept both the old and the new argument order for the ten functions sprout reordered, warning about the old one under--verbose.Two things needed more than a name mapping.
diglost its default-value argument entirely in sprout (dig(keys..., dict)where sprig haddig(keys..., default, dict)), and the two forms cannot be told apart by type — Task keeps sprig's meaning, since that is what every existing Taskfile was written against. Andmerge,fromYaml,toYaml,mustFromYamlandmustToYamlare re-applied after the handler is built, because sprout ships functions and aliases of the same name with different semantics (deep merge, errors raised instead of swallowed).Notices are routed to the Executor's logger at verbose level and deduplicated. sprout logs them to stdout by default, which would corrupt the
groupand--jsonoutput.Reviewers should look at the behaviour changes below: they are corrections of long-standing sprig bugs and are not opt-in. Notably, functions that used to swallow an error or panic now fail the task instead of rendering an empty string —
{{ atoi "abc" }}and{{ fromJson "not json" }}are the common cases.Closes #1638. Supersedes #2006 by @42atomys, whose approach this follows.
Test plan
The first commit is a safety net, generated against the slim-sprig implementation before anything changed: two golden files in
internal/templater/testdata/, one listing every template function name, the other the rendered output of ~90 representative expressions. The diff after the switch is the exhaustive, auditable inventory of what changed for users.substrwith a negative index ({{ substr 0 -3 "foobar" }}nowfoo, wasfoobar),titlewith Unicode casing ({{ title "hello wORLD" }}nowHello World, wasHello WORLD),atoiandfromJsonreporting errors,{{ duration 90 }}now1m30sinstead of0s,digsplitting keys on dots, and a rewordedmustFromJsonerror.Added tests:
TestSprigSignatureShimscovers the ten reordered functions in both orders,TestDigKeepsSprigDefaultcovers sixdigcases, andTestTaskFuncsShadowSproutpins the functions that must win over their sprout namesakes.go test ./...andgolangci-lint runpass on the whole repository. No existing integration test or golden file needed touching.Manual passes: deprecation notices are silent by default and appear once each under
-v;--output groupand--list-all --jsonkeep a clean stdout, including under-v.The binary grows from 72.3 MB to 73.3 MB (+1.3%), the cost of the wider function surface plus
mergo,copystructureandcast.The behaviour golden pins the local timezone to UTC in a
TestMain, without which it would fail on CI. Thedate/toDatelocal-vs-UTC difference is therefore documented in the migration guide rather than captured there.