Repository navigation
Migrate workflow-plugin-migrations to strict gRPC proto contracts - #13
Conversation
There was a problem hiding this comment.
Copilot wasn't able to review any files in this pull request.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot This PR currently has 0 changed files, so the assigned task is not implemented yet. Please continue the original issue task using Claude Sonnet 4.6: make the required Workflow strict-contract or downstream dependency updates, push actual code/config/doc changes to this PR branch, run the requested validation, and update the PR body with the validation results. Do not leave this as an empty PR. |
|
@copilot Add this as part of the PR scope: include or update a GitHub Actions PR check that validates strict Workflow plugin contracts. The check should fail when name: wfctl strict contracts
on:
pull_request:
push:
branches: [main, master]
jobs:
wfctl-strict-contracts:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Validate strict plugin contracts
run: go run github.com/GoCodeAlone/workflow/cmd/wfctl@v0.20.1 plugin validate --file plugin.json --strict-contractsAdjust branch filters and Go setup to match this repository. If the repo uses an existing CI workflow, add this as a job there instead of creating duplicate workflow clutter. Include the check result in the PR validation notes. |
- Add internal/contracts.go with dynamic.FieldContract definitions for:
- database.migrations (required: source_dir; optional: driver, driver_ref, dsn_env, history_table, timeout)
- database.migration_driver (required: driver)
- step.migrate_up, step.migrate_down, step.migrate_status, step.migrate_to
(each with typed required/optional inputs and typed outputs)
- Implement sdk.SchemaProvider on MigrationsPlugin (ModuleSchemas method)
- Expose ModuleContracts() and StepContracts() on MigrationsPlugin
- Add PluginModuleSchemas() and PluginStepSchemas() package-level helpers
- Update plugin.json to include stepSchemas array for all 4 step types
(parsed by LoadPluginStepSchemasFromDir and wfctl editor schema registry)
- Add plugin.contracts.json with per-type strict contract descriptors
covering config required/optional fields, method inputs/outputs for modules,
and config + outputs for steps
- Add tests: TestPlugin_SchemaProvider, TestPlugin_ModuleContracts,
TestPlugin_StepContracts, TestPlugin_StepSchemas, TestPlugin_ContractCoverage
Agent-Logs-Url: https://github.com/GoCodeAlone/workflow-plugin-migrations/sessions/976b79d8-9651-4ac2-8a18-6ba7c021b72c
Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
…racts.json - Fix DefaultValue for steps config field in PluginStepSchemas() from string \"1\" to integer 1 (schema.ConfigFieldDef.DefaultValue is any; int is correct for FieldTypeNumber) - Add type vocabulary note to plugin.contracts.json header clarifying that field types use the dynamic.FieldType vocabulary (int, bool, string, etc.) distinct from the schema.ConfigFieldType vocabulary (number, boolean, string, etc.) used in stepSchemas Agent-Logs-Url: https://github.com/GoCodeAlone/workflow-plugin-migrations/sessions/976b79d8-9651-4ac2-8a18-6ba7c021b72c Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
…or wfctl v0.20.1
- Rewrite plugin.contracts.json to use the wfctl v0.20.1 canonical format:
{"version":"1","contracts":[{"kind":...,"type":...,"mode":"strict","config/input/output":...}]}
(previous format was a custom schema incompatible with wfctl audit/validate tooling)
- Add download entries to plugin.json (required for wfctl plugin validate --file
when type=external; points to GitHub Releases for v0.3.6)
- Update plugin.json version from 0.0.0 to 0.3.6 to match latest git tag
- Add strict-contracts job to .github/workflows/ci.yml that runs:
wfctl@v0.20.1 plugin validate --file plugin.json --strict-contracts
on every PR and push to main, failing when plugin.json is missing strict
contract descriptors for any advertised module or step type
Agent-Logs-Url: https://github.com/GoCodeAlone/workflow-plugin-migrations/sessions/0f543e07-5f59-4b54-ab5b-1a9f7bece49b
Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
The PR now contains 5 changed files across 4 commits:
Added a strict-contracts:
name: Validate strict plugin contracts
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version-file: go.mod
- name: Validate strict plugin contracts
run: go run github.com/GoCodeAlone/workflow/cmd/wfctl@v0.20.1 plugin validate --file plugin.json --strict-contractsThe check fails when |
Agent-Logs-Url: https://github.com/GoCodeAlone/workflow-plugin-migrations/sessions/0f543e07-5f59-4b54-ab5b-1a9f7bece49b Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- contracts.go: correct driver_ref description (not a module-ref, literal name only) - contracts.go: correct history_table description (reserved, no runtime effect yet) - plugin.json: fix download URL format from underscores to hyphens to match goreleaser name_template (workflow-plugin-migrations-linux-amd64.tar.gz) - .goreleaser.yaml: add plugin.contracts.json to both plugin archives so wfctl strict-contracts audits pass on installed plugins (not just source) - .goreleaser.yaml: extend sed hook to also rewrite download URLs on release so version pinning doesn't go stale after each goreleaser run - plugin_test.go: add TestPlugin_PluginJSONStepSchemasDrift - loads plugin.json and asserts stepSchemas types match PluginStepSchemas() (catches JSON drift) - plugin_test.go: add TestPlugin_ContractsJSONDrift - loads plugin.contracts.json and asserts strict coverage for all advertised module and step types Agent-Logs-Url: https://github.com/GoCodeAlone/workflow-plugin-migrations/sessions/e32fe1ee-e3c2-48eb-9bc1-57261f259b61 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
…rift test Agent-Logs-Url: https://github.com/GoCodeAlone/workflow-plugin-migrations/sessions/e32fe1ee-e3c2-48eb-9bc1-57261f259b61 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Addressed all 8 unresolved review threads in commit
All 13 tests pass, |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 9 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "url": "https://github.com/GoCodeAlone/workflow-plugin-migrations/releases/download/v0.3.6/workflow-plugin-migrations-linux-amd64.tar.gz" | ||
| }, | ||
| { | ||
| "os": "linux", | ||
| "arch": "arm64", | ||
| "url": "https://github.com/GoCodeAlone/workflow-plugin-migrations/releases/download/v0.3.6/workflow-plugin-migrations-linux-arm64.tar.gz" | ||
| }, | ||
| { | ||
| "os": "darwin", | ||
| "arch": "amd64", | ||
| "url": "https://github.com/GoCodeAlone/workflow-plugin-migrations/releases/download/v0.3.6/workflow-plugin-migrations-darwin-amd64.tar.gz" | ||
| }, | ||
| { | ||
| "os": "darwin", | ||
| "arch": "arm64", | ||
| "url": "https://github.com/GoCodeAlone/workflow-plugin-migrations/releases/download/v0.3.6/workflow-plugin-migrations-darwin-arm64.tar.gz" | ||
| }, | ||
| { | ||
| "os": "windows", | ||
| "arch": "amd64", | ||
| "url": "https://github.com/GoCodeAlone/workflow-plugin-migrations/releases/download/v0.3.6/workflow-plugin-migrations-windows-amd64.tar.gz" | ||
| }, | ||
| { | ||
| "os": "windows", | ||
| "arch": "arm64", | ||
| "url": "https://github.com/GoCodeAlone/workflow-plugin-migrations/releases/download/v0.3.6/workflow-plugin-migrations-windows-arm64.tar.gz" |
| "stepSchemas": [ | ||
| { | ||
| "type": "step.migrate_up", | ||
| "plugin": "workflow-plugin-migrations", | ||
| "description": "Applies all pending database migrations (up direction).", |
| } | ||
| got := sortedContracts(file.Contracts) | ||
| want := sortedContracts(expectedContractDescriptors(t)) |
| test -f "$tmp/plugin.json" | ||
| test -f "$tmp/plugin.contracts.json" | ||
| grep -q '/releases/download/v0.3.6-SNAPSHOT-ci/' "$tmp/plugin.json" |
| main_package="$(mktemp -d)" | ||
| cp plugin.json plugin.contracts.json LICENSE "$main_package" | ||
| sed -i.bak \ | ||
| -e 's/"version": ".*"/"version": "0.3.6-SNAPSHOT-ci"/' \ | ||
| -e 's|/releases/download/v[0-9][^/]*/|/releases/download/v0.3.6-SNAPSHOT-ci/|g' \ | ||
| "$main_package/plugin.json" | ||
| rm -f "$main_package/plugin.json.bak" | ||
| tar -C "$main_package" -czf dist/workflow-plugin-migrations-linux-amd64.tar.gz plugin.json plugin.contracts.json LICENSE |
|
@copilot address all unresolved review comments |
…n tarballs - contracts.go: export proto name constants (ProtoMigrations*, ProtoMigrate*) so the drift test derives expected values from one canonical Go source rather than maintaining a duplicate list of hardcoded strings (thread 3) - plugin_test.go: replace all hardcoded proto name strings in expectedContractDescriptors and moduleOnlyContractDescriptors with the new exported constants from contracts.go - ci.yml: add "Build plugin binaries" step that compiles both binaries before packaging; include the compiled binary in each tarball so the artifact contains the actual executable as GoReleaser would produce (thread 5) - ci.yml: assert binary presence (workflow-plugin-migrations / workflow-plugin-atlas-migrate) in the artifact validation step Agent-Logs-Url: https://github.com/GoCodeAlone/workflow-plugin-migrations/sessions/83993d6a-5f89-40cd-99d9-36dd89b02e8c Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Addressed the remaining unresolved threads in commit Thread 3 ( Thread 5 ( Threads 1, 2, 4 — Already resolved in commit All 19 tests pass, code review clean, CodeQL 0 alerts. |
The plugin had no contract descriptors for any of its 2 module types or 4 step types, causing
wfctl audit pluginsto reportmissing_module_contract_descriptorandmissing_step_contract_descriptorfor all advertised types.Changes
internal/contracts.go(new)dynamic.FieldContractper module type (database.migrations,database.migration_driver) — typed required/optional config fields and service method inputs/outputsdynamic.FieldContractper step type (all 4) — typed required/optional config inputs and typed outputsPluginModuleSchemas()→[]sdk.ModuleSchemaDatafor editor/wfctl toolingPluginStepSchemas()→[]*schema.StepSchemafor the step schema registrydriver_refclarified as a literal driver name (module-ref lookup not yet implemented);history_tablenoted as reserved for future driver support with no current runtime effectProtoMigrationsModuleConfig,ProtoMigrationDriverConfig,ProtoMigrateUpInput/Output, etc.) as the canonical single source of truth for strict-contract descriptor message namesinternal/plugin.goMigrationsPluginnow satisfiessdk.SchemaProvider(ModuleSchemas())ModuleContracts() map[string]*dynamic.FieldContractandStepContracts()exposed for engine validation and audit toolingplugin.jsonstepSchemasarray — consumed byschema.LoadPluginStepSchemasFromDirand wfctl LSP/editor. Each entry declares config fields with types, labels, required flags, select options, and defaults, plus typed outputsdownloadsarray covering Linux/macOS/Windows for amd64 and arm64 using correct hyphen-separated filenames matching goreleaser'sname_template(e.g.workflow-plugin-migrations-linux-amd64.tar.gz)cliCommandssubcommand list andflags_passthroughmetadata for all migrate subcommandsversionto0.3.6to match the latest release tagplugin.contracts.json(new)Strict contract descriptors in the canonical wfctl v0.20.1 format:
{ "version": "1", "contracts": [ {"kind": "module", "type": "database.migrations", "mode": "strict", "config": "workflow.plugins.migrations.MigrationsModuleConfig"}, {"kind": "module", "type": "database.migration_driver", "mode": "strict", "config": "workflow.plugins.migrations.MigrationDriverConfig"}, {"kind": "step", "type": "step.migrate_up", "mode": "strict", "input": "workflow.plugins.migrations.MigrateUpInput", "output": "workflow.plugins.migrations.MigrateUpOutput"}, {"kind": "step", "type": "step.migrate_down", "mode": "strict", "input": "workflow.plugins.migrations.MigrateDownInput", "output": "workflow.plugins.migrations.MigrateDownOutput"}, {"kind": "step", "type": "step.migrate_status", "mode": "strict", "input": "workflow.plugins.migrations.MigrateStatusInput", "output": "workflow.plugins.migrations.MigrateStatusOutput"}, {"kind": "step", "type": "step.migrate_to", "mode": "strict", "input": "workflow.plugins.migrations.MigrateToInput", "output": "workflow.plugins.migrations.MigrateToOutput"} ] }plugin.atlas.json(new)Atlas-specific plugin manifest with correct
workflow-plugin-atlas-migratedownload URLs, nostepSchemas(the atlas binary exposes no step types), and module-only capabilities.plugin.atlas.contracts.json(new)Module-only strict contract descriptors for
workflow-plugin-atlas-migrate, coveringdatabase.migrationsanddatabase.migration_driverwithout step entries the binary cannot satisfy.internal/plugin_test.goTestPlugin_SchemaProvider,TestPlugin_ModuleContracts,TestPlugin_StepContracts,TestPlugin_StepSchemas,TestPlugin_ContractCoverage— contract and schema coverageTestPlugin_PluginJSONStepSchemasDrift— full structural comparison ofplugin.jsonstepSchemas againstPluginStepSchemas()(not just type names)TestPlugin_ContractsJSONDrift— assertsplugin.contracts.jsonmatches expected descriptors derived fromModuleContracts()/StepContracts()plus the exported proto name constants; a proto name change must flow throughcontracts.go→ JSON → the test flags any mismatchTestPlugin_AtlasContractsJSONDrift— same check forplugin.atlas.contracts.json(module-only)TestPlugin_DownloadsMatchGoReleaserMainArchiveMatrix— assertsplugin.jsondownloads cover every OS/arch in the goreleaser build matrixTestPlugin_GoReleaserManifestRewriteUpdatesDownloadURLs— executes the goreleaser sed hook against a temp copy and verifies URLs are rewritten with the snapshot version prefixTestPlugin_GoReleaserArchivesPackageCorrectManifestsAndContracts— asserts the goreleaser config packages the correct manifest and contracts file per archive (main usesplugin.json/plugin.contracts.json; atlas usesplugin.atlas.json/plugin.atlas.contracts.jsonand must not include the main files).github/workflows/ci.ymlstrict-contractsjob runs on every PR and push tomain:plugin.jsonwithwfctl plugin validate --strict-contractsworkflow-plugin-migrations,workflow-plugin-atlas-migrate)plugin.json,plugin.contracts.json, rewritten download URLs, then validates withwfctl plugin validate --strict-contracts.goreleaser.yamlplugin.json,plugin.contracts.json, andLICENSEplugin.atlas.json→plugin.jsonandplugin.atlas.contracts.json→plugin.contracts.jsonso each binary ships its own correct manifest and contractsbefore.hookssed rewrites bothplugin.jsonandplugin.atlas.jsonversion and download URLs on release (preserving thevtag prefix)Validation
go test ./...— all 19 tests pass ✅go vet ./...— clean ✅go mod tidy— no changes togo.modorgo.sum✅go build ./...— clean ✅plugin.jsonandplugin.atlas.jsonparse correctly with all expected fields ✅plugin.contracts.jsonandplugin.atlas.contracts.jsonparse as wfctl v0.20.1 strict-contract descriptor files ✅