diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..0ed3153 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,2 @@ +linters: + enable: errorlint diff --git a/cmd/agola/cmd/directrunstart.go b/cmd/agola/cmd/directrunstart.go index 43c1865..d2b70ff 100644 --- a/cmd/agola/cmd/directrunstart.go +++ b/cmd/agola/cmd/directrunstart.go @@ -97,7 +97,7 @@ func directRunStart(cmd *cobra.Command, args []string) error { for _, res := range directRunStartOpts.prRefRegexes { if _, err := regexp.Compile(res); err != nil { - return fmt.Errorf("wrong regular expression %q: %v", res, err) + return fmt.Errorf("wrong regular expression %q: %w", res, err) } } @@ -145,7 +145,7 @@ func directRunStart(cmd *cobra.Command, args []string) error { } if err := yaml.Unmarshal(data, &variables); err != nil { - return errors.Errorf("failed to unmarshal values: %v", err) + return errors.Errorf("failed to unmarshal values: %w", err) } // TODO(sgotti) validate variable name @@ -165,7 +165,7 @@ func directRunStart(cmd *cobra.Command, args []string) error { if repoUUID == "" { repoUUID = uuid.Must(uuid.NewV4()).String() if _, err := git.ConfigSet(context.Background(), "agola.repouuid", repoUUID); err != nil { - return fmt.Errorf("failed to set agola repo uid in git config: %v", err) + return fmt.Errorf("failed to set agola repo uid in git config: %w", err) } } diff --git a/cmd/toolbox/cmd/sleeper.go b/cmd/toolbox/cmd/sleeper.go index c4b4e06..2b90902 100644 --- a/cmd/toolbox/cmd/sleeper.go +++ b/cmd/toolbox/cmd/sleeper.go @@ -15,6 +15,7 @@ package cmd import ( + "errors" "os" "os/signal" "syscall" @@ -41,7 +42,7 @@ func childsReaper() { for range sigs { for { var wstatus syscall.WaitStatus - if _, err := syscall.Wait4(-1, &wstatus, syscall.WNOHANG|syscall.WUNTRACED|syscall.WCONTINUED, nil); err == syscall.EINTR { + if _, err := syscall.Wait4(-1, &wstatus, syscall.WNOHANG|syscall.WUNTRACED|syscall.WCONTINUED, nil); errors.Is(err, syscall.EINTR) { continue } break diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 6dca33e..d817396 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -207,7 +207,8 @@ func TestParseConfig(t *testing.T) { if tt.err == nil { t.Fatalf("got error: %v, expected no error", err) } - if errs, ok := err.(*util.Errors); ok { + var errs *util.Errors + if errors.As(err, &errs) { if !errs.Equal(tt.err) { t.Fatalf("got error: %v, want error: %v", err, tt.err) } diff --git a/internal/datamanager/changes.go b/internal/datamanager/changes.go index 6851129..d009b30 100644 --- a/internal/datamanager/changes.go +++ b/internal/datamanager/changes.go @@ -143,7 +143,7 @@ func (d *DataManager) applyWalChanges(ctx context.Context, walData *WalData, rev var action *Action err := dec.Decode(&action) - if err == io.EOF { + if errors.Is(err, io.EOF) { // all done break } @@ -261,7 +261,7 @@ func (d *DataManager) watcher(ctx context.Context) error { for wresp := range wch { if wresp.Canceled { err := wresp.Err() - if err == etcdclientv3rpc.ErrCompacted { + if errors.Is(err, etcdclientv3rpc.ErrCompacted) { d.log.Errorf("required events already compacted, reinitializing watcher changes") d.changes.Lock() d.changes.initialized = false diff --git a/internal/datamanager/data.go b/internal/datamanager/data.go index 7aa3ba0..37a341d 100644 --- a/internal/datamanager/data.go +++ b/internal/datamanager/data.go @@ -111,7 +111,7 @@ func (d *DataManager) walIndex(ctx context.Context, wals []*WalData) (walIndex, var action *Action err := dec.Decode(&action) - if err == io.EOF { + if errors.Is(err, io.EOF) { // all done break } @@ -349,7 +349,7 @@ func (d *DataManager) writeDataType(ctx context.Context, wi walIndex, dataType s var de *DataEntry err := dec.Decode(&de) - if err == io.EOF { + if errors.Is(err, io.EOF) { // all done break } @@ -743,7 +743,7 @@ func (d *DataManager) Import(ctx context.Context, r io.Reader) error { var de *DataEntry err := dec.Decode(&de) - if err == io.EOF { + if errors.Is(err, io.EOF) { dataFileID := d.dataFileID(dataSequence, uuid.Must(uuid.NewV4()).String()) if err := d.writeDataFile(ctx, &buf, int64(buf.Len()), dataFileIndex, dataFileID, curDataType); err != nil { return err diff --git a/internal/datamanager/datamanager_test.go b/internal/datamanager/datamanager_test.go index fe3baf1..163f633 100644 --- a/internal/datamanager/datamanager_test.go +++ b/internal/datamanager/datamanager_test.go @@ -371,7 +371,7 @@ func TestConcurrentUpdate(t *testing.T) { // this must fail since we are using the old cgt _, err = dm.WriteWal(ctx, actions, oldcgt) - if err != ErrConcurrency { + if !errors.Is(err, ErrConcurrency) { t.Fatalf("expected err: %v, got %v", ErrConcurrency, err) } @@ -384,7 +384,7 @@ func TestConcurrentUpdate(t *testing.T) { // this must fail since we are using the old cgt _, err = dm.WriteWal(ctx, actions, oldcgt) - if err != ErrConcurrency { + if !errors.Is(err, ErrConcurrency) { t.Fatalf("expected err: %v, got %v", ErrConcurrency, err) } } @@ -670,7 +670,7 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected var de *DataEntry err := dec.Decode(&de) - if err == io.EOF { + if errors.Is(err, io.EOF) { // all done break } diff --git a/internal/datamanager/wal.go b/internal/datamanager/wal.go index 9ab779e..d898a82 100644 --- a/internal/datamanager/wal.go +++ b/internal/datamanager/wal.go @@ -296,10 +296,10 @@ func (d *DataManager) FirstAvailableWalData(ctx context.Context) (*WalData, int6 func (d *DataManager) LastCommittedStorageWal(ctx context.Context) (string, int64, error) { resp, err := d.e.Get(ctx, etcdLastCommittedStorageWalSeqKey, 0) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return "", 0, err } - if err == etcd.ErrKeyNotFound { + if errors.Is(err, etcd.ErrKeyNotFound) { return "", 0, errors.Errorf("no last committedstorage wal on etcd") } lastCommittedStorageWal := string(resp.Kvs[0].Value) @@ -334,10 +334,9 @@ func (d *DataManager) Watch(ctx context.Context, revision int64) <-chan *WatchEl if wresp.Canceled { err := wresp.Err() - switch err { - case etcdclientv3rpc.ErrCompacted: + if errors.Is(err, etcdclientv3rpc.ErrCompacted) { we.Err = ErrCompacted - default: + } else { we.Err = err } @@ -1054,7 +1053,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro } dec := json.NewDecoder(walFile) var header *WalHeader - if err = dec.Decode(&header); err != nil && err != io.EOF { + if err = dec.Decode(&header); err != nil && !errors.Is(err, io.EOF) { walFile.Close() return err } @@ -1113,7 +1112,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro _, err = d.e.Get(ctx, etcdWalsDataKey, 0) if err != nil { - if err != etcd.ErrKeyNotFound { + if !errors.Is(err, etcd.ErrKeyNotFound) { return err } mustInit = true diff --git a/internal/etcd/etcd.go b/internal/etcd/etcd.go index 84fdba7..c7286af 100644 --- a/internal/etcd/etcd.go +++ b/internal/etcd/etcd.go @@ -62,8 +62,7 @@ type Config struct { } func FromEtcdError(err error) error { - switch err { - case rpctypes.ErrKeyNotFound: + if errors.Is(err, rpctypes.ErrKeyNotFound) { return ErrKeyNotFound } return err diff --git a/internal/git-handler/handler.go b/internal/git-handler/handler.go index e799b74..7a627e1 100644 --- a/internal/git-handler/handler.go +++ b/internal/git-handler/handler.go @@ -166,7 +166,7 @@ func (h *GitSmartHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { repoAbsPath, exists, err := h.repoAbsPathFunc(h.reposDir, repoPath) if err != nil { - if err == ErrWrongRepoPath { + if errors.Is(err, ErrWrongRepoPath) { http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -257,7 +257,7 @@ func (h *FetchFileHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { repoAbsPath, _, err := h.repoAbsPathFunc(h.reposDir, fetchData.RepoPath) if err != nil { - if err == ErrWrongRepoPath { + if errors.Is(err, ErrWrongRepoPath) { http.Error(w, err.Error(), http.StatusBadRequest) return } diff --git a/internal/log/log.go b/internal/log/log.go index 13692bb..974398c 100644 --- a/internal/log/log.go +++ b/internal/log/log.go @@ -36,7 +36,7 @@ func New(level zap.AtomicLevel) *zap.Logger { logger, err := config.Build() if err != nil { - panic(fmt.Errorf("failed to initialize logger: %v", err)) + panic(fmt.Errorf("failed to initialize logger: %w", err)) } return logger diff --git a/internal/objectstorage/objectstorage.go b/internal/objectstorage/objectstorage.go index 3a6c0de..e4aefcf 100644 --- a/internal/objectstorage/objectstorage.go +++ b/internal/objectstorage/objectstorage.go @@ -46,13 +46,13 @@ func (e *ErrNotExist) Error() string { return e.err.Error() } -func (*ErrNotExist) Is(err error) bool { - _, ok := err.(*ErrNotExist) - return ok +func (e *ErrNotExist) Unwrap() error { + return e.err } func IsNotExist(err error) bool { - return errors.Is(err, &ErrNotExist{}) + var e *ErrNotExist + return errors.As(err, &e) } type ReadSeekCloser interface { diff --git a/internal/objectstorage/posix.go b/internal/objectstorage/posix.go index 09846e1..348050a 100644 --- a/internal/objectstorage/posix.go +++ b/internal/objectstorage/posix.go @@ -133,7 +133,7 @@ func (s *PosixStorage) DeleteObject(p string) error { } _, err = f.Readdirnames(1) - if err == io.EOF { + if errors.Is(err, io.EOF) { f.Close() if err := os.Remove(pdir); err != nil { return nil @@ -221,7 +221,7 @@ func (s *PosixStorage) List(prefix, startWith, delimiter string, doneCh <-chan s return nil }) - if err != nil && err != io.EOF { + if err != nil && !errors.Is(err, io.EOF) { objectCh <- ObjectInfo{ Err: err, } diff --git a/internal/objectstorage/posixflat.go b/internal/objectstorage/posixflat.go index cfa1352..1a4de39 100644 --- a/internal/objectstorage/posixflat.go +++ b/internal/objectstorage/posixflat.go @@ -307,7 +307,7 @@ func (s *PosixFlatStorage) DeleteObject(p string) error { } _, err = f.Readdirnames(1) - if err == io.EOF { + if errors.Is(err, io.EOF) { f.Close() if err := os.Remove(pdir); err != nil { return nil @@ -418,7 +418,7 @@ func (s *PosixFlatStorage) List(prefix, startWith, delimiter string, doneCh <-ch return nil }) - if err != nil && err != io.EOF { + if err != nil && !errors.Is(err, io.EOF) { objectCh <- ObjectInfo{ Err: err, } diff --git a/internal/objectstorage/posixflat_test.go b/internal/objectstorage/posixflat_test.go index 2741243..a9cca81 100644 --- a/internal/objectstorage/posixflat_test.go +++ b/internal/objectstorage/posixflat_test.go @@ -20,6 +20,8 @@ import ( "os" "path/filepath" "testing" + + errors "golang.org/x/xerrors" ) func TestEscapeUnescape(t *testing.T) { @@ -64,7 +66,7 @@ func TestEscapeUnescape(t *testing.T) { if err != nil { if tt.err == nil { t.Errorf("%d: unescape: expected no error got %v", i, err) - } else if tt.err != err { + } else if !errors.Is(tt.err, err) { t.Errorf("%d: unescape: expected error %v got %v", i, tt.err, err) } } else { diff --git a/internal/runconfig/runconfig_test.go b/internal/runconfig/runconfig_test.go index ab13c34..baff22b 100644 --- a/internal/runconfig/runconfig_test.go +++ b/internal/runconfig/runconfig_test.go @@ -663,7 +663,8 @@ func TestCheckRunConfig(t *testing.T) { } if err := CheckRunConfigTasks(inRcts); err != nil { - if errs, ok := err.(*util.Errors); ok { + var errs *util.Errors + if errors.As(err, &errs) { if !errs.Equal(tt.err) { t.Fatalf("got error: %v, want error: %v", err, tt.err) } diff --git a/internal/sequence/sequence.go b/internal/sequence/sequence.go index 077de3f..10e2896 100644 --- a/internal/sequence/sequence.go +++ b/internal/sequence/sequence.go @@ -73,15 +73,15 @@ func (s *Sequence) EqualEpoch(s2 *Sequence) bool { func CurSequence(ctx context.Context, e *etcd.Store, key string) (*Sequence, bool, error) { resp, err := e.Get(ctx, key, 0) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return nil, false, err } - if err == etcd.ErrKeyNotFound { + if errors.Is(err, etcd.ErrKeyNotFound) { return nil, false, nil } seq := &Sequence{} - if err != etcd.ErrKeyNotFound { + if !errors.Is(err, etcd.ErrKeyNotFound) { kv := resp.Kvs[0] if err := json.Unmarshal(kv.Value, &seq); err != nil { return nil, false, err @@ -92,13 +92,13 @@ func CurSequence(ctx context.Context, e *etcd.Store, key string) (*Sequence, boo func IncSequence(ctx context.Context, e *etcd.Store, key string) (*Sequence, error) { resp, err := e.Get(ctx, key, 0) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return nil, err } var revision int64 seq := &Sequence{} - if err != etcd.ErrKeyNotFound { + if !errors.Is(err, etcd.ErrKeyNotFound) { kv := resp.Kvs[0] if err := json.Unmarshal(kv.Value, &seq); err != nil { return nil, err diff --git a/internal/services/configstore/action/maintenance.go b/internal/services/configstore/action/maintenance.go index 780243c..f71e107 100644 --- a/internal/services/configstore/action/maintenance.go +++ b/internal/services/configstore/action/maintenance.go @@ -27,7 +27,7 @@ import ( func (h *ActionHandler) MaintenanceMode(ctx context.Context, enable bool) error { resp, err := h.e.Get(ctx, common.EtcdMaintenanceKey, 0) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return err } diff --git a/internal/services/configstore/configstore.go b/internal/services/configstore/configstore.go index def9e7b..8002318 100644 --- a/internal/services/configstore/configstore.go +++ b/internal/services/configstore/configstore.go @@ -40,6 +40,7 @@ import ( "go.etcd.io/etcd/mvcc/mvccpb" "go.uber.org/zap" "go.uber.org/zap/zapcore" + errors "golang.org/x/xerrors" ) var level = zap.NewAtomicLevelAt(zapcore.InfoLevel) @@ -67,7 +68,7 @@ func (s *Configstore) maintenanceModeWatcherLoop(ctx context.Context, runCtxCanc func (s *Configstore) maintenanceModeWatcher(ctx context.Context, runCtxCancel context.CancelFunc, maintenanceModeEnabled bool) error { log.Infof("watcher: maintenance mode enabled: %t", maintenanceModeEnabled) resp, err := s.e.Get(ctx, common.EtcdMaintenanceKey, 0) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return err } @@ -351,7 +352,7 @@ func (s *Configstore) run(ctx context.Context) error { } resp, err := s.e.Get(ctx, common.EtcdMaintenanceKey, 0) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return err } diff --git a/internal/services/configstore/readdb/readdb.go b/internal/services/configstore/readdb/readdb.go index 78c6e57..4424b36 100644 --- a/internal/services/configstore/readdb/readdb.go +++ b/internal/services/configstore/readdb/readdb.go @@ -144,7 +144,7 @@ func (r *ReadDB) SyncFromDump(ctx context.Context) (string, error) { var de *datamanager.DataEntry err := dec.Decode(&de) - if err == io.EOF { + if errors.Is(err, io.EOF) { // all done break } @@ -488,7 +488,7 @@ func (r *ReadDB) handleEvents(ctx context.Context) error { err := r.rdb.Do(ctx, func(tx *db.Tx) error { err := tx.QueryRow("select revision from revision order by revision desc limit 1").Scan(&revision) if err != nil { - if err == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { revision = 0 } else { return err @@ -508,7 +508,7 @@ func (r *ReadDB) handleEvents(ctx context.Context) error { r.log.Debugf("we: %s", util.Dump(we)) if we.Err != nil { err := we.Err - if err == datamanager.ErrCompacted { + if errors.Is(err, datamanager.ErrCompacted) { r.log.Warnf("required events already compacted, reinitializing readdb") r.Initialized = false return nil @@ -612,7 +612,7 @@ func (r *ReadDB) applyWal(tx *db.Tx, walDataFileID string) error { var action *datamanager.Action err := dec.Decode(&action) - if err == io.EOF { + if errors.Is(err, io.EOF) { // all done break } @@ -755,7 +755,7 @@ func (r *ReadDB) getRevision(tx *db.Tx) (int64, error) { } err = tx.QueryRow(q, args...).Scan(&revision) - if err == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { return 0, nil } return revision, err @@ -787,7 +787,7 @@ func (r *ReadDB) GetCommittedWalSequence(tx *db.Tx) (string, error) { } err = tx.QueryRow(q, args...).Scan(&seq) - if err == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { return "", nil } return seq, err diff --git a/internal/services/executor/driver/k8s.go b/internal/services/executor/driver/k8s.go index 8b9abd0..4007a2f 100644 --- a/internal/services/executor/driver/k8s.go +++ b/internal/services/executor/driver/k8s.go @@ -106,7 +106,7 @@ func NewK8sDriver(logger *zap.Logger, executorID, toolboxPath, initImage string, } kubecli, err := kubernetes.NewForConfig(kubecfg) if err != nil { - return nil, fmt.Errorf("cannot create kubernetes client: %v", err) + return nil, fmt.Errorf("cannot create kubernetes client: %w", err) } namespace, _, err := kubeClientConfig.Namespace() @@ -133,7 +133,7 @@ func NewK8sDriver(logger *zap.Logger, executorID, toolboxPath, initImage string, sv, err := parseGitVersion(serverVersion.GitVersion) // if server version parsing fails just warn but ignore it if err != nil { - d.log.Warnf("failed to parse k8s server version: %v", err) + d.log.Warnf("failed to parse k8s server version: %w", err) } if sv != nil { // for k8s version < v1.14.x use old arch label @@ -800,10 +800,10 @@ func (e *K8sContainerExec) Wait(ctx context.Context) (int, error) { var exitCode int if err != nil { - switch err := err.(type) { - case utilexec.ExitError: - exitCode = err.ExitStatus() - default: + var verr utilexec.ExitError + if errors.As(err, &verr) { + exitCode = verr.ExitStatus() + } else { return -1, err } } diff --git a/internal/services/gateway/action/user.go b/internal/services/gateway/action/user.go index 7e6ff05..ac5cd6b 100644 --- a/internal/services/gateway/action/user.go +++ b/internal/services/gateway/action/user.go @@ -571,7 +571,7 @@ func (h *ActionHandler) HandleRemoteSourceAuth(ctx context.Context, remoteSource tokenName := "agola-" + h.agolaID accessToken, err := passwordSource.LoginPassword(loginName, loginPassword, tokenName) if err != nil { - if err == gitsource.ErrUnauthorized { + if errors.Is(err, gitsource.ErrUnauthorized) { return nil, util.NewErrUnauthorized(errors.Errorf("failed to login to remotesource %q: %w", remoteSourceName, err)) } return nil, errors.Errorf("failed to login to remote source %q with login name %q: %w", rs.Name, loginName, err) @@ -836,7 +836,7 @@ func (h *ActionHandler) UserCreateRun(ctx context.Context, req *UserCreateRunReq for _, res := range req.PullRequestRefRegexes { re, err := regexp.Compile(res) if err != nil { - return fmt.Errorf("wrong regular expression %q: %v", res, err) + return fmt.Errorf("wrong regular expression %q: %w", res, err) } prRefRegexes = append(prRefRegexes, re) } diff --git a/internal/services/runservice/action/action.go b/internal/services/runservice/action/action.go index d6a0f5a..be15fc3 100644 --- a/internal/services/runservice/action/action.go +++ b/internal/services/runservice/action/action.go @@ -591,7 +591,7 @@ func (h *ActionHandler) getRunCounter(ctx context.Context, group string) (uint64 func (h *ActionHandler) GetExecutorTask(ctx context.Context, etID string) (*types.ExecutorTask, error) { et, err := store.GetExecutorTask(ctx, h.e, etID) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return nil, err } if et == nil { @@ -619,7 +619,7 @@ func (h *ActionHandler) GetExecutorTask(ctx context.Context, etID string) (*type func (h *ActionHandler) GetExecutorTasks(ctx context.Context, executorID string) ([]*types.ExecutorTask, error) { ets, err := store.GetExecutorTasksForExecutor(ctx, h.e, executorID) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return nil, err } diff --git a/internal/services/runservice/action/maintenance.go b/internal/services/runservice/action/maintenance.go index 677ac32..0ef5bf2 100644 --- a/internal/services/runservice/action/maintenance.go +++ b/internal/services/runservice/action/maintenance.go @@ -27,7 +27,7 @@ import ( func (h *ActionHandler) MaintenanceMode(ctx context.Context, enable bool) error { resp, err := h.e.Get(ctx, common.EtcdMaintenanceKey, 0) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return err } diff --git a/internal/services/runservice/api/api.go b/internal/services/runservice/api/api.go index 08a2630..a5bbeff 100644 --- a/internal/services/runservice/api/api.go +++ b/internal/services/runservice/api/api.go @@ -241,14 +241,14 @@ func (h *LogsHandler) readTaskLogs(ctx context.Context, runID, taskID string, se et, err := store.GetExecutorTask(ctx, h.e, task.ID) if err != nil { - if err == etcd.ErrKeyNotFound { + if errors.Is(err, etcd.ErrKeyNotFound) { return util.NewErrNotExist(errors.Errorf("executor task with id %q doesn't exist", task.ID)), true } return err, true } executor, err := store.GetExecutor(ctx, h.e, et.Spec.ExecutorID) if err != nil { - if err == etcd.ErrKeyNotFound { + if errors.Is(err, etcd.ErrKeyNotFound) { return util.NewErrNotExist(errors.Errorf("executor with id %q doesn't exist", et.Spec.ExecutorID)), true } return err, true @@ -832,7 +832,7 @@ func (h *RunEventsHandler) sendRunEvents(ctx context.Context, startRunEventID st for wresp := range wch { if wresp.Canceled { err := wresp.Err() - if err == etcdclientv3rpc.ErrCompacted { + if errors.Is(err, etcdclientv3rpc.ErrCompacted) { h.log.Errorf("required events already compacted") } return errors.Errorf("watch error: %w", err) diff --git a/internal/services/runservice/readdb/readdb.go b/internal/services/runservice/readdb/readdb.go index 746c251..a60a2e6 100644 --- a/internal/services/runservice/readdb/readdb.go +++ b/internal/services/runservice/readdb/readdb.go @@ -400,7 +400,7 @@ func (r *ReadDB) handleEvents(ctx context.Context) error { for wresp := range wch { if wresp.Canceled { err = wresp.Err() - if err == etcdclientv3rpc.ErrCompacted { + if errors.Is(err, etcdclientv3rpc.ErrCompacted) { r.log.Errorf("required events already compacted, reinitializing readdb") r.SetInitialized(false) } @@ -682,7 +682,7 @@ func (r *ReadDB) SyncFromDump(ctx context.Context) (string, error) { var de *datamanager.DataEntry err := dec.Decode(&de) - if err == io.EOF { + if errors.Is(err, io.EOF) { // all done break } @@ -784,7 +784,7 @@ func (r *ReadDB) handleEventsOST(ctx context.Context) error { err := r.rdb.Do(ctx, func(tx *db.Tx) error { err := tx.QueryRow("select revision from revision order by revision desc limit 1").Scan(&revision) if err != nil { - if err == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { revision = 0 } else { return err @@ -804,7 +804,7 @@ func (r *ReadDB) handleEventsOST(ctx context.Context) error { r.log.Debugf("we: %s", util.Dump(we)) if we.Err != nil { err := we.Err - if err == datamanager.ErrCompacted { + if errors.Is(err, datamanager.ErrCompacted) { r.log.Warnf("required events already compacted, reinitializing readdb") r.Initialized = false return nil @@ -876,7 +876,7 @@ func (r *ReadDB) applyWal(tx *db.Tx, walDataFileID string) error { var action *datamanager.Action err := dec.Decode(&action) - if err == io.EOF { + if errors.Is(err, io.EOF) { // all done break } @@ -1104,7 +1104,7 @@ func (r *ReadDB) getRevision(tx *db.Tx) (int64, error) { } err = tx.QueryRow(q, args...).Scan(&revision) - if err == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { return 0, nil } return revision, err @@ -1485,7 +1485,7 @@ func (r *ReadDB) GetCommittedWalSequenceOST(tx *db.Tx) (string, error) { } err = tx.QueryRow(q, args...).Scan(&seq) - if err == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { return "", nil } return seq, err @@ -1593,7 +1593,7 @@ func (r *ReadDB) GetRunCounterOST(tx *db.Tx, group string) (uint64, error) { } err = tx.QueryRow(q, args...).Scan(&g, &counter) - if err == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { return 0, nil } return counter, err diff --git a/internal/services/runservice/runservice.go b/internal/services/runservice/runservice.go index 09e504d..5ca0fc5 100644 --- a/internal/services/runservice/runservice.go +++ b/internal/services/runservice/runservice.go @@ -40,6 +40,7 @@ import ( "go.etcd.io/etcd/mvcc/mvccpb" "go.uber.org/zap" "go.uber.org/zap/zapcore" + errors "golang.org/x/xerrors" ) var level = zap.NewAtomicLevelAt(zapcore.InfoLevel) @@ -94,7 +95,7 @@ func (s *Runservice) maintenanceModeWatcherLoop(ctx context.Context, runCtxCance func (s *Runservice) maintenanceModeWatcher(ctx context.Context, runCtxCancel context.CancelFunc, maintenanceModeEnabled bool) error { log.Infof("watcher: maintenance mode enabled: %t", maintenanceModeEnabled) resp, err := s.e.Get(ctx, common.EtcdMaintenanceKey, 0) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return err } @@ -330,7 +331,7 @@ func (s *Runservice) run(ctx context.Context) error { } resp, err := s.e.Get(ctx, common.EtcdMaintenanceKey, 0) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return err } diff --git a/internal/services/runservice/scheduler.go b/internal/services/runservice/scheduler.go index 9a5730e..d77a3cd 100644 --- a/internal/services/runservice/scheduler.go +++ b/internal/services/runservice/scheduler.go @@ -247,7 +247,7 @@ func (s *Runservice) submitRunTasks(ctx context.Context, r *types.Run, rc *types // just a check but it's not really needed since the call to // atomicPutExecutorTask will fail if it already exists tet, err := store.GetExecutorTask(ctx, s.e, et.ID) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return err } if tet != nil { @@ -335,7 +335,7 @@ func chooseExecutor(executors []*types.Executor, executorTasksCount map[string]i // will periodically fetch the executortask anyway func (s *Runservice) sendExecutorTask(ctx context.Context, et *types.ExecutorTask) error { executor, err := store.GetExecutor(ctx, s.e, et.Spec.ExecutorID) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return err } if executor == nil { @@ -768,7 +768,7 @@ func (s *Runservice) executorTaskCleaner(ctx context.Context, et *types.Executor if et.Status.Phase.IsFinished() { r, _, err := store.GetRun(ctx, s.e, et.Spec.RunID) if err != nil { - if err == etcd.ErrKeyNotFound { + if errors.Is(err, etcd.ErrKeyNotFound) { // run doesn't exists, remove executor task if err := store.DeleteExecutorTask(ctx, s.e, et.ID); err != nil { log.Errorf("err: %+v", err) @@ -798,7 +798,7 @@ func (s *Runservice) executorTaskCleaner(ctx context.Context, et *types.Executor if !et.Status.Phase.IsFinished() { // if the executor doesn't exists anymore mark the not finished executor tasks as failed executor, err := store.GetExecutor(ctx, s.e, et.Spec.ExecutorID) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return err } if executor == nil { @@ -886,7 +886,7 @@ func (s *Runservice) OSTFileExists(path string) (bool, error) { func (s *Runservice) fetchLog(ctx context.Context, rt *types.RunTask, setup bool, stepnum int) error { et, err := store.GetExecutorTask(ctx, s.e, rt.ID) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return err } if et == nil { @@ -896,7 +896,7 @@ func (s *Runservice) fetchLog(ctx context.Context, rt *types.RunTask, setup bool return nil } executor, err := store.GetExecutor(ctx, s.e, et.Spec.ExecutorID) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return err } if executor == nil { @@ -1049,7 +1049,7 @@ func (s *Runservice) fetchTaskLogs(ctx context.Context, runID string, rt *types. func (s *Runservice) fetchArchive(ctx context.Context, rt *types.RunTask, stepnum int) error { et, err := store.GetExecutorTask(ctx, s.e, rt.ID) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return err } if et == nil { @@ -1059,7 +1059,7 @@ func (s *Runservice) fetchArchive(ctx context.Context, rt *types.RunTask, stepnu return nil } executor, err := store.GetExecutor(ctx, s.e, et.Spec.ExecutorID) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return err } if executor == nil { diff --git a/internal/services/runservice/store/store.go b/internal/services/runservice/store/store.go index d0c472f..a292079 100644 --- a/internal/services/runservice/store/store.go +++ b/internal/services/runservice/store/store.go @@ -420,10 +420,10 @@ func AtomicPutRun(ctx context.Context, e *etcd.Store, r *types.Run, runEvent *ty // insert only if the run as changed curRun, _, err := GetRun(ctx, e, r.ID) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return nil, err } - if err != etcd.ErrKeyNotFound { + if !errors.Is(err, etcd.ErrKeyNotFound) { if curRun.Revision != r.Revision { // fast fail path if the run was already updated return nil, errors.Errorf("run modified") @@ -522,7 +522,7 @@ func GetRuns(ctx context.Context, e *etcd.Store) ([]*types.Run, error) { func GetRunEtcdOrOST(ctx context.Context, e *etcd.Store, dm *datamanager.DataManager, runID string) (*types.Run, error) { r, _, err := GetRun(ctx, e, runID) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return nil, err } if r == nil { diff --git a/internal/testutil/utils.go b/internal/testutil/utils.go index bfe40b3..8ff29c7 100644 --- a/internal/testutil/utils.go +++ b/internal/testutil/utils.go @@ -38,6 +38,7 @@ import ( "github.com/gofrs/uuid" "github.com/sgotti/gexpect" + errors "golang.org/x/xerrors" ) const ( @@ -193,7 +194,7 @@ func NewTestEmbeddedEtcd(t *testing.T, logger *zap.Logger, dir string, a ...stri } e, err := etcd.New(storeConfig) if err != nil { - return nil, fmt.Errorf("cannot create store: %v", err) + return nil, fmt.Errorf("cannot create store: %w", err) } tectd := &TestEmbeddedEtcd{ @@ -267,7 +268,7 @@ func NewTestExternalEtcd(t *testing.T, logger *zap.Logger, dir string, a ...stri } e, err := etcd.New(storeConfig) if err != nil { - return nil, fmt.Errorf("cannot create store: %v", err) + return nil, fmt.Errorf("cannot create store: %w", err) } bin := os.Getenv("ETCD_BIN") @@ -303,7 +304,7 @@ func (te *TestEtcd) Compact() error { ctx, cancel := context.WithTimeout(context.Background(), etcdTimeout) defer cancel() resp, err := te.Get(ctx, "anykey", 0) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return err } @@ -317,7 +318,7 @@ func (te *TestEtcd) WaitUp(timeout time.Duration) error { ctx, cancel := context.WithTimeout(context.Background(), etcdTimeout) defer cancel() _, err := te.Get(ctx, "anykey", 0) - if err != nil && err == etcd.ErrKeyNotFound { + if err != nil && errors.Is(err, etcd.ErrKeyNotFound) { return nil } if err == nil { @@ -335,7 +336,7 @@ func (te *TestEtcd) WaitDown(timeout time.Duration) error { ctx, cancel := context.WithTimeout(context.Background(), etcdTimeout) defer cancel() _, err := te.Get(ctx, "anykey", 0) - if err != nil && err != etcd.ErrKeyNotFound { + if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { return nil } time.Sleep(sleepInterval) @@ -567,7 +568,7 @@ func GetFreePort(tcp bool, udp bool) (string, string, error) { } localhostIP, err := net.ResolveIPAddr("ip", "localhost") if err != nil { - return "", "", fmt.Errorf("failed to resolve ip addr: %v", err) + return "", "", fmt.Errorf("failed to resolve ip addr: %w", err) } for { curPort++ diff --git a/internal/toolbox/archive/archive.go b/internal/toolbox/archive/archive.go index db86759..dfbc6a3 100644 --- a/internal/toolbox/archive/archive.go +++ b/internal/toolbox/archive/archive.go @@ -50,7 +50,7 @@ func CreateTar(archiveInfos []*ArchiveInfo, w io.Writer) error { sourceDirInfo, err := os.Stat(sourceDir) if err != nil { - return fmt.Errorf("%s: stat: %v", sourceDir, err) + return fmt.Errorf("%s: stat: %w", sourceDir, err) } if !sourceDirInfo.IsDir() { return fmt.Errorf("sourceDir %q is not a directory", sourceDir) @@ -62,7 +62,7 @@ func CreateTar(archiveInfos []*ArchiveInfo, w io.Writer) error { } if err != nil { - return fmt.Errorf("error accessing path %q: %v. Skipping.", path, err) + return fmt.Errorf("error accessing path %q: %w. Skipping.", path, err) } match := false for _, pattern := range ai.Paths { @@ -104,19 +104,19 @@ func CreateTar(archiveInfos []*ArchiveInfo, w io.Writer) error { var err error linkTarget, err = os.Readlink(path) if err != nil { - return fmt.Errorf("%s: readlink: %v", path, err) + return fmt.Errorf("%s: readlink: %w", path, err) } } hdr, err := tar.FileInfoHeader(fi, filepath.ToSlash(linkTarget)) if err != nil { - return fmt.Errorf("%s: making header: %v", path, err) + return fmt.Errorf("%s: making header: %w", path, err) } hdr.Name = destPath err = tw.WriteHeader(hdr) if err != nil { - return fmt.Errorf("%s: writing header: %v", hdr.Name, err) + return fmt.Errorf("%s: writing header: %w", hdr.Name, err) } if fi.IsDir() { @@ -130,14 +130,14 @@ func CreateTar(archiveInfos []*ArchiveInfo, w io.Writer) error { } defer f.Close() if _, err := io.Copy(tw, f); err != nil { - return fmt.Errorf("%s: copying contents: %v", f.Name(), err) + return fmt.Errorf("%s: copying contents: %w", f.Name(), err) } } return nil }) if err != nil { - return fmt.Errorf("error walking the path %q: %v\n", sourceDir, err) + return fmt.Errorf("error walking the path %q: %w", sourceDir, err) } } diff --git a/internal/toolbox/unarchive/unarchive.go b/internal/toolbox/unarchive/unarchive.go index c3ad26f..54f7ff5 100644 --- a/internal/toolbox/unarchive/unarchive.go +++ b/internal/toolbox/unarchive/unarchive.go @@ -16,6 +16,7 @@ package unarchive import ( "archive/tar" + "errors" "fmt" "io" "log" @@ -32,12 +33,12 @@ func Unarchive(source io.Reader, destDir string, overwrite, removeDestDir bool) var err error destDir, err = filepath.Abs(destDir) if err != nil { - return fmt.Errorf("failed to calculate destination dir absolute path: %v", err) + return fmt.Errorf("failed to calculate destination dir absolute path: %w", err) } // don't follow destdir if it's a symlink fi, err := os.Lstat(destDir) if err != nil && !os.IsNotExist(err) { - return fmt.Errorf("failed to lstat destination dir: %v", err) + return fmt.Errorf("failed to lstat destination dir: %w", err) } if fi != nil && !fi.IsDir() { return fmt.Errorf("destination path %q already exists and it's not a directory (mode: %q)", destDir, fi.Mode().String()) @@ -52,11 +53,11 @@ func Unarchive(source io.Reader, destDir string, overwrite, removeDestDir bool) for { err := untarNext(tr, destDir, overwrite) - if err == io.EOF { + if errors.Is(err, io.EOF) { break } if err != nil { - return fmt.Errorf("error reading file in tar archive: %v", err) + return fmt.Errorf("error reading file in tar archive: %w", err) } } @@ -132,7 +133,7 @@ func fileExists(name string) bool { func mkdir(dirPath string, mode os.FileMode) error { err := os.MkdirAll(dirPath, mode) if err != nil { - return fmt.Errorf("%s: making directory: %v", dirPath, err) + return fmt.Errorf("%s: making directory: %w", dirPath, err) } return nil } @@ -140,23 +141,23 @@ func mkdir(dirPath string, mode os.FileMode) error { func writeNewFile(fpath string, in io.Reader, mode os.FileMode) error { err := os.MkdirAll(filepath.Dir(fpath), defaultDirPerm) if err != nil { - return fmt.Errorf("%s: making directory for file: %v", fpath, err) + return fmt.Errorf("%s: making directory for file: %w", fpath, err) } out, err := os.Create(fpath) if err != nil { - return fmt.Errorf("%s: creating new file: %v", fpath, err) + return fmt.Errorf("%s: creating new file: %w", fpath, err) } defer out.Close() err = out.Chmod(mode) if err != nil && runtime.GOOS != "windows" { - return fmt.Errorf("%s: changing file mode: %v", fpath, err) + return fmt.Errorf("%s: changing file mode: %w", fpath, err) } _, err = io.Copy(out, in) if err != nil { - return fmt.Errorf("%s: writing file: %v", fpath, err) + return fmt.Errorf("%s: writing file: %w", fpath, err) } return nil } @@ -164,11 +165,11 @@ func writeNewFile(fpath string, in io.Reader, mode os.FileMode) error { func writeNewSymbolicLink(fpath string, target string) error { err := os.MkdirAll(filepath.Dir(fpath), defaultDirPerm) if err != nil { - return fmt.Errorf("%s: making directory for file: %v", fpath, err) + return fmt.Errorf("%s: making directory for file: %w", fpath, err) } err = os.Symlink(target, fpath) if err != nil { - return fmt.Errorf("%s: making symbolic link for: %v", fpath, err) + return fmt.Errorf("%s: making symbolic link for: %w", fpath, err) } return nil } @@ -176,11 +177,11 @@ func writeNewSymbolicLink(fpath string, target string) error { func writeNewHardLink(fpath string, target string) error { err := os.MkdirAll(filepath.Dir(fpath), defaultDirPerm) if err != nil { - return fmt.Errorf("%s: making directory for file: %v", fpath, err) + return fmt.Errorf("%s: making directory for file: %w", fpath, err) } err = os.Link(target, fpath) if err != nil { - return fmt.Errorf("%s: making hard link for: %v", fpath, err) + return fmt.Errorf("%s: making hard link for: %w", fpath, err) } return nil } diff --git a/internal/util/errors.go b/internal/util/errors.go index 27119ad..a69cf44 100644 --- a/internal/util/errors.go +++ b/internal/util/errors.go @@ -47,7 +47,8 @@ func (e *Errors) Equal(e2 error) bool { for _, err := range e.Errs { errs1 = append(errs1, err.Error()) } - if es2, ok := e2.(*Errors); ok { + var es2 *Errors + if errors.As(e2, &es2) { for _, err := range es2.Errs { errs2 = append(errs2, err.Error()) } @@ -72,13 +73,13 @@ func NewErrBadRequest(err error) *ErrBadRequest { return &ErrBadRequest{Err: err} } -func (*ErrBadRequest) Is(err error) bool { - _, ok := err.(*ErrBadRequest) - return ok +func (e *ErrBadRequest) Unwrap() error { + return e.Err } func IsBadRequest(err error) bool { - return errors.Is(err, &ErrBadRequest{}) + var e *ErrBadRequest + return errors.As(err, &e) } // ErrNotExist represent a not exist error @@ -95,13 +96,13 @@ func NewErrNotExist(err error) *ErrNotExist { return &ErrNotExist{Err: err} } -func (*ErrNotExist) Is(err error) bool { - _, ok := err.(*ErrNotExist) - return ok +func (e *ErrNotExist) Unwrap() error { + return e.Err } func IsNotExist(err error) bool { - return errors.Is(err, &ErrNotExist{}) + var e *ErrNotExist + return errors.As(err, &e) } // ErrForbidden represent an error caused by an forbidden operation @@ -118,13 +119,13 @@ func NewErrForbidden(err error) *ErrForbidden { return &ErrForbidden{Err: err} } -func (*ErrForbidden) Is(err error) bool { - _, ok := err.(*ErrForbidden) - return ok +func (e *ErrForbidden) Unwrap() error { + return e.Err } func IsForbidden(err error) bool { - return errors.Is(err, &ErrForbidden{}) + var e *ErrForbidden + return errors.As(err, &e) } // ErrUnauthorized represent an error caused by an unauthorized request @@ -141,13 +142,13 @@ func NewErrUnauthorized(err error) *ErrUnauthorized { return &ErrUnauthorized{Err: err} } -func (*ErrUnauthorized) Is(err error) bool { - _, ok := err.(*ErrUnauthorized) - return ok +func (e *ErrUnauthorized) Unwrap() error { + return e.Err } func IsUnauthorized(err error) bool { - return errors.Is(err, &ErrUnauthorized{}) + var e *ErrUnauthorized + return errors.As(err, &e) } type ErrInternal struct { @@ -163,11 +164,11 @@ func NewErrInternal(err error) *ErrInternal { return &ErrInternal{Err: err} } -func (*ErrInternal) Is(err error) bool { - _, ok := err.(*ErrInternal) - return ok +func (e *ErrInternal) Unwrap() error { + return e.Err } func IsInternal(err error) bool { - return errors.Is(err, &ErrInternal{}) + var e *ErrInternal + return errors.As(err, &e) } diff --git a/internal/util/git.go b/internal/util/git.go index be9bf89..fee4f5f 100644 --- a/internal/util/git.go +++ b/internal/util/git.go @@ -154,7 +154,8 @@ func (g *Git) ConfigGet(ctx context.Context, args ...string) (string, error) { out, err := g.Output(ctx, nil, args...) if err != nil { - if exitError, ok := err.(*exec.ExitError); ok { + var exitError *exec.ExitError + if errors.As(err, &exitError) { if waitStatus, ok := exitError.Sys().(syscall.WaitStatus); ok { if waitStatus.ExitStatus() == 1 { return "", &ErrGitKeyNotFound{Key: args[len(args)-1]} @@ -172,7 +173,8 @@ func (g *Git) ConfigSet(ctx context.Context, args ...string) (string, error) { out, err := g.Output(ctx, nil, args...) if err != nil { - if exitError, ok := err.(*exec.ExitError); ok { + var exitError *exec.ExitError + if errors.As(err, &exitError) { if waitStatus, ok := exitError.Sys().(syscall.WaitStatus); ok { if waitStatus.ExitStatus() == 1 { return "", &ErrGitKeyNotFound{Key: args[len(args)-1]} diff --git a/internal/util/password.go b/internal/util/password.go index 1fcefc1..34f7f0b 100644 --- a/internal/util/password.go +++ b/internal/util/password.go @@ -16,6 +16,8 @@ package util import ( "golang.org/x/crypto/bcrypt" + + errors "golang.org/x/xerrors" ) func PasswordHash(password string) (string, error) { @@ -25,7 +27,7 @@ func PasswordHash(password string) (string, error) { func CompareHashAndPassword(passwordHash, password string) (bool, error) { if err := bcrypt.CompareHashAndPassword([]byte(passwordHash), []byte(password)); err != nil { - if err == bcrypt.ErrMismatchedHashAndPassword { + if errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) { return false, nil } return false, err diff --git a/tests/setup_test.go b/tests/setup_test.go index d0e1de4..2d8232b 100644 --- a/tests/setup_test.go +++ b/tests/setup_test.go @@ -359,7 +359,7 @@ func setup(ctx context.Context, t *testing.T, dir string) (*testutil.TestEmbedde go func() { err := <-errCh if err != nil { - panic(fmt.Errorf("agola component returned error: %+v", err)) + panic(fmt.Errorf("agola component returned error: %w", err)) } }()