Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions docs/migrations/2026-05-14-cloud-sdk-extraction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# 2026-05-14 — Cloud-SDK extraction: `azure_blob` IaC state backend moves to a plugin

## What changed

The in-core `azure_blob` IaC state backend was removed from workflow core.
`module/iac_state_azure.go` (the `AzureBlobIaCStateStore`) and the `azure_blob`
case in `IaCModule.Init` are gone. As a result, `github.com/Azure/azure-sdk-for-go`
is no longer a dependency of the workflow module — `go mod tidy` drops `azcore`,
`storage/azblob`, and their transitive `sdk/internal` entirely.

`backend: azure_blob` is still a valid `iac.state` config value — but it now
resolves to an `IaCStateBackend` gRPC client served by
[`workflow-plugin-azure`](https://github.com/GoCodeAlone/workflow-plugin-azure)
v1.1.0+. The plugin advertises the backend via the `iacStateBackends` field in
its `plugin.json`; the engine populates the in-core backend registry at
plugin-load time, and `IaCModule.Init` constructs a `grpcIaCStateStore` for it.

## Why

Workflow core should own IaC interfaces and orchestration, not provider SDKs.
Dependabot bumps to `azure-sdk-for-go` now target the Azure plugin repo, not
core. This mirrors the pattern established by the godo removal (issue #617) and
the AWS IaC removal (v0.53.0). See the design plan at
`docs/plans/2026-05-14-cloud-sdk-extraction-design.md`.

## Breaking change

An `iac.state` module with `backend: azure_blob` now **requires
`workflow-plugin-azure` (>= v1.1.0) to be loaded**. With no plugin loaded, the
module fails to initialize with an actionable error:

```
iac.state "<name>": backend "azure_blob" is not built into workflow core
(in-core backends: 'memory', 'filesystem', 'spaces', 'gcs', 'postgres').
If "azure_blob" is a plugin-provided backend (e.g. 'azure_blob' via
workflow-plugin-azure), install and load that plugin
```

The yaml `backend: azure_blob` value itself is **unchanged** — no config
rewrite is needed beyond installing the plugin. The `account_url`,
`account_name`, `account_key`, `container`, and `prefix` config keys are
unchanged and continue to be honored by the plugin's backend.

## Unaffected backends

The `memory`, `filesystem`, `spaces`, `gcs`, and `postgres` IaC state backends
remain in workflow core and are **not** affected by this change. Only
`azure_blob` moved to a plugin.

## Migration recipe

1. Install the Azure plugin (v1.1.0+):
```sh
wfctl plugin install workflow-plugin-azure@1.1.0
```
Or declare it in your workflow config under `plugins.external`:
```yaml
plugins:
external:
- name: workflow-plugin-azure
version: ">=1.1.0"
autoFetch: true
```

To declare the dependency without auto-fetch:
```yaml
requires:
plugins:
- name: workflow-plugin-azure
```

2. No config rewrite is required. The `iac.state` module keeps its
`backend: azure_blob` value and all its existing config keys:
```yaml
modules:
- name: iac-state
type: iac.state
config:
backend: azure_blob
container: my-state-container
account_url: https://myaccount.blob.core.windows.net
account_name: myaccount
account_key: <key>
```

## Phases B/C/D

This is Phase A of the cloud-SDK extraction. Phases B, C, and D apply the same
pattern to the AWS, GCP, and DigitalOcean IaC state backends in subsequent
releases — each backend moves to its provider plugin, and the corresponding
cloud SDK drops from workflow core's `go.mod`.

## Rollback

If you need to roll back, revert the commit
`feat(module)!: drop in-core azure_blob IaC state backend` and run
`go mod tidy` — this restores `module/iac_state_azure.go`, the in-core
`azure_blob` case, and re-adds `azure-sdk-for-go` to `go.mod`. Smoke-check with
an `azure_blob` config and no plugin loaded.
3 changes: 0 additions & 3 deletions example/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ require (
cloud.google.com/go/iam v1.8.0 // indirect
cloud.google.com/go/monitoring v1.26.0 // indirect
cloud.google.com/go/storage v1.62.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4 // indirect
github.com/BurntSushi/toml v1.6.0 // indirect
github.com/DataDog/datadog-go/v5 v5.8.3 // indirect
github.com/GoCodeAlone/modular/modules/auth v1.15.0 // indirect
Expand Down
14 changes: 0 additions & 14 deletions example/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,8 @@ cloud.google.com/go/trace v1.12.0 h1:XvWHYfr9q88cX4pZyou6qCcSagnuASyUq2ej1dB6NzQ
cloud.google.com/go/trace v1.12.0/go.mod h1:TOYfyeoyCGsSH0ifXD6Aius24uQI9xV3RyvOdljFIyg=
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 h1:fou+2+WFTib47nS+nz/ozhEBnvU96bKHy6LjRsY4E28=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0/go.mod h1:t76Ruy8AHvUAC8GfMWJMa0ElSbuIcO03NLpynfbgsPA=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 h1:Hk5QBxZQC1jb2Fwj6mpzme37xbCDdNTxU7O9eb5+LB4=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1/go.mod h1:IYus9qsFobWIc2YVwe/WPjcnyCkPKtnHAqUYeebc8z0=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0 h1:fhqpLE3UEXi9lPaBRpQ6XuRW0nU7hgg4zlmZZa+a9q4=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0/go.mod h1:7dCRMLwisfRH3dBupKeNCioWYUZ4SS09Z14H+7i8ZoY=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 h1:/Zt+cDPnpC3OVDm/JKLOs7M2DKmLRIIp3XIx9pHHiig=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1/go.mod h1:Ng3urmn6dYe8gnbCMoHHVl5APYz2txho3koEkV2o2HA=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4 h1:jWQK1GI+LeGGUKBADtcH2rRqPxYB1Ljwms5gFA2LqrM=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4/go.mod h1:8mwH4klAm9DUgR2EEHyEEAQlRDvLPyg5fQry3y+cDew=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs=
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk=
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
Expand Down Expand Up @@ -512,8 +500,6 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4/v4 v4.1.26 h1:GrpZw1gZttORinvzBdXPUXATeqlJjqUG/D87TKMnhjY=
github.com/pierrec/lz4/v4 v4.1.26/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down
3 changes: 0 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ require (
charm.land/bubbletea/v2 v2.0.2
charm.land/lipgloss/v2 v2.0.2
cloud.google.com/go/storage v1.61.3
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4
github.com/GoCodeAlone/go-plugin v1.7.0
github.com/GoCodeAlone/modular v1.13.0
github.com/GoCodeAlone/modular/modules/auth v1.15.0
Expand Down Expand Up @@ -87,7 +85,6 @@ require (
cloud.google.com/go/compute/metadata v0.9.0 // indirect
cloud.google.com/go/iam v1.5.3 // indirect
cloud.google.com/go/monitoring v1.24.3 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
github.com/BurntSushi/toml v1.6.0 // indirect
github.com/DataDog/datadog-go/v5 v5.8.3 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0 // indirect
Expand Down
14 changes: 0 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,8 @@ cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U
cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s=
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 h1:fou+2+WFTib47nS+nz/ozhEBnvU96bKHy6LjRsY4E28=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0/go.mod h1:t76Ruy8AHvUAC8GfMWJMa0ElSbuIcO03NLpynfbgsPA=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 h1:Hk5QBxZQC1jb2Fwj6mpzme37xbCDdNTxU7O9eb5+LB4=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1/go.mod h1:IYus9qsFobWIc2YVwe/WPjcnyCkPKtnHAqUYeebc8z0=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 h1:/Zt+cDPnpC3OVDm/JKLOs7M2DKmLRIIp3XIx9pHHiig=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1/go.mod h1:Ng3urmn6dYe8gnbCMoHHVl5APYz2txho3koEkV2o2HA=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4 h1:jWQK1GI+LeGGUKBADtcH2rRqPxYB1Ljwms5gFA2LqrM=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4/go.mod h1:8mwH4klAm9DUgR2EEHyEEAQlRDvLPyg5fQry3y+cDew=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs=
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk=
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
Expand Down Expand Up @@ -624,8 +612,6 @@ github.com/petermattis/goid v0.0.0-20260226131333-17d1149c6ac6/go.mod h1:pxMtw7c
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4/v4 v4.1.26 h1:GrpZw1gZttORinvzBdXPUXATeqlJjqUG/D87TKMnhjY=
github.com/pierrec/lz4/v4 v4.1.26/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down
39 changes: 8 additions & 31 deletions module/iac_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,14 @@ import (
"context"
"fmt"

"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
"github.com/GoCodeAlone/modular"
)

// newAzureSharedKeyCredential is a thin wrapper so iac_module.go doesn't import azblob directly
// in multiple places and can be easily replaced with other credential types.
func newAzureSharedKeyCredential(name, key string) (*azblob.SharedKeyCredential, error) {
return azblob.NewSharedKeyCredential(name, key)
}

// IaCModule registers an IaCStateStore in the service registry.
// Supported backends: "memory" (default), "filesystem", and "spaces"
// (DigitalOcean Spaces / S3-compatible).
// Supported in-core backends: "memory" (default), "filesystem", "spaces"
// (DigitalOcean Spaces / S3-compatible), "gcs", and "postgres" — plus any
// backend provided by a loaded plugin (e.g. "azure_blob" via
// workflow-plugin-azure).
//
// Config example:
//
Expand Down Expand Up @@ -83,27 +78,6 @@ func (m *IaCModule) Init(app modular.Application) error {
return fmt.Errorf("iac.state %q: gcs backend: %w", m.name, err)
}
m.store = store
case "azure_blob":
container, _ := m.config["container"].(string)
prefix, _ := m.config["prefix"].(string)
accountURL, _ := m.config["account_url"].(string)
accountName, _ := m.config["account_name"].(string)
accountKey, _ := m.config["account_key"].(string)
if container == "" {
return fmt.Errorf("iac.state %q: azure_blob backend requires 'container' config", m.name)
}
if accountURL == "" || accountName == "" || accountKey == "" {
return fmt.Errorf("iac.state %q: azure_blob backend requires 'account_url', 'account_name', and 'account_key' config", m.name)
}
cred, err := newAzureSharedKeyCredential(accountName, accountKey)
if err != nil {
return fmt.Errorf("iac.state %q: azure_blob backend: credential: %w", m.name, err)
}
store, err := NewAzureBlobIaCStateStore(accountURL, container, prefix, *cred)
if err != nil {
return fmt.Errorf("iac.state %q: azure_blob backend: %w", m.name, err)
}
m.store = store
case "postgres":
dsn, _ := m.config["dsn"].(string)
if dsn == "" {
Comment thread
intel352 marked this conversation as resolved.
Expand All @@ -122,7 +96,10 @@ func (m *IaCModule) Init(app modular.Application) error {
m.store = newGRPCIaCStateStore(client)
break
}
return fmt.Errorf("iac.state %q: unsupported backend %q (use 'memory', 'filesystem', 'spaces', 'gcs', 'azure_blob', or 'postgres', or load the plugin that provides it)", m.name, m.backend)
return fmt.Errorf("iac.state %q: backend %q is not built into workflow core "+
"(in-core backends: 'memory', 'filesystem', 'spaces', 'gcs', 'postgres'). "+
"If %q is a plugin-provided backend (e.g. 'azure_blob' via workflow-plugin-azure), "+
"install and load that plugin", m.name, m.backend, m.backend)
}

return app.RegisterService(m.name, m.store)
Expand Down
Loading
Loading