Skip to content

Various feature additions for CUE #5352

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 3 commits into from
Jun 13, 2025
Merged

Various feature additions for CUE #5352

merged 3 commits into from
Jun 13, 2025

Conversation

refi64
Copy link
Contributor

@refi64 refi64 commented Jun 10, 2025

This adds two particular changes that I found useful while using the experimental CUE integration for a project:

  • feat(experimental): Expose given values to CUE as #values

    Currently, CUE code can't interact with given values directly; instead, the rendered yaml is then templated with the values, which isn't particularly useful.

    This instead will add all the values to the CUE code's scope as a new definition named #values, which can then be accessed for the purpose of generating the final manifest. Effectively, the "templating" becomes the unification of the CUE manifest with values object.

  • feat(experimental): Treat updatecli.cue as a default filename

    We already have to pass --experimental, so also passing the filename doesn't add very much.

Test

To test this pull request, you can run the following commands:

cd <to_package_directory>
go test

Additional Information

Checklist

  • I have updated the documentation via pull request in website repository.
    • CUE doesn't seem to be documented at all here yet?

Tradeoff

Potential improvement

@olblak olblak added enhancement New feature or request cuelang labels Jun 10, 2025
@olblak
Copy link
Member

olblak commented Jun 10, 2025

CUE doesn't seem to be documented at all here yet?

It's true, I now wonder how you discover this experiment :D

I am really interested in Cuelang as I think it can make complex YAML manifests easier to maintain but I didn't have the time to finish working on it and then got distracted.

refi64 added 2 commits June 10, 2025 19:25
We already have to pass --experimental, so also passing the filename
doesn't add very much.
Currently, CUE code can't interact with given values directly; instead,
the rendered yaml is then templated with the values, which isn't
particularly useful.

This instead will add all the values to the CUE code's scope as a new
definition named `#values`, which can then be accessed for the purpose
of generating the final manifest. Effectively, the "templating" becomes
the unification of the CUE manifest with values object.
@refi64
Copy link
Contributor Author

refi64 commented Jun 11, 2025

It's true, I now wonder how you discover this experiment :D

basically random luck: I have a strange vendetta against templated YAML, and when I found updatecli I was like "huh what are the chances it supports literally anything else", lo and behold...

@olblak
Copy link
Member

olblak commented Jun 11, 2025

After experimenting a bit with your pull request, I now remember where I stopped.

I am not a Cuelang expert so maybe you'll have good suggestion.

My first problem was dynamic values, and how to handle them correctly in Cuelang.
It's quite common to use source output in manifest.
In go templates, it looks like

# Make sure that found URLs exist
conditions:
  checkGetLatestLTSLinuxAMD64InstallerURL:
    name: Check if getLatestLTSLinuxAMD64InstallerURL returns an existing URL 
    kind: file
    disablesourceinput: true
    spec:
      files:
        - '{{ source "getLatestLTSLinuxAMD64InstallerURL" }}' 

Where source is a custom Updatecli function.

The value of '{{ source "getLatestLTSLinuxAMD64InstallerURL" }}' is defined by the source configurated with the id "getLatestLTSLinuxAMD64InstallerURL"

That's an information, we only know a runtime.

That's why I was converting cuelang to yaml.
So that the following snippet could work:

sources: {
  default: {
    name: "Get latest Jenkins version"
    kind: "jenkins"
  }

  echo: {
    name: "Echo latest Jenkins version"
    kind: "shell"
    dependson: [
      "default",
    ]   
    spec: {
      command: #"echo {{ source "default" }}"#
    }   
  }

Unfortunately, I wasn't a big fan of this solution, as we now need to understand Cuelang, Updatecli. and Go templating to write a manifest...

The second limitation I faced was about using standard Cuelang libraries for example to get a value from environment variable which is a very common practice to get credentials from CI pipelines.

The final question I had was how to handle this files in an OCI registry.

Today we can publish any Updatecli manifests to an OCI registry. The way we do that is by having a specific artifact type for values files and another one for configuration files.
But If we decide to also support Cuelang module, then my understanding is that we also need to publish the cue.mod filet
I know many project just create a tgz with all the files, which could be an option

@refi64
Copy link
Contributor Author

refi64 commented Jun 13, 2025

Unfortunately, I wasn't a big fan of this solution, as we now need to understand Cuelang, Updatecli. and Go templating to write a manifest...

Ah yeah, tbh as-is this doesn't bother me too much since the only Go templating you really need to know is {{ source "name" }}. That being said, it's technically possible in CUE to get something similar, like:

sources: {
  default: Source & {
    name: "Get latest Jenkins version"
    kind: "jenkins"
  }

  echo: {
    name: "Echo latest Jenkins version"
    kind: "shell"
    dependson: [
      "default",
    ]   
    spec: {
      command: "\(sources.default.output)"
    }   
  }

You can see examples of it in CUE's tasks support or KubeVela's workflows. It's a bit tricky to implement though, because you need to partially evaluate things to get the initial sources and then re-evaluate it with those filled in.

The second limitation I faced was about using standard Cuelang libraries for example to get a value from environment variable which is a very common practice to get credentials from CI pipelines.

I think you can do something similar here, but I'm not super sure.

Today we can publish any Updatecli manifests to an OCI registry. The way we do that is by having a specific artifact type for values files and another one for configuration files.
But If we decide to also support Cuelang module, then my understanding is that we also need to publish the cue.mod filet

I...am not sure, I haven't looked into this before! I'd imagine Timoni has this sorted out though, because it lets you publish OCI images containing CUE inside.

@olblak
Copy link
Member

olblak commented Jun 13, 2025

I think we still have many open questions, but since it's an experimental feature, I am happy to merge it as is and to iterate on this
I am curious about your feedback

@olblak olblak merged commit a619432 into updatecli:main Jun 13, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cuelang enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants