Skip to content

fix: manual building block outputs computed from API; BBD apply regression coverage#197

Merged
grubmeshi merged 7 commits into
mainfrom
fix-bbd-apply
Jun 10, 2026
Merged

fix: manual building block outputs computed from API; BBD apply regression coverage#197
grubmeshi merged 7 commits into
mainfrom
fix-bbd-apply

Conversation

@grubmeshi

@grubmeshi grubmeshi commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Addresses the meshstack_building_block_definition "Provider produced inconsistent result after apply" failures from #131 and #176.

1. Manual outputs computed from the API (#176, manual side of #131)

The backend derives a manual building block's outputs from its inputs (one output per input, assignment_type = NONE, with SINGLE_SELECT/MULTI_SELECT/LIST translated). Mirroring those outputs in config — or letting the old static {} default fight the API — produced inconsistent-result errors whenever the backend added/changed an output the plan didn't predict, especially when toggling draft false→true together with input changes.

Changes:

  • version_spec.outputs is now Optional + Computed with no static default (+ UseStateForUnknown). Omit it for manual building blocks; it is reconciled from the API response.
  • ModifyPlan leaves manual outputs (and the dependent content_hash) unknown when the inputs or the configured PLATFORM_TENANT_ID outputs change, and reuses the reconciled state value otherwise (no perpetual diff).
  • ValidateConfig rejects manual outputs with any assignment_type other than PLATFORM_TENANT_ID (the only assignment the backend preserves — used to mark the tenant-id output). Manual Create/Update source that hint from config.
  • The mock client mirrors the backend's manual output generation, so the behavior is covered by unit tests too.
  • Examples updated to omit outputs for manual building blocks; docs regenerated. Breaking: existing manual configs must remove non-PLATFORM_TENANT_ID outputs blocks (noted in CHANGELOG v0.21.1).

New tests: TestAccBuildingBlockDefinition/07_manual_computed_outputs (create → release → re-draft with an added input, asserting reconciled outputs incl. SINGLE_SELECTSTRING and a stable released-version hash) and TestAccBuildingBlockDefinitionManualOutputsValidation.

2. Released-version mutation regression test (terraform side of #131)

TestAccBuildingBlockDefinition/06_release_redraft_implementation_change releases a terraform version, then flips it back to draft with a pre_run_script change, asserting the already-released version stays immutable. The backend fix is meshcloud/meshfed-release#10116.

Verification

  • task lint clean; full unit suite passes.
  • Acceptance suite against a local meshStack passes: TestAccBuildingBlockDefinition (all subtests), TestAccBuildingBlockV2, TestAccLandingZone, and the BBD data sources.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Breaking Changes

    • Manual building blocks: version_spec.outputs must be omitted; outputs are now derived from inputs by the backend.
    • Output assignment types other than PLATFORM_TENANT_ID are no longer accepted for manual blocks.
  • Bug Fixes

    • Outputs are reconciled from API responses, preventing "inconsistent result after apply" errors when backend-generated outputs are involved.
  • New Features

    • Added scratch-config-testing skill for debugging via git-ignored configs run against locally built binaries.
  • Documentation

    • Updated examples and guides for manual building block configuration.

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@grubmeshi, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 36 minutes and 40 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: cf06eae9-4073-40c5-b9e6-8191f09b5271

📥 Commits

Reviewing files that changed from the base of the PR and between 5357a4b and 2b3d418.

📒 Files selected for processing (10)
  • CHANGELOG.md
  • docs/resources/building_block_definition.md
  • examples/resources/meshstack_building_block_definition/resource_03_manual.tf
  • examples/resources/meshstack_building_block_v2/test-support_01_workspace.tf
  • examples/resources/meshstack_building_block_v2/test-support_02_tenant.tf
  • internal/clientmock/mock_buildingblock_definition_version.go
  • internal/provider/building_block_definition_resource.go
  • internal/provider/building_block_definition_resource_model.go
  • internal/provider/building_block_definition_resource_schema.go
  • internal/provider/building_block_definition_resource_test.go
📝 Walkthrough

Walkthrough

Adds developer tooling to dump acceptance-test Terraform into git-ignored scratch/ dirs and run them with a dev-built provider; implements server- and provider-side derivation and validation of outputs for manual building blocks, updates schema/docs/examples/changelog, and adds tests for immutability and manual-output validation.

Changes

Scratch-config-testing developer infrastructure

Layer / File(s) Summary
Documentation and conventions
.agents/skills/scratch-config-testing/SKILL.md, AGENTS.md
Adds a SKILL guide and AGENTS.md links describing prerequisites, building the dev provider, Terraform dev_overrides, MESHSTACK_SCRATCH_DUMP usage, and expected scratch/<TestName>/stepNN layout.
Test helper implementation for config dumping
internal/provider/provider_test.go
Adds scratch-dump mode: when MESHSTACK_SCRATCH_DUMP is set, ApplyAndTest writes per-step main.tf and provider.tf to a per-test scratch directory; includes dumpStepConfigs, moduleRoot, and sanitizeTestName helpers and import updates.
Repository ignore configuration
.gitignore
Adds dist/ and scratch/ to .gitignore.

Manual building-block outputs behavior and validation

Layer / File(s) Summary
Mock backend: derive outputs for manual implementations
internal/clientmock/mock_buildingblock_definition_version.go
Calls applyManualOutputBehavior on Create/Update to rebuild versionSpec.Outputs from Inputs, translating input IO types to output types and preserving any PLATFORM_TENANT_ID hints.
Provider: ValidateConfig, ModifyPlan, Create/Update output handling
internal/provider/building_block_definition_resource.go
Adds ValidateConfig to reject non-PLATFORM_TENANT_ID assignments for manual outputs, helpers to compute/compare PLATFORM_TENANT_ID key sets, reads null outputs as empty map, marks outputs unknown in ModifyPlan when inputs or PLATFORM_TENANT_ID keys differ, and refreshes DTO outputs from config during Create/Update.
Resource schema: outputs map plan modifier
internal/provider/building_block_definition_resource_schema.go
Adds mapplanmodifier.UseStateForUnknown() to the outputs map attribute, extends description for manual behavior, and removes prior default initialization.
Tests: regression and manual-output validation
internal/provider/building_block_definition_resource_test.go
Adds import for compare, a regression subtest ensuring released-version immutability when drafts change implementation, and TestAccBuildingBlockDefinitionManualOutputsValidation (mock-only) validating assignment rules (reject non-PLATFORM_TENANT_ID).
Docs, examples, and changelog
CHANGELOG.md, docs/resources/building_block_definition.md, examples/.../*
Documents that manual building-block outputs are derived by the backend and version_spec.outputs must be omitted (except PLATFORM_TENANT_ID static hints); updates examples and changelog accordingly.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • sttomm
  • nroi
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the two main changes: computing manual building block outputs from the API and adding a regression test for BBD apply.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-bbd-apply

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

📊 Test Coverage: 73.5%

Top uncovered files
github.com/meshcloud/terraform-provider-meshstack/client/api_key.go:43:									newApiKeyClient					0.0%
github.com/meshcloud/terraform-provider-meshstack/client/api_key.go:47:									Create						0.0%
github.com/meshcloud/terraform-provider-meshstack/client/api_key.go:51:									Read						0.0%
github.com/meshcloud/terraform-provider-meshstack/client/api_key.go:55:									Update						0.0%
github.com/meshcloud/terraform-provider-meshstack/client/api_key.go:59:									Delete						0.0%
github.com/meshcloud/terraform-provider-meshstack/client/api_key_permissions.go:20:							AllCodes					100.0%
github.com/meshcloud/terraform-provider-meshstack/client/api_key_permissions.go:33:							WorkspaceCodes					100.0%
github.com/meshcloud/terraform-provider-meshstack/client/api_key_permissions.go:49:							MarkdownString					100.0%
github.com/meshcloud/terraform-provider-meshstack/client/api_key_permissions.go:225:							AllApiKeyPermissions				0.0%
github.com/meshcloud/terraform-provider-meshstack/client/api_key_permissions.go:230:							WorkspacePermissionCodes			100.0%

Coverage measured across all packages with -coverpkg=./...

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.agents/skills/scratch-config-testing/SKILL.md:
- Around line 19-21: The fenced code block containing "set -a && source .env &&
set +a   # MESHSTACK_ENDPOINT, MESHSTACK_API_KEY, MESHSTACK_API_SECRET" needs
surrounding blank lines and the code-fence should include a language identifier
(e.g., text) to satisfy markdownlint MD031/MD040; update that block by adding an
empty line before and after the triple-backtick fence and change ``` to ```text,
and do the same for the other fenced example starting at the fence around lines
56-59 so both examples have blank lines around them and explicit language
identifiers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 02934715-ae30-4eba-982b-606bffbec0b6

📥 Commits

Reviewing files that changed from the base of the PR and between 335b893 and 1757f60.

📒 Files selected for processing (5)
  • .agents/skills/scratch-config-testing/SKILL.md
  • .gitignore
  • AGENTS.md
  • internal/provider/building_block_definition_resource_test.go
  • internal/provider/provider_test.go

Comment thread .agents/skills/scratch-config-testing/SKILL.md
@grubmeshi grubmeshi changed the title test: add BBD regression test for released-version mutation (#131) fix: manual building block outputs computed from API; BBD apply regression coverage Jun 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/provider/building_block_definition_resource.go`:
- Around line 176-177: The loop over outputAssignmentTypes currently permits
empty assignmentType values, allowing manual outputs with omitted
assignment_type to bypass validation; update the logic in outputAssignmentTypes
and the caller loop that iterates "for key, assignmentType := range
outputAssignmentTypes(outputs)" to treat empty string the same as NONE and
reject it: if assignmentType == "" || assignmentType ==
client.MeshBuildingBlockDefinitionOutputAssignmentTypeNone.String() then return
an error (or mark invalid) for that output key. Also adjust the code path that
currently drops null/omitted assignment values (the branch that removes entries
when assignment is nil) so it no longer silently removes them but instead
surfaces/returns the same validation error for omitted (nil/empty)
assignment_type in outputs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f211f379-ef02-4857-b019-3185b1c10d80

📥 Commits

Reviewing files that changed from the base of the PR and between 1757f60 and 5357a4b.

📒 Files selected for processing (9)
  • CHANGELOG.md
  • docs/resources/building_block_definition.md
  • examples/resources/meshstack_building_block_definition/resource_03_manual.tf
  • examples/resources/meshstack_building_block_v2/test-support_01_workspace.tf
  • examples/resources/meshstack_building_block_v2/test-support_02_tenant.tf
  • internal/clientmock/mock_buildingblock_definition_version.go
  • internal/provider/building_block_definition_resource.go
  • internal/provider/building_block_definition_resource_schema.go
  • internal/provider/building_block_definition_resource_test.go

Comment thread internal/provider/building_block_definition_resource.go Outdated
grubmeshi and others added 7 commits June 10, 2026 08:58
Turn an acceptance test's generated HCL (or hand-written HCL) into a
self-contained, re-runnable Terraform config under git-ignored scratch/,
run against a local meshStack via the dev-built provider binary.

- ApplyAndTest dumps each step's config to scratch/<test>/stepNN/
  {main.tf,provider.tf} when MESHSTACK_SCRATCH_DUMP is set, then returns
  without running the test (dump-only; no backend or terraform binary needed).
  provider.tf resolves the dev-built provider via dev_overrides, so the dump
  is runnable standalone — unlike the framework's TF_ACC_PERSIST_WORKING_DIR.
- Add the scratch-config-testing skill: build, ~/.terraformrc.dev dev_override
  setup, dumping/hand-writing a config, and running plan/apply against a local
  meshStack.
- Ignore scratch/ and wire the skill into AGENTS.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a Terraform-implementation subtest that creates a building block
definition draft, releases it, then flips it back to draft together with
a pre_run_script change. It asserts the already-released version stays
immutable: its content_hash is unchanged across the new draft creation
and no "inconsistent result after apply" occurs.

This is the provider-side reproducer for #131. The underlying fix is in
the backend (meshcloud/meshfed-release#10116), which previously shared
the implementation object across versions.

Closes #131 via internal PR meshcloud/meshfed-release#10116

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Manual building block definitions have their outputs derived from the
inputs on the backend (one output per input, assignment type NONE, with
SINGLE_SELECT/MULTI_SELECT/LIST translated). Configuring outputs that
mirror the inputs caused "Provider produced inconsistent result after
apply" whenever the backend added or changed an output the config did not
predict, especially when toggling draft false->true together with input
changes (#131, #176).

version_spec.outputs is now Optional+Computed without a static default:
omit it for manual building blocks and it is reconciled from the API. The
plan leaves outputs (and the content hash) unknown when the inputs or the
configured PLATFORM_TENANT_ID outputs change, and reuses the reconciled
state value otherwise. ValidateConfig rejects manual outputs with any
assignment_type other than PLATFORM_TENANT_ID, which the backend still
honors to mark the tenant-id output. The mock client mirrors the backend's
manual output generation so unit tests cover the behavior.

Closes #176

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rotating a sensitive input's secret on a released (non-draft, immutable)
building block definition version failed with an opaque "Failed to
determine content hash ... [plaintext]" error: the planned version_spec
DTO carries the rotated secret's plaintext, which the content hash
disallows (the backend only ever returns secret hashes).

Released versions are immutable, so the rotation must be rejected. Detect
the plaintext secret in the DTO (an unambiguous version_spec change) and
return the existing "Updating a version_spec in non-draft state is not
allowed" error with guidance to create a new draft version first, instead
of feeding plaintext into the content hash.

Adds a regression test covering create -> release -> rotate.

Closes #196

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Companion to the released-version immutability fix (#131): CI implementations
like github_workflows carry an integration_ref besides the implementation.
Add a regression test that releases a github BBD version, then re-drafts it
(draft false->true) while switching to a different integration, asserting the
new draft v2 points at the new integration while the released v1 keeps its
original integration and stays immutable (stable content_hash).

Adds a BBDGithubTwoIntegrations testconfig builder that wires the BBD to a
first integration plus a second github integration (reusing the integration
test-support file via RenameKey) so the test can switch between them. The BBD
depends_on the first integration so teardown deletes the BBD before both
integrations (the released version pins the first on the backend, which refuses
integration deletion while still referenced).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@grubmeshi grubmeshi merged commit 2071996 into main Jun 10, 2026
4 checks passed
@grubmeshi grubmeshi deleted the fix-bbd-apply branch June 10, 2026 07:06
@jannymeshi

jannymeshi commented Jun 10, 2026

Copy link
Copy Markdown

📋 This PR has been linked to Feature Shipping Tracker #1344: Fix Manual Building Block Output Type Handling (SINGLE_SELECT / MULTI_SELECT).

DoD item 5 (Terraform provider updated) has been checked off. Remaining open items: docs (meshcloud/meshfed-release#9999), API docs (meshcloud/meshfed-release#10123), hub reference examples (meshcloud/meshstack-hub#198), and Canny Known Issue resolution.

[edited: corrected cross-repo PR references to use owner/repo#NNN format]

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

Labels

None yet

Projects

None yet

2 participants