Skip to content

Allow variables to be explicitly typed (and enforced) #3167

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 12, 2025

Conversation

rrjjvv
Copy link
Contributor

@rrjjvv rrjjvv commented May 4, 2025

Resolves #3160 and likely replaces #3161

In #3160 (comment) it was suggested that prior to allowing variable lists to be overridden via environment, proper typing capabilities should be implemented (and used). This implements that typing, which results in the actual override code being superior to #3161 in every way, but touches more code.

This allows (but does not require) variables to have explicit types, similar to Terraform variables. It uses HCL's typeexpr extension for the specification. For conversion of overrides to complex types (when explicit typing is provided), HCL's native JSON-based unmarshalling is used.

Typing is independent of any default value, but if a default is provided, it will be validated. Similarly, if an override is provided, it will be converted to that type. If typing is not provided, previous behavior is used.

For complex types, the happy path is lists of primitives, but in theory any complex/composite type can be used provided they are expressed correctly in JSON. In the interest of simplicity and correctness, there are no shortcuts for lists (i.e., VAR='["foo","bar"]' and not VAR=foo,bar). There is a shortcut for strings as users don't provide them for untyped variables and would be unintuitive (i.e. VAR=foo is valid for a string, though not valid JSON).


There should be no changes in behavior (for current or future un-typed usage), with one theoretical exception. Today, extraneous attributes (for variables at least) are accepted, but ignored with no warnings. It is theoretical possibly that users may have become reliant on this, e.g.

variable "server" {
  default = "some.host"
  type = "linux"
}

Anyone using that attribute for their own purposes will encounter breaking behavior with this implementation (unless it happens to be a legitimate type expression). I don't know if that is a real concern.

Also, this PR only contains code changes. I assumed that 1) this change was unlikely to go through on the first submission and may require changes (or, of course, rejected), and 2) you may have dedicated people/processes for updating user docs. Let me know if you want/need me to do anything in this regard.

Copy link
Member

@tonistiigi tonistiigi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good, but I would expect just csv values to work for env instead of [. Eg. PLATFORMS=linux/amd64,linux/arm64 bake instead of the JSON form. This looks like something that we can't change later so should be done as same PR.

Copy link
Member

@tonistiigi tonistiigi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rrjjvv
Copy link
Contributor Author

rrjjvv commented May 7, 2025

I have the new behavior all wired in and it's looking good. I'll push them tonight after revisiting the tests once more to ensure I didn't miss anything.

@thompson-shaun thompson-shaun added this to the v0.24.0 milestone May 9, 2025
@tonistiigi tonistiigi requested a review from Copilot May 9, 2025 23:57
Copy link
Member

@tonistiigi tonistiigi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from test failure this looks good to me.

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR enables explicit variable typing and enforces type conversion for variable overrides, following HCL's type expression syntax.

  • Introduces a new "type" field in variable declarations to support explicit typing.
  • Updates the variable resolution flow to apply JSON and CSV conversions based on the specified type.
  • Adds helper functions to parse CSV values and to resolve type constraints with fallback handling.

rrjjvv and others added 5 commits May 9, 2025 18:36
This allows variables to have explicit types, similar to Terraform
variables.  It uses HCL's `typeexpr` extension for the specification.
For conversion of overrides to complex types (when explicit typing is
provided), HCL's native JSON-based unmarshalling is used.

Typing is independent of any default, but if a default is provided, it
will be validated.  Similarly, if an override is provided, it will be
converted to that type.

When typing is not provided, previous behavior is used, namely
passing through as a string when no default, converting to primitives if
 the default was primitive, and failing otherwise (complex types).

For complex types, the happy path is lists of primitives, but in theory
any complex/composite type can be used provided they are expressed
correctly in JSON.  In the interest of simplicity and correctness, there
 are no shortcuts for lists.  There *is* a shortcut for strings as users
  don't provide them for untyped variables and would be unintuitive.

Signed-off-by: Roberto Villarreal <[email protected]>
Though CSV is favored for 'simple' lists, a JSON value will be used if
it parses without error.  This assumes that it is extremely unlikely
that something that parses as JSON would be intended to be parsed as
CSV, e.g. `["a"` and `"b"]`, as opposed to `a` and `b`.  If
parsing/conversion fails, it is treated as if it was a CSV.

Since the CSV approach required processing of each element, code was
refactored to reuse the same logic used for individual non-typed
variables.

Signed-off-by: Roberto Villarreal <[email protected]>
The primary intent is to make JSON parsing explicitly opt-in rather than
 using heuristics to determine intent.

With some exceptions, given bake variable `VAR`, an environment variable
 `VAR_JSON` must be used to provide JSON content.  The value in
 `VAR_JSON` will be ignored when:
* a bake built-in of that same name exists
* a user-provided variable of that same name exists
* typing (attribute `type`) is not present

The first is unlikely to happen as built-ins will likely start with
`BUILDX_BAKE_`, an unlikely prefix for end users.  The second may be a
real scenario, where users have `VAR_JSON` dedicated to accepting a
string with JSON content and decoding via an HCL function.  This will
continue to work as-is, but can be simplified by removing the variable
from their bake file (`VAR_JSON`) and applying typing (to `VAR`).

Signed-off-by: Roberto Villarreal <[email protected]>
Co-authored-by: Copilot <[email protected]>
Signed-off-by: Roberto Villarreal <[email protected]>
Signed-off-by: Roberto Villarreal <[email protected]>
@rrjjvv rrjjvv force-pushed the variable-typing branch from de674c1 to 56d39e6 Compare May 10, 2025 00:37
@rrjjvv rrjjvv requested a review from tonistiigi May 10, 2025 00:38
Copy link
Member

@crazy-max crazy-max left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rrjjvv
Copy link
Contributor Author

rrjjvv commented May 12, 2025

We should update the documentation to reflect this new type constraint.

Does "we" mean me? I can give it a shot. (I didn't know whether you folks had dedicated technical writers and/or if docs followed a separate release process, so figured I'd wait for clarity.)

@tonistiigi tonistiigi merged commit 865ad2b into docker:master May 12, 2025
138 checks passed
@tonistiigi
Copy link
Member

@rrjjvv You can open up a docs update in follow-up if you can. We will ping the necessary people for review.

@rrjjvv rrjjvv deleted the variable-typing branch May 12, 2025 17:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bake: allow override of list variables via environment
5 participants