Skip to content

feat(client): add the runner API and export the HTTP client as client/http - #33

Draft
grubmeshi wants to merge 4 commits into
mainfrom
feature/single-go-bin-runner
Draft

grubmeshi wants to merge 4 commits into
mainfrom
feature/single-go-bin-runner

Conversation

@grubmeshi

@grubmeshi grubmeshi commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

🤖 Written by AI agent

building-block-runner moves all its runners into one Go binary (meshcloud/building-block-runner#86). It builds its meshStack client through pkg/auth.ResolveClient, as the Terraform provider does, and needs a client it can call from another module.

Reading order

  1. Move. internal/http becomes client/http and internal/version becomes client/types/version, with only the imports rewritten.
  2. client/http API. No exported name of client uses an internal/ type any more, and TestPublicApiNamesNoInternalType checks it. New client options: WithoutRedirects(), and WithRetry(policy), which picks per request which failures are retried. Without options, NewClient returns the shared client as before.
  3. client.Runner. A runner claims a run, registers as a status source, reports status, and downloads or uploads the plan artifact, using the run token. ForRunUuid reports with the runner's own credentials. A run's implementation decodes into one typed variant by its type; the Terraform variant carries async. An INTEGER input keeps every digit as *big.Int. NewRunnerClient builds this API alone.
  4. Comments that pointed into the old runner layout.

Changes for callers of client

  • WithHeader replaces WithAccept and WithHeaders, and WithBody takes the content type.
  • Send returns the raw response, and an Error names the method and URL.
  • The client.Authorization alias is gone; use http.Authorization.
  • ListOptions and Page move to client/types.

Merge order

Merge and release this first. #86 then pins the release in place of this branch's head.

Cross-repo PRs

🤖 Generated with Claude Code

@meshcloud-gh-actions

meshcloud-gh-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Coverage of the acceptance run against the meshStack backend, on 3926fcc3a2a66393c1424e6317e14d821883c8c8.

Scope Coverage
Unit tests 76.6%
Acceptance tests 54.7%
Combined 79.2%
Uncovered functions
client/api_key.go:55: meshApiKeyClient.Create 0.0%
client/api_key.go:59: meshApiKeyClient.Read 0.0%
client/api_key.go:63: meshApiKeyClient.Update 0.0%
client/api_key.go:71: meshApiKeyClient.Delete 0.0%
client/api_key_permissions.go:20: ApiKeyPermissions.AllCodes 0.0%
client/api_key_permissions.go:33: ApiKeyPermissions.WorkspaceCodes 0.0%
client/api_key_permissions.go:295: AllApiKeyPermissions 0.0%
client/api_key_permissions.go:299: WorkspacePermissionCodes 0.0%
client/building_block_definition.go:71: MeshBuildingBlockDefinitionApprovalPolicies.NothingRequiresApproval 0.0%
client/building_block_definition.go:82: DisabledSchedule 0.0%
client/building_block_definition.go:89: MeshBuildingBlockDefinitionSchedule.IsDisabled 0.0%
client/building_block_definition.go:93: MeshBuildingBlockDefinitionSpec.HasNeutralPolicies 0.0%
client/building_block_definition.go:97: MeshBuildingBlockDefinitionSpec.WithNeutralPolicies 0.0%
client/building_block_definition.go:166: meshBuildingBlockDefinitionClient.List 0.0%
client/building_block_definition.go:173: meshBuildingBlockDefinitionClient.Read 0.0%
client/building_block_definition.go:177: meshBuildingBlockDefinitionClient.Create 0.0%
client/building_block_definition.go:181: meshBuildingBlockDefinitionClient.Update 0.0%
client/building_block_definition.go:185: meshBuildingBlockDefinitionClient.Delete 0.0%
client/building_block_definition_version.go:100: MeshBuildingBlockType.TagInputTargets 0.0%
client/building_block_definition_version.go:245: meshBuildingBlockDefinitionVersionClient.Create 0.0%
client/building_block_definition_version.go:254: meshBuildingBlockDefinitionVersionClient.Update 0.0%
client/building_block_definition_version_implementation.go:80: MeshBuildingBlockDefinitionImplementation.InferType 0.0%
client/building_block_definition_version_implementation.go:94: MeshBuildingBlockDefinitionImplementation.MarshalJSON 0.0%
client/building_block_definition_version_implementation.go:107: *MeshBuildingBlockDefinitionImplementation.UnmarshalJSON 0.0%
client/building_block_runner.go:87: meshBuildingBlockRunnerClient.Create 0.0%
... and 149 more

covdata func names a method without its receiver, so an entry can belong to an implementation nothing selects rather than to a function the tests never reached. Open the file and line before reading one as a coverage gap.

@grubmeshi
grubmeshi force-pushed the feature/single-go-bin-runner branch from f7111e1 to 73db1b9 Compare October 13, 2026 13:52
@grubmeshi grubmeshi changed the title feat(client): publish the HTTP layer as client/http, with Basic auth feat: basic auth credential and the runner API in client Oct 13, 2026
@grubmeshi
grubmeshi force-pushed the feature/single-go-bin-runner branch from 73db1b9 to ebf91ce Compare October 13, 2026 13:58
@grubmeshi
grubmeshi force-pushed the feature/single-go-bin-runner branch 2 times, most recently from 9ab69a7 to 322b873 Compare October 15, 2026 19:18
@grubmeshi
grubmeshi force-pushed the feature/single-go-bin-runner branch 10 times, most recently from 3a034bf to eb512e3 Compare October 23, 2026 11:53
@grubmeshi grubmeshi changed the title feat: basic auth credential and the runner API in client feat: basic auth, client/http and the runner API in client Oct 23, 2026
@grubmeshi
grubmeshi force-pushed the feature/single-go-bin-runner branch 2 times, most recently from 5975d78 to 98854c7 Compare October 28, 2026 11:58
@grubmeshi
grubmeshi force-pushed the feature/single-go-bin-runner branch 3 times, most recently from abbd309 to e90226d Compare October 29, 2026 04:56
@grubmeshi grubmeshi changed the title feat: basic auth, client/http and the runner API in client feat(client): add the runner API and export the HTTP client as client/http Oct 29, 2026
@grubmeshi
grubmeshi force-pushed the feature/single-go-bin-runner branch from e90226d to c85b993 Compare October 29, 2026 14:19
… to client/types/version

Another module may not import an internal package, so client.New, which
takes an http.Client, could only be called from this module. A pure move
with the imports rewritten.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@grubmeshi
grubmeshi force-pushed the feature/single-go-bin-runner branch from c85b993 to 0332c2c Compare October 30, 2026 09:04
Comment thread client/http/options.go Outdated
if body == nil {
return
}
WithHeader("Content-Type", contentType)(opts)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f: introduce WithContentType (using WithHeader), so have the string Content-Type then only there defined once

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added http.WithContentType; WithBody, WithBodyFile, WithJsonPayload, WithFormPayload, AbortRun and ClaimRun use it, so Content-Type is spelled only there.

Comment thread client/runner_test.go Outdated
"github.com/meshcloud/meshstack-cli/internal/testutil/fakemeshstack"
)

func TestRunnerRun(t *testing.T) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f: do not have this test or this logic here in cli client, discuss how to move into bb runner repo

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved TestRunnerRun and its fixture to the runner (internal/executor/runyml_test.go). The decoding of inputs and implementation variants stays, as it reads the claim response, and so does MeshRunnerRunImplementation.MarshalJSON, so the public type encodes what it decodes. If you want it out of the CLI, the runner could encode runs with a json/v2 WithMarshalers option instead.

Comment thread client/api_surface_test.go Outdated

// TestPublicApiNamesNoInternalType keeps client callable from another module, which Go's internal
// rule forbids to name an internal type.
func TestPublicApiNamesNoInternalType(t *testing.T) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f: remove this test, rely on instructions / already complying design

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed; the development skill keeps the rule as one line.

Comment thread client/runner.go Outdated
Comment on lines +354 to +356
ForRun(run MeshRunnerRun) MeshRunnerRunClient
// ForRunUuid authorizes with the runner's own credentials and can only register a source and patch its status.
ForRunUuid(runUuid uuid.UUID) MeshRunnerRunClient

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f: remove this / move this to the bb runner repo, using the client/http AUthorization interface if possible (which allows to just provide the bearer token aka the run token then i hope)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ForRunUuid is gone; ForRun(auth http.Authorization, links MeshRunnerRunLinks) is the only way to a run client. The runner passes http.BearerToken(run token) in the child and its session in the poller, which builds the source links from the run uuid itself (building-block-runner#86).

…ptions

client.New and RawClient.DoRequest are now callable from another module:
no exported name of client uses an internal type. So ListOptions and Page
move to client/types, the client.Authorization alias goes, and the API
docs download moves to internal/apidocs, its only caller.

NewClient takes WithoutRedirects and WithRetry, whose RetryPolicy picks
per request which of RetryOnBusy, RetryOnGatewayError and
RetryOnBrokenConnection apply; without options it returns the shared
client as before. WithHeader replaces WithAccept and WithHeaders,
WithContentType sets the Content-Type header, WithBody takes the content
type, Send returns the raw response, and an Error names the method and
URL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@grubmeshi
grubmeshi force-pushed the feature/single-go-bin-runner branch from 0332c2c to 2ac56de Compare November 2, 2026 10:32
grubmeshi and others added 2 commits November 2, 2026 12:36
…rClient

A building block runner claims runs, registers as a status source,
reports status and moves the plan artifact through client.Runner. ForRun
addresses a run by its links and authorizes with the given credentials,
so the runner chooses between the run token and its own. The
implementation of a run is decoded into one typed variant by its type,
the Terraform one with async. NewRunnerClient builds only this API, since
client.New builds every meshObject client and logs a debug line for each.

client/http gains what the runner needs: streaming a download, a request
body read from a file and reopened on a retry, and PATCH.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@grubmeshi
grubmeshi force-pushed the feature/single-go-bin-runner branch from 2ac56de to 3926fcc Compare November 2, 2026 11:36
@sonarqubecloud

sonarqubecloud Bot commented Nov 2, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant