Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions internal/configloader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ func LoadConfig(opts ...LoadOption) (*Config, error) {
if err := taskValidator.ValidateSemantic(); err != nil {
return nil, fmt.Errorf("task config semantic validation failed: %w", err)
}
for _, w := range taskValidator.Warnings() {
o.logger.Warn(o.ctx, w)
}
}

// 3. Merge into unified Config
Expand Down
15 changes: 11 additions & 4 deletions internal/configloader/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func (v *AdapterConfigValidator) ValidateStructure() error {
type TaskConfigValidator struct {
config *AdapterTaskConfig
errors *ValidationErrors
warnings []string
definedVars map[string]bool
celEnv *cel.Env
baseDir string
Expand All @@ -72,6 +73,11 @@ func NewTaskConfigValidator(config *AdapterTaskConfig, baseDir string) *TaskConf
}
}

// Warnings returns deprecation warnings collected during validation.
func (v *TaskConfigValidator) Warnings() []string {
return v.warnings
}

// ValidateStructure validates the structural requirements of AdapterTaskConfig
func (v *TaskConfigValidator) ValidateStructure() error {
if v.config == nil {
Expand Down Expand Up @@ -182,15 +188,16 @@ func (v *TaskConfigValidator) validatePreconditionAPICallForbidden() {
for i, precond := range v.config.Preconditions {
if precond.APICall != nil {
path := fmt.Sprintf("%s[%d].%s", FieldPreconditions, i, FieldAPICall)
v.errors.Add(path, fmt.Sprintf(
"precondition %q contains api_call. api_call is no longer valid in the precondition phase.\n"+
"Move the api_call block to a params entry:\n"+
v.warnings = append(v.warnings, fmt.Sprintf(
"%s: DEPRECATED: precondition %q uses api_call directly. "+
"Move the api_call block to a params entry with source.api_call instead. "+
"Direct api_call on preconditions will be removed in a future release.\n"+
" params:\n"+
" - name: %q\n"+
" source:\n"+
" api_call:\n"+
" ...",
precond.Name, precond.Name))
path, precond.Name, precond.Name))
}
}
}
Expand Down
14 changes: 9 additions & 5 deletions internal/configloader/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1228,7 +1228,7 @@ func TestValidateParamsAPICallSource(t *testing.T) {
}

func TestValidatePreconditionAPICallForbidden(t *testing.T) {
t.Run("precondition with api_call produces migration error", func(t *testing.T) {
t.Run("precondition with api_call produces deprecation warning not error", func(t *testing.T) {
cfg := baseTaskConfig()
cfg.Preconditions = []Precondition{{
ActionBase: ActionBase{
Expand All @@ -1239,12 +1239,15 @@ func TestValidatePreconditionAPICallForbidden(t *testing.T) {
v := newTaskValidator(cfg)
_ = v.ValidateStructure()
err := v.ValidateSemantic()
require.Error(t, err)
assert.Contains(t, err.Error(), "api_call is no longer valid in the precondition phase")
assert.Contains(t, err.Error(), "fetchCluster")
require.NoError(t, err)
warnings := v.Warnings()
require.Len(t, warnings, 1)
assert.Contains(t, warnings[0], "DEPRECATED")
assert.Contains(t, warnings[0], "fetchCluster")
assert.Contains(t, warnings[0], "source.api_call")
})

t.Run("precondition without api_call passes", func(t *testing.T) {
t.Run("precondition without api_call passes with no warnings", func(t *testing.T) {
cfg := baseTaskConfig()
cfg.Preconditions = []Precondition{{
ActionBase: ActionBase{Name: "check"},
Expand All @@ -1253,5 +1256,6 @@ func TestValidatePreconditionAPICallForbidden(t *testing.T) {
v := newTaskValidator(cfg)
require.NoError(t, v.ValidateStructure())
require.NoError(t, v.ValidateSemantic())
assert.Empty(t, v.Warnings())
})
}