Skip to content

feat: add CRE runner to environment object#877

Open
ecPablo wants to merge 11 commits intomainfrom
ecpablo/add-cre-cli-runner
Open

feat: add CRE runner to environment object#877
ecPablo wants to merge 11 commits intomainfrom
ecpablo/add-cre-cli-runner

Conversation

@ecPablo
Copy link
Contributor

@ecPablo ecPablo commented Mar 19, 2026

Adds CRE CLI runner to the environment object as well as config variables.

AI Summary

This pull request introduces a new abstraction for invoking the CRE CLI tool within the deployment framework. The main changes are the addition of the Runner interface (with a default implementation CLIRunner), integration of this runner into the environment loading process, and support for configuration and testing of CRE CLI invocations. These changes enable flexible and testable interaction with the CRE CLI, including error handling and output inspection.

CRE CLI Integration

  • Added the cre.Runner interface and cre.CLIRunner implementation for running the CRE CLI, along with supporting types (CallResult, ExitError) and comprehensive unit tests. [1] [2] [3] [4] [5]
  • Integrated CRERunner into the Environment struct and environment loading logic, allowing CRE CLI invocation from changesets and supporting cloning of environments with the runner. [1] [2] [3] [4] [5] [6] [7] [8]

Configuration and Options

  • Added environment options for configuring the CRE CLI runner and binary path (WithCRERunner, WithCREBinaryPath), and implemented logic to resolve the runner based on overrides or binary path. [1] [2]
  • Extended environment variable mapping to include CRE-related settings such as authentication and storage address.

Testing and Mocking

  • Generated a mock for the Runner interface using mockery and added tests for runner configuration and resolution logic. [1] [2]

Dependency and Import Updates

  • Updated imports across multiple files to reference the new cre package and runner abstraction. [1] [2] [3] [4]

Test Environment Support

  • Updated test environment components and loader to support injecting a mock CRE runner for testing scenarios. [1] [2] [3]

These changes collectively provide a robust, configurable, and testable mechanism for interacting with the CRE CLI in deployment environments.

@changeset-bot
Copy link

changeset-bot bot commented Mar 19, 2026

⚠️ No Changeset found

Latest commit: d85660e

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

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

Adds a CRE CLI runner abstraction and threads it through environment construction so changesets/tests can invoke CRE via a pluggable runner.

Changes:

  • Introduce cre.Runner interface, CLIRunner implementation, ExitError, plus unit tests and a mock.
  • Add CRERunner to deployment.Environment, propagate it through cloning/runtime env regeneration, and expose options for CLD/test environments.
  • Minor mermaid renderer change to avoid fmt.Sprintf + WriteString pattern.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pkg/cre/runner.go Defines the core Runner interface and CallResult.
pkg/cre/cli_runner.go Implements Runner using os/exec and captures stdout/stderr/exit code.
pkg/cre/exit.go Adds ExitError for non-zero process exits.
pkg/cre/cli_runner_test.go Tests CLIRunner behavior (success, non-zero exit, missing binary, canceled ctx).
pkg/cre/exit_test.go Tests ExitError formatting and errors.As behavior.
pkg/cre/mocks/mock_runner.go Adds mockery-generated mock for cre.Runner.
deployment/environment.go Adds CRERunner field + WithCRERunner option + clones the field.
engine/test/environment/components.go Adds CRERunner to test environment components.
engine/test/environment/options.go Adds WithCRERunner LoadOpt for test environments.
engine/test/environment/environment.go Wires cmps.CRERunner into the returned test Environment.
engine/test/runtime/environment.go Preserves CRERunner when regenerating env from state.
engine/cld/environment/options.go Adds CLD options for CRE runner override and binary path + resolver helper.
engine/cld/environment/environment.go Sets Environment.CRERunner during CLD env load.
engine/cld/environment/fork.go Injects resolved runner into fork env creation.
engine/cld/config/env/config.go Adds viper env bindings for cre.* config keys.
engine/cld/mcms/proposalanalysis/examples/ccip/renderers/mermaid/renderer.go Switches to fmt.Fprintf(&builder, ...) for a few writes.
.mockery.yml Configures mockery generation for cre.Runner.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@ecPablo ecPablo marked this pull request as ready for review March 20, 2026 14:26
@ecPablo ecPablo requested a review from a team as a code owner March 20, 2026 14:27
Copilot AI review requested due to automatic review settings March 20, 2026 14:27
Copy link
Contributor

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

Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@ecPablo ecPablo marked this pull request as draft March 20, 2026 16:38
ecPablo and others added 4 commits March 20, 2026 10:50
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@cl-sonarqube-production
Copy link

@ecPablo ecPablo marked this pull request as ready for review March 20, 2026 19:35
Copilot AI review requested due to automatic review settings March 20, 2026 19:35
Copy link
Contributor

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

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +84 to +85
return &MockRunner_Call_Call{Call: _e.mock.On("Call",
append([]interface{}{ctx}, args...)...)}
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

The generated mock’s variadic handling is inconsistent: Call(ctx, args...) forwards the variadic as a single []string argument (_mock.Called(ctx, args)), but the EXPECT().Call(...) helper builds expectations as if each variadic element were a separate argument (append([]interface{}{ctx}, args...)). As a result, EXPECT().Call(ctx, "build") will never match a real call; expectations must use a single []string, which is surprising and easy to misuse. Consider changing the Runner API to Call(ctx, args []string) (non-variadic), or adjust the mock generation/template so the expecter helper also expects a single []string argument.

Suggested change
return &MockRunner_Call_Call{Call: _e.mock.On("Call",
append([]interface{}{ctx}, args...)...)}
// Normalize the variadic arguments so that the underlying mock always
// sees the same shape as (*MockRunner).Call, i.e. (ctx, []string).
var argSlice []string
if len(args) == 1 {
// If the caller passed a single []string, use it directly.
if s, ok := args[0].([]string); ok {
argSlice = s
}
}
if argSlice == nil {
// Otherwise, treat each variadic element as a string and build []string.
argSlice = make([]string, len(args))
for i, a := range args {
argSlice[i] = a.(string)
}
}
return &MockRunner_Call_Call{Call: _e.mock.On("Call", ctx, argSlice)}

Copilot uses AI. Check for mistakes.
Comment on lines +143 to +149
// CREAuthConfig holds authentication settings for CRE (Chainlink Runtime Environment) deploy operations.
type CREAuthConfig struct {
HMACKeyID string `mapstructure:"hmac_key_id" yaml:"hmac_key_id"` // Secret: HMAC key ID
HMACKeySecret string `mapstructure:"hmac_key_secret" yaml:"hmac_key_secret"` // Secret: HMAC key secret
TenantID string `mapstructure:"tenant_id" yaml:"tenant_id"`
OrgID string `mapstructure:"org_id" yaml:"org_id"`
}
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

CREAuthConfig introduces secret fields (HMAC key ID/secret) but lacks the same WARNING header used by other secret-bearing config structs in this file (e.g., KMSConfig, EVMConfig, JobDistributorAuth). Adding a similar warning helps prevent accidental logging or committing these credentials to config files.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

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

it'd be good to hear from cldf original maintainers if a root cre package is the way to go


// Runner is used to invoke the CRE CLI.
type Runner interface {
Call(ctx context.Context, args ...string) (*CallResult, error)
Copy link
Contributor

Choose a reason for hiding this comment

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

if it's a Runner maybe the method should be called Run?

cmd.Stdout = &stdout
cmd.Stderr = &stderr

err := cmd.Run()
Copy link
Contributor

Choose a reason for hiding this comment

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

minor observation: this means we can only run the cli commands synchronously, and will get no feedback until it's finished, correct?

I just wanted to check if this is desired, as it might be a good idea to review the design in case some of the commands take several seconds (for instance, by providing options to stream the commands stdout and/or stderr to custom io writers).

{
name: "success",
skip: "windows",
runner: &CLIRunner{BinaryPath: "true"},
Copy link
Contributor

@gustavogama-cll gustavogama-cll Mar 20, 2026

Choose a reason for hiding this comment

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

problaby better to use a command that outputs something to stderr and stdout, and then add the associated assertions.

// CRERunner invokes the CRE CLI from changesets. Optional in environment loading, so it won't
// fail to load environment if cre binary not available; failures (e.g. binary not found) only occur
// when CRERunner.Call() is used inside changesets. May be nil in test environments that did not set it.
CRERunner cre.Runner
Copy link
Contributor

Choose a reason for hiding this comment

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

forgive the ignorance, but does the cre client communicate with the blockchain directly? If not, should if be part of offchain.Client?

Onchain OnchainConfig `mapstructure:"onchain" yaml:"onchain"`
Offchain OffchainConfig `mapstructure:"offchain" yaml:"offchain"`
Catalog CatalogConfig `mapstructure:"catalog" yaml:"catalog"`
// CRE is optional. If the cre block is absent from YAML and CRE_* env vars are unset,
Copy link
Contributor

Choose a reason for hiding this comment

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

this is true for several other parts of the config. Maybe the comment is not needed. Or just use a shorter one.

}

// resolveCRERunner returns override if set, otherwise a CLIRunner for the given path.
func resolveCRERunner(override cre.Runner, binaryPath string) cre.Runner {
Copy link
Contributor

Choose a reason for hiding this comment

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

hmm.. this looks a bit confusing. Why can't we get away with WithCRERunner alone? At first glance it seems the resolveCRERunner and WithCREBinaryPath functions are redundant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants