Summary
I'd like to propose allowing parameters (e.g. vars:) to be passed to runbooks invoked from the needs: section, so that a single "fixture / provisioning" runbook can be reused across many scenarios with different inputs.
Currently needs: only accepts a key-to-path mapping:
needs:
prebook: path/to/prebook.yml
prebook2: path/to/prebook2.yml
There is no way to parameterize the called runbook, so variations of the same fixture have to be created as separate runbook files.
Motivation / Use case
I want to use needs: runbooks as common fixture / provisioning templates to minimize the amount of dependent data each scenario has to own. This is primarily for regression testing, where I don't want to keep increasing the number of test accounts.
Concretely, my goals are:
- Reduce total test execution time. Shared, expensive setup should run only once.
- Make dependencies easy to manage. The dependent data effectively becomes the identifier of the
needs:, which is easier to reason about than duplicating similar data everywhere.
- Register SaaS provisioning data. Many features need to be verified; the scenarios themselves have few dependencies, but provisioning data is always required and is expensive to create (authentication & authorization data must be set up).
- Avoid mass-producing near-identical data/runbooks.
Why the existing options don't fully cover this
needs:
needs: already deduplicates the same runbook across scenarios (via lo.Uniq in sortWithNeeds), so "run the shared setup only once" is effectively achieved and I don't have to write any "already executed?" guard in my scenarios. This is exactly why needs: is attractive for shared/expensive provisioning.
However, because needs: takes only map[string]string (key → path), I cannot pass vars:. When I need data variations, I'm forced to duplicate the runbook, which leads to a lot of near-identical runbooks.
include:
include: does support vars:, but it runs every time and is not deduplicated. To reuse a shared fixture with include:, I'd have to implement an "is it already executed?" check inside my scenarios myself, which is exactly the boilerplate I want to avoid.
So there is a gap between the two mechanisms:
| Need |
needs: |
include: |
| Run shared setup only once (dedup) |
✅ automatic |
❌ must guard manually |
Pass parameters (vars:) |
❌ not supported |
✅ supported |
The goal of this request is to close that gap: keep the "run once / declarative dependency" behavior of needs:, while allowing parameterization like include:.
Proposed idea
Allow a vars:-like input for needs: entries, e.g. (syntax is just for illustration):
needs:
admin_account:
path: path/to/provision_account.yml
vars:
role: admin
member_account:
path: path/to/provision_account.yml
vars:
role: member
Bound values would still be referenced via needs.<key>.* as today.
Points to discuss
I understand needs: and runbook-to-runbook interaction is a sensitive area (the Include + needs: combination in #1002 was reverted once and reworked in #1006, and #1017 addressed result overwriting), so I'd like to raise the following design points:
- Dedup key design: should two
needs: entries that point to the same path but have different vars: be treated as distinct executions? (i.e. how should lo.Uniq in sortWithNeeds account for vars:?)
- Result structure: impact on
needs.<key> results when the same path is run multiple times with different parameters.
- Backward compatibility: the existing
needs: { key: path } shorthand should keep working unchanged.
Summary
I'd like to propose allowing parameters (e.g.
vars:) to be passed to runbooks invoked from theneeds:section, so that a single "fixture / provisioning" runbook can be reused across many scenarios with different inputs.Currently
needs:only accepts a key-to-path mapping:There is no way to parameterize the called runbook, so variations of the same fixture have to be created as separate runbook files.
Motivation / Use case
I want to use
needs:runbooks as common fixture / provisioning templates to minimize the amount of dependent data each scenario has to own. This is primarily for regression testing, where I don't want to keep increasing the number of test accounts.Concretely, my goals are:
needs:, which is easier to reason about than duplicating similar data everywhere.Why the existing options don't fully cover this
needs:needs:already deduplicates the same runbook across scenarios (vialo.UniqinsortWithNeeds), so "run the shared setup only once" is effectively achieved and I don't have to write any "already executed?" guard in my scenarios. This is exactly whyneeds:is attractive for shared/expensive provisioning.However, because
needs:takes onlymap[string]string(key → path), I cannot passvars:. When I need data variations, I'm forced to duplicate the runbook, which leads to a lot of near-identical runbooks.include:include:does supportvars:, but it runs every time and is not deduplicated. To reuse a shared fixture withinclude:, I'd have to implement an "is it already executed?" check inside my scenarios myself, which is exactly the boilerplate I want to avoid.So there is a gap between the two mechanisms:
needs:include:vars:)The goal of this request is to close that gap: keep the "run once / declarative dependency" behavior of
needs:, while allowing parameterization likeinclude:.Proposed idea
Allow a
vars:-like input forneeds:entries, e.g. (syntax is just for illustration):Bound values would still be referenced via
needs.<key>.*as today.Points to discuss
I understand
needs:and runbook-to-runbook interaction is a sensitive area (the Include +needs:combination in #1002 was reverted once and reworked in #1006, and #1017 addressed result overwriting), so I'd like to raise the following design points:needs:entries that point to the same path but have differentvars:be treated as distinct executions? (i.e. how shouldlo.UniqinsortWithNeedsaccount forvars:?)needs.<key>results when the same path is run multiple times with different parameters.needs: { key: path }shorthand should keep working unchanged.