From 3867a4f1200dc306e7eff9dd741a364353e9e948 Mon Sep 17 00:00:00 2001 From: Ky_pham <57948086+hongky-1994@users.noreply.github.com> Date: Mon, 28 Apr 2025 16:19:32 +0700 Subject: [PATCH 1/3] Fix deployment tracing loading nonStop when loadmore (#5780) Signed-off-by: kypham Signed-off-by: pipecd-bot --- .../deployment-trace-page/useGroupedDeploymentTrace.tsx | 5 ++++- web/src/modules/deploymentTrace/index.ts | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/web/src/components/deployment-trace-page/useGroupedDeploymentTrace.tsx b/web/src/components/deployment-trace-page/useGroupedDeploymentTrace.tsx index 2f2505e74b..9a327bde8d 100644 --- a/web/src/components/deployment-trace-page/useGroupedDeploymentTrace.tsx +++ b/web/src/components/deployment-trace-page/useGroupedDeploymentTrace.tsx @@ -41,7 +41,10 @@ const useGroupedDeploymentTrace = (): GroupedDeploymentTrace => { }, [traceList]); const dates = useMemo( - () => Object.keys(deploymentTracesMap).sort(sortDateFunc), + () => + Object.keys(deploymentTracesMap).sort((a, b) => + sortDateFunc(a, b, "DESC") + ), [deploymentTracesMap] ); diff --git a/web/src/modules/deploymentTrace/index.ts b/web/src/modules/deploymentTrace/index.ts index fce65b8130..9dcba2954f 100644 --- a/web/src/modules/deploymentTrace/index.ts +++ b/web/src/modules/deploymentTrace/index.ts @@ -82,13 +82,13 @@ export const fetchMoreDeploymentTraces = createAsyncThunk< DeploymentTraceFilterOptions, { state: AppState } >("deploymentTrace/fetchMoreList", async (options, thunkAPI) => { - const { deployments } = thunkAPI.getState(); + const { deploymentTrace } = thunkAPI.getState(); const response = await deploymentTracesApi.getDeploymentTraces({ options: convertFilterOptions(options), pageSize: FETCH_MORE_ITEMS_PER_PAGE, - cursor: deployments.cursor, - pageMinUpdatedAt: deployments.minUpdatedAt, + cursor: deploymentTrace.cursor, + pageMinUpdatedAt: deploymentTrace.minUpdatedAt, }); return response; From 847b48f2d699e2a254f849f2a71c87673e895fed Mon Sep 17 00:00:00 2001 From: Shinnosuke Sawada-Dazai Date: Tue, 13 May 2025 10:15:26 +0900 Subject: [PATCH 2/3] Implement comparing bool with boolean string value (#5811) * Add support for comparing boolean values with boolean strings in the differ package Signed-off-by: Shinnosuke Sawada-Dazai * Add support for rendering boolean values in the diff package Signed-off-by: Shinnosuke Sawada-Dazai * Port of pkgs/diff to pkg/plugin/diff Signed-off-by: Shinnosuke Sawada-Dazai * Add support for comparing boolean values with boolean strings in cloudrundiff function Signed-off-by: Shinnosuke Sawada-Dazai --------- Signed-off-by: Shinnosuke Sawada-Dazai Signed-off-by: pipecd-bot --- .../piped/driftdetector/cloudrun/detector.go | 1 + pkg/app/piped/planpreview/cloudrundiff.go | 1 + pkg/diff/diff.go | 50 +++++++++++++++++-- pkg/diff/diff_test.go | 1 + pkg/diff/renderer.go | 3 ++ pkg/diff/renderer_test.go | 20 ++++++++ pkg/diff/testdata/no_diff.yaml | 8 +++ pkg/plugin/diff/diff.go | 50 +++++++++++++++++-- pkg/plugin/diff/diff_test.go | 1 + pkg/plugin/diff/renderer.go | 3 ++ pkg/plugin/diff/renderer_test.go | 20 ++++++++ pkg/plugin/diff/testdata/no_diff.yaml | 8 +++ 12 files changed, 156 insertions(+), 10 deletions(-) diff --git a/pkg/app/piped/driftdetector/cloudrun/detector.go b/pkg/app/piped/driftdetector/cloudrun/detector.go index fc0386c995..5f31f520dc 100644 --- a/pkg/app/piped/driftdetector/cloudrun/detector.go +++ b/pkg/app/piped/driftdetector/cloudrun/detector.go @@ -211,6 +211,7 @@ func (d *detector) checkApplication(ctx context.Context, app *model.Application, diff.WithEquateEmpty(), diff.WithIgnoreAddingMapKeys(), diff.WithCompareNumberAndNumericString(), + diff.WithCompareBooleanAndBooleanString(), ) if err != nil { return err diff --git a/pkg/app/piped/planpreview/cloudrundiff.go b/pkg/app/piped/planpreview/cloudrundiff.go index 1ffa3a4794..8ad7212996 100644 --- a/pkg/app/piped/planpreview/cloudrundiff.go +++ b/pkg/app/piped/planpreview/cloudrundiff.go @@ -66,6 +66,7 @@ func (b *builder) cloudrundiff( newManifest, diff.WithEquateEmpty(), diff.WithCompareNumberAndNumericString(), + diff.WithCompareBooleanAndBooleanString(), ) if err != nil { fmt.Fprintf(buf, "failed to compare manifests (%v)\n", err) diff --git a/pkg/diff/diff.go b/pkg/diff/diff.go index 1d4d1aad14..0542ef655d 100644 --- a/pkg/diff/diff.go +++ b/pkg/diff/diff.go @@ -25,11 +25,12 @@ import ( ) type differ struct { - ignoreAddingMapKeys bool - equateEmpty bool - compareNumberAndNumericString bool - ignoredPaths map[string]struct{} - ignoreConfig map[string][]string + ignoreAddingMapKeys bool + equateEmpty bool + compareNumberAndNumericString bool + compareBooleanAndBooleanString bool + ignoredPaths map[string]struct{} + ignoreConfig map[string][]string result *Result } @@ -60,6 +61,15 @@ func WithCompareNumberAndNumericString() Option { } } +// WithCompareBooleanAndBooleanString configures differ to compare a boolean with a string. +// Differ parses the string to boolean before comparing their values. +// e.g. true == "true" +func WithCompareBooleanAndBooleanString() Option { + return func(d *differ) { + d.compareBooleanAndBooleanString = true + } +} + // WithIgnoreConfig configures ignored fields. func WithIgnoreConfig(config map[string][]string) Option { return func(d *differ) { @@ -170,6 +180,24 @@ func (d *differ) diff(path []PathStep, vx, vy reflect.Value) error { } } + if isBooleanValue(vx) && isBooleanValue(vy) { + return d.diffBool(path, vx, vy) + } + + if d.compareBooleanAndBooleanString { + if isBooleanValue(vx) { + if y, ok := convertToBoolean(vy); ok { + return d.diffBool(path, vx, y) + } + } + + if isBooleanValue(vy) { + if x, ok := convertToBoolean(vx); ok { + return d.diffBool(path, x, vy) + } + } + } + if vx.Type() != vy.Type() { d.addNode(path, vx.Type(), vy.Type(), vx, vy) return nil @@ -360,6 +388,18 @@ func convertToNumber(v reflect.Value) (reflect.Value, bool) { } } +func isBooleanValue(v reflect.Value) bool { + return v.Kind() == reflect.Bool +} + +func convertToBoolean(v reflect.Value) (reflect.Value, bool) { + if v.Kind() == reflect.String { + b, err := strconv.ParseBool(v.String()) + return reflect.ValueOf(b), err == nil + } + return v, false +} + func newSlicePath(path []PathStep, index int) []PathStep { next := make([]PathStep, len(path)) copy(next, path) diff --git a/pkg/diff/diff_test.go b/pkg/diff/diff_test.go index 1f19234e0d..d836905295 100644 --- a/pkg/diff/diff_test.go +++ b/pkg/diff/diff_test.go @@ -42,6 +42,7 @@ func TestDiff(t *testing.T) { WithEquateEmpty(), WithIgnoreAddingMapKeys(), WithCompareNumberAndNumericString(), + WithCompareBooleanAndBooleanString(), }, diffNum: 0, }, diff --git a/pkg/diff/renderer.go b/pkg/diff/renderer.go index 0ad9e5cd7b..b9c077d48f 100644 --- a/pkg/diff/renderer.go +++ b/pkg/diff/renderer.go @@ -206,6 +206,9 @@ func renderNodeValue(v reflect.Value, prefix string) (string, bool) { case reflect.Float32, reflect.Float64: return strconv.FormatFloat(v.Float(), 'f', -1, 64), false + case reflect.Bool: + return strconv.FormatBool(v.Bool()), false + default: return v.String(), false } diff --git a/pkg/diff/renderer_test.go b/pkg/diff/renderer_test.go index d9b0595f92..400c896297 100644 --- a/pkg/diff/renderer_test.go +++ b/pkg/diff/renderer_test.go @@ -43,6 +43,10 @@ func TestRenderNodeValue(t *testing.T) { "one": []string{"one-1", "one-2"}, "two": []string{"two-1", "two-2"}, } + mapOfBool = map[string]interface{}{ + "false": false, + "true": true, + } ) testcases := []struct { @@ -65,6 +69,16 @@ func TestRenderNodeValue(t *testing.T) { value: reflect.ValueOf("hello"), expected: "hello", }, + { + name: "bool value (true)", + value: reflect.ValueOf(true), + expected: "true", + }, + { + name: "bool value (false)", + value: reflect.ValueOf(false), + expected: "false", + }, { name: "slice of primitive elements", value: func() reflect.Value { @@ -142,6 +156,12 @@ two: two-value`, - b 7-string: hi`, }, + { + name: "map of bool", + value: reflect.ValueOf(mapOfBool), + expected: `false: false +true: true`, + }, } for _, tc := range testcases { diff --git a/pkg/diff/testdata/no_diff.yaml b/pkg/diff/testdata/no_diff.yaml index 3f5f689c5e..7a2637023b 100644 --- a/pkg/diff/testdata/no_diff.yaml +++ b/pkg/diff/testdata/no_diff.yaml @@ -9,6 +9,10 @@ metadata: zeroString1: "" zeroInt1: 0 zeroFloat1: 0.0 + booleanString1: "true" + booleanString2: true + booleanString3: "false" + booleanString4: false spec: replicas: 2 number: 1 @@ -53,6 +57,10 @@ metadata: zeroString2: "" zeroInt2: 0 zeroFloat2: 0.0 + booleanString1: true + booleanString2: "true" + booleanString3: false + booleanString4: "false" spec: replicas: 2 number: 1.0 diff --git a/pkg/plugin/diff/diff.go b/pkg/plugin/diff/diff.go index 9b188bd1c1..1f373e0620 100644 --- a/pkg/plugin/diff/diff.go +++ b/pkg/plugin/diff/diff.go @@ -24,11 +24,12 @@ import ( ) type differ struct { - ignoreAddingMapKeys bool - equateEmpty bool - compareNumberAndNumericString bool - ignoredPaths map[string]struct{} - ignoreConfig map[string][]string + ignoreAddingMapKeys bool + equateEmpty bool + compareNumberAndNumericString bool + compareBooleanAndBooleanString bool + ignoredPaths map[string]struct{} + ignoreConfig map[string][]string result *Result } @@ -59,6 +60,15 @@ func WithCompareNumberAndNumericString() Option { } } +// WithCompareBooleanAndBooleanString configures differ to compare a boolean with a string. +// Differ parses the string to boolean before comparing their values. +// e.g. true == "true" +func WithCompareBooleanAndBooleanString() Option { + return func(d *differ) { + d.compareBooleanAndBooleanString = true + } +} + // WithIgnoreConfig configures ignored fields. func WithIgnoreConfig(config map[string][]string) Option { return func(d *differ) { @@ -135,6 +145,24 @@ func (d *differ) diff(path []PathStep, vx, vy reflect.Value) error { } } + if isBooleanValue(vx) && isBooleanValue(vy) { + return d.diffBool(path, vx, vy) + } + + if d.compareBooleanAndBooleanString { + if isBooleanValue(vx) { + if y, ok := convertToBoolean(vy); ok { + return d.diffBool(path, vx, y) + } + } + + if isBooleanValue(vy) { + if x, ok := convertToBoolean(vx); ok { + return d.diffBool(path, x, vy) + } + } + } + if vx.Type() != vy.Type() { d.addNode(path, vx.Type(), vy.Type(), vx, vy) return nil @@ -325,6 +353,18 @@ func convertToNumber(v reflect.Value) (reflect.Value, bool) { } } +func isBooleanValue(v reflect.Value) bool { + return v.Kind() == reflect.Bool +} + +func convertToBoolean(v reflect.Value) (reflect.Value, bool) { + if v.Kind() == reflect.String { + b, err := strconv.ParseBool(v.String()) + return reflect.ValueOf(b), err == nil + } + return v, false +} + func newSlicePath(path []PathStep, index int) []PathStep { next := make([]PathStep, len(path)) copy(next, path) diff --git a/pkg/plugin/diff/diff_test.go b/pkg/plugin/diff/diff_test.go index d1bffcf4c5..f26816b9a0 100644 --- a/pkg/plugin/diff/diff_test.go +++ b/pkg/plugin/diff/diff_test.go @@ -42,6 +42,7 @@ func TestDiff(t *testing.T) { WithEquateEmpty(), WithIgnoreAddingMapKeys(), WithCompareNumberAndNumericString(), + WithCompareBooleanAndBooleanString(), }, diffNum: 0, }, diff --git a/pkg/plugin/diff/renderer.go b/pkg/plugin/diff/renderer.go index 0bdbe22828..a5655aacea 100644 --- a/pkg/plugin/diff/renderer.go +++ b/pkg/plugin/diff/renderer.go @@ -201,6 +201,9 @@ func renderNodeValue(v reflect.Value, prefix string) (string, bool) { case reflect.Float32, reflect.Float64: return strconv.FormatFloat(v.Float(), 'f', -1, 64), false + case reflect.Bool: + return strconv.FormatBool(v.Bool()), false + default: return v.String(), false } diff --git a/pkg/plugin/diff/renderer_test.go b/pkg/plugin/diff/renderer_test.go index 74f621e02f..859d125653 100644 --- a/pkg/plugin/diff/renderer_test.go +++ b/pkg/plugin/diff/renderer_test.go @@ -43,6 +43,10 @@ func TestRenderNodeValue(t *testing.T) { "one": []string{"one-1", "one-2"}, "two": []string{"two-1", "two-2"}, } + mapOfBool = map[string]interface{}{ + "false": false, + "true": true, + } ) testcases := []struct { @@ -65,6 +69,16 @@ func TestRenderNodeValue(t *testing.T) { value: reflect.ValueOf("hello"), expected: "hello", }, + { + name: "bool value (true)", + value: reflect.ValueOf(true), + expected: "true", + }, + { + name: "bool value (false)", + value: reflect.ValueOf(false), + expected: "false", + }, { name: "slice of primitive elements", value: func() reflect.Value { @@ -142,6 +156,12 @@ two: two-value`, - b 7-string: hi`, }, + { + name: "map of bool", + value: reflect.ValueOf(mapOfBool), + expected: `false: false +true: true`, + }, } for _, tc := range testcases { diff --git a/pkg/plugin/diff/testdata/no_diff.yaml b/pkg/plugin/diff/testdata/no_diff.yaml index 3f5f689c5e..6e2fd93610 100644 --- a/pkg/plugin/diff/testdata/no_diff.yaml +++ b/pkg/plugin/diff/testdata/no_diff.yaml @@ -9,6 +9,10 @@ metadata: zeroString1: "" zeroInt1: 0 zeroFloat1: 0.0 + booleanString1: "true" + booleanString2: true + booleanString3: "false" + booleanString4: false spec: replicas: 2 number: 1 @@ -53,6 +57,10 @@ metadata: zeroString2: "" zeroInt2: 0 zeroFloat2: 0.0 + booleanString1: true + booleanString2: "true" + booleanString3: false + booleanString4: "false" spec: replicas: 2 number: 1.0 From 44ead3b35a78e1ca0a63026eb598574e624d84e1 Mon Sep 17 00:00:00 2001 From: Yoshiki Fujikane <40124947+ffjlabo@users.noreply.github.com> Date: Thu, 15 May 2025 14:11:21 +0900 Subject: [PATCH 3/3] Release v0.51.3 (#5821) Signed-off-by: Yoshiki Fujikane Signed-off-by: pipecd-bot --- RELEASE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE b/RELEASE index 419bdfe053..34ea9212bb 100644 --- a/RELEASE +++ b/RELEASE @@ -1,6 +1,6 @@ # Generated by `make release` command. # DO NOT EDIT. -tag: v0.51.2 +tag: v0.51.3 releaseNoteGenerator: showCommitter: false