Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
fc17398
docs(#653): design doc for Phase 1 AWS IaC cutover
intel352 May 13, 2026
68c876b
docs(#653): revise design doc per adversarial review cycle 1
intel352 May 13, 2026
c44660d
docs: fix C-3 in aws-cutover design (app_container.go compile break)
intel352 May 13, 2026
1642311
docs: remove dead ECS code from app_container.go in design (cycle 2 f…
intel352 May 13, 2026
c7dbd3e
docs: adversarial cycle 3 PASS — finalize aws-cutover design
intel352 May 13, 2026
4342c5a
docs(#653): implementation plan for Phase 1 AWS IaC cutover
intel352 May 13, 2026
90d7c17
fix(plan#653): fix T2 DNS test assertion + T4 test stub (adversarial …
intel352 May 13, 2026
57b8d4c
fix(plan#653): fix T5 modernize test stub (adversarial cycle 2)
intel352 May 13, 2026
8456128
chore: lock scope for issue-653-aws-iac-cutover (alignment passed)
intel352 May 13, 2026
5d837c5
feat(#653): T1 — delete legacy AWS IaC module files + regression gate
intel352 May 13, 2026
87f4dd5
feat(#653): T2 — replace Route53 backend with migration error stub
intel352 May 13, 2026
456e402
feat(#653): strip registration sites + add infra.autoscaling_group (T3)
intel352 May 13, 2026
4297f42
feat(#653): add legacyaws package + wire migration errors (T4)
intel352 May 13, 2026
c2bc54c
feat(#653): add legacy-aws-types modernize rule + migration guide (T5)
intel352 May 13, 2026
6df5371
chore(#653): go mod tidy + add aws-sdk-banned CI gate (T6)
intel352 May 13, 2026
7b8d67b
fix(#653): update wfctl test fixtures for removed AWS step types
intel352 May 13, 2026
93c2436
fix(#653): fix nilerr lint in aws_absent_test.go
intel352 May 13, 2026
2e9cf44
fix(#653): correct platform.dns ConfigKeys: zone+records not domain
intel352 May 13, 2026
950a0f0
docs: post-merge retro for issue #653 AWS IaC removal (PR #657)
intel352 May 13, 2026
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
24 changes: 24 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -393,3 +393,27 @@ jobs:
- name: Grep gate — go.mod files must not list godo
run: |
! grep -qH "digitalocean/godo" go.mod example/go.mod

aws-sdk-banned:
name: Verify removed AWS SDK packages are not imported (issue #653)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Grep gate — *.go files must not import removed AWS service packages
run: |
! grep -rn --include="*.go" \
--exclude-dir=_worktrees \
--exclude-dir=.worktrees \
--exclude-dir=.claude \
--exclude="aws_absent_test.go" \
-e "aws-sdk-go-v2/service/apigatewayv2" \
-e "aws-sdk-go-v2/service/applicationautoscaling" \
-e "aws-sdk-go-v2/service/route53" \
.
- name: Grep gate — go.mod files must not list removed AWS SDK packages
run: |
! grep -qH \
-e "aws-sdk-go-v2/service/apigatewayv2" \
-e "aws-sdk-go-v2/service/applicationautoscaling" \
-e "aws-sdk-go-v2/service/route53" \
go.mod example/go.mod
27 changes: 7 additions & 20 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,6 @@ flowchart TD
| `step.k8s_apply` | Applies a Kubernetes manifest or deployment config | platform |
| `step.k8s_status` | Retrieves the status of a Kubernetes workload | platform |
| `step.k8s_destroy` | Tears down a Kubernetes workload | platform |
| `step.ecs_plan` | Generates an ECS task/service deployment plan | platform |
| `step.ecs_apply` | Deploys a task or service to AWS ECS | platform |
| `step.ecs_status` | Retrieves the status of an ECS service | platform |
| `step.ecs_destroy` | Removes an ECS task or service | platform |
| `step.iac_plan` | Plans IaC changes (Terraform plan, Pulumi preview, etc.) | platform |
| `step.iac_apply` | Applies IaC changes | platform |
| `step.iac_status` | Retrieves the current state of an IaC stack | platform |
Expand All @@ -297,17 +293,6 @@ flowchart TD
| `step.dns_plan` | Plans DNS record changes | platform |
| `step.dns_apply` | Applies DNS record changes | platform |
| `step.dns_status` | Retrieves the current DNS records for a domain | platform |
| `step.network_plan` | Plans networking resource changes (VPC, subnets, etc.) | platform |
| `step.network_apply` | Applies networking resource changes | platform |
| `step.network_status` | Retrieves the status of networking resources | platform |
| `step.apigw_plan` | Plans API gateway configuration changes | platform |
| `step.apigw_apply` | Applies API gateway configuration changes | platform |
| `step.apigw_status` | Retrieves API gateway deployment status | platform |
| `step.apigw_destroy` | Removes an API gateway configuration | platform |
| `step.scaling_plan` | Plans auto-scaling policy changes | platform |
| `step.scaling_apply` | Applies auto-scaling policies | platform |
| `step.scaling_status` | Retrieves current auto-scaling state | platform |
| `step.scaling_destroy` | Removes auto-scaling policies | platform |
| `step.app_deploy` | Deploys a containerized application | platform |
| `step.app_status` | Retrieves deployment status of an application | platform |
| `step.app_rollback` | Rolls back an application to a previous deployment | platform |
Expand Down Expand Up @@ -503,11 +488,7 @@ Strict mode applies to **both** direct dot-access (`{{ .steps.auth.field }}`) an
| `platform.resource` | Infrastructure resource managed by a platform provider | platform |
| `platform.context` | Execution context for platform operations (org, environment, tier) | platform |
| `platform.kubernetes` | Kubernetes cluster deployment target | platform |
| `platform.ecs` | AWS ECS cluster deployment target | platform |
| `platform.dns` | DNS provider for managing records (Route53, CloudFlare, etc.) | platform |
| `platform.networking` | VPC and networking resource management | platform |
| `platform.apigateway` | API gateway resource management (AWS API GW, etc.) | platform |
| `platform.autoscaling` | Auto-scaling policy and target management | platform |
| `platform.dns` | DNS provider for managing records (mock; AWS Route53 backend removed in v0.53.0) | platform |
| `platform.region` | Multi-region deployment configuration | platform |
| `platform.region_router` | Routes traffic across regions by weight, latency, or failover | platform |

Expand All @@ -516,6 +497,11 @@ Strict mode applies to **both** direct dot-access (`{{ .steps.auth.field }}`) an
external plugin. After loading the plugin, use the generic `infra.*` module
types with `provider: digitalocean` and the generic `step.iac_*` pipeline
steps. See [v0.52.0 migration guide](docs/migrations/v0.52.0-godo-removal.md).

**AWS IaC modules** (`platform.ecs`, `platform.networking`, `platform.apigateway`, `platform.autoscaling`) were removed from workflow core in v0.53.0 and are provided by the
[workflow-plugin-aws](https://github.com/GoCodeAlone/workflow-plugin-aws) v0.2.0+ plugin.
Use the generic `infra.*` module types with `provider: aws` and `step.iac_*` pipeline steps.
See [v0.53.0 migration guide](docs/migrations/v0.53.0-aws-iac-removal.md).
| `iac.provider` | Cloud provider configuration (aws, gcp, azure, digitalocean) for IaC operations | platform |
| `iac.state` | IaC state persistence (memory, filesystem, spaces, gcs, azure_blob, postgres) | platform |
| `infra.vpc` | Virtual Private Cloud and subnet management | platform |
Expand All @@ -531,6 +517,7 @@ steps. See [v0.52.0 migration guide](docs/migrations/v0.52.0-godo-removal.md).
| `infra.iam_role` | IAM role and policy creation and management | platform |
| `infra.storage` | Object storage provisioning and access configuration | platform |
| `infra.certificate` | SSL/TLS certificate provisioning and renewal | platform |
| `infra.autoscaling_group` | Auto-scaling group provisioning and policy management | platform |
| `app.container` | Containerised application deployment descriptor | platform |
| `argo.workflows` | Argo Workflows integration for Kubernetes-native workflow orchestration | platform |
| `aws.codebuild` | AWS CodeBuild project and build management | cicd |
Expand Down
14 changes: 13 additions & 1 deletion cmd/wfctl/ci_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"time"

"github.com/GoCodeAlone/workflow/config"
"github.com/GoCodeAlone/workflow/internal/legacyaws"
"github.com/GoCodeAlone/workflow/internal/legacydo"
"github.com/GoCodeAlone/workflow/schema"
"github.com/GoCodeAlone/workflow/validation"
Expand Down Expand Up @@ -138,15 +139,23 @@ func ciValidateFile(cfgPath string, strict, immutableConfig bool, immutableSecti
for t := range legacydo.ModuleTypes {
opts = append(opts, schema.WithExtraModuleTypes(t))
}
// Same for legacy AWS module types removed in issue #653.
for t := range legacyaws.ModuleTypes {
opts = append(opts, schema.WithExtraModuleTypes(t))
}
if err := schema.ValidateConfig(cfg, opts...); err != nil {
errs = append(errs, fmt.Errorf("schema: %w", err))
}

// Post-validate sweep: accumulate legacy DO module/step errors (issue #617).
// Post-validate sweep: accumulate legacy DO and AWS module/step errors
// (issues #617, #653).
for _, m := range cfg.Modules {
if legacydo.IsModuleType(m.Type) {
errs = append(errs, legacydo.FormatModuleError(m.Type, m.Name, false))
}
if legacyaws.IsModuleType(m.Type) {
errs = append(errs, legacyaws.FormatModuleError(m.Type, m.Name, false))
}
}
for _, rawPipeline := range cfg.Pipelines {
yamlBytes, err := yaml.Marshal(rawPipeline)
Expand All @@ -161,6 +170,9 @@ func ciValidateFile(cfgPath string, strict, immutableConfig bool, immutableSecti
if legacydo.IsStepType(s.Type) {
errs = append(errs, legacydo.FormatStepError(s.Type, false))
}
if legacyaws.IsStepType(s.Type) {
errs = append(errs, legacyaws.FormatStepError(s.Type, false))
}
}
}

Expand Down
89 changes: 89 additions & 0 deletions cmd/wfctl/legacy_aws_types_removed_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package main

import (
"os"
"path/filepath"
"strings"
"testing"
)

// TestLegacyAWSTypesAbsent_FromTypeRegistry locks the post-cutover state of
// cmd/wfctl/type_registry.go for issue #653. If any legacy AWS type leaks back
// in, this test fires and the CI gate fires.
func TestLegacyAWSTypesAbsent_FromTypeRegistry(t *testing.T) {
modules := KnownModuleTypes()
steps := KnownStepTypes()
legacyModules := []string{
"platform.ecs", "platform.networking",
"platform.apigateway", "platform.autoscaling",
}
legacySteps := []string{
"step.ecs_plan", "step.ecs_apply", "step.ecs_status", "step.ecs_destroy",
"step.network_plan", "step.network_apply", "step.network_status",
"step.apigw_plan", "step.apigw_apply", "step.apigw_status", "step.apigw_destroy",
"step.scaling_plan", "step.scaling_apply", "step.scaling_status", "step.scaling_destroy",
}
for _, tname := range legacyModules {
if _, ok := modules[tname]; ok {
t.Errorf("module type registry still contains legacy AWS type %q (issue #653)", tname)
}
}
for _, tname := range legacySteps {
if _, ok := steps[tname]; ok {
t.Errorf("step type registry still contains legacy AWS type %q (issue #653)", tname)
}
}
}

// TestValidateFile_LegacyAWSModule_ReturnsActionableError verifies that
// wfctl validate emits the actionable migration error when the config
// references a removed legacy AWS module type (issue #653). Covers the
// validate path (the engine path is covered by
// TestLegacyAWSModuleError_PluginNotLoaded in the workflow package).
func TestValidateFile_LegacyAWSModule_ReturnsActionableError(t *testing.T) {
dir := t.TempDir()
cfgPath := filepath.Join(dir, "legacy.yaml")
yamlContent := []byte("modules:\n - name: svc\n type: platform.ecs\n config: {}\n")
if err := os.WriteFile(cfgPath, yamlContent, 0o600); err != nil {
t.Fatal(err)
}
err := validateFile(cfgPath, false, false, false)
if err == nil {
t.Fatal("expected error for legacy AWS module type")
}
msg := err.Error()
for _, want := range []string{
"removed from workflow core",
"workflow-plugin-aws",
"infra.container_service",
} {
if !strings.Contains(msg, want) {
t.Errorf("error missing %q; got: %s", want, msg)
}
}
}

// TestCIValidateFile_LegacyAWSStep_ReturnsActionableError covers ciValidateFile's
// accumulating return for legacy AWS step types.
func TestCIValidateFile_LegacyAWSStep_ReturnsActionableError(t *testing.T) {
dir := t.TempDir()
cfgPath := filepath.Join(dir, "legacy.yaml")
yamlContent := []byte("pipelines:\n deploy:\n steps:\n - type: step.ecs_apply\n")
if err := os.WriteFile(cfgPath, yamlContent, 0o600); err != nil {
t.Fatal(err)
}
errs := ciValidateFile(cfgPath, false, false, "")
if len(errs) == 0 {
t.Fatal("expected error for legacy AWS step type")
}
found := false
for _, e := range errs {
if strings.Contains(e.Error(), "step.iac_apply") && strings.Contains(e.Error(), "removed from workflow core") {
found = true
break
}
}
if !found {
t.Errorf("expected actionable migration error in errs; got: %v", errs)
}
}
1 change: 1 addition & 0 deletions cmd/wfctl/modernize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ func TestModernizeAllRulesRegistered(t *testing.T) {
"camelcase-config",
"request-parse-config",
"legacy-do-types",
"legacy-aws-types",
}
if len(rules) != len(expectedIDs) {
t.Errorf("expected %d rules, got %d", len(expectedIDs), len(rules))
Expand Down
115 changes: 7 additions & 108 deletions cmd/wfctl/type_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -519,35 +519,11 @@ func KnownModuleTypes() map[string]ModuleTypeInfo {
Stateful: false,
ConfigKeys: []string{"account", "cluster", "namespace", "kubeconfig"},
},
"platform.ecs": {
Type: "platform.ecs",
Plugin: "platform",
Stateful: false,
ConfigKeys: []string{"account", "cluster", "region"},
},
"platform.dns": {
Type: "platform.dns",
Plugin: "platform",
Stateful: false,
ConfigKeys: []string{"account", "provider", "domain"},
},
"platform.networking": {
Type: "platform.networking",
Plugin: "platform",
Stateful: false,
ConfigKeys: []string{"account", "provider", "vpc"},
},
"platform.apigateway": {
Type: "platform.apigateway",
Plugin: "platform",
Stateful: false,
ConfigKeys: []string{"account", "provider", "name", "region"},
},
"platform.autoscaling": {
Type: "platform.autoscaling",
Plugin: "platform",
Stateful: false,
ConfigKeys: []string{"account", "provider", "resource"},
ConfigKeys: []string{"account", "provider", "zone", "records"},
},
"platform.region": {
Type: "platform.region",
Expand Down Expand Up @@ -653,6 +629,12 @@ func KnownModuleTypes() map[string]ModuleTypeInfo {
Stateful: false,
ConfigKeys: []string{"provider", "size", "resources"},
},
"infra.autoscaling_group": {
Type: "infra.autoscaling_group",
Plugin: "infra",
Stateful: false,
ConfigKeys: []string{"provider", "size", "resources"},
},

// actors plugin
"actor.system": {
Expand Down Expand Up @@ -1426,28 +1408,6 @@ func KnownStepTypes() map[string]StepTypeInfo {
ConfigKeys: []string{"cluster"},
},

// platform plugin steps (scaling)
"step.scaling_plan": {
Type: "step.scaling_plan",
Plugin: "platform",
ConfigKeys: []string{"scaling"},
},
"step.scaling_apply": {
Type: "step.scaling_apply",
Plugin: "platform",
ConfigKeys: []string{"scaling"},
},
"step.scaling_status": {
Type: "step.scaling_status",
Plugin: "platform",
ConfigKeys: []string{"scaling"},
},
"step.scaling_destroy": {
Type: "step.scaling_destroy",
Plugin: "platform",
ConfigKeys: []string{"scaling"},
},

// platform plugin steps (iac)
"step.iac_plan": {
Type: "step.iac_plan",
Expand Down Expand Up @@ -1492,67 +1452,6 @@ func KnownStepTypes() map[string]StepTypeInfo {
ConfigKeys: []string{"zone"},
},

// platform plugin steps (networking)
"step.network_plan": {
Type: "step.network_plan",
Plugin: "platform",
ConfigKeys: []string{"network"},
},
"step.network_apply": {
Type: "step.network_apply",
Plugin: "platform",
ConfigKeys: []string{"network"},
},
"step.network_status": {
Type: "step.network_status",
Plugin: "platform",
ConfigKeys: []string{"network"},
},

// platform plugin steps (api gateway)
"step.apigw_plan": {
Type: "step.apigw_plan",
Plugin: "platform",
ConfigKeys: []string{"gateway"},
},
"step.apigw_apply": {
Type: "step.apigw_apply",
Plugin: "platform",
ConfigKeys: []string{"gateway"},
},
"step.apigw_status": {
Type: "step.apigw_status",
Plugin: "platform",
ConfigKeys: []string{"gateway"},
},
"step.apigw_destroy": {
Type: "step.apigw_destroy",
Plugin: "platform",
ConfigKeys: []string{"gateway"},
},

// platform plugin steps (ecs)
"step.ecs_plan": {
Type: "step.ecs_plan",
Plugin: "platform",
ConfigKeys: []string{"service"},
},
"step.ecs_apply": {
Type: "step.ecs_apply",
Plugin: "platform",
ConfigKeys: []string{"service"},
},
"step.ecs_status": {
Type: "step.ecs_status",
Plugin: "platform",
ConfigKeys: []string{"service"},
},
"step.ecs_destroy": {
Type: "step.ecs_destroy",
Plugin: "platform",
ConfigKeys: []string{"service"},
},

// platform plugin steps (app container)
"step.app_deploy": {
Type: "step.app_deploy",
Expand Down
Loading
Loading