Skip to content

feat: add guarded workflow-migrate force command#6

Merged
intel352 merged 1 commit into
mainfrom
feat/workflow-migrate-force
Apr 26, 2026
Merged

feat: add guarded workflow-migrate force command#6
intel352 merged 1 commit into
mainfrom
feat/workflow-migrate-force

Conversation

@intel352
Copy link
Copy Markdown
Contributor

Summary

  • add guarded workflow-migrate force for golang-migrate metadata repair
  • require typed confirmation and refuse clean databases unless --allow-clean is provided
  • support -1 nil-version repair, validate positive targets exist, and report zero applied migrations

Verification

  • GOWORK=off go test ./internal/golangmigrate ./pkg/cli -count=1
  • GOWORK=off go test ./... -count=1
  • go run ./cmd/workflow-migrate force -1 --source-dir /tmp --dsn postgres://user:pass@example.invalid/db --confirm-force FORCE_MIGRATION_METADATA reached the expected DB DNS failure, with no Cobra shorthand-flag or invalid-version parsing error
  • git diff --check

Review

  • initial adversarial review blocked unsafe force semantics
  • revised implementation was re-reviewed as SHIP-IT

Copilot AI review requested due to automatic review settings April 26, 2026 20:42
@intel352 intel352 merged commit 9991325 into main Apr 26, 2026
10 checks passed
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

Adds a new guarded force subcommand to workflow-migrate/shared migrate CLI to repair golang-migrate metadata without applying SQL, with safety checks and supporting tests/docs.

Changes:

  • Add workflow-migrate force <version> command with typed confirmation and optional --allow-clean.
  • Implement Driver.Force() in the golang-migrate driver, including target validation, source-version existence checks, and clean/dirty safety gating.
  • Add CLI + driver tests and update plugin manifest, binary usage docs, and changelog.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
plugin.json Registers the new force command in the plugin manifest.
pkg/cli/root.go Adds the force Cobra subcommand and custom arg splitting to support -1 as a positional version.
pkg/cli/root_test.go Adds tests ensuring the command is present and guarded by typed confirmation; verifies -1 parsing.
internal/golangmigrate/driver.go Implements metadata-only Force() with validation and safety checks.
internal/golangmigrate/driver_test.go Adds coverage for force behavior (clean refusal, dirty-only default, missing target, -1 nil version).
cmd/workflow-migrate/main.go Updates usage comment to include force.
CHANGELOG.md Documents the new force command under Unreleased.

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

Comment thread pkg/cli/root.go
Comment on lines +208 to +218
Use: "force <version>",
Short: "Force-set the recorded migration version",
DisableFlagParsing: true,
RunE: func(cmd *cobra.Command, args []string) error {
target, flagArgs, err := splitForceArgs(args)
if err != nil {
return err
}
if err := cmd.Flags().Parse(flagArgs); err != nil {
return err
}
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

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

With DisableFlagParsing enabled and custom parsing in splitForceArgs, force --help / force -h will not show help. For example, --help is treated as a flag arg and (when no version is provided) results in "force requires exactly one version" instead of displaying usage. Consider handling help explicitly before enforcing the version/confirmation (e.g., detect -h/--help in args and call cmd.Help()), or restructure parsing so Cobra's built-in help handling still works.

Copilot uses AI. Check for mistakes.
Comment thread pkg/cli/root.go
Comment on lines +264 to +271
if arg == "-1" || !strings.HasPrefix(arg, "-") {
if target != "" {
return "", nil, fmt.Errorf("force requires exactly one version")
}
target = arg
continue
}
flagArgs = append(flagArgs, arg)
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

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

splitForceArgs only treats -1 as a positional version; any other negative number (e.g. force -2) is treated as a flag and will produce a misleading parse error (or "force requires exactly one version") rather than the intended "invalid target version" message. If the intent is to reject all negatives except -1, it would be clearer to accept any ^-?\d+$ as the target positionally and let parseForceTarget validate it, or explicitly detect ^-\d+$ here and return an "invalid target version" error.

Copilot uses AI. Check for mistakes.
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