fix(sdlc): make phase transitions idempotent
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Allow transitioning to the current phase (no-op success) instead of rejecting it as a "backward" transition. This fixes issues where external systems retry transition commands. Before: draft -> draft returned error After: draft -> draft returns nil (already there) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
00f55f7f6f
commit
a419c53592
@ -140,7 +140,13 @@ func (f *Feature) CanTransitionTo(target FeaturePhase, cfg *Config) error {
|
||||
currentIdx := PhaseIndex(f.Phase)
|
||||
targetIdx := PhaseIndex(target)
|
||||
|
||||
if targetIdx <= currentIdx {
|
||||
// Idempotent: if already in target phase, return success
|
||||
if targetIdx == currentIdx {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reject backward transitions
|
||||
if targetIdx < currentIdx {
|
||||
return fmt.Errorf("%w: cannot move from %s to %s (backward)", ErrInvalidTransition, f.Phase, target)
|
||||
}
|
||||
|
||||
|
||||
@ -128,9 +128,9 @@ func TestCanTransitionTo(t *testing.T) {
|
||||
t.Error("CanTransitionTo(planned) = nil, want error (skip)")
|
||||
}
|
||||
|
||||
// Invalid: draft -> draft (backward)
|
||||
if err := f.CanTransitionTo(PhaseDraft, cfg); err == nil {
|
||||
t.Error("CanTransitionTo(draft) = nil, want error (backward)")
|
||||
// Idempotent: draft -> draft (allowed, returns nil)
|
||||
if err := f.CanTransitionTo(PhaseDraft, cfg); err != nil {
|
||||
t.Errorf("CanTransitionTo(draft) = %v, want nil (idempotent)", err)
|
||||
}
|
||||
|
||||
// Invalid phase
|
||||
|
||||
Loading…
Reference in New Issue
Block a user