Add Plugin Framework conventions doc #33

Merged
ldraney merged 2 commits from docs/plugin-framework-conventions into main 2026-06-14 18:45:06 +00:00
Owner

Summary

  • Adds docs/conventions.md capturing audit findings from comparing our provider against HashiCorp's scaffolding provider, terraform-plugin-framework source, and OpenTofu internals
  • Covers provider setup, resource patterns, error handling, HTTP client, acceptance test structure, and build automation
  • Updates README docs table to include the new doc

Changes

  • docs/conventions.md (new) — comprehensive Plugin Framework best practices reference
  • README.md — added Conventions entry to Documentation table

Test Plan

  • Doc renders correctly in Forgejo markdown preview
  • Code examples are syntactically correct
  • No conflicts with existing docs

Review Checklist

  • Docs only — no code changes
  • No secrets committed
  • No unnecessary file changes
  • Commit messages are descriptive
  • Closes #32
  • Refs #31 (convention gap fixes)
  • Informs #13 (acceptance tests)
## Summary - Adds `docs/conventions.md` capturing audit findings from comparing our provider against HashiCorp's scaffolding provider, terraform-plugin-framework source, and OpenTofu internals - Covers provider setup, resource patterns, error handling, HTTP client, acceptance test structure, and build automation - Updates README docs table to include the new doc ## Changes - `docs/conventions.md` (new) — comprehensive Plugin Framework best practices reference - `README.md` — added Conventions entry to Documentation table ## Test Plan - [ ] Doc renders correctly in Forgejo markdown preview - [ ] Code examples are syntactically correct - [ ] No conflicts with existing docs ## Review Checklist - [x] Docs only — no code changes - [x] No secrets committed - [x] No unnecessary file changes - [x] Commit messages are descriptive ## Related Notes - Closes #32 - Refs #31 (convention gap fixes) - Informs #13 (acceptance tests)
Captures audit findings from comparing against scaffolding provider,
terraform-plugin-framework source, and OpenTofu internals. Covers
provider setup, resource patterns, error handling, HTTP client,
acceptance test structure, and build automation.

Refs #31

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
Owner

PR #33 Review

DOMAIN REVIEW

Tech stack: Go / Terraform Plugin Framework documentation. Applied domain checks for Go syntax correctness, Plugin Framework API accuracy, and consistency with the existing codebase.

1. Provider Factory Example -- Incorrect Invocation in Test Code (docs/conventions.md, line 130)

The conventions doc defines New() as returning a factory:

func New(version string) func() provider.Provider {
    return func() provider.Provider { ... }
}

But the acceptance test provider factory example calls New("test")() (with double invocation):

"godaddy": providerserver.NewProtocol6WithError(New("test")()),

providerserver.NewProtocol6WithError expects a func() provider.Provider, not a provider.Provider. Since New("test") already returns func() provider.Provider, the correct call is:

"godaddy": providerserver.NewProtocol6WithError(New("test")),

The trailing () unwraps the factory prematurely, passing a bare provider.Provider -- this would not compile. This is a real bug in the documentation example.

2. Factory Pattern vs Current Code -- Prescriptive Gap is Fine but Should Be Explicit

Current provider.go has New() provider.Provider (returns provider directly). The conventions doc prescribes New(version string) func() provider.Provider (factory pattern with version injection). This is clearly an intentional improvement target, not a mismatch -- the doc is a conventions reference, not a mirror of current state. However, a brief note like "NOTE: current code uses a simpler signature; migrate to this pattern per #31" would prevent confusion about whether the doc is descriptive or prescriptive.

3. All Other Code Examples -- Verified Correct

  • errors.As pattern matches the actual godaddy.APIError struct in client.go (pointer receiver, StatusCode and Message fields)
  • godaddy.NewClient(key, secret) 2-arg call is valid against actual variadic signature NewClient(apiKey, apiSecret string, opts ...Option)
  • client.GetRecords(ctx, domain, type, name) matches actual signature in dns.go
  • MarkdownDescription recommendation is consistent -- current code uses Description on provider schema attributes, confirming this is a forward-looking convention
  • resp.State.RemoveResource(ctx) drift detection pattern is standard Plugin Framework
  • Compile-time interface checks pattern matches existing var _ provider.Provider = (*godaddyProvider)(nil) in provider.go
  • Makefile targets use correct Go commands

4. ConfigStateChecks vs Check in Test Example

The test example uses ConfigStateChecks with statecheck.StateCheck -- this is the newer Plugin Framework testing API (v1.7+). This is correct and forward-looking. The older pattern uses Check: resource.ComposeAggregateTestCheckFunc(...). Good choice to document the modern approach.

BLOCKERS

Provider factory test example has a compile error (finding #1 above). New("test")() passes provider.Provider to a function expecting func() provider.Provider. Fix: remove the trailing (). This is a docs-only PR, so this is not a production code bug, but shipping incorrect Go code examples in a conventions reference undermines the doc's purpose as an authoritative guide. This should be fixed before merge.

NITS

  1. Prescriptive vs descriptive clarity: Consider adding a brief note at the top of docs/conventions.md stating whether examples reflect current code or target conventions. Something like: "Examples show target patterns. Where current code differs, convention gap issues track the migration." This prevents developers from assuming the doc mirrors current state.

  2. GODADDY_TEST_DOMAIN env var: The test isolation section mentions GODADDY_TEST_DOMAIN but the testAccPreCheck example only checks GODADDY_API_KEY and GODADDY_API_SECRET. Consider adding the domain check to the precheck example for consistency.

  3. go-retryablehttp mention: The HTTP Client section recommends hashicorp/go-retryablehttp but does not show an example of wiring it. A 2-line snippet showing retryablehttp.NewClient() wrapped with the existing WithHTTPClient option would make this actionable.

  4. Description field in provider schema: Current provider.go uses Description on schema attributes (lines 46, 50). The conventions doc recommends MarkdownDescription. Might be worth noting this as a gap to fix in #31.

SOP COMPLIANCE

  • PR body has Summary, Changes, Test Plan, Review Checklist, Related Notes -- all present and substantive
  • No secrets committed
  • No unnecessary file changes -- exactly 2 files, both relevant
  • Commit messages are descriptive (PR title is clear)
  • Closes #32, references #31 and #13 -- good cross-linking
  • README table entry is correct: link path, description, and table position are all appropriate

PROCESS OBSERVATIONS

  • Clean docs-only PR with well-structured PR body. Good practice for knowledge capture.
  • The conventions doc bridges a real gap -- having an authoritative reference for Plugin Framework patterns will reduce review friction on future implementation PRs.
  • Cross-references to #31 (convention gaps) and #13 (acceptance tests) create good traceability.

VERDICT: NOT APPROVED

One blocker: the provider factory test example contains a Go compilation error (New("test")() should be New("test")). Fix the trailing () and this is ready to merge. Everything else is solid.

## PR #33 Review ### DOMAIN REVIEW **Tech stack**: Go / Terraform Plugin Framework documentation. Applied domain checks for Go syntax correctness, Plugin Framework API accuracy, and consistency with the existing codebase. **1. Provider Factory Example -- Incorrect Invocation in Test Code (docs/conventions.md, line 130)** The conventions doc defines `New()` as returning a factory: ```go func New(version string) func() provider.Provider { return func() provider.Provider { ... } } ``` But the acceptance test provider factory example calls `New("test")()` (with double invocation): ```go "godaddy": providerserver.NewProtocol6WithError(New("test")()), ``` `providerserver.NewProtocol6WithError` expects a `func() provider.Provider`, not a `provider.Provider`. Since `New("test")` already returns `func() provider.Provider`, the correct call is: ```go "godaddy": providerserver.NewProtocol6WithError(New("test")), ``` The trailing `()` unwraps the factory prematurely, passing a bare `provider.Provider` -- this would not compile. This is a real bug in the documentation example. **2. Factory Pattern vs Current Code -- Prescriptive Gap is Fine but Should Be Explicit** Current `provider.go` has `New() provider.Provider` (returns provider directly). The conventions doc prescribes `New(version string) func() provider.Provider` (factory pattern with version injection). This is clearly an intentional improvement target, not a mismatch -- the doc is a conventions reference, not a mirror of current state. However, a brief note like "NOTE: current code uses a simpler signature; migrate to this pattern per #31" would prevent confusion about whether the doc is descriptive or prescriptive. **3. All Other Code Examples -- Verified Correct** - `errors.As` pattern matches the actual `godaddy.APIError` struct in `client.go` (pointer receiver, `StatusCode` and `Message` fields) - `godaddy.NewClient(key, secret)` 2-arg call is valid against actual variadic signature `NewClient(apiKey, apiSecret string, opts ...Option)` - `client.GetRecords(ctx, domain, type, name)` matches actual signature in `dns.go` - `MarkdownDescription` recommendation is consistent -- current code uses `Description` on provider schema attributes, confirming this is a forward-looking convention - `resp.State.RemoveResource(ctx)` drift detection pattern is standard Plugin Framework - Compile-time interface checks pattern matches existing `var _ provider.Provider = (*godaddyProvider)(nil)` in `provider.go` - Makefile targets use correct Go commands **4. `ConfigStateChecks` vs `Check` in Test Example** The test example uses `ConfigStateChecks` with `statecheck.StateCheck` -- this is the newer Plugin Framework testing API (v1.7+). This is correct and forward-looking. The older pattern uses `Check: resource.ComposeAggregateTestCheckFunc(...)`. Good choice to document the modern approach. ### BLOCKERS **Provider factory test example has a compile error** (finding #1 above). `New("test")()` passes `provider.Provider` to a function expecting `func() provider.Provider`. Fix: remove the trailing `()`. This is a docs-only PR, so this is not a production code bug, but shipping incorrect Go code examples in a conventions reference undermines the doc's purpose as an authoritative guide. This should be fixed before merge. ### NITS 1. **Prescriptive vs descriptive clarity**: Consider adding a brief note at the top of `docs/conventions.md` stating whether examples reflect current code or target conventions. Something like: "Examples show target patterns. Where current code differs, convention gap issues track the migration." This prevents developers from assuming the doc mirrors current state. 2. **`GODADDY_TEST_DOMAIN` env var**: The test isolation section mentions `GODADDY_TEST_DOMAIN` but the `testAccPreCheck` example only checks `GODADDY_API_KEY` and `GODADDY_API_SECRET`. Consider adding the domain check to the precheck example for consistency. 3. **`go-retryablehttp` mention**: The HTTP Client section recommends `hashicorp/go-retryablehttp` but does not show an example of wiring it. A 2-line snippet showing `retryablehttp.NewClient()` wrapped with the existing `WithHTTPClient` option would make this actionable. 4. **Description field in provider schema**: Current `provider.go` uses `Description` on schema attributes (lines 46, 50). The conventions doc recommends `MarkdownDescription`. Might be worth noting this as a gap to fix in #31. ### SOP COMPLIANCE - [x] PR body has Summary, Changes, Test Plan, Review Checklist, Related Notes -- all present and substantive - [x] No secrets committed - [x] No unnecessary file changes -- exactly 2 files, both relevant - [x] Commit messages are descriptive (PR title is clear) - [x] Closes #32, references #31 and #13 -- good cross-linking - [x] README table entry is correct: link path, description, and table position are all appropriate ### PROCESS OBSERVATIONS - Clean docs-only PR with well-structured PR body. Good practice for knowledge capture. - The conventions doc bridges a real gap -- having an authoritative reference for Plugin Framework patterns will reduce review friction on future implementation PRs. - Cross-references to #31 (convention gaps) and #13 (acceptance tests) create good traceability. ### VERDICT: NOT APPROVED One blocker: the provider factory test example contains a Go compilation error (`New("test")()` should be `New("test")`). Fix the trailing `()` and this is ready to merge. Everything else is solid.
NewProtocol6WithError expects func() provider.Provider, not
provider.Provider directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
Owner

PR #33 Re-Review

DOMAIN REVIEW

Stack: Documentation (Go/Terraform Plugin Framework conventions)

Re-review after fix for the blocker found in initial review.

Previous blocker (RESOLVED): The provider factory example previously had New("test")() -- a double invocation that would pass a provider.Provider instance where NewProtocol6WithError expects a func() provider.Provider factory. This has been corrected to New("test"), which correctly passes the factory function. Fix verified.

Full doc audit (231 lines):

  • All Go code examples are syntactically correct and use current Plugin Framework APIs
  • ConfigStateChecks with statecheck.ExpectKnownValue / tfjsonpath reflects the modern testing API (v1.6+), not the deprecated Check field
  • errors.As usage is correct Go idiom for wrapped error handling
  • RemoveResource drift detection pattern is correct
  • No hardcoded credentials, API keys, or secrets in any example
  • README documentation table entry is correctly formatted

BLOCKERS

None. Previous blocker resolved.

NITS

None.

SOP COMPLIANCE

  • PR body has Summary, Changes, Test Plan, Related
  • No secrets committed
  • No unnecessary file changes (2 files, docs only)
  • Commit messages are descriptive

PROCESS OBSERVATIONS

Clean docs-only PR. The conventions doc provides a solid reference for implementation tickets (#31, #13). No deployment risk.

VERDICT: APPROVED

## PR #33 Re-Review ### DOMAIN REVIEW **Stack:** Documentation (Go/Terraform Plugin Framework conventions) Re-review after fix for the blocker found in initial review. **Previous blocker (RESOLVED):** The provider factory example previously had `New("test")()` -- a double invocation that would pass a `provider.Provider` instance where `NewProtocol6WithError` expects a `func() provider.Provider` factory. This has been corrected to `New("test")`, which correctly passes the factory function. Fix verified. **Full doc audit (231 lines):** - All Go code examples are syntactically correct and use current Plugin Framework APIs - `ConfigStateChecks` with `statecheck.ExpectKnownValue` / `tfjsonpath` reflects the modern testing API (v1.6+), not the deprecated `Check` field - `errors.As` usage is correct Go idiom for wrapped error handling - `RemoveResource` drift detection pattern is correct - No hardcoded credentials, API keys, or secrets in any example - README documentation table entry is correctly formatted ### BLOCKERS None. Previous blocker resolved. ### NITS None. ### SOP COMPLIANCE - [x] PR body has Summary, Changes, Test Plan, Related - [x] No secrets committed - [x] No unnecessary file changes (2 files, docs only) - [x] Commit messages are descriptive ### PROCESS OBSERVATIONS Clean docs-only PR. The conventions doc provides a solid reference for implementation tickets (#31, #13). No deployment risk. ### VERDICT: APPROVED
ldraney deleted branch docs/plugin-framework-conventions 2026-06-14 18:45:06 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ldraney/godaddy-tofu!33
No description provided.