Skip to content

fix/refactor(provider): Initialize ctx + Plan canonicalization (#62, #63)#68

Merged
intel352 merged 3 commits intomainfrom
fix/initialize-ctx-and-plan-canonical
May 5, 2026
Merged

fix/refactor(provider): Initialize ctx + Plan canonicalization (#62, #63)#68
intel352 merged 3 commits intomainfrom
fix/initialize-ctx-and-plan-canonical

Conversation

@intel352
Copy link
Copy Markdown
Contributor

@intel352 intel352 commented May 5, 2026

Summary

Closes two correctness gaps in DOProvider:

Reference: iac-deferred-cleanup plan rev10 §PR 6.

This PR is scoped to #62 + #63 only. The Enumerator interface implementation lives in the follow-up PR 6b (feat/do-enumerator-impl), which blocks on workflow PR 4 reaching main.

Changes

  • internal/provider.go
    • Initialize accepts ctx (was _), forwards to oauth2.NewClient, rejects nil.
    • Plan becomes plan, err := platform.ComputePlan(ctx, p, desired, current); return &plan, err.
    • Removed the dead resourceOutputFromState helper.
  • internal/provider_test.go
    • TestMain sets WFCTL_DIFFCACHE=disabled so the platform diff cache cannot poison test runs.
    • planDiffFakeDriver gains a sync.Mutex around its observable state (ComputePlan dispatches Diff in parallel via errgroup).
    • TestDOProvider_Initialize_NilCtxRejected and TestDOProvider_Initialize_ThreadsCtxToGodoClient pin DOProvider.Initialize ignores ctx parameter — godo client uses context.Background() #62.
    • TestDOProvider_Plan_KeepsDistinctCurrentStatePerConfigHashAction (legacy configHash-fallback) replaced with TestDOProvider_Plan_RejectsUnregisteredDriverType matching the new contract.

Test plan

  • GOWORK=off go test -race -count=1 ./... (all green: internal + drivers + root)
  • iac-codemod lint -dry-run internal/provider.go reports 0 findings (Plan canonical pattern recognized)
  • CI on the PR: build, lint, conformance, release-dry-run all green

Out of scope

  • DO Enumerator impl — separate PR 6b (feat/do-enumerator-impl); blocks on workflow PR 4 (Enumerator interface) reaching main.
  • DO plugin v0.10.1 tag — cut after PR 6b merges (not after this PR), per plan rev10 §Coordination.

🤖 Generated with Claude Code

intel352 added 2 commits May 5, 2026 06:37
Initialize previously discarded its caller-supplied ctx and constructed
the oauth2 client with context.Background(), silently dropping any
oauth2.HTTPClient injected via the provided ctx (tests, custom
transports, proxy configurations).

Now the ctx is forwarded to oauth2.NewClient, and a nil-ctx guard
returns a typed error instead of panicking inside the oauth2 stack.

Tests: nil-ctx guard + a capturing-transport regression test that
verifies a custom http.Client injected via oauth2.HTTPClient observes
a real outbound godo request.

Refs: workflow-plugin-digitalocean#62
The hand-rolled Plan body duplicated logic that already lives in
platform.ComputePlan and silently dropped two correctness paths the
canonical helper enforces:

  1. ForceNew → replace promotion: ComputePlan upgrades update→replace
     when any FieldChange has ForceNew=true; the prior body only
     honored DiffResult.NeedsReplace, so any driver that returned
     ForceNew=true on a per-field basis (without setting NeedsReplace)
     emitted update actions that would later fail at Apply time.
  2. DependsOn-ordered dispatch: ComputePlan parallelises Diff with an
     errgroup worker pool and topologically sorts the resulting actions
     so the Apply stage sees creates-before-replaces-before-deletes
     order. The previous body iterated desired in input order with no
     ordering guarantee.

The 2-statement (call + pointer-bridge return) shape matches the
W-Refactor / iac-codemod canonical target asserted by
cmd/iac-codemod AssertPlanDelegatesToHelper. Lint reports 0 findings on
internal/provider.go after this change.

Test impact:
- planDiffFakeDriver gains a sync.Mutex around its observable state
  (Diff is dispatched in parallel by ComputePlan).
- TestMain sets WFCTL_DIFFCACHE=disabled so per-test Diff dispatches
  are reproducible (the filesystem cache is global per UID and would
  otherwise let one test poison another).
- TestDOProvider_Plan_KeepsDistinctCurrentStatePerConfigHashAction
  retired and replaced by TestDOProvider_Plan_RejectsUnregisteredDriverType
  — the configHash-fallback semantic it pinned no longer applies, since
  ComputePlan surfaces the missing-driver error rather than masking it.

Refs: workflow-plugin-digitalocean#63
Copilot AI review requested due to automatic review settings May 5, 2026 10:49
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR closes two correctness gaps in DOProvider by (1) properly threading the caller’s context.Context into the DigitalOcean client initialization path, and (2) delegating planning to the workflow platform’s canonical platform.ComputePlan helper to restore replace/ordering semantics.

Changes:

  • Update DOProvider.Initialize to require a non-nil ctx and pass it to oauth2.NewClient, ensuring ctx-injected oauth2.HTTPClient is honored end-to-end.
  • Collapse DOProvider.Plan to the canonical 2-statement delegation to platform.ComputePlan, restoring ForceNew→replace promotion and dependency-correct action ordering.
  • Adjust tests to disable the diffcache backend, add Initialize ctx coverage, and make the plan Diff fake concurrency-safe.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
internal/provider.go Thread ctx into oauth2 client creation; delegate Plan to platform.ComputePlan and remove the now-unneeded local helper logic.
internal/provider_test.go Disable diffcache for reproducible tests; add Initialize ctx tests; mutex-protect fake driver state; update Plan contract test expectations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/provider_test.go Outdated
Comment on lines +115 to +121
// Return a minimal 200 with empty JSON body so godo doesn't choke.
return &http.Response{
StatusCode: http.StatusOK,
Body: http.NoBody,
Header: make(http.Header),
Request: req,
}, nil
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 48b380e — capturing transport now returns a minimal valid JSON object body ({}) with a Content-Type header, and the comment is updated to match.

Copilot review #68: the capturing transport returned http.NoBody, which
godo's response decoder can error on (EOF / invalid JSON), making the
test more brittle than necessary and rendering the inline comment about
"empty JSON body" misleading. Return a minimal valid JSON object body
("{}") with a Content-Type header instead — the test still only cares
that the transport observed the request, but the path is robust against
godo's decode-on-success behavior on pointer-to-struct destinations.
@intel352 intel352 merged commit a43aeda into main May 5, 2026
4 of 5 checks passed
@intel352 intel352 deleted the fix/initialize-ctx-and-plan-canonical branch May 5, 2026 11:00
Copilot AI added a commit that referenced this pull request May 7, 2026
intel352 added a commit that referenced this pull request May 7, 2026
* Initial plan

* fix: update stale comment in provider_conformance_test.go (issue #62 already fixed in PR #68)

Agent-Logs-Url: https://github.com/GoCodeAlone/workflow-plugin-digitalocean/sessions/962a09f7-575b-460c-85b7-d4de08c75f7b

Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>

* docs: clarify initialize context behavior

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Co-authored-by: Jon Langevin <codingsloth@pm.me>
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.

2 participants