github.com/sudo-bmitch/version-bump@v0.0.0-20240503123857-70b0e3f646dd/internal/action/action.go (about) 1 // Package action processes the result of a scanner match, the source, and the 2 // configuration to take an action (log, modify the version). 3 package action 4 5 import ( 6 "fmt" 7 8 "github.com/sudo-bmitch/version-bump/internal/config" 9 "github.com/sudo-bmitch/version-bump/internal/lockfile" 10 "github.com/sudo-bmitch/version-bump/internal/source" 11 ) 12 13 // Opts specifies runtime configuration inputs and outputs 14 type Opts struct { 15 Action runAction // which action to run 16 DryRun bool // when set, lock file and scanned files are unchanged 17 Locks *lockfile.Locks // lock entries to use or set 18 Changes []*Change // results of the run 19 } 20 21 type runAction int 22 23 const ( 24 ActionScan runAction = iota // scan: search files for versions and saves to lock 25 ActionCheck // check: scans for versions and compares to source 26 ActionSet // set: updates a version without checking the source 27 ActionUpdate // update: modifies versions using sources 28 ActionReset // reset: sets versions to the lock value without checking source 29 ) 30 31 // Change lists changes found or made to scanned files 32 type Change struct { 33 Filename string // filename modified 34 Source string // name of the source 35 Scan string // name of the scan 36 Key string // key of the scan 37 Orig string // previous version 38 New string // new version 39 } 40 41 type Action struct { 42 opts *Opts 43 conf config.Config 44 } 45 46 func New(opts *Opts, conf config.Config) *Action { 47 return &Action{ 48 opts: opts, 49 conf: conf, 50 } 51 } 52 53 // Done should be called after all HandleMatch calls are finished. 54 // It will perform any final steps. 55 func (a *Action) Done() error { 56 // TODO: is this needed? 57 return nil 58 } 59 60 // HandleMatch processes a scan result, checking the sources and config, and returning the resulting action 61 // Output: 62 // - change bool: should the scan modify the version 63 // - version string: version the scan should use 64 // - err error: not nil on any failure 65 func (a *Action) HandleMatch(filename string, scan string, sourceName string, version string, data config.SourceTmplData) (bool, string, error) { 66 if _, ok := a.conf.Sources[sourceName]; !ok { 67 return false, "", fmt.Errorf("source not found: %s", sourceName) 68 } 69 s, err := source.Get(*a.conf.Sources[sourceName]) 70 if err != nil { 71 return false, "", fmt.Errorf("could not get source %s: %w", sourceName, err) 72 } 73 data.SourceArgs = a.conf.Sources[sourceName].Args 74 key, err := s.Key(data) 75 if err != nil { 76 return false, "", fmt.Errorf("could not get key for source %s: %w", sourceName, err) 77 } 78 // determine curVer 79 var curVer string 80 switch a.opts.Action { 81 case ActionCheck, ActionUpdate: 82 // query from source 83 curVer, err = s.Get(data) 84 if err != nil { 85 return false, "", fmt.Errorf("could not get current version from source %s: %w", sourceName, err) 86 } 87 case ActionSet, ActionReset: 88 // TODO: get curVer from lock, requires getting the key from the source 89 90 case ActionScan: 91 // scan doesn't change the version, set from file contents 92 curVer = version 93 } 94 95 // store any changes when version != curVer 96 if version != curVer { 97 a.opts.Changes = append(a.opts.Changes, &Change{ 98 Filename: filename, 99 Source: sourceName, 100 Scan: scan, 101 Key: key, 102 Orig: version, 103 New: curVer, 104 }) 105 } 106 107 // for dry-run, never return a change 108 if a.opts.DryRun || a.opts.Action == ActionCheck { 109 return false, version, nil 110 } 111 112 // update lock file 113 switch a.opts.Action { 114 case ActionScan, ActionUpdate: 115 err = a.opts.Locks.Set(sourceName, key, curVer) 116 if err != nil { 117 return false, "", fmt.Errorf("could not set lock for %s/%s: %w", sourceName, key, err) 118 } 119 } 120 return version != curVer, curVer, nil 121 }