From 2975a1f3ae84ac945b1a308187c7c8bb6f0ccd35 Mon Sep 17 00:00:00 2001 From: Andreas Grub Date: Mon, 2 Nov 2026 08:48:21 +0100 Subject: [PATCH] feat(client): let a building block update skip its run MeshBuildingBlockV2Client.Update takes MeshBuildingBlockV2UpdateOptions, sent as query parameters. SkipRun asks meshStack to save the update without starting a run; the zero value sends no parameter. Co-Authored-By: Claude Opus 5.5 --- client/building_block_v2.go | 13 ++++++++++--- client/building_block_v2_test.go | 20 ++++++++++++++++++++ client/internal/mesh_object.go | 4 ++-- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/client/building_block_v2.go b/client/building_block_v2.go index ae13eafd..febb050e 100644 --- a/client/building_block_v2.go +++ b/client/building_block_v2.go @@ -336,12 +336,19 @@ type MeshBuildingBlockV2ListFilter struct { Sort SortCriteria `json:"sort"` } +// MeshBuildingBlockV2UpdateOptions go out as query parameters, and a zero field as none, so the +// zero value works against a meshStack that does not know them. +type MeshBuildingBlockV2UpdateOptions struct { + // SkipRun saves the update without starting a run. + SkipRun bool `json:"skipRun"` +} + type MeshBuildingBlockV2Client interface { Read(ctx context.Context, uuid string) (*MeshBuildingBlockV2, error) ReadFunc(uuid string) func(ctx context.Context) (*MeshBuildingBlockV2, error) List(ctx context.Context, filter MeshBuildingBlockV2ListFilter) ([]MeshBuildingBlockV2, error) Create(ctx context.Context, bb *MeshBuildingBlockV2) (*MeshBuildingBlockV2, error) - Update(ctx context.Context, bb *MeshBuildingBlockV2) (*MeshBuildingBlockV2, error) + Update(ctx context.Context, bb *MeshBuildingBlockV2, options MeshBuildingBlockV2UpdateOptions) (*MeshBuildingBlockV2, error) Delete(ctx context.Context, uuid string, purge bool) error TriggerRun(ctx context.Context, uuid string) (*MeshBuildingBlockV2, error) } @@ -372,11 +379,11 @@ func (c meshBuildingBlockV2Client) Create(ctx context.Context, bb *MeshBuildingB return c.meshObject.Post(ctx, bb) } -func (c meshBuildingBlockV2Client) Update(ctx context.Context, bb *MeshBuildingBlockV2) (*MeshBuildingBlockV2, error) { +func (c meshBuildingBlockV2Client) Update(ctx context.Context, bb *MeshBuildingBlockV2, options MeshBuildingBlockV2UpdateOptions) (*MeshBuildingBlockV2, error) { if bb.Metadata.Uuid == nil { return nil, errors.New("cannot update building block without UUID") } - return c.meshObject.Put(ctx, *bb.Metadata.Uuid, bb) + return c.meshObject.Put(ctx, *bb.Metadata.Uuid, bb, http.WithUrlQuery(options)) } func (c meshBuildingBlockV2Client) Delete(ctx context.Context, uuid string, purge bool) error { diff --git a/client/building_block_v2_test.go b/client/building_block_v2_test.go index 96663228..71e6d282 100644 --- a/client/building_block_v2_test.go +++ b/client/building_block_v2_test.go @@ -1,12 +1,15 @@ package client import ( + "io" + gohttp "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/meshcloud/meshstack-cli/client/types/enum" + "github.com/meshcloud/meshstack-cli/internal/testutil/fakemeshstack" ) func TestMeshBuildingBlockV2Status_RunChangedSince(t *testing.T) { @@ -170,3 +173,20 @@ func TestMeshBuildingBlockV2_DeletionSuccessful(t *testing.T) { }) } } + +func TestMeshBuildingBlockV2Client_UpdateSendsSkipRunOnlyWhenSet(t *testing.T) { + server := fakemeshstack.Start(t, fakemeshstack.Options{}) + server.Route("/", func(w gohttp.ResponseWriter, _ *gohttp.Request) { _, _ = io.WriteString(w, `{}`) }) + blocks := newBuildingBlockV2Client(t.Context(), newTestHttpClient(server)) + bb := &MeshBuildingBlockV2{Metadata: MeshBuildingBlockV2Metadata{Uuid: new("0b5c1d3e-5f1a-4c2b-9d7e-2a6f8e4b1c90")}} + + for _, options := range []MeshBuildingBlockV2UpdateOptions{{}, {SkipRun: true}} { + _, err := blocks.Update(t.Context(), bb, options) + require.NoError(t, err) + } + + requests := server.TakeRequests() + require.Len(t, requests, 2) + assert.Empty(t, requests[0].URL.RawQuery) + assert.Equal(t, "skipRun=true", requests[1].URL.RawQuery) +} diff --git a/client/internal/mesh_object.go b/client/internal/mesh_object.go index 9147f6f0..425addb1 100644 --- a/client/internal/mesh_object.go +++ b/client/internal/mesh_object.go @@ -102,8 +102,8 @@ func (c MeshObjectApi) PostAtPath[R, P any](ctx context.Context, payload P, extr http.WithAccept(c.MeshObjectMimeType()), c.withMeshObjectPayload(payload)) } -func (c MeshObjectClient[M]) Put[P any](ctx context.Context, id string, payload P) (*M, error) { - return c.DoRequest[*M](ctx, http.MethodPut, c.ApiUrl.JoinPath(id), c.withMeshObjectPayload(payload), http.Retryable()) +func (c MeshObjectClient[M]) Put[P any](ctx context.Context, id string, payload P, options ...http.RequestOption) (*M, error) { + return c.DoRequest[*M](ctx, http.MethodPut, c.ApiUrl.JoinPath(id), append(options, c.withMeshObjectPayload(payload), http.Retryable())...) } func (c MeshObjectClient[M]) Delete(ctx context.Context, id string) (err error) {