From daccc5b18f30a77e10ad09699e2ce09ec1bba0b7 Mon Sep 17 00:00:00 2001 From: "Christian G. Warden" Date: Tue, 17 Mar 2026 17:51:19 -0500 Subject: [PATCH] Add --no-ancestor Flag And Extend `package version create` Timeout Add a --no-ancestor flag to package version create and make it mutually exclusive with ancestor-id. When the flag is set, skip automatic ancestor lookup so the descriptor is sent with an explicit empty ancestor ID. Increase the package version creation polling window from 10 minutes to 30 minutes and update the timeout message to match the new limit. --- command/package.go | 19 +++++++++++++------ command/package_test.go | 23 ++++++++++++++++++++++- docs/force_package_version_create.md | 2 +- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/command/package.go b/command/package.go index e61fd638..c20ee06e 100644 --- a/command/package.go +++ b/command/package.go @@ -41,12 +41,14 @@ func init() { packageVersionCreateCmd.Flags().StringP("version-name", "m", "", "Version name (optional, defaults to version-number)") packageVersionCreateCmd.Flags().StringP("version-description", "d", "", "Version description (optional, defaults to version-number)") packageVersionCreateCmd.Flags().StringP("ancestor-id", "", "", "Ancestor version ID (optional)") + packageVersionCreateCmd.Flags().BoolP("no-ancestor", "", false, "Explicitly set ancestorId to an empty string") packageVersionCreateCmd.Flags().StringArrayP("dependency", "", []string{}, "Subscriber Package Version ID (04t) dependency (can be specified multiple times)") packageVersionCreateCmd.Flags().StringP("tag", "", "", "Tag to set on the Package2VersionCreateRequest") packageVersionCreateCmd.Flags().BoolP("skip-validation", "s", false, "Skip validation") packageVersionCreateCmd.Flags().BoolP("async-validation", "y", false, "Async validation") packageVersionCreateCmd.Flags().BoolP("code-coverage", "c", true, "Calculate code coverage") packageVersionCreateCmd.MarkFlagRequired("version-number") + packageVersionCreateCmd.MarkFlagsMutuallyExclusive("ancestor-id", "no-ancestor") packageVersionReleaseCmd.Flags().StringP("version-id", "v", "", "Package Version ID (required)") packageVersionReleaseCmd.MarkFlagRequired("version-id") @@ -167,6 +169,7 @@ var packageVersionCreateCmd = &cobra.Command{ versionName, _ := cmd.Flags().GetString("version-name") versionDescription, _ := cmd.Flags().GetString("version-description") ancestorId, _ := cmd.Flags().GetString("ancestor-id") + noAncestor, _ := cmd.Flags().GetBool("no-ancestor") dependencies, _ := cmd.Flags().GetStringArray("dependency") tag, _ := cmd.Flags().GetString("tag") skipValidation, _ := cmd.Flags().GetBool("skip-validation") @@ -174,7 +177,7 @@ var packageVersionCreateCmd = &cobra.Command{ codeCoverage, _ := cmd.Flags().GetBool("code-coverage") runCreatePackageVersion(path, packageId, namespace, versionNumber, versionName, - versionDescription, ancestorId, dependencies, tag, skipValidation, asyncValidation, codeCoverage) + versionDescription, ancestorId, noAncestor, dependencies, tag, skipValidation, asyncValidation, codeCoverage) }, } @@ -572,7 +575,7 @@ func pollPackageUninstallStatus(requestId string) { } func runCreatePackageVersion(path string, packageId string, namespace string, versionNumber string, - versionName string, versionDescription string, ancestorId string, dependencies []string, tag string, + versionName string, versionDescription string, ancestorId string, noAncestor bool, dependencies []string, tag string, skipValidation bool, asyncValidation bool, codeCoverage bool) { // Use version-number as default for version-name and version-description if not provided @@ -617,8 +620,12 @@ func runCreatePackageVersion(path string, packageId string, namespace string, ve } } - // If ancestor-id is not provided, query for the last released version - if ancestorId == "" { + if noAncestor { + ancestorId = "" + } + + // If ancestor-id is not provided and --no-ancestor is not set, query for the last released version + if ancestorId == "" && !noAncestor { query := fmt.Sprintf("SELECT Id FROM Package2Version WHERE Package2Id = '%s' AND IsReleased = true AND PatchVersion = 0 ORDER BY MajorVersion DESC, MinorVersion DESC, PatchVersion DESC, BuildNumber DESC LIMIT 1", packageId) result, err := force.Query(query, func(options *lib.QueryOptions) { options.IsTooling = true @@ -849,7 +856,7 @@ func buildPackageVersionDescriptor(versionName string, versionNumber string, ver func pollPackageVersionStatus(requestId string) string { query := fmt.Sprintf("SELECT Id, Status, Package2VersionId FROM Package2VersionCreateRequest WHERE Id = '%s'", requestId) - for i := 0; i < 120; i++ { // Poll for up to 10 minutes + for i := 0; i < 360; i++ { // Poll for up to 30 minutes (5 seconds * 360) time.Sleep(5 * time.Second) result, err := force.Query(query, func(options *lib.QueryOptions) { @@ -894,7 +901,7 @@ func pollPackageVersionStatus(requestId string) string { } } - ErrorAndExit("Package version creation timed out") + ErrorAndExit("Package version creation timed out after 30 minutes") return "" } diff --git a/command/package_test.go b/command/package_test.go index 22a46b39..003f658a 100644 --- a/command/package_test.go +++ b/command/package_test.go @@ -50,7 +50,7 @@ func Test_package_version_create_command_has_optional_flags(t *testing.T) { cmd := packageVersionCreateCmd // Test that optional flags exist - optionalFlags := []string{"version-name", "version-description", "ancestor-id", "dependency", "skip-validation", "async-validation", "code-coverage"} + optionalFlags := []string{"version-name", "version-description", "ancestor-id", "no-ancestor", "dependency", "skip-validation", "async-validation", "code-coverage"} for _, flagName := range optionalFlags { flag := cmd.Flags().Lookup(flagName) @@ -60,6 +60,27 @@ func Test_package_version_create_command_has_optional_flags(t *testing.T) { } } +func Test_package_version_create_command_marks_ancestor_flags_mutually_exclusive(t *testing.T) { + cmd := packageVersionCreateCmd + + for _, flagName := range []string{"ancestor-id", "no-ancestor"} { + flag := cmd.Flags().Lookup(flagName) + if flag == nil { + t.Fatalf("Flag %s not found", flagName) + } + + annotations := flag.Annotations + if annotations == nil { + t.Fatalf("Flag %s is missing annotations", flagName) + } + + values, ok := annotations["cobra_annotation_mutually_exclusive"] + if !ok || len(values) == 0 { + t.Fatalf("Flag %s is not marked mutually exclusive", flagName) + } + } +} + func Test_package_version_create_command_dependency_flag_is_repeatable(t *testing.T) { cmd := packageVersionCreateCmd diff --git a/docs/force_package_version_create.md b/docs/force_package_version_create.md index 5db58ba1..20523536 100644 --- a/docs/force_package_version_create.md +++ b/docs/force_package_version_create.md @@ -13,6 +13,7 @@ force package version create [path] [flags] -y, --async-validation Async validation -c, --code-coverage Calculate code coverage (default true) -h, --help help for create + --no-ancestor Explicitly set ancestorId to an empty string --namespace string Package namespace (alternative to --package-id) -i, --package-id string Package ID (required if --namespace not provided) -s, --skip-validation Skip validation @@ -33,4 +34,3 @@ force package version create [path] [flags] ### SEE ALSO * [force package version](force_package_version.md) - Manage package versions -