diff --git a/app/cli/cmd/attestation_init.go b/app/cli/cmd/attestation_init.go index e70584e80..bd3d75812 100644 --- a/app/cli/cmd/attestation_init.go +++ b/app/cli/cmd/attestation_init.go @@ -57,19 +57,23 @@ func newAttestationInitCmd() *cobra.Command { return errors.New("workflow name is required, set it via --workflow flag") } - // load version from the file if not set and not using --latest-version - if projectVersion == "" && !useLatestVersion { - // load the cfg from the file + // Load project name and version from .chainloop.yaml when the + // corresponding CLI flags are not provided. + // Precedence: CLI flag > .chainloop.yaml > default/auto-discovery. + if projectName == "" || (projectVersion == "" && !useLatestVersion) { cfg, path, err := loadDotChainloopConfigWithParentTraversal() - // we do gracefully load, if not found, or any other error we continue if err != nil { logger.Debug().Msgf("failed to load chainloop config: %s", err) - return nil + } else { + if projectName == "" && cfg.Project != "" { + logger.Debug().Msgf("loaded project %q from config file %s", cfg.Project, path) + projectName = cfg.Project + } + if projectVersion == "" && !useLatestVersion && cfg.ProjectVersion != "" { + logger.Debug().Msgf("loaded version %q from config file %s", cfg.ProjectVersion, path) + projectVersion = cfg.ProjectVersion + } } - - logger.Debug().Msgf("loaded version %s from config file %s", cfg.ProjectVersion, path) - - projectVersion = cfg.ProjectVersion } if useLatestVersion && projectVersion != "" { @@ -172,7 +176,7 @@ func newAttestationInitCmd() *cobra.Command { } if projectName == "" { - logger.Warn().Msg("DEPRECATION WARNING: --project not set, this will be required in the near future") + logger.Warn().Msg("DEPRECATION WARNING: project not set via --project flag or .chainloop.yaml, this will be required in the near future") } return output.EncodeOutput(flagOutputFormat, res, fullStatusTable) @@ -191,8 +195,7 @@ func newAttestationInitCmd() *cobra.Command { cmd.Flags().StringVar(&workflowName, "workflow-name", "", "name of the workflow to run the attestation") cobra.CheckErr(cmd.Flags().MarkDeprecated("workflow-name", "please use --workflow instead")) - cmd.Flags().StringVar(&projectName, "project", "", "name of the project of this workflow") - cobra.CheckErr(cmd.MarkFlagRequired("project")) + cmd.Flags().StringVar(&projectName, "project", "", "name of the project of this workflow (can also be set in .chainloop.yaml)") cmd.Flags().StringVar(&newWorkflowcontract, "contract", "", "name of an existing contract or the path/URL to a contract file, to attach it to the auto-created workflow (it doesn't update an existing one)") cmd.Flags().StringVar(&projectVersion, "version", "", "project version, i.e 0.1.0") diff --git a/app/cli/cmd/attestation_test.go b/app/cli/cmd/attestation_test.go index 686df0dff..3f7b7aaa5 100644 --- a/app/cli/cmd/attestation_test.go +++ b/app/cli/cmd/attestation_test.go @@ -77,6 +77,31 @@ func TestOrgFromLocalState(t *testing.T) { }) } +func TestAttestationInitProjectFromDotChainloop(t *testing.T) { + t.Chdir(t.TempDir()) + require.NoError(t, os.WriteFile(".chainloop.yaml", []byte("project: config-project\n"), 0o600)) + + for _, tc := range []struct { + name string + cliProject string + want string + }{ + {name: "from config", want: "config-project"}, + {name: "CLI takes precedence", cliProject: "cli-project", want: "cli-project"}, + } { + t.Run(tc.name, func(t *testing.T) { + cmd := newAttestationInitCmd() + require.NoError(t, cmd.Flags().Set("workflow", "test-workflow")) + if tc.cliProject != "" { + require.NoError(t, cmd.Flags().Set("project", tc.cliProject)) + } + + require.NoError(t, cmd.PreRunE(cmd, nil)) + assert.Equal(t, tc.want, cmd.Flags().Lookup("project").Value.String()) + }) + } +} + func TestExtractAnnotations(t *testing.T) { testCases := []struct { input []string diff --git a/app/cli/cmd/config.go b/app/cli/cmd/config.go index 8feaae581..12ec10c0a 100644 --- a/app/cli/cmd/config.go +++ b/app/cli/cmd/config.go @@ -165,4 +165,5 @@ func isDir(filename string) bool { type DotChainloopConfig struct { ProjectVersion string `yaml:"projectVersion"` + Project string `yaml:"project"` } diff --git a/app/cli/documentation/cli-reference.mdx b/app/cli/documentation/cli-reference.mdx index 63e58e572..e069d76a1 100755 --- a/app/cli/documentation/cli-reference.mdx +++ b/app/cli/documentation/cli-reference.mdx @@ -351,7 +351,7 @@ Options --latest-version use the latest existing project version instead of specifying one --mark-latest explicitly mark the project version as latest (default: automatic for new versions; use =false to skip promotion) (default true) --pr mark this attestation as a pull/merge request build (skips latest promotion and sets the chainloop.dev/is-pull-request annotation; auto-detected from CI env if not set) ---project string name of the project of this workflow +--project string name of the project of this workflow (can also be set in .chainloop.yaml) --release promote the provided version as a release --remote-state Store the attestation state remotely -f, --replace replace any existing in-progress attestation