*: use new errors handling library

Implement a new error handling library based on pkg/errors. It provides
stack saving on wrapping and exports some function to add stack saving
also to external errors.
It also implements custom zerolog error formatting without adding too
much verbosity by just printing the chain error file:line without a full
stack trace of every error.

* Add a --detailed-errors options to print error with they full chain
* Wrap all error returns. Use errors.WithStack to wrap without adding a
  new messsage and error.Wrap[f] to add a message.
* Add golangci-lint wrapcheck to check that external packages errors are
  wrapped. This won't check that internal packages error are wrapped.
  But we want also to ensure this case so we'll have to find something
  else to check also these.
This commit is contained in:
Simone Gotti 2022-02-22 15:01:29 +01:00
parent 5df9ee19c4
commit d2b09d854f
183 changed files with 2912 additions and 2348 deletions

View File

@ -1,2 +1,25 @@
linters:
enable: errorlint
enable:
- errorlint
- wrapcheck
linters-settings:
wrapcheck:
# An array of strings that specify substrings of signatures to ignore.
# If this set, it will override the default set of ignored signatures.
# See https://github.com/tomarrell/wrapcheck#configuration for more information.
ignoreSigs:
- .Errorf(
- errors.New(
- errors.Unwrap(
- .Wrap(
- .Wrapf(
- .WithMessage(
- .WithMessagef(
- .WithStack(
- .NewDetailedError(
ignoreSigRegexps:
- \.New.*Error\(
ignorePackageGlobs:
- encoding/*
- github.com/pkg/*

View File

@ -20,19 +20,20 @@ import (
"time"
"agola.io/agola/cmd"
"agola.io/agola/internal/errors"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var token string
func init() {
cw := zerolog.ConsoleWriter{
Out: os.Stderr,
TimeFormat: time.RFC3339Nano,
Out: os.Stderr,
TimeFormat: time.RFC3339Nano,
FormatErrFieldValue: errors.FormatErrFieldValue,
}
zerolog.TimeFieldFormat = time.RFC3339Nano
@ -53,6 +54,9 @@ var cmdAgola = &cobra.Command{
if agolaOpts.debug {
log.Logger = log.Level(zerolog.DebugLevel)
}
if agolaOpts.detailedErrors {
zerolog.ErrorMarshalFunc = errors.ErrorMarshalFunc
}
},
Run: func(c *cobra.Command, args []string) {
if err := c.Help(); err != nil {
@ -62,8 +66,9 @@ var cmdAgola = &cobra.Command{
}
type agolaOptions struct {
gatewayURL string
debug bool
gatewayURL string
debug bool
detailedErrors bool
}
var agolaOpts agolaOptions
@ -84,6 +89,7 @@ func init() {
flags.StringVarP(&agolaOpts.gatewayURL, "gateway-url", "u", gatewayURL, "agola gateway exposed url")
flags.StringVar(&token, "token", token, "api token")
flags.BoolVarP(&agolaOpts.debug, "debug", "d", false, "debug")
flags.BoolVar(&agolaOpts.detailedErrors, "detailed-errors", false, "enabled detailed errors logging")
}
func Execute() {

View File

@ -17,6 +17,7 @@ package cmd
import (
"os"
"agola.io/agola/internal/errors"
"github.com/spf13/cobra"
)
@ -33,11 +34,11 @@ func completionShell(cmd *cobra.Command, args []string, shell string) error {
switch shell {
case "bash":
if err := cmdAgola.GenBashCompletion(os.Stdout); err != nil {
return err
return errors.WithStack(err)
}
case "zsh":
if err := cmdAgola.GenZshCompletion(os.Stdout); err != nil {
return err
return errors.WithStack(err)
}
}
return nil

View File

@ -23,6 +23,7 @@ import (
"strings"
"unicode"
"agola.io/agola/internal/errors"
gitsave "agola.io/agola/internal/git-save"
"agola.io/agola/internal/util"
gwapitypes "agola.io/agola/services/gateway/api/types"
@ -32,7 +33,6 @@ import (
"github.com/gofrs/uuid"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdDirectRunStart = &cobra.Command{
@ -80,15 +80,15 @@ func parseVariable(variable string) (string, string, error) {
variable = strings.TrimLeftFunc(variable, unicode.IsSpace)
arr := strings.SplitN(variable, "=", 2)
if len(arr) != 2 {
return "", "", fmt.Errorf("invalid variable definition: %s", variable)
return "", "", errors.Errorf("invalid variable definition: %s", variable)
}
varname := arr[0]
varvalue := arr[1]
if varname == "" {
return "", "", fmt.Errorf("invalid variable definition: %s", variable)
return "", "", errors.Errorf("invalid variable definition: %s", variable)
}
if varvalue == "" {
return "", "", fmt.Errorf("invalid variable definition: %s", variable)
return "", "", errors.Errorf("invalid variable definition: %s", variable)
}
return varname, varvalue, nil
}
@ -98,7 +98,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: %w", res, err)
return errors.Wrapf(err, "wrong regular expression %q", res)
}
}
@ -123,12 +123,12 @@ func directRunStart(cmd *cobra.Command, args []string) error {
branch = ""
}
if set > 1 {
return fmt.Errorf(`only one of "--branch", "--tag" or "--ref" can be provided`)
return errors.Errorf(`only one of "--branch", "--tag" or "--ref" can be provided`)
}
user, _, err := gwclient.GetCurrentUser(context.TODO())
if err != nil {
return err
return errors.WithStack(err)
}
variables := map[string]string{}
@ -142,11 +142,11 @@ func directRunStart(cmd *cobra.Command, args []string) error {
var err error
data, err = ioutil.ReadFile(varFile)
if err != nil {
return err
return errors.WithStack(err)
}
if err := yaml.Unmarshal(data, &variables); err != nil {
return errors.Errorf("failed to unmarshal values: %w", err)
return errors.Wrapf(err, "failed to unmarshal values")
}
// TODO(sgotti) validate variable name
@ -155,7 +155,7 @@ func directRunStart(cmd *cobra.Command, args []string) error {
for _, variable := range directRunStartOpts.vars {
varname, varvalue, err := parseVariable(variable)
if err != nil {
return err
return errors.WithStack(err)
}
variables[varname] = varvalue
}
@ -166,7 +166,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: %w", err)
return errors.Wrapf(err, "failed to set agola repo uid in git config")
}
}
@ -180,7 +180,7 @@ func directRunStart(cmd *cobra.Command, args []string) error {
commitSHA, err := gs.Save(message, localBranch)
if err != nil {
return err
return errors.WithStack(err)
}
log.Info().Msgf("pushing branch")
@ -190,15 +190,15 @@ func directRunStart(cmd *cobra.Command, args []string) error {
// push to a branch with default branch refs "refs/heads/branch"
if branch != "" {
if err := gitsave.GitPush("", repoURL, fmt.Sprintf("%s:refs/heads/%s", path.Join(gs.RefsPrefix(), localBranch), branch)); err != nil {
return err
return errors.WithStack(err)
}
} else if tag != "" {
if err := gitsave.GitPush("", repoURL, fmt.Sprintf("%s:refs/tags/%s", path.Join(gs.RefsPrefix(), localBranch), tag)); err != nil {
return err
return errors.WithStack(err)
}
} else if ref != "" {
if err := gitsave.GitPush("", repoURL, fmt.Sprintf("%s:%s", path.Join(gs.RefsPrefix(), localBranch), ref)); err != nil {
return err
return errors.WithStack(err)
}
}
@ -215,7 +215,7 @@ func directRunStart(cmd *cobra.Command, args []string) error {
Variables: variables,
}
if _, err := gwclient.UserCreateRun(context.TODO(), req); err != nil {
return err
return errors.WithStack(err)
}
return nil

View File

@ -17,12 +17,12 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdLogDelete = &cobra.Command{
@ -93,7 +93,7 @@ func logDelete(cmd *cobra.Command, args []string) error {
run, _, err := gwclient.GetRun(context.TODO(), logDeleteOpts.runid)
if err != nil {
return err
return errors.WithStack(err)
}
for _, t := range run.Tasks {
if t.Name == logDeleteOpts.taskname {

View File

@ -19,12 +19,12 @@ import (
"io"
"os"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdLogGet = &cobra.Command{
@ -102,7 +102,7 @@ func logGet(cmd *cobra.Command, args []string) error {
run, _, err := gwclient.GetRun(context.TODO(), logGetOpts.runid)
if err != nil {
return err
return errors.WithStack(err)
}
for _, t := range run.Tasks {
if t.Name == logGetOpts.taskname {
@ -127,7 +127,7 @@ func logGet(cmd *cobra.Command, args []string) error {
if flags.Changed("output") {
f, err := os.Create(logGetOpts.output)
if err != nil {
return err
return errors.WithStack(err)
}
defer f.Close()
if _, err := io.Copy(f, resp.Body); err != nil {

View File

@ -17,12 +17,12 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdOrgCreate = &cobra.Command{
@ -71,7 +71,7 @@ func orgCreate(cmd *cobra.Command, args []string) error {
log.Info().Msgf("creating org")
org, _, err := gwclient.CreateOrg(context.TODO(), req)
if err != nil {
return errors.Errorf("failed to create org: %w", err)
return errors.Wrapf(err, "failed to create org")
}
log.Info().Msgf("org %q created, ID: %q", org.Name, org.ID)

View File

@ -17,11 +17,11 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdOrgDelete = &cobra.Command{
@ -57,7 +57,7 @@ func orgDelete(cmd *cobra.Command, args []string) error {
log.Info().Msgf("deleting organization %q", orgDeleteOpts.name)
if _, err := gwclient.DeleteOrg(context.TODO(), orgDeleteOpts.name); err != nil {
return errors.Errorf("failed to delete organization: %w", err)
return errors.Wrapf(err, "failed to delete organization")
}
return nil

View File

@ -17,12 +17,12 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdOrgMemberAdd = &cobra.Command{
@ -66,7 +66,7 @@ func orgMemberAdd(cmd *cobra.Command, args []string) error {
log.Info().Msgf("adding/updating member %q to organization %q with role %q", orgMemberAddOpts.username, orgMemberAddOpts.orgname, orgMemberAddOpts.role)
_, _, err := gwclient.AddOrgMember(context.TODO(), orgMemberAddOpts.orgname, orgMemberAddOpts.username, gwapitypes.MemberRole(orgMemberAddOpts.role))
if err != nil {
return errors.Errorf("failed to add/update organization member: %w", err)
return errors.Wrapf(err, "failed to add/update organization member")
}
return nil

View File

@ -19,11 +19,11 @@ import (
"encoding/json"
"os"
"agola.io/agola/internal/errors"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdOrgMemberList = &cobra.Command{
@ -59,12 +59,12 @@ func orgMemberList(cmd *cobra.Command, args []string) error {
orgMembers, _, err := gwclient.GetOrgMembers(context.TODO(), orgMemberListOpts.orgname)
if err != nil {
return errors.Errorf("failed to get organization member: %w", err)
return errors.Wrapf(err, "failed to get organization member")
}
out, err := json.MarshalIndent(orgMembers, "", "\t")
if err != nil {
return err
return errors.WithStack(err)
}
os.Stdout.Write(out)

View File

@ -17,11 +17,11 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdOrgMemberRemove = &cobra.Command{
@ -63,7 +63,7 @@ func orgMemberRemove(cmd *cobra.Command, args []string) error {
log.Info().Msgf("removing member %q from organization %q", orgMemberRemoveOpts.username, orgMemberRemoveOpts.orgname)
_, err := gwclient.RemoveOrgMember(context.TODO(), orgMemberRemoveOpts.orgname, orgMemberRemoveOpts.username)
if err != nil {
return errors.Errorf("failed to remove organization member: %w", err)
return errors.Wrapf(err, "failed to remove organization member")
}
return nil

View File

@ -17,12 +17,12 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdProjectCreate = &cobra.Command{
@ -106,7 +106,7 @@ func projectCreate(cmd *cobra.Command, args []string) error {
project, _, err := gwclient.CreateProject(context.TODO(), req)
if err != nil {
return errors.Errorf("failed to create project: %w", err)
return errors.Wrapf(err, "failed to create project")
}
log.Info().Msgf("project %s created, ID: %s", project.Name, project.ID)

View File

@ -17,11 +17,11 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdProjectDelete = &cobra.Command{
@ -58,7 +58,7 @@ func projectDelete(cmd *cobra.Command, args []string) error {
log.Info().Msgf("deleting project")
if _, err := gwclient.DeleteProject(context.TODO(), projectDeleteOpts.ref); err != nil {
return errors.Errorf("failed to delete project: %w", err)
return errors.Wrapf(err, "failed to delete project")
}
return nil

View File

@ -17,12 +17,12 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdProjectGroupCreate = &cobra.Command{
@ -78,7 +78,7 @@ func projectGroupCreate(cmd *cobra.Command, args []string) error {
projectGroup, _, err := gwclient.CreateProjectGroup(context.TODO(), req)
if err != nil {
return errors.Errorf("failed to create project group: %w", err)
return errors.Wrapf(err, "failed to create project group")
}
log.Info().Msgf("project group %s created, ID: %s", projectGroup.Name, projectGroup.ID)

View File

@ -17,11 +17,11 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdProjectGroupDelete = &cobra.Command{
@ -58,7 +58,7 @@ func projectGroupDelete(cmd *cobra.Command, args []string) error {
log.Info().Msgf("deleting project group")
if _, err := gwclient.DeleteProjectGroup(context.TODO(), projectGroupDeleteOpts.ref); err != nil {
return errors.Errorf("failed to delete project group: %w", err)
return errors.Wrapf(err, "failed to delete project group")
}
return nil

View File

@ -17,12 +17,12 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdProjectGroupUpdate = &cobra.Command{
@ -82,7 +82,7 @@ func projectGroupUpdate(cmd *cobra.Command, args []string) error {
log.Info().Msgf("updating project group")
projectGroup, _, err := gwclient.UpdateProjectGroup(context.TODO(), projectGroupUpdateOpts.ref, req)
if err != nil {
return errors.Errorf("failed to update project group: %w", err)
return errors.Wrapf(err, "failed to update project group")
}
log.Info().Msgf("project group %s update, ID: %s", projectGroup.Name, projectGroup.ID)

View File

@ -18,6 +18,7 @@ import (
"context"
"fmt"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
@ -64,7 +65,7 @@ func projectList(cmd *cobra.Command, args []string) error {
projects, _, err := gwclient.GetProjectGroupProjects(context.TODO(), projectListOpts.parentPath)
if err != nil {
return err
return errors.WithStack(err)
}
printProjects(projects)

View File

@ -17,11 +17,11 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdProjectReconfig = &cobra.Command{
@ -57,7 +57,7 @@ func projectReconfig(cmd *cobra.Command, args []string) error {
log.Info().Msgf("reconfiguring remote project")
if _, err := gwclient.ReconfigProject(context.TODO(), projectReconfigOpts.name); err != nil {
return errors.Errorf("failed to reconfigure remote project: %w", err)
return errors.Wrapf(err, "failed to reconfigure remote project")
}
log.Info().Msgf("project reconfigured")

View File

@ -19,13 +19,13 @@ import (
"io/ioutil"
"os"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/ghodss/yaml"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdProjectSecretCreate = &cobra.Command{
@ -82,12 +82,12 @@ func secretCreate(cmd *cobra.Command, ownertype string, args []string) error {
if secretCreateOpts.file == "-" {
data, err = ioutil.ReadAll(os.Stdin)
if err != nil {
return err
return errors.WithStack(err)
}
} else {
data, err = ioutil.ReadFile(secretCreateOpts.file)
if err != nil {
return err
return errors.WithStack(err)
}
}
@ -106,14 +106,14 @@ func secretCreate(cmd *cobra.Command, ownertype string, args []string) error {
log.Info().Msgf("creating project secret")
secret, _, err := gwclient.CreateProjectSecret(context.TODO(), secretCreateOpts.parentRef, req)
if err != nil {
return errors.Errorf("failed to create project secret: %w", err)
return errors.Wrapf(err, "failed to create project secret")
}
log.Info().Msgf("project secret %q created, ID: %q", secret.Name, secret.ID)
case "projectgroup":
log.Info().Msgf("creating project group secret")
secret, _, err := gwclient.CreateProjectGroupSecret(context.TODO(), secretCreateOpts.parentRef, req)
if err != nil {
return errors.Errorf("failed to create project group secret: %w", err)
return errors.Wrapf(err, "failed to create project group secret")
}
log.Info().Msgf("project group secret %q created, ID: %q", secret.Name, secret.ID)
}

View File

@ -17,11 +17,11 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdProjectSecretDelete = &cobra.Command{
@ -65,14 +65,14 @@ func secretDelete(cmd *cobra.Command, ownertype string, args []string) error {
log.Info().Msgf("deleting project secret")
_, err := gwclient.DeleteProjectSecret(context.TODO(), secretDeleteOpts.parentRef, secretDeleteOpts.name)
if err != nil {
return errors.Errorf("failed to delete project secret: %w", err)
return errors.Wrapf(err, "failed to delete project secret")
}
log.Info().Msgf("project secret deleted")
case "projectgroup":
log.Info().Msgf("deleting project group secret")
_, err := gwclient.DeleteProjectGroupSecret(context.TODO(), secretDeleteOpts.parentRef, secretDeleteOpts.name)
if err != nil {
return errors.Errorf("failed to delete project group secret: %w", err)
return errors.Wrapf(err, "failed to delete project group secret")
}
log.Info().Msgf("project group secret deleted")
}

View File

@ -19,12 +19,12 @@ import (
"encoding/json"
"fmt"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdProjectSecretList = &cobra.Command{
@ -57,10 +57,10 @@ func init() {
func secretList(cmd *cobra.Command, ownertype string, args []string) error {
if err := printSecrets(ownertype, fmt.Sprintf("%s secrets", ownertype), false, false); err != nil {
return err
return errors.WithStack(err)
}
if err := printSecrets(ownertype, "All secrets (local and inherited)", true, true); err != nil {
return err
return errors.WithStack(err)
}
return nil
}
@ -79,11 +79,11 @@ func printSecrets(ownertype, description string, tree, removeoverridden bool) er
secrets, _, err = gwclient.GetProjectGroupSecrets(context.TODO(), secretListOpts.parentRef, tree, removeoverridden)
}
if err != nil {
return errors.Errorf("failed to list %s secrets: %w", ownertype, err)
return errors.Wrapf(err, "failed to list %s secrets", ownertype)
}
prettyJSON, err := json.MarshalIndent(secrets, "", "\t")
if err != nil {
return errors.Errorf("failed to convert %s secrets to json: %w", ownertype, err)
return errors.Wrapf(err, "failed to convert %s secrets to json", ownertype)
}
fmt.Printf("%s:\n%s\n", description, string(prettyJSON))
return nil

View File

@ -19,13 +19,13 @@ import (
"io/ioutil"
"os"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/ghodss/yaml"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdProjectSecretUpdate = &cobra.Command{
@ -84,12 +84,12 @@ func secretUpdate(cmd *cobra.Command, ownertype string, args []string) error {
if secretUpdateOpts.file == "-" {
data, err = ioutil.ReadAll(os.Stdin)
if err != nil {
return err
return errors.WithStack(err)
}
} else {
data, err = ioutil.ReadFile(secretUpdateOpts.file)
if err != nil {
return err
return errors.WithStack(err)
}
}
@ -113,14 +113,14 @@ func secretUpdate(cmd *cobra.Command, ownertype string, args []string) error {
log.Info().Msgf("creating project secret")
secret, _, err := gwclient.UpdateProjectSecret(context.TODO(), secretUpdateOpts.parentRef, secretUpdateOpts.name, req)
if err != nil {
return errors.Errorf("failed to update project secret: %w", err)
return errors.Wrapf(err, "failed to update project secret")
}
log.Info().Msgf("project secret %q updated, ID: %q", secret.Name, secret.ID)
case "projectgroup":
log.Info().Msgf("creating project group secret")
secret, _, err := gwclient.UpdateProjectGroupSecret(context.TODO(), secretUpdateOpts.parentRef, secretUpdateOpts.name, req)
if err != nil {
return errors.Errorf("failed to update project group secret: %w", err)
return errors.Wrapf(err, "failed to update project group secret")
}
log.Info().Msgf("project group secret %q updated, ID: %q", secret.Name, secret.ID)
}

View File

@ -17,12 +17,12 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdProjectUpdate = &cobra.Command{
@ -88,7 +88,7 @@ func projectUpdate(cmd *cobra.Command, args []string) error {
log.Info().Msgf("updating project")
project, _, err := gwclient.UpdateProject(context.TODO(), projectUpdateOpts.ref, req)
if err != nil {
return errors.Errorf("failed to update project: %w", err)
return errors.Wrapf(err, "failed to update project")
}
log.Info().Msgf("project %s update, ID: %s", project.Name, project.ID)

View File

@ -20,13 +20,13 @@ import (
"os"
config "agola.io/agola/internal/config"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/ghodss/yaml"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdProjectVariableCreate = &cobra.Command{
@ -105,12 +105,12 @@ func variableCreate(cmd *cobra.Command, ownertype string, args []string) error {
if variableCreateOpts.file == "-" {
data, err = ioutil.ReadAll(os.Stdin)
if err != nil {
return err
return errors.WithStack(err)
}
} else {
data, err = ioutil.ReadFile(variableCreateOpts.file)
if err != nil {
return err
return errors.WithStack(err)
}
}
@ -136,14 +136,14 @@ func variableCreate(cmd *cobra.Command, ownertype string, args []string) error {
log.Info().Msgf("creating project variable")
variable, _, err := gwclient.CreateProjectVariable(context.TODO(), variableCreateOpts.parentRef, req)
if err != nil {
return errors.Errorf("failed to create project variable: %w", err)
return errors.Wrapf(err, "failed to create project variable")
}
log.Info().Msgf("project variable %q created, ID: %q", variable.Name, variable.ID)
case "projectgroup":
log.Info().Msgf("creating project group variable")
variable, _, err := gwclient.CreateProjectGroupVariable(context.TODO(), variableCreateOpts.parentRef, req)
if err != nil {
return errors.Errorf("failed to create project group variable: %w", err)
return errors.Wrapf(err, "failed to create project group variable")
}
log.Info().Msgf("project group variable %q created, ID: %q", variable.Name, variable.ID)
}

View File

@ -17,11 +17,11 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdProjectVariableDelete = &cobra.Command{
@ -65,14 +65,14 @@ func variableDelete(cmd *cobra.Command, ownertype string, args []string) error {
log.Info().Msgf("deleting project variable")
_, err := gwclient.DeleteProjectVariable(context.TODO(), variableDeleteOpts.parentRef, variableDeleteOpts.name)
if err != nil {
return errors.Errorf("failed to delete project variable: %w", err)
return errors.Wrapf(err, "failed to delete project variable")
}
log.Info().Msgf("project variable deleted")
case "projectgroup":
log.Info().Msgf("deleting project group variable")
_, err := gwclient.DeleteProjectGroupVariable(context.TODO(), variableDeleteOpts.parentRef, variableDeleteOpts.name)
if err != nil {
return errors.Errorf("failed to delete project group variable: %w", err)
return errors.Wrapf(err, "failed to delete project group variable")
}
log.Info().Msgf("project group variable deleted")
}

View File

@ -19,12 +19,12 @@ import (
"encoding/json"
"fmt"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdProjectVariableList = &cobra.Command{
@ -57,10 +57,10 @@ func init() {
func variableList(cmd *cobra.Command, ownertype string, args []string) error {
if err := printVariables(ownertype, fmt.Sprintf("%s variables", ownertype), false, false); err != nil {
return err
return errors.WithStack(err)
}
if err := printVariables(ownertype, "All variables (local and inherited)", true, true); err != nil {
return err
return errors.WithStack(err)
}
return nil
}
@ -79,11 +79,11 @@ func printVariables(ownertype, description string, tree, removeoverridden bool)
variables, _, err = gwclient.GetProjectGroupVariables(context.TODO(), variableListOpts.parentRef, tree, removeoverridden)
}
if err != nil {
return errors.Errorf("failed to list %s variables: %w", ownertype, err)
return errors.Wrapf(err, "failed to list %s variables", ownertype)
}
prettyJSON, err := json.MarshalIndent(variables, "", "\t")
if err != nil {
return errors.Errorf("failed to convert %s variables to json: %w", ownertype, err)
return errors.Wrapf(err, "failed to convert %s variables to json", ownertype)
}
fmt.Printf("%s:\n%s\n", description, string(prettyJSON))
return nil

View File

@ -19,13 +19,13 @@ import (
"io/ioutil"
"os"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/ghodss/yaml"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdProjectVariableUpdate = &cobra.Command{
@ -77,12 +77,12 @@ func variableUpdate(cmd *cobra.Command, ownertype string, args []string) error {
if variableUpdateOpts.file == "-" {
data, err = ioutil.ReadAll(os.Stdin)
if err != nil {
return err
return errors.WithStack(err)
}
} else {
data, err = ioutil.ReadFile(variableUpdateOpts.file)
if err != nil {
return err
return errors.WithStack(err)
}
}
@ -113,14 +113,14 @@ func variableUpdate(cmd *cobra.Command, ownertype string, args []string) error {
log.Info().Msgf("updating project variable")
variable, _, err := gwclient.UpdateProjectVariable(context.TODO(), variableUpdateOpts.parentRef, variableUpdateOpts.name, req)
if err != nil {
return errors.Errorf("failed to update project variable: %w", err)
return errors.Wrapf(err, "failed to update project variable")
}
log.Info().Msgf("project variable %q updated, ID: %q", variable.Name, variable.ID)
case "projectgroup":
log.Info().Msgf("updating project group variable")
variable, _, err := gwclient.UpdateProjectGroupVariable(context.TODO(), variableUpdateOpts.parentRef, variableUpdateOpts.name, req)
if err != nil {
return errors.Errorf("failed to update project group variable: %w", err)
return errors.Wrapf(err, "failed to update project group variable")
}
log.Info().Msgf("project group variable %q updated, ID: %q", variable.Name, variable.ID)
}

View File

@ -17,6 +17,7 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/gitsources/github"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
@ -24,7 +25,6 @@ import (
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdRemoteSourceCreate = &cobra.Command{
@ -117,7 +117,7 @@ func remoteSourceCreate(cmd *cobra.Command, args []string) error {
log.Info().Msgf("creating remotesource")
remoteSource, _, err := gwclient.CreateRemoteSource(context.TODO(), req)
if err != nil {
return errors.Errorf("failed to create remotesource: %w", err)
return errors.Wrapf(err, "failed to create remotesource")
}
log.Info().Msgf("remotesource %s created, ID: %s", remoteSource.Name, remoteSource.ID)

View File

@ -18,6 +18,7 @@ import (
"context"
"fmt"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
@ -62,7 +63,7 @@ func remoteSourceList(cmd *cobra.Command, args []string) error {
remouteSources, _, err := gwclient.GetRemoteSources(context.TODO(), remoteSourceListOpts.start, remoteSourceListOpts.limit, false)
if err != nil {
return err
return errors.WithStack(err)
}
printRemoteSources(remouteSources)

View File

@ -17,12 +17,12 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdRemoteSourceUpdate = &cobra.Command{
@ -109,7 +109,7 @@ func remoteSourceUpdate(cmd *cobra.Command, args []string) error {
log.Info().Msgf("updating remotesource")
remoteSource, _, err := gwclient.UpdateRemoteSource(context.TODO(), remoteSourceUpdateOpts.ref, req)
if err != nil {
return errors.Errorf("failed to update remotesource: %w", err)
return errors.Wrapf(err, "failed to update remotesource")
}
log.Info().Msgf("remotesource %s updated, ID: %s", remoteSource.Name, remoteSource.ID)

View File

@ -16,8 +16,8 @@ package cmd
import (
"context"
"fmt"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
@ -76,7 +76,7 @@ func runCreate(cmd *cobra.Command, args []string) error {
set++
}
if set != 1 {
return fmt.Errorf(`one of "--branch", "--tag" or "--ref" must be provided`)
return errors.Errorf(`one of "--branch", "--tag" or "--ref" must be provided`)
}
req := &gwapitypes.ProjectCreateRunRequest{
@ -88,5 +88,5 @@ func runCreate(cmd *cobra.Command, args []string) error {
_, err := gwclient.ProjectCreateRun(context.TODO(), runCreateOpts.projectRef, req)
return err
return errors.WithStack(err)
}

View File

@ -20,9 +20,9 @@ import (
"path"
"sort"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
errors "golang.org/x/xerrors"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
@ -104,14 +104,14 @@ func runList(cmd *cobra.Command, args []string) error {
groups := []string{path.Join("/project", project.ID)}
runsResp, _, err := gwclient.GetRuns(context.TODO(), runListOpts.phaseFilter, nil, groups, nil, runListOpts.start, runListOpts.limit, false)
if err != nil {
return err
return errors.WithStack(err)
}
runs := make([]*runDetails, len(runsResp))
for i, runResponse := range runsResp {
run, _, err := gwclient.GetRun(context.TODO(), runResponse.ID)
if err != nil {
return err
return errors.WithStack(err)
}
tasks := []*taskDetails{}

View File

@ -19,6 +19,7 @@ import (
"fmt"
"agola.io/agola/cmd"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/services/config"
"agola.io/agola/internal/services/configstore"
"agola.io/agola/internal/services/executor"
@ -33,7 +34,6 @@ import (
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"go.etcd.io/etcd/embed"
errors "golang.org/x/xerrors"
)
var (
@ -96,7 +96,7 @@ func embeddedEtcd(ctx context.Context) error {
log.Info().Msgf("starting embedded etcd server")
e, err := embed.StartEtcd(cfg)
if err != nil {
return err
return errors.WithStack(err)
}
go func() {
@ -132,12 +132,12 @@ func serve(cmd *cobra.Command, args []string) error {
c, err := config.Parse(serveOpts.config, serveOpts.components)
if err != nil {
return errors.Errorf("config error: %w", err)
return errors.Wrapf(err, "config error")
}
if serveOpts.embeddedEtcd {
if err := embeddedEtcd(ctx); err != nil {
return errors.Errorf("failed to start run service scheduler: %w", err)
return errors.Wrapf(err, "failed to start run service scheduler")
}
}
@ -145,7 +145,7 @@ func serve(cmd *cobra.Command, args []string) error {
if isComponentEnabled("runservice") {
rs, err = rsscheduler.NewRunservice(ctx, log.Logger, &c.Runservice)
if err != nil {
return errors.Errorf("failed to start run service scheduler: %w", err)
return errors.Wrapf(err, "failed to start run service scheduler")
}
}
@ -153,7 +153,7 @@ func serve(cmd *cobra.Command, args []string) error {
if isComponentEnabled("executor") {
ex, err = executor.NewExecutor(ctx, log.Logger, &c.Executor)
if err != nil {
return errors.Errorf("failed to start run service executor: %w", err)
return errors.Wrapf(err, "failed to start run service executor")
}
}
@ -161,7 +161,7 @@ func serve(cmd *cobra.Command, args []string) error {
if isComponentEnabled("configstore") {
cs, err = configstore.NewConfigstore(ctx, log.Logger, &c.Configstore)
if err != nil {
return errors.Errorf("failed to start config store: %w", err)
return errors.Wrapf(err, "failed to start config store")
}
}
@ -169,7 +169,7 @@ func serve(cmd *cobra.Command, args []string) error {
if isComponentEnabled("scheduler") {
sched, err = scheduler.NewScheduler(ctx, log.Logger, &c.Scheduler)
if err != nil {
return errors.Errorf("failed to start scheduler: %w", err)
return errors.Wrapf(err, "failed to start scheduler")
}
}
@ -177,7 +177,7 @@ func serve(cmd *cobra.Command, args []string) error {
if isComponentEnabled("notification") {
ns, err = notification.NewNotificationService(ctx, log.Logger, c)
if err != nil {
return errors.Errorf("failed to start notification service: %w", err)
return errors.Wrapf(err, "failed to start notification service")
}
}
@ -185,7 +185,7 @@ func serve(cmd *cobra.Command, args []string) error {
if isComponentEnabled("gateway") {
gw, err = gateway.NewGateway(ctx, log.Logger, c)
if err != nil {
return errors.Errorf("failed to start gateway: %w", err)
return errors.Wrapf(err, "failed to start gateway")
}
}
@ -193,7 +193,7 @@ func serve(cmd *cobra.Command, args []string) error {
if isComponentEnabled("gitserver") {
gs, err = gitserver.NewGitserver(ctx, log.Logger, &c.Gitserver)
if err != nil {
return errors.Errorf("failed to start git server: %w", err)
return errors.Wrapf(err, "failed to start git server")
}
}

View File

@ -17,12 +17,12 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdUserCreate = &cobra.Command{
@ -63,7 +63,7 @@ func userCreate(cmd *cobra.Command, args []string) error {
log.Info().Msgf("creating user")
user, _, err := gwclient.CreateUser(context.TODO(), req)
if err != nil {
return errors.Errorf("failed to create user: %w", err)
return errors.Wrapf(err, "failed to create user")
}
log.Info().Msgf("user %q created, ID: %q", user.UserName, user.ID)

View File

@ -17,11 +17,11 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdUserDelete = &cobra.Command{
@ -57,7 +57,7 @@ func userDelete(cmd *cobra.Command, args []string) error {
log.Info().Msgf("deleting user %q", userDeleteOpts.username)
if _, err := gwclient.DeleteUser(context.TODO(), userDeleteOpts.username); err != nil {
return errors.Errorf("failed to delete user: %w", err)
return errors.Wrapf(err, "failed to delete user")
}
return nil

View File

@ -17,12 +17,12 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdUserLACreate = &cobra.Command{
@ -74,7 +74,7 @@ func userLACreate(cmd *cobra.Command, args []string) error {
log.Info().Msgf("creating linked account for user %q", userLACreateOpts.username)
resp, _, err := gwclient.CreateUserLA(context.TODO(), userLACreateOpts.username, req)
if err != nil {
return errors.Errorf("failed to create linked account: %w", err)
return errors.Wrapf(err, "failed to create linked account")
}
if resp.Oauth2Redirect != "" {
log.Info().Msgf("visit %s to continue", resp.Oauth2Redirect)

View File

@ -17,11 +17,11 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdUserLADelete = &cobra.Command{
@ -66,7 +66,7 @@ func userLADelete(cmd *cobra.Command, args []string) error {
log.Info().Msgf("deleting linked account %q for user %q", laID, userName)
_, err := gwclient.DeleteUserLA(context.TODO(), userName, laID)
if err != nil {
return errors.Errorf("failed to delete linked account: %w", err)
return errors.Wrapf(err, "failed to delete linked account")
}
log.Info().Msgf("linked account %q for user %q deleted", laID, userName)

View File

@ -18,6 +18,7 @@ import (
"context"
"fmt"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
@ -62,7 +63,7 @@ func userList(cmd *cobra.Command, args []string) error {
users, _, err := gwclient.GetUsers(context.TODO(), userListOpts.start, userListOpts.limit, false)
if err != nil {
return err
return errors.WithStack(err)
}
printUsers(users)

View File

@ -18,12 +18,12 @@ import (
"context"
"fmt"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdUserTokenCreate = &cobra.Command{
@ -69,7 +69,7 @@ func userTokenCreate(cmd *cobra.Command, args []string) error {
log.Info().Msgf("creating token for user %q", userTokenCreateOpts.username)
resp, _, err := gwclient.CreateUserToken(context.TODO(), userTokenCreateOpts.username, req)
if err != nil {
return errors.Errorf("failed to create token: %w", err)
return errors.Wrapf(err, "failed to create token")
}
log.Info().Msgf("token for user %q created: %s", userTokenCreateOpts.username, resp.Token)
fmt.Println(resp.Token)

View File

@ -17,11 +17,11 @@ package cmd
import (
"context"
"agola.io/agola/internal/errors"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
errors "golang.org/x/xerrors"
)
var cmdUserTokenDelete = &cobra.Command{
@ -66,7 +66,7 @@ func userTokenDelete(cmd *cobra.Command, args []string) error {
log.Info().Msgf("deleting token %q for user %q", tokenName, userName)
_, err := gwclient.DeleteUserToken(context.TODO(), userName, tokenName)
if err != nil {
return errors.Errorf("failed to delete user token: %w", err)
return errors.Wrapf(err, "failed to delete user token")
}
log.Info().Msgf("token %q for user %q deleted", tokenName, userName)

View File

@ -18,6 +18,7 @@ import (
"context"
"fmt"
"agola.io/agola/internal/errors"
gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log"
@ -43,7 +44,7 @@ func printVersions(cmd *cobra.Command, args []string) error {
gwversion, _, err := gwclient.GetVersion(context.TODO())
if err != nil {
return err
return errors.WithStack(err)
}
fmt.Printf("Gateway version:\t%s\n", gwversion.Version)

View File

@ -21,6 +21,7 @@ import (
"log"
"os"
"agola.io/agola/internal/errors"
"github.com/spf13/cobra"
)
@ -48,18 +49,18 @@ func createFile(r io.Reader) (string, error) {
// create a temp dir if the image doesn't have one
tmpDir := os.TempDir()
if err := os.MkdirAll(tmpDir, 0777); err != nil {
return "", fmt.Errorf("failed to create tmp dir %q", tmpDir)
return "", errors.Errorf("failed to create tmp dir %q", tmpDir)
}
file, err := ioutil.TempFile("", "")
if err != nil {
return "", err
return "", errors.WithStack(err)
}
filename := file.Name()
if _, err := io.Copy(file, r); err != nil {
file.Close()
return "", err
return "", errors.WithStack(err)
}
file.Close()

View File

@ -17,7 +17,6 @@ package cmd
import (
"crypto/md5"
"crypto/sha256"
"errors"
"fmt"
"io"
"io/ioutil"
@ -28,6 +27,8 @@ import (
"text/template"
"time"
"agola.io/agola/internal/errors"
"github.com/spf13/cobra"
)
@ -48,20 +49,20 @@ func md5sum(filename string) (string, error) {
if info, err := os.Stat(filename); err == nil {
if info.Size() > 1024*1024 {
return "", fmt.Errorf("file %q is too big", filename)
return "", errors.Errorf("file %q is too big", filename)
}
} else {
return "", err
return "", errors.WithStack(err)
}
f, err := os.Open(filename)
if err != nil {
return "", err
return "", errors.WithStack(err)
}
h := md5.New()
if _, err := io.Copy(h, f); err != nil {
return "", err
return "", errors.WithStack(err)
}
return fmt.Sprintf("%x", h.Sum(nil)), nil
@ -74,20 +75,20 @@ func sha256sum(filename string) (string, error) {
if info, err := os.Stat(filename); err == nil {
if info.Size() > 1024*1024 {
return "", fmt.Errorf("file %q is too big", filename)
return "", errors.Errorf("file %q is too big", filename)
}
} else {
return "", err
return "", errors.WithStack(err)
}
f, err := os.Open(filename)
if err != nil {
return "", err
return "", errors.WithStack(err)
}
h := sha256.New()
if _, err := io.Copy(h, f); err != nil {
return "", err
return "", errors.WithStack(err)
}
return fmt.Sprintf("%x", h.Sum(nil)), nil

View File

@ -2,7 +2,7 @@
#### Start the web interface
* Clone the [agola-web repository](https://github.com/agola-io/agola-web)
- Clone the [agola-web repository](https://github.com/agola-io/agola-web)
For the first time you'll need the `vue cli` and its services installed as global modules:
@ -27,7 +27,7 @@ make
### Start the agola server
* Copy the `example/config.yml` where you prefer
- Copy the `example/config.yml` where you prefer
```
./bin/agola serve --embedded-etcd --config /path/to/your/config.yml --components all-base,executor
@ -38,3 +38,9 @@ or use an external etcd (set it in the config.yml):
```
./bin/agola serve --config /path/to/your/config.yml --components all-base,executor
```
### Error handling
Use the `--detailed-errors` option to easily follow the errors chain.
When developing you should wrap every error using `errors.Wrap[f]` or `errors.WithStack`. The ci uses `golangci-lint` with the `wrapcheck` linter enabled to check if some errors aren't wrapped.

1
go.mod
View File

@ -35,7 +35,6 @@ require (
go.starlark.net v0.0.0-20200203144150-6677ee5c7211
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
gopkg.in/src-d/go-billy.v4 v4.3.2
gopkg.in/src-d/go-git.v4 v4.13.1
gopkg.in/yaml.v2 v2.2.8

View File

@ -21,12 +21,12 @@ import (
"os"
"path"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/etcd"
"agola.io/agola/internal/objectstorage"
"agola.io/agola/internal/services/config"
"github.com/rs/zerolog"
errors "golang.org/x/xerrors"
)
const (
@ -43,7 +43,7 @@ func WriteFileAtomicFunc(filename string, perm os.FileMode, writeFunc func(f io.
dir, name := path.Split(filename)
f, err := ioutil.TempFile(dir, name)
if err != nil {
return err
return errors.WithStack(err)
}
err = writeFunc(f)
if err == nil {
@ -62,7 +62,7 @@ func WriteFileAtomicFunc(filename string, perm os.FileMode, writeFunc func(f io.
if err != nil {
os.Remove(f.Name())
}
return err
return errors.WithStack(err)
}
// WriteFileAtomic atomically writes a file
@ -70,7 +70,7 @@ func WriteFileAtomic(filename string, data []byte, perm os.FileMode) error {
return WriteFileAtomicFunc(filename, perm,
func(f io.Writer) error {
_, err := f.Write(data)
return err
return errors.WithStack(err)
})
}
@ -84,7 +84,7 @@ func NewObjectStorage(c *config.ObjectStorage) (*objectstorage.ObjStorage, error
case config.ObjectStorageTypePosix:
ost, err = objectstorage.NewPosix(c.Path)
if err != nil {
return nil, errors.Errorf("failed to create posix object storage: %w", err)
return nil, errors.Wrapf(err, "failed to create posix object storage")
}
case config.ObjectStorageTypeS3:
// minio golang client doesn't accept an url as an endpoint
@ -103,7 +103,7 @@ func NewObjectStorage(c *config.ObjectStorage) (*objectstorage.ObjStorage, error
}
ost, err = objectstorage.NewS3(c.Bucket, c.Location, endpoint, c.AccessKey, c.SecretAccessKey, secure)
if err != nil {
return nil, errors.Errorf("failed to create s3 object storage: %w", err)
return nil, errors.Wrapf(err, "failed to create s3 object storage")
}
}
@ -121,7 +121,7 @@ func NewEtcd(c *config.Etcd, log zerolog.Logger, prefix string) (*etcd.Store, er
SkipTLSVerify: c.TLSSkipVerify,
})
if err != nil {
return nil, errors.Errorf("failed to create etcd store: %w", err)
return nil, errors.Wrapf(err, "failed to create etcd store")
}
return e, nil

View File

@ -20,12 +20,12 @@ import (
"regexp"
"strings"
"agola.io/agola/internal/errors"
itypes "agola.io/agola/internal/services/types"
"agola.io/agola/internal/util"
"agola.io/agola/services/types"
"github.com/ghodss/yaml"
errors "golang.org/x/xerrors"
"k8s.io/apimachinery/pkg/api/resource"
)
@ -201,7 +201,7 @@ type SaveContent struct {
func (s *Steps) UnmarshalJSON(b []byte) error {
var stepsRaw []json.RawMessage
if err := json.Unmarshal(b, &stepsRaw); err != nil {
return err
return errors.WithStack(err)
}
steps := make(Steps, len(stepsRaw))
@ -210,13 +210,13 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
var stepMap map[string]json.RawMessage
if err := json.Unmarshal(stepRaw, &stepMap); err != nil {
return err
return errors.WithStack(err)
}
// handle default step definition using format { type: "steptype", other steps fields }
if _, ok := stepMap["type"]; ok {
var stepTypeI interface{}
if err := json.Unmarshal(stepMap["type"], &stepTypeI); err != nil {
return err
return errors.WithStack(err)
}
stepType, ok := stepTypeI.(string)
if !ok {
@ -227,7 +227,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
case "clone":
var s CloneStep
if err := json.Unmarshal(stepRaw, &s); err != nil {
return err
return errors.WithStack(err)
}
s.Type = stepType
step = &s
@ -235,7 +235,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
case "run":
var s RunStep
if err := json.Unmarshal(stepRaw, &s); err != nil {
return err
return errors.WithStack(err)
}
if s.Tty == nil {
s.Tty = util.BoolP(true)
@ -246,7 +246,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
case "save_to_workspace":
var s SaveToWorkspaceStep
if err := json.Unmarshal(stepRaw, &s); err != nil {
return err
return errors.WithStack(err)
}
s.Type = stepType
step = &s
@ -254,7 +254,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
case "restore_workspace":
var s RestoreWorkspaceStep
if err := json.Unmarshal(stepRaw, &s); err != nil {
return err
return errors.WithStack(err)
}
s.Type = stepType
step = &s
@ -262,7 +262,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
case "save_cache":
var s SaveCacheStep
if err := json.Unmarshal(stepRaw, &s); err != nil {
return err
return errors.WithStack(err)
}
s.Type = stepType
step = &s
@ -270,7 +270,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
case "restore_cache":
var s RestoreCacheStep
if err := json.Unmarshal(stepRaw, &s); err != nil {
return err
return errors.WithStack(err)
}
s.Type = stepType
step = &s
@ -285,14 +285,14 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
for stepType, stepSpecRaw := range stepMap {
var stepSpec interface{}
if err := json.Unmarshal(stepSpecRaw, &stepSpec); err != nil {
return err
return errors.WithStack(err)
}
switch stepType {
case "clone":
var s CloneStep
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
return err
return errors.WithStack(err)
}
s.Type = stepType
step = &s
@ -304,7 +304,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
s.Command = stepSpec
default:
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
return err
return errors.WithStack(err)
}
}
s.Type = stepType
@ -313,7 +313,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
case "save_to_workspace":
var s SaveToWorkspaceStep
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
return err
return errors.WithStack(err)
}
s.Type = stepType
step = &s
@ -321,7 +321,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
case "restore_workspace":
var s RestoreWorkspaceStep
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
return err
return errors.WithStack(err)
}
s.Type = stepType
step = &s
@ -329,7 +329,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
case "save_cache":
var s SaveCacheStep
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
return err
return errors.WithStack(err)
}
s.Type = stepType
step = &s
@ -337,7 +337,7 @@ func (s *Steps) UnmarshalJSON(b []byte) error {
case "restore_cache":
var s RestoreCacheStep
if err := json.Unmarshal(stepSpecRaw, &s); err != nil {
return err
return errors.WithStack(err)
}
s.Type = stepType
step = &s
@ -359,14 +359,14 @@ func (d *Depends) UnmarshalJSON(b []byte) error {
var dependsRaw []json.RawMessage
if err := json.Unmarshal(b, &dependsRaw); err != nil {
return err
return errors.WithStack(err)
}
depends := make([]*Depend, len(dependsRaw))
for i, dependRaw := range dependsRaw {
var dependi interface{}
if err := json.Unmarshal(dependRaw, &dependi); err != nil {
return err
return errors.WithStack(err)
}
var depend *Depend
isSimpler := false
@ -391,7 +391,7 @@ func (d *Depends) UnmarshalJSON(b []byte) error {
if !isSimpler {
// handle default depends definition using format "task": "taskname", conditions: [ list of conditions ]
if err := json.Unmarshal(dependRaw, &depend); err != nil {
return err
return errors.WithStack(err)
}
} else {
// handle simpler (for yaml) depends definition using format "taskname": [ list of conditions ]
@ -401,7 +401,7 @@ func (d *Depends) UnmarshalJSON(b []byte) error {
type deplist map[string][]DependCondition
var dl deplist
if err := json.Unmarshal(dependRaw, &dl); err != nil {
return err
return errors.WithStack(err)
}
if len(dl) != 1 {
return errors.Errorf("unsupported depend entry format")
@ -440,7 +440,7 @@ type Value struct {
func (val *Value) UnmarshalJSON(b []byte) error {
var ival interface{}
if err := json.Unmarshal(b, &ival); err != nil {
return err
return errors.WithStack(err)
}
switch valValue := ival.(type) {
case string:
@ -479,7 +479,7 @@ func (w *When) ToWhen() *types.When {
func (w *When) UnmarshalJSON(b []byte) error {
var wi *when
if err := json.Unmarshal(b, &wi); err != nil {
return err
return errors.WithStack(err)
}
var err error
@ -487,21 +487,21 @@ func (w *When) UnmarshalJSON(b []byte) error {
if wi.Branch != nil {
w.Branch, err = parseWhenConditions(wi.Branch)
if err != nil {
return err
return errors.WithStack(err)
}
}
if wi.Tag != nil {
w.Tag, err = parseWhenConditions(wi.Tag)
if err != nil {
return err
return errors.WithStack(err)
}
}
if wi.Ref != nil {
w.Ref, err = parseWhenConditions(wi.Ref)
if err != nil {
return err
return errors.WithStack(err)
}
}
@ -521,7 +521,7 @@ func parseWhenConditions(wi interface{}) (*types.WhenConditions, error) {
case []interface{}:
ss, err := parseSliceString(c)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
include = ss
case map[string]interface{}:
@ -530,12 +530,12 @@ func parseWhenConditions(wi interface{}) (*types.WhenConditions, error) {
case "include":
include, err = parseStringOrSlice(v)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
case "exclude":
exclude, err = parseStringOrSlice(v)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
default:
return nil, errors.Errorf(`expected one of "include" or "exclude", got %s`, k)
@ -547,11 +547,11 @@ func parseWhenConditions(wi interface{}) (*types.WhenConditions, error) {
w.Include, err = parseWhenConditionSlice(include)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
w.Exclude, err = parseWhenConditionSlice(exclude)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return w, nil
@ -566,7 +566,7 @@ func parseWhenConditionSlice(conds []string) ([]types.WhenCondition, error) {
for _, cond := range conds {
wc, err := parseWhenCondition(cond)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
wcs = append(wcs, *wc)
}
@ -590,7 +590,7 @@ func parseWhenCondition(s string) (*types.WhenCondition, error) {
if isRegExp {
if _, err := regexp.Compile(s); err != nil {
return nil, errors.Errorf("wrong regular expression: %w", err)
return nil, errors.Wrapf(err, "wrong regular expression")
}
wc.Type = types.WhenConditionTypeRegExp
} else {
@ -608,7 +608,7 @@ func parseStringOrSlice(si interface{}) ([]string, error) {
var err error
ss, err = parseSliceString(c)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
}
return ss, nil
@ -669,14 +669,14 @@ func ParseConfig(configData []byte, format ConfigFormat, configContext *ConfigCo
var err error
configData, err = execJsonnet(configData, configContext)
if err != nil {
return nil, errors.Errorf("failed to execute jsonnet: %w", err)
return nil, errors.Wrapf(err, "failed to execute jsonnet")
}
case ConfigFormatStarlark:
// Generate json from starlark
var err error
configData, err = execStarlark(configData, configContext)
if err != nil {
return nil, errors.Errorf("failed to execute starlark: %w", err)
return nil, errors.Wrapf(err, "failed to execute starlark")
}
}
@ -686,7 +686,7 @@ func ParseConfig(configData []byte, format ConfigFormat, configContext *ConfigCo
config := DefaultConfig
if err := yaml.Unmarshal(configData, &config); err != nil {
return nil, errors.Errorf("failed to unmarshal config: %w", err)
return nil, errors.Wrapf(err, "failed to unmarshal config")
}
return &config, checkConfig(&config)

View File

@ -15,14 +15,13 @@
package config
import (
"fmt"
"testing"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util"
"agola.io/agola/services/types"
"github.com/google/go-cmp/cmp"
errors "golang.org/x/xerrors"
"k8s.io/apimachinery/pkg/api/resource"
)
@ -35,14 +34,14 @@ func TestParseConfig(t *testing.T) {
{
name: "test no runs 1",
in: ``,
err: fmt.Errorf(`no runs defined`),
err: errors.Errorf(`no runs defined`),
},
{
name: "test no runs 2",
in: `
runs:
`,
err: fmt.Errorf(`no runs defined`),
err: errors.Errorf(`no runs defined`),
},
{
name: "test empty run",
@ -50,7 +49,7 @@ func TestParseConfig(t *testing.T) {
runs:
-
`,
err: fmt.Errorf(`run at index 0 is empty`),
err: errors.Errorf(`run at index 0 is empty`),
},
{
name: "test empty task",
@ -60,7 +59,7 @@ func TestParseConfig(t *testing.T) {
tasks:
-
`,
err: fmt.Errorf(`run "run01": task at index 0 is empty`),
err: errors.Errorf(`run "run01": task at index 0 is empty`),
},
{
name: "test empty runtime arch",
@ -88,7 +87,7 @@ func TestParseConfig(t *testing.T) {
containers:
- image: busybox
`,
err: fmt.Errorf(`task "task01" runtime: invalid arch "invalidarch"`),
err: errors.Errorf(`task "task01" runtime: invalid arch "invalidarch"`),
},
{
name: "test missing task dependency",
@ -104,7 +103,7 @@ func TestParseConfig(t *testing.T) {
depends:
- task02
`,
err: fmt.Errorf(`run task "task02" needed by task "task01" doesn't exist`),
err: errors.Errorf(`run task "task02" needed by task "task01" doesn't exist`),
},
{
name: "test circular dependency between 2 tasks a -> b -> a",

View File

@ -17,21 +17,21 @@ package config
import (
"encoding/json"
"agola.io/agola/internal/errors"
"github.com/google/go-jsonnet"
errors "golang.org/x/xerrors"
)
func execJsonnet(configData []byte, configContext *ConfigContext) ([]byte, error) {
vm := jsonnet.MakeVM()
cj, err := json.Marshal(configContext)
if err != nil {
return nil, errors.Errorf("failed to marshal config context: %w", err)
return nil, errors.Wrapf(err, "failed to marshal config context")
}
vm.TLACode("ctx", string(cj))
out, err := vm.EvaluateSnippet("", string(configData))
if err != nil {
return nil, errors.Errorf("failed to evaluate jsonnet config: %w", err)
return nil, errors.Wrapf(err, "failed to evaluate jsonnet config")
}
return []byte(out), nil

View File

@ -19,29 +19,29 @@ import (
"encoding/json"
"fmt"
"agola.io/agola/internal/errors"
"go.starlark.net/starlark"
errors "golang.org/x/xerrors"
)
func starlarkArgs(cc *ConfigContext) (starlark.Tuple, error) {
d := &starlark.Dict{}
if err := d.SetKey(starlark.String("ref_type"), starlark.String(cc.RefType)); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if err := d.SetKey(starlark.String("ref"), starlark.String(cc.Ref)); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if err := d.SetKey(starlark.String("branch"), starlark.String(cc.Branch)); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if err := d.SetKey(starlark.String("tag"), starlark.String(cc.Tag)); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if err := d.SetKey(starlark.String("pull_request_id"), starlark.String(cc.PullRequestID)); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if err := d.SetKey(starlark.String("commit_sha"), starlark.String(cc.CommitSHA)); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return []starlark.Value{d}, nil
@ -59,13 +59,13 @@ func starlarkJSON(out *bytes.Buffer, v starlark.Value) error {
case starlark.Int:
data, err := json.Marshal(v.BigInt())
if err != nil {
return err
return errors.WithStack(err)
}
out.Write(data)
case starlark.Float:
data, err := json.Marshal(float64(v))
if err != nil {
return err
return errors.WithStack(err)
}
out.Write(data)
case starlark.String:
@ -76,7 +76,7 @@ func starlarkJSON(out *bytes.Buffer, v starlark.Value) error {
e := json.NewEncoder(data)
e.SetEscapeHTML(false)
if err := e.Encode(string(v)); err != nil {
return err
return errors.WithStack(err)
}
// remove final \n introduced by the encoder
out.Write(bytes.TrimSuffix(data.Bytes(), []byte("\n")))
@ -87,7 +87,7 @@ func starlarkJSON(out *bytes.Buffer, v starlark.Value) error {
out.WriteString(", ")
}
if err := starlarkJSON(out, v.Index(i)); err != nil {
return err
return errors.WithStack(err)
}
}
out.WriteByte(']')
@ -98,20 +98,20 @@ func starlarkJSON(out *bytes.Buffer, v starlark.Value) error {
out.WriteString(", ")
}
if _, ok := item[0].(starlark.String); !ok {
return fmt.Errorf("cannot convert non-string dict key to JSON")
return errors.Errorf("cannot convert non-string dict key to JSON")
}
if err := starlarkJSON(out, item[0]); err != nil {
return err
return errors.WithStack(err)
}
out.WriteString(": ")
if err := starlarkJSON(out, item[1]); err != nil {
return err
return errors.WithStack(err)
}
}
out.WriteByte('}')
default:
return fmt.Errorf("cannot convert starlark type %q to JSON", v.Type())
return errors.Errorf("cannot convert starlark type %q to JSON", v.Type())
}
return nil
}
@ -124,7 +124,7 @@ func execStarlark(configData []byte, configContext *ConfigContext) ([]byte, erro
}
globals, err := starlark.ExecFile(thread, "config.star", configData, nil)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
// we require a main function that will be called wiht one
@ -139,18 +139,18 @@ func execStarlark(configData []byte, configContext *ConfigContext) ([]byte, erro
}
args, err := starlarkArgs(configContext)
if err != nil {
return nil, errors.Errorf("cannot create startlark arguments: %w", err)
return nil, errors.Wrapf(err, "cannot create startlark arguments")
}
mainVal, err = starlark.Call(thread, main, args, nil)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
buf := new(bytes.Buffer)
switch v := mainVal.(type) {
case *starlark.Dict:
if err := starlarkJSON(buf, v); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
default:
return nil, errors.Errorf("wrong starlark output, must be a dict")

View File

@ -16,10 +16,10 @@ package config
import (
"bytes"
"fmt"
"math"
"testing"
"agola.io/agola/internal/errors"
"github.com/google/go-cmp/cmp"
"go.starlark.net/starlark"
)
@ -48,7 +48,7 @@ func TestStarlarkJSON(t *testing.T) {
_ = s.SetKey(starlark.MakeInt(10), starlark.String("string01"))
return starlark.Value(s)
}(),
err: fmt.Errorf("cannot convert non-string dict key to JSON"),
err: errors.Errorf("cannot convert non-string dict key to JSON"),
},
{
name: "test list",

View File

@ -24,11 +24,11 @@ import (
"sync"
"time"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/etcd"
etcdclientv3rpc "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
"go.etcd.io/etcd/mvcc/mvccpb"
errors "golang.org/x/xerrors"
)
// TODO(sgotti) rewrite this to use a sqlite local cache
@ -132,7 +132,7 @@ func (d *DataManager) applyWalChanges(ctx context.Context, walData *WalData, rev
walDataFile, err := d.ost.ReadObject(walDataFilePath)
if err != nil {
return errors.Errorf("failed to read waldata %q: %w", walDataFilePath, err)
return errors.Wrapf(err, "failed to read waldata %q", walDataFilePath)
}
defer walDataFile.Close()
dec := json.NewDecoder(walDataFile)
@ -148,7 +148,7 @@ func (d *DataManager) applyWalChanges(ctx context.Context, walData *WalData, rev
break
}
if err != nil {
return errors.Errorf("failed to decode wal file: %w", err)
return errors.Wrapf(err, "failed to decode wal file")
}
d.applyWalChangesAction(ctx, action, walData.WalSequence, revision)
@ -200,7 +200,7 @@ func (d *DataManager) initializeChanges(ctx context.Context) error {
for {
listResp, err := d.e.ListPaged(ctx, etcdWalsDir+"/", 0, 10, continuation)
if err != nil {
return err
return errors.WithStack(err)
}
resp := listResp.Resp
continuation = listResp.Continuation
@ -210,10 +210,10 @@ func (d *DataManager) initializeChanges(ctx context.Context) error {
for _, kv := range resp.Kvs {
var walData *WalData
if err := json.Unmarshal(kv.Value, &walData); err != nil {
return err
return errors.WithStack(err)
}
if err := d.applyWalChanges(ctx, walData, revision); err != nil {
return err
return errors.WithStack(err)
}
}
if !listResp.HasMore {
@ -226,7 +226,7 @@ func (d *DataManager) initializeChanges(ctx context.Context) error {
for {
listResp, err := d.e.ListPaged(ctx, etcdChangeGroupsDir+"/", 0, 10, continuation)
if err != nil {
return err
return errors.WithStack(err)
}
resp := listResp.Resp
continuation = listResp.Continuation
@ -267,7 +267,7 @@ func (d *DataManager) watcher(ctx context.Context) error {
d.changes.initialized = false
d.changes.Unlock()
}
return errors.Errorf("watch error: %w", err)
return errors.Wrapf(err, "watch error")
}
revision := wresp.Header.Revision
@ -280,13 +280,13 @@ func (d *DataManager) watcher(ctx context.Context) error {
case mvccpb.PUT:
var walData *WalData
if err := json.Unmarshal(ev.Kv.Value, &walData); err != nil {
return err
return errors.WithStack(err)
}
if walData.WalStatus != WalStatusCommitted {
continue
}
if err := d.applyWalChanges(ctx, walData, revision); err != nil {
return err
return errors.WithStack(err)
}
case mvccpb.DELETE:
walseq := path.Base(string(key))

View File

@ -26,11 +26,11 @@ import (
"sort"
"strings"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/objectstorage"
"agola.io/agola/internal/sequence"
"github.com/gofrs/uuid"
errors "golang.org/x/xerrors"
)
// ErrNoDataStatus represent when there's no data status files in the ost
@ -96,12 +96,12 @@ func (d *DataManager) walIndex(ctx context.Context, wals []*WalData) (walIndex,
for _, walData := range wals {
header, err := d.ReadWal(walData.WalSequence)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
walFile, err := d.ReadWalData(header.WalDataFileID)
if err != nil {
return nil, errors.Errorf("cannot read wal data file %q: %w", header.WalDataFileID, err)
return nil, errors.Wrapf(err, "cannot read wal data file %q", header.WalDataFileID)
}
defer walFile.Close()
@ -115,7 +115,7 @@ func (d *DataManager) walIndex(ctx context.Context, wals []*WalData) (walIndex,
break
}
if err != nil {
return nil, errors.Errorf("failed to decode wal file: %w", err)
return nil, errors.Wrapf(err, "failed to decode wal file")
}
if _, ok := wimap[action.DataType]; !ok {
@ -148,7 +148,7 @@ func (d *DataManager) walIndex(ctx context.Context, wals []*WalData) (walIndex,
func (d *DataManager) writeDataSnapshot(ctx context.Context, wals []*WalData) error {
dataSequence, err := sequence.IncSequence(ctx, d.e, etcdCheckpointSeqKey)
if err != nil {
return err
return errors.WithStack(err)
}
var lastWalSequence string
@ -164,7 +164,7 @@ func (d *DataManager) writeDataSnapshot(ctx context.Context, wals []*WalData) er
curDataStatus, err := d.GetLastDataStatus()
if err != nil && !errors.Is(err, ErrNoDataStatus) {
return err
return errors.WithStack(err)
}
startWalIndex := 0
@ -184,7 +184,7 @@ func (d *DataManager) writeDataSnapshot(ctx context.Context, wals []*WalData) er
wi, err := d.walIndex(ctx, wals)
if err != nil {
return err
return errors.WithStack(err)
}
for _, dataType := range d.dataTypes {
@ -194,14 +194,14 @@ func (d *DataManager) writeDataSnapshot(ctx context.Context, wals []*WalData) er
}
dataStatusFiles, err := d.writeDataType(ctx, wi, dataType, dataSequence, curDataStatusFiles)
if err != nil {
return err
return errors.WithStack(err)
}
dataStatus.Files[dataType] = dataStatusFiles
}
dataStatusj, err := json.Marshal(dataStatus)
if err != nil {
return err
return errors.WithStack(err)
}
if err := d.ost.WriteObject(d.dataStatusPath(dataSequence), bytes.NewReader(dataStatusj), int64(len(dataStatusj)), true); err != nil {
return fromOSTError(err)
@ -212,7 +212,7 @@ func (d *DataManager) writeDataSnapshot(ctx context.Context, wals []*WalData) er
func (d *DataManager) writeDataFile(ctx context.Context, buf *bytes.Buffer, size int64, dataFileIndex *DataFileIndex, dataFileID, dataType string) error {
if buf.Len() == 0 {
return fmt.Errorf("empty data entries")
return errors.Errorf("empty data entries")
}
if err := d.ost.WriteObject(d.DataFilePath(dataType, dataFileID), buf, size, true); err != nil {
@ -221,7 +221,7 @@ func (d *DataManager) writeDataFile(ctx context.Context, buf *bytes.Buffer, size
dataFileIndexj, err := json.Marshal(dataFileIndex)
if err != nil {
return err
return errors.WithStack(err)
}
if err := d.ost.WriteObject(d.DataFileIndexPath(dataType, dataFileID), bytes.NewReader(dataFileIndexj), int64(len(dataFileIndexj)), true); err != nil {
return fromOSTError(err)
@ -354,7 +354,7 @@ func (d *DataManager) writeDataType(ctx context.Context, wi walIndex, dataType s
}
if err != nil {
oldDataf.Close()
return nil, err
return nil, errors.WithStack(err)
}
dataEntries = append(dataEntries, de)
@ -434,10 +434,10 @@ func (d *DataManager) writeDataType(ctx context.Context, wi walIndex, dataType s
lastEntryID = de.ID
dataEntryj, err := json.Marshal(de)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if _, err := buf.Write(dataEntryj); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
dataFileIndex.Index[de.ID] = pos - lastSplitPos
prevPos := pos
@ -470,7 +470,7 @@ func (d *DataManager) writeDataType(ctx context.Context, wi walIndex, dataType s
for i, sp := range splitPoints {
curDataFileID := d.dataFileID(dataSequence, uuid.Must(uuid.NewV4()).String())
if err := d.writeDataFile(ctx, &buf, sp.pos-curPos, dataFileIndexes[i], curDataFileID, dataType); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
// insert new dataStatusFile
dataStatusFiles = append(dataStatusFiles, &DataStatusFile{
@ -492,7 +492,7 @@ func (d *DataManager) writeDataType(ctx context.Context, wi walIndex, dataType s
func (d *DataManager) Read(dataType, id string) (io.Reader, error) {
curDataStatus, err := d.GetLastDataStatus()
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
curFiles := curDataStatus.Files
@ -519,7 +519,7 @@ func (d *DataManager) Read(dataType, id string) (io.Reader, error) {
err = dec.Decode(&dataFileIndex)
if err != nil {
dataFileIndexf.Close()
return nil, err
return nil, errors.WithStack(err)
}
dataFileIndexf.Close()
@ -534,13 +534,13 @@ func (d *DataManager) Read(dataType, id string) (io.Reader, error) {
}
if _, err := dataf.Seek(int64(pos), io.SeekStart); err != nil {
dataf.Close()
return nil, err
return nil, errors.WithStack(err)
}
var de *DataEntry
dec = json.NewDecoder(dataf)
if err := dec.Decode(&de); err != nil {
dataf.Close()
return nil, err
return nil, errors.WithStack(err)
}
dataf.Close()
@ -640,7 +640,7 @@ func (d *DataManager) GetDataStatus(dataSequence *sequence.Sequence) (*DataStatu
func (d *DataManager) GetFirstDataStatusSequence() (*sequence.Sequence, error) {
dataStatusSequences, err := d.GetFirstDataStatusSequences(1)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return dataStatusSequences[0], nil
@ -649,7 +649,7 @@ func (d *DataManager) GetFirstDataStatusSequence() (*sequence.Sequence, error) {
func (d *DataManager) GetLastDataStatusSequence() (*sequence.Sequence, error) {
dataStatusSequences, err := d.GetLastDataStatusSequences(1)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return dataStatusSequences[0], nil
@ -658,7 +658,7 @@ func (d *DataManager) GetLastDataStatusSequence() (*sequence.Sequence, error) {
func (d *DataManager) GetFirstDataStatus() (*DataStatus, error) {
dataStatusSequence, err := d.GetFirstDataStatusSequence()
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return d.GetDataStatus(dataStatusSequence)
@ -667,7 +667,7 @@ func (d *DataManager) GetFirstDataStatus() (*DataStatus, error) {
func (d *DataManager) GetLastDataStatus() (*DataStatus, error) {
dataStatusSequence, err := d.GetLastDataStatusSequence()
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return d.GetDataStatus(dataStatusSequence)
@ -675,12 +675,12 @@ func (d *DataManager) GetLastDataStatus() (*DataStatus, error) {
func (d *DataManager) Export(ctx context.Context, w io.Writer) error {
if err := d.checkpoint(ctx, true); err != nil {
return err
return errors.WithStack(err)
}
curDataStatus, err := d.GetLastDataStatus()
if err != nil {
return err
return errors.WithStack(err)
}
for _, dataType := range d.dataTypes {
@ -695,7 +695,7 @@ func (d *DataManager) Export(ctx context.Context, w io.Writer) error {
}
if _, err := io.Copy(w, dataf); err != nil {
dataf.Close()
return err
return errors.WithStack(err)
}
dataf.Close()
@ -708,7 +708,7 @@ func (d *DataManager) Export(ctx context.Context, w io.Writer) error {
func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
// delete contents in etcd
if err := d.deleteEtcd(ctx); err != nil {
return err
return errors.WithStack(err)
}
// we require all entries of the same datatypes grouped together
@ -717,7 +717,7 @@ func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
// create a new sequence, we assume that it'll be greater than previous data sequences
dataSequence, err := sequence.IncSequence(ctx, d.e, etcdCheckpointSeqKey)
if err != nil {
return err
return errors.WithStack(err)
}
dataStatus := &DataStatus{
@ -745,7 +745,7 @@ func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
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
return errors.WithStack(err)
}
dataStatusFiles = append(dataStatusFiles, &DataStatusFile{
@ -779,7 +779,7 @@ func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
if mustWrite {
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
return errors.WithStack(err)
}
dataStatusFiles = append(dataStatusFiles, &DataStatusFile{
@ -810,10 +810,10 @@ func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
dataEntryj, err := json.Marshal(de)
if err != nil {
return err
return errors.WithStack(err)
}
if _, err := buf.Write(dataEntryj); err != nil {
return err
return errors.WithStack(err)
}
dataFileIndex.Index[de.ID] = pos
pos += int64(len(dataEntryj))
@ -821,7 +821,7 @@ func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
dataStatusj, err := json.Marshal(dataStatus)
if err != nil {
return err
return errors.WithStack(err)
}
if err := d.ost.WriteObject(d.dataStatusPath(dataSequence), bytes.NewReader(dataStatusj), int64(len(dataStatusj)), true); err != nil {
return fromOSTError(err)
@ -829,7 +829,7 @@ func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
// initialize etcd providing the specific datastatus
if err := d.InitEtcd(ctx, dataStatus); err != nil {
return err
return errors.WithStack(err)
}
return nil
@ -838,7 +838,7 @@ func (d *DataManager) Import(ctx context.Context, r io.Reader) error {
func (d *DataManager) CleanOldCheckpoints(ctx context.Context) error {
dataStatusSequences, err := d.GetLastDataStatusSequences(dataStatusToKeep)
if err != nil {
return err
return errors.WithStack(err)
}
return d.cleanOldCheckpoints(ctx, dataStatusSequences)
@ -894,7 +894,7 @@ func (d *DataManager) cleanOldCheckpoints(ctx context.Context, dataStatusSequenc
for _, dataStatusSequence := range dataStatusSequences {
dataStatus, err := d.GetDataStatus(dataStatusSequence)
if err != nil {
return err
return errors.WithStack(err)
}
for dataType := range dataStatus.Files {

View File

@ -21,12 +21,12 @@ import (
"strings"
"time"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/etcd"
"agola.io/agola/internal/objectstorage"
"agola.io/agola/internal/sequence"
"github.com/rs/zerolog"
errors "golang.org/x/xerrors"
)
// TODO(sgotti) handle etcd unwanted changes:
@ -252,7 +252,7 @@ func (d *DataManager) deleteEtcd(ctx context.Context) error {
}
for _, prefix := range prefixes {
if err := d.e.DeletePrefix(ctx, prefix); err != nil {
return err
return errors.WithStack(err)
}
}

View File

@ -29,12 +29,12 @@ import (
"testing"
"time"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/objectstorage"
"agola.io/agola/internal/testutil"
"github.com/google/go-cmp/cmp"
"github.com/rs/zerolog"
errors "golang.org/x/xerrors"
)
func setupEtcd(t *testing.T, log zerolog.Logger, dir string) *testutil.TestEmbeddedEtcd {
@ -612,7 +612,7 @@ func doAndCheckCheckpoint(t *testing.T, ctx context.Context, dm *DataManager, ac
// populate with a wal
_, err := dm.WriteWal(ctx, actionGroup, nil)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
}
@ -621,11 +621,11 @@ func doAndCheckCheckpoint(t *testing.T, ctx context.Context, dm *DataManager, ac
// do a checkpoint
if err := dm.checkpoint(ctx, true); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if err := checkDataFiles(ctx, t, dm, expectedEntries); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return expectedEntries, nil
@ -635,7 +635,7 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
// read the data file
curDataStatus, err := dm.GetLastDataStatus()
if err != nil {
return err
return errors.WithStack(err)
}
allEntriesMap := map[string]*DataEntry{}
@ -645,14 +645,14 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
for i, file := range curDataStatus.Files[dataType] {
dataFileIndexf, err := dm.ost.ReadObject(dm.DataFileIndexPath(dataType, file.ID))
if err != nil {
return err
return errors.WithStack(err)
}
var dataFileIndex *DataFileIndex
dec := json.NewDecoder(dataFileIndexf)
err = dec.Decode(&dataFileIndex)
if err != nil {
dataFileIndexf.Close()
return err
return errors.WithStack(err)
}
dataFileIndexf.Close()
@ -660,7 +660,7 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
dataEntries := []*DataEntry{}
dataf, err := dm.ost.ReadObject(dm.DataFilePath(dataType, file.ID))
if err != nil {
return err
return errors.WithStack(err)
}
dec = json.NewDecoder(dataf)
var prevEntryID string
@ -674,15 +674,15 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
}
if err != nil {
dataf.Close()
return err
return errors.WithStack(err)
}
// check that there are no duplicate entries
if _, ok := allEntriesMap[de.ID]; ok {
return fmt.Errorf("duplicate entry id: %s", de.ID)
return errors.Errorf("duplicate entry id: %s", de.ID)
}
// check that the entries are in order
if de.ID < prevEntryID {
return fmt.Errorf("previous entry id: %s greater than entry id: %s", prevEntryID, de.ID)
return errors.Errorf("previous entry id: %s greater than entry id: %s", prevEntryID, de.ID)
}
dataEntriesMap[de.ID] = de
@ -693,7 +693,7 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
// check that the index matches the entries
if len(dataFileIndex.Index) != len(dataEntriesMap) {
return fmt.Errorf("index entries: %d different than data entries: %d", len(dataFileIndex.Index), len(dataEntriesMap))
return errors.Errorf("index entries: %d different than data entries: %d", len(dataFileIndex.Index), len(dataEntriesMap))
}
indexIDs := make([]string, len(dataFileIndex.Index))
entriesIDs := make([]string, len(dataEntriesMap))
@ -706,19 +706,19 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
sort.Strings(indexIDs)
sort.Strings(entriesIDs)
if !reflect.DeepEqual(indexIDs, entriesIDs) {
return fmt.Errorf("index entries ids don't match data entries ids: index: %v, data: %v", indexIDs, entriesIDs)
return errors.Errorf("index entries ids don't match data entries ids: index: %v, data: %v", indexIDs, entriesIDs)
}
if file.LastEntryID != dataEntries[len(dataEntries)-1].ID {
return fmt.Errorf("lastEntryID for datafile %d: %s is different than real last entry id: %s", i, file.LastEntryID, dataEntries[len(dataEntries)-1].ID)
return errors.Errorf("lastEntryID for datafile %d: %s is different than real last entry id: %s", i, file.LastEntryID, dataEntries[len(dataEntries)-1].ID)
}
// check that all the files are in order
if file.LastEntryID == prevLastEntryID {
return fmt.Errorf("lastEntryID for datafile %d is equal than previous file lastEntryID: %s == %s", i, file.LastEntryID, prevLastEntryID)
return errors.Errorf("lastEntryID for datafile %d is equal than previous file lastEntryID: %s == %s", i, file.LastEntryID, prevLastEntryID)
}
if file.LastEntryID < prevLastEntryID {
return fmt.Errorf("lastEntryID for datafile %d is less than previous file lastEntryID: %s < %s", i, file.LastEntryID, prevLastEntryID)
return errors.Errorf("lastEntryID for datafile %d is less than previous file lastEntryID: %s < %s", i, file.LastEntryID, prevLastEntryID)
}
prevLastEntryID = file.LastEntryID
}
@ -726,10 +726,10 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
// check that the number of entries is right
if len(allEntriesMap) != len(expectedEntriesMap) {
return fmt.Errorf("expected %d total entries, got %d", len(expectedEntriesMap), len(allEntriesMap))
return errors.Errorf("expected %d total entries, got %d", len(expectedEntriesMap), len(allEntriesMap))
}
if !reflect.DeepEqual(expectedEntriesMap, allEntriesMap) {
return fmt.Errorf("expected entries don't match current entries")
return errors.Errorf("expected entries don't match current entries")
}
return nil

View File

@ -25,6 +25,7 @@ import (
"strings"
"time"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/etcd"
"agola.io/agola/internal/objectstorage"
"agola.io/agola/internal/sequence"
@ -34,7 +35,6 @@ import (
"go.etcd.io/etcd/clientv3/concurrency"
etcdclientv3rpc "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
"go.etcd.io/etcd/mvcc/mvccpb"
errors "golang.org/x/xerrors"
)
type ActionType string
@ -127,7 +127,7 @@ func (d *DataManager) ReadObject(dataType, id string, cgNames []string) (io.Read
}
f, err := d.Read(dataType, id)
return ioutil.NopCloser(f), cgt, err
return ioutil.NopCloser(f), cgt, errors.WithStack(err)
}
func (d *DataManager) HasOSTWal(walseq string) (bool, error) {
@ -150,7 +150,7 @@ func (d *DataManager) ReadWal(walseq string) (*WalHeader, error) {
dec := json.NewDecoder(walFilef)
var header *WalHeader
if err = dec.Decode(&header); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return header, nil
@ -260,7 +260,7 @@ func (d *DataManager) ListEtcdChangeGroups(ctx context.Context, revision int64)
changeGroupsRevisions := changeGroupsRevisions{}
resp, err := d.e.List(ctx, etcdChangeGroupsDir, "", revision)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
for _, kv := range resp.Kvs {
changegroupID := path.Base(string(kv.Key))
@ -277,7 +277,7 @@ func (d *DataManager) FirstAvailableWalData(ctx context.Context) (*WalData, int6
// list waldata and just get the first if available
listResp, err := d.e.ListPaged(ctx, etcdWalsDir, 0, 1, nil)
if err != nil {
return nil, 0, err
return nil, 0, errors.WithStack(err)
}
resp := listResp.Resp
revision := resp.Header.Revision
@ -288,7 +288,7 @@ func (d *DataManager) FirstAvailableWalData(ctx context.Context) (*WalData, int6
var walData *WalData
if err := json.Unmarshal(resp.Kvs[0].Value, &walData); err != nil {
return nil, 0, err
return nil, 0, errors.WithStack(err)
}
return walData, revision, nil
@ -297,7 +297,7 @@ 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 && !errors.Is(err, etcd.ErrKeyNotFound) {
return "", 0, err
return "", 0, errors.WithStack(err)
}
if errors.Is(err, etcd.ErrKeyNotFound) {
return "", 0, errors.Errorf("no last committedstorage wal on etcd")
@ -424,17 +424,17 @@ func (d *DataManager) WriteWalAdditionalOps(ctx context.Context, actions []*Acti
walSequence, err := sequence.IncSequence(ctx, d.e, etcdWalSeqKey)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
resp, err := d.e.Get(ctx, etcdWalsDataKey, 0)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
var walsData WalsData
if err := json.Unmarshal(resp.Kvs[0].Value, &walsData); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
walsData.Revision = resp.Kvs[0].ModRevision
@ -446,10 +446,10 @@ func (d *DataManager) WriteWalAdditionalOps(ctx context.Context, actions []*Acti
for _, action := range actions {
actionj, err := json.Marshal(action)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if _, err := buf.Write(actionj); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
}
if err := d.ost.WriteObject(walDataFilePath, bytes.NewReader(buf.Bytes()), int64(buf.Len()), true); err != nil {
@ -468,11 +468,11 @@ func (d *DataManager) WriteWalAdditionalOps(ctx context.Context, actions []*Acti
walsDataj, err := json.Marshal(walsData)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
walDataj, err := json.Marshal(walData)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if cmp == nil {
@ -512,7 +512,7 @@ func (d *DataManager) WriteWalAdditionalOps(ctx context.Context, actions []*Acti
txn := d.e.Client().Txn(ctx).If(cmp...).Then(then...).Else(getWalsData, getWal)
tresp, err := txn.Commit()
if err != nil {
return nil, etcd.FromEtcdError(err)
return nil, errors.WithStack(etcd.FromEtcdError(err))
}
if !tresp.Succeeded {
walsDataRev := tresp.Responses[0].GetResponseRange().Kvs[0].ModRevision
@ -559,7 +559,7 @@ func (d *DataManager) syncLoop(ctx context.Context) {
func (d *DataManager) sync(ctx context.Context) error {
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
if err != nil {
return err
return errors.WithStack(err)
}
defer session.Close()
@ -569,18 +569,18 @@ func (d *DataManager) sync(ctx context.Context) error {
if errors.Is(err, etcd.ErrLocked) {
return nil
}
return err
return errors.WithStack(err)
}
defer func() { _ = m.Unlock(ctx) }()
resp, err := d.e.List(ctx, etcdWalsDir+"/", "", 0)
if err != nil {
return err
return errors.WithStack(err)
}
for _, kv := range resp.Kvs {
var walData WalData
if err := json.Unmarshal(kv.Value, &walData); err != nil {
return err
return errors.WithStack(err)
}
// wals must be committed and checkpointed in order.
// TODO(sgotti) this could be optimized by parallelizing writes of wals that don't have common change groups
@ -594,7 +594,7 @@ func (d *DataManager) sync(ctx context.Context) error {
}
headerj, err := json.Marshal(header)
if err != nil {
return err
return errors.WithStack(err)
}
walFileCommittedPath := walFilePath + ".committed"
@ -606,7 +606,7 @@ func (d *DataManager) sync(ctx context.Context) error {
walData.WalStatus = WalStatusCommittedStorage
walDataj, err := json.Marshal(walData)
if err != nil {
return err
return errors.WithStack(err)
}
cmp := []etcdclientv3.Cmp{}
@ -619,7 +619,7 @@ func (d *DataManager) sync(ctx context.Context) error {
txn := d.e.Client().Txn(ctx).If(cmp...).Then(then...)
tresp, err := txn.Commit()
if err != nil {
return etcd.FromEtcdError(err)
return errors.WithStack(etcd.FromEtcdError(err))
}
if !tresp.Succeeded {
return errors.Errorf("failed to write committedstorage wal: concurrent update")
@ -648,7 +648,7 @@ func (d *DataManager) checkpointLoop(ctx context.Context) {
func (d *DataManager) checkpoint(ctx context.Context, force bool) error {
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
if err != nil {
return err
return errors.WithStack(err)
}
defer session.Close()
@ -658,19 +658,19 @@ func (d *DataManager) checkpoint(ctx context.Context, force bool) error {
if errors.Is(err, etcd.ErrLocked) {
return nil
}
return err
return errors.WithStack(err)
}
defer func() { _ = m.Unlock(ctx) }()
resp, err := d.e.List(ctx, etcdWalsDir+"/", "", 0)
if err != nil {
return err
return errors.WithStack(err)
}
walsData := []*WalData{}
for _, kv := range resp.Kvs {
var walData *WalData
if err := json.Unmarshal(kv.Value, &walData); err != nil {
return err
return errors.WithStack(err)
}
walData.Revision = kv.ModRevision
@ -692,7 +692,7 @@ func (d *DataManager) checkpoint(ctx context.Context, force bool) error {
}
if err := d.writeDataSnapshot(ctx, walsData); err != nil {
return errors.Errorf("checkpoint function error: %w", err)
return errors.Wrapf(err, "checkpoint function error")
}
for _, walData := range walsData {
@ -700,11 +700,11 @@ func (d *DataManager) checkpoint(ctx context.Context, force bool) error {
walData.WalStatus = WalStatusCheckpointed
walDataj, err := json.Marshal(walData)
if err != nil {
return err
return errors.WithStack(err)
}
walKey := etcdWalKey(walData.WalSequence)
if _, err := d.e.AtomicPut(ctx, walKey, walDataj, walData.Revision, nil); err != nil {
return err
return errors.WithStack(err)
}
}
@ -730,7 +730,7 @@ func (d *DataManager) checkpointCleanLoop(ctx context.Context) {
func (d *DataManager) checkpointClean(ctx context.Context) error {
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
if err != nil {
return err
return errors.WithStack(err)
}
defer session.Close()
@ -740,12 +740,12 @@ func (d *DataManager) checkpointClean(ctx context.Context) error {
if errors.Is(err, etcd.ErrLocked) {
return nil
}
return err
return errors.WithStack(err)
}
defer func() { _ = m.Unlock(ctx) }()
if err := d.CleanOldCheckpoints(ctx); err != nil {
return err
return errors.WithStack(err)
}
return nil
@ -773,7 +773,7 @@ func (d *DataManager) etcdWalCleanerLoop(ctx context.Context) {
func (d *DataManager) etcdWalCleaner(ctx context.Context) error {
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
if err != nil {
return err
return errors.WithStack(err)
}
defer session.Close()
@ -783,13 +783,13 @@ func (d *DataManager) etcdWalCleaner(ctx context.Context) error {
if errors.Is(err, etcd.ErrLocked) {
return nil
}
return err
return errors.WithStack(err)
}
defer func() { _ = m.Unlock(ctx) }()
resp, err := d.e.List(ctx, etcdWalsDir+"/", "", 0)
if err != nil {
return err
return errors.WithStack(err)
}
if len(resp.Kvs) <= d.etcdWalsKeepNum {
return nil
@ -799,7 +799,7 @@ func (d *DataManager) etcdWalCleaner(ctx context.Context) error {
for _, kv := range resp.Kvs {
var walData WalData
if err := json.Unmarshal(kv.Value, &walData); err != nil {
return err
return errors.WithStack(err)
}
if walData.WalStatus != WalStatusCheckpointed {
break
@ -814,7 +814,7 @@ func (d *DataManager) etcdWalCleaner(ctx context.Context) error {
// arrive to a differnt S3 server that is not yet in sync?
d.log.Info().Msgf("removing wal %q from etcd", walData.WalSequence)
if _, err := d.e.AtomicDelete(ctx, string(kv.Key), kv.ModRevision); err != nil {
return err
return errors.WithStack(err)
}
removeCount--
@ -846,7 +846,7 @@ func (d *DataManager) storageWalCleanerLoop(ctx context.Context) {
func (d *DataManager) storageWalCleaner(ctx context.Context) error {
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
if err != nil {
return err
return errors.WithStack(err)
}
defer session.Close()
@ -856,13 +856,13 @@ func (d *DataManager) storageWalCleaner(ctx context.Context) error {
if errors.Is(err, etcd.ErrLocked) {
return nil
}
return err
return errors.WithStack(err)
}
defer func() { _ = m.Unlock(ctx) }()
firstDataStatus, err := d.GetFirstDataStatus()
if err != nil {
return err
return errors.WithStack(err)
}
firstWalSequence := firstDataStatus.WalSequence
@ -870,14 +870,14 @@ func (d *DataManager) storageWalCleaner(ctx context.Context) error {
// it's lesser than the first data status wal sequence
resp, err := d.e.List(ctx, etcdWalsDir+"/", "", 0)
if err != nil {
return err
return errors.WithStack(err)
}
if len(resp.Kvs) == 0 {
return errors.Errorf("no wals in etcd")
}
var walData WalData
if err := json.Unmarshal(resp.Kvs[0].Value, &walData); err != nil {
return err
return errors.WithStack(err)
}
if walData.WalSequence < firstWalSequence {
firstWalSequence = walData.WalSequence
@ -902,7 +902,7 @@ func (d *DataManager) storageWalCleaner(ctx context.Context) error {
header, err := d.ReadWal(walSequence)
if err != nil {
return err
return errors.WithStack(err)
}
// first remove wal data file
@ -956,7 +956,7 @@ func (d *DataManager) compactChangeGroupsLoop(ctx context.Context) {
func (d *DataManager) compactChangeGroups(ctx context.Context) error {
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
if err != nil {
return err
return errors.WithStack(err)
}
defer session.Close()
@ -966,13 +966,13 @@ func (d *DataManager) compactChangeGroups(ctx context.Context) error {
if errors.Is(err, etcd.ErrLocked) {
return nil
}
return err
return errors.WithStack(err)
}
defer func() { _ = m.Unlock(ctx) }()
resp, err := d.e.Client().Get(ctx, etcdChangeGroupMinRevisionKey)
if err != nil {
return err
return errors.WithStack(err)
}
if len(resp.Kvs) == 0 {
@ -986,7 +986,8 @@ func (d *DataManager) compactChangeGroups(ctx context.Context) error {
txn := d.e.Client().Txn(ctx).If(cmp).Then(then)
tresp, err := txn.Commit()
if err != nil {
return etcd.FromEtcdError(err)
return errors.WithStack(etcd.FromEtcdError(err))
}
if !tresp.Succeeded {
return errors.Errorf("failed to update change group min revision key due to concurrent update")
@ -997,7 +998,7 @@ func (d *DataManager) compactChangeGroups(ctx context.Context) error {
// then remove all the groups keys with modrevision < minrevision
resp, err = d.e.List(ctx, etcdChangeGroupsDir, "", 0)
if err != nil {
return err
return errors.WithStack(err)
}
for _, kv := range resp.Kvs {
if kv.ModRevision < revision-etcdChangeGroupMinRevisionRange {
@ -1006,7 +1007,7 @@ func (d *DataManager) compactChangeGroups(ctx context.Context) error {
txn := d.e.Client().Txn(ctx).If(cmp).Then(then)
tresp, err := txn.Commit()
if err != nil {
return etcd.FromEtcdError(err)
return errors.WithStack(etcd.FromEtcdError(err))
}
if !tresp.Succeeded {
d.log.Err(err).Msgf("failed to update change group min revision key due to concurrent update")
@ -1040,7 +1041,7 @@ func (d *DataManager) etcdPingerLoop(ctx context.Context) {
func (d *DataManager) etcdPinger(ctx context.Context) error {
if _, err := d.e.Put(ctx, etcdPingKey, []byte{}, nil); err != nil {
return err
return errors.WithStack(err)
}
return nil
}
@ -1055,7 +1056,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
var header *WalHeader
if err = dec.Decode(&header); err != nil && !errors.Is(err, io.EOF) {
walFile.Close()
return err
return errors.WithStack(err)
}
walFile.Close()
@ -1073,7 +1074,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
}
walDataj, err := json.Marshal(walData)
if err != nil {
return err
return errors.WithStack(err)
}
cmp := []etcdclientv3.Cmp{}
@ -1084,7 +1085,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
txn := d.e.Client().Txn(ctx).If(cmp...).Then(then...)
tresp, err := txn.Commit()
if err != nil {
return etcd.FromEtcdError(err)
return errors.WithStack(etcd.FromEtcdError(err))
}
if !tresp.Succeeded {
return errors.Errorf("failed to sync etcd: wal %q already written", wal.WalSequence)
@ -1094,7 +1095,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
session, err := concurrency.NewSession(d.e.Client(), concurrency.WithTTL(5), concurrency.WithContext(ctx))
if err != nil {
return err
return errors.WithStack(err)
}
defer session.Close()
@ -1104,7 +1105,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
if errors.Is(err, etcd.ErrLocked) {
return nil
}
return err
return errors.WithStack(err)
}
defer func() { _ = m.Unlock(ctx) }()
@ -1113,7 +1114,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
_, err = d.e.Get(ctx, etcdWalsDataKey, 0)
if err != nil {
if !errors.Is(err, etcd.ErrKeyNotFound) {
return err
return errors.WithStack(err)
}
mustInit = true
}
@ -1123,7 +1124,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
// delete all wals from etcd
if err := d.deleteEtcd(ctx); err != nil {
return err
return errors.WithStack(err)
}
}
@ -1135,7 +1136,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
then = append(then, etcdclientv3.OpPut(etcdChangeGroupMinRevisionKey, ""))
txn := d.e.Client().Txn(ctx).If(cmp...).Then(then...)
if _, err := txn.Commit(); err != nil {
return etcd.FromEtcdError(err)
return errors.WithStack(etcd.FromEtcdError(err))
}
if !mustInit {
@ -1150,7 +1151,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
} else {
dataStatus, err = d.GetLastDataStatus()
if err != nil && !errors.Is(err, ErrNoDataStatus) {
return err
return errors.WithStack(err)
}
// set the first wal to import in etcd if there's a snapshot. In this way we'll
// ignore older wals (or wals left after an import)
@ -1172,7 +1173,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
}
d.log.Debug().Msgf("wal: %s", wal)
if wal.Err != nil {
return wal.Err
return errors.WithStack(wal.Err)
}
if wal.WalSequence < firstWal {
@ -1182,7 +1183,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
lastCommittedStorageWalSequence = wal.WalSequence
if err := writeWal(wal, previousWalSequence); err != nil {
return err
return errors.WithStack(err)
}
previousWalSequence = wal.WalSequence
wroteWals++
@ -1192,7 +1193,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
// insert an empty wal and make it already committedstorage
walSequence, err := sequence.IncSequence(ctx, d.e, etcdWalSeqKey)
if err != nil {
return err
return errors.WithStack(err)
}
walDataFileID := uuid.Must(uuid.NewV4()).String()
@ -1212,7 +1213,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
}
headerj, err := json.Marshal(header)
if err != nil {
return err
return errors.WithStack(err)
}
walFileCommittedPath := walFilePath + ".committed"
if err := d.ost.WriteObject(walFileCommittedPath, bytes.NewReader(headerj), int64(len(headerj)), true); err != nil {
@ -1234,12 +1235,12 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
walDataj, err := json.Marshal(walData)
if err != nil {
return err
return errors.WithStack(err)
}
walsDataj, err := json.Marshal(walsData)
if err != nil {
return err
return errors.WithStack(err)
}
// save walsdata and lastcommittedstoragewalseq only after writing all the
@ -1256,7 +1257,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
txn = d.e.Client().Txn(ctx).If(cmp...).Then(then...)
tresp, err := txn.Commit()
if err != nil {
return etcd.FromEtcdError(err)
return errors.WithStack(etcd.FromEtcdError(err))
}
if !tresp.Succeeded {
return errors.Errorf("failed to sync etcd: walsdata already written")
@ -1264,7 +1265,7 @@ func (d *DataManager) InitEtcd(ctx context.Context, dataStatus *DataStatus) erro
// force a checkpoint
if err := d.checkpoint(ctx, true); err != nil {
return err
return errors.WithStack(err)
}
return nil

View File

@ -18,8 +18,8 @@ import (
"context"
"database/sql"
"agola.io/agola/internal/errors"
sq "github.com/Masterminds/squirrel"
errors "golang.org/x/xerrors"
)
const dbVersionTableDDLTmpl = `
@ -33,22 +33,22 @@ func (db *DB) Create(ctx context.Context, stmts []string) error {
err := db.Do(ctx, func(tx *Tx) error {
if _, err := tx.Exec(dbVersionTableDDLTmpl); err != nil {
return errors.Errorf("failed to create dbversion table: %w", err)
return errors.Wrapf(err, "failed to create dbversion table")
}
return nil
})
if err != nil {
return err
return errors.WithStack(err)
}
err = db.Do(ctx, func(tx *Tx) error {
var version sql.NullInt64
q, args, err := sb.Select("max(version)").From("dbversion").ToSql()
if err != nil {
return err
return errors.WithStack(err)
}
if err := tx.QueryRow(q, args...).Scan(&version); err != nil {
return errors.Errorf("cannot get current db version: %w", err)
return errors.Wrapf(err, "cannot get current db version")
}
if version.Valid {
return nil
@ -56,18 +56,18 @@ func (db *DB) Create(ctx context.Context, stmts []string) error {
for _, stmt := range stmts {
if _, err := tx.Exec(stmt); err != nil {
return errors.Errorf("creation failed: %w", err)
return errors.Wrapf(err, "creation failed")
}
}
q, args, err = sb.Insert("dbversion").Columns("version", "time").Values(dbVersion, "now()").ToSql()
if err != nil {
return err
return errors.WithStack(err)
}
if _, err := tx.Exec(q, args...); err != nil {
return errors.Errorf("failed to update dbversion table: %w", err)
return errors.Wrapf(err, "failed to update dbversion table")
}
return nil
})
return err
return errors.WithStack(err)
}

View File

@ -20,8 +20,8 @@ import (
"regexp"
"time"
"agola.io/agola/internal/errors"
"github.com/mattn/go-sqlite3"
errors "golang.org/x/xerrors"
)
type Type string
@ -128,7 +128,7 @@ func NewDB(dbType Type, dbConnString string) (*DB, error) {
sqldb, err := sql.Open(driverName, dbConnString)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
db := &DB{
@ -151,11 +151,12 @@ type Tx struct {
}
func (db *DB) Close() error {
return db.db.Close()
return errors.WithStack(db.db.Close())
}
func (db *DB) Conn(ctx context.Context) (*sql.Conn, error) {
return db.db.Conn(ctx)
c, err := db.db.Conn(ctx)
return c, errors.WithStack(err)
}
func (db *DB) NewUnstartedTx() *Tx {
@ -167,7 +168,7 @@ func (db *DB) NewUnstartedTx() *Tx {
func (db *DB) NewTx(ctx context.Context) (*Tx, error) {
tx := db.NewUnstartedTx()
if err := tx.Start(ctx); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return tx, nil
@ -188,14 +189,14 @@ func (db *DB) Do(ctx context.Context, f func(tx *Tx) error) error {
}
}
}
return err
return errors.WithStack(err)
}
}
func (db *DB) do(ctx context.Context, f func(tx *Tx) error) error {
tx, err := db.NewTx(ctx)
if err != nil {
return err
return errors.WithStack(err)
}
defer func() {
if p := recover(); p != nil {
@ -205,7 +206,7 @@ func (db *DB) do(ctx context.Context, f func(tx *Tx) error) error {
}()
if err = f(tx); err != nil {
_ = tx.Rollback()
return err
return errors.WithStack(err)
}
return tx.Commit()
}
@ -213,12 +214,12 @@ func (db *DB) do(ctx context.Context, f func(tx *Tx) error) error {
func (tx *Tx) Start(ctx context.Context) error {
wtx, err := tx.db.db.Begin()
if err != nil {
return err
return errors.WithStack(err)
}
switch tx.db.data.t {
case Postgres:
if _, err := wtx.Exec("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"); err != nil {
return err
return errors.WithStack(err)
}
}
tx.tx = wtx
@ -230,26 +231,26 @@ func (tx *Tx) Commit() error {
if tx.tx == nil {
return nil
}
return tx.tx.Commit()
return errors.WithStack(tx.tx.Commit())
}
func (tx *Tx) Rollback() error {
if tx.tx == nil {
return nil
}
return tx.tx.Rollback()
return errors.WithStack(tx.tx.Rollback())
}
func (tx *Tx) Exec(query string, args ...interface{}) (sql.Result, error) {
query = tx.db.data.translate(query)
r, err := tx.tx.ExecContext(tx.ctx, query, tx.db.data.translateArgs(args)...)
return r, err
return r, errors.WithStack(err)
}
func (tx *Tx) Query(query string, args ...interface{}) (*sql.Rows, error) {
query = tx.db.data.translate(query)
r, err := tx.tx.QueryContext(tx.ctx, query, tx.db.data.translateArgs(args)...)
return r, err
return r, errors.WithStack(err)
}
func (tx *Tx) QueryRow(query string, args ...interface{}) *sql.Row {
@ -262,13 +263,14 @@ func (tx *Tx) CurTime() (time.Time, error) {
case Sqlite3:
var timestring string
if err := tx.QueryRow("select now()").Scan(&timestring); err != nil {
return time.Time{}, err
return time.Time{}, errors.WithStack(err)
}
return time.ParseInLocation("2006-01-02 15:04:05.999999999", timestring, time.UTC)
t, err := time.ParseInLocation("2006-01-02 15:04:05.999999999", timestring, time.UTC)
return t, errors.WithStack(err)
case Postgres:
var now time.Time
if err := tx.QueryRow("select now()").Scan(&now); err != nil {
return time.Time{}, err
return time.Time{}, errors.WithStack(err)
}
return now, nil
}

89
internal/errors/errors.go Normal file
View File

@ -0,0 +1,89 @@
package errors
import (
"fmt"
"io"
)
type werror struct {
cause error
msg string
*Stack
}
func (w *werror) Error() string {
if w.cause == nil {
return w.msg
}
if w.msg != "" {
return w.msg + ": " + w.cause.Error()
} else {
return w.cause.Error()
}
}
func (w *werror) Format(s fmt.State, verb rune) {
_, _ = io.WriteString(s, w.Error())
}
func (w *werror) Unwrap() error { return w.cause }
// New returns an error with the supplied message.
// New also records the stack trace at the point it was called.
func New(message string) error {
return &werror{
msg: message,
Stack: Callers(0),
}
}
// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
// Errorf also records the stack trace at the point it was called.
func Errorf(format string, args ...interface{}) error {
return &werror{
msg: fmt.Sprintf(format, args...),
Stack: Callers(0),
}
}
// WithStack annotates err with a stack trace at the point WithStack was called.
// If err is nil, WithStack returns nil.
func WithStack(err error) error {
if err == nil {
return nil
}
return &werror{
err,
"",
Callers(0),
}
}
// Wrap returns an error annotating err with a stack trace
// at the point Wrap is called, and the supplied message.
// If err is nil, Wrap returns nil.
func Wrap(err error, message string) error {
if err == nil {
return nil
}
return &werror{
err,
message,
Callers(0),
}
}
// Wrapf returns an error annotating err with a stack trace
// at the point Wrapf is called, and the format specifier.
// If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error {
if err == nil {
return nil
}
return &werror{
err,
fmt.Sprintf(format, args...),
Callers(0),
}
}

47
internal/errors/format.go Normal file
View File

@ -0,0 +1,47 @@
package errors
import (
"errors"
"fmt"
)
func PrintErrorDetails(err error) []string {
type stackTracer interface {
StackTrace() StackTrace
}
type errWithStack struct {
err error
msg string
stack StackTrace
}
var stackErrs []errWithStack
errCause := err
for errCause != nil {
stackErr := errWithStack{
err: errCause,
msg: errCause.Error(),
}
//nolint:errorlint
if s, ok := errCause.(stackTracer); ok {
stackErr.stack = s.StackTrace()
}
stackErrs = append(stackErrs, stackErr)
errCause = errors.Unwrap(errCause)
if err == nil {
break
}
}
var lines []string
for _, stackErr := range stackErrs {
if len(stackErr.stack) > 0 {
frame := stackErr.stack[0]
lines = append(lines, fmt.Sprintf("(%T) %+v: %s", stackErr.err, frame, stackErr.msg))
} else {
lines = append(lines, fmt.Sprintf("(%T) %s", stackErr.err, stackErr.msg))
}
}
return lines
}

38
internal/errors/go113.go Normal file
View File

@ -0,0 +1,38 @@
// +build go1.13
package errors
import (
stderrors "errors"
)
// Is reports whether any error in err's chain matches target.
//
// The chain consists of err itself followed by the sequence of errors obtained by
// repeatedly calling Unwrap.
//
// An error is considered to match a target if it is equal to that target or if
// it implements a method Is(error) bool such that Is(target) returns true.
func Is(err, target error) bool { return stderrors.Is(err, target) }
// As finds the first error in err's chain that matches target, and if so, sets
// target to that error value and returns true.
//
// The chain consists of err itself followed by the sequence of errors obtained by
// repeatedly calling Unwrap.
//
// An error matches target if the error's concrete value is assignable to the value
// pointed to by target, or if the error has a method As(interface{}) bool such that
// As(target) returns true. In the latter case, the As method is responsible for
// setting target.
//
// As will panic if target is not a non-nil pointer to either a type that implements
// error, or to any interface type. As returns false if err is nil.
func As(err error, target interface{}) bool { return stderrors.As(err, target) }
// Unwrap returns the result of calling the Unwrap method on err, if err's
// type contains an Unwrap method returning error.
// Otherwise, Unwrap returns nil.
func Unwrap(err error) error {
return stderrors.Unwrap(err)
}

181
internal/errors/stack.go Normal file
View File

@ -0,0 +1,181 @@
package errors
import (
"fmt"
"io"
"path"
"runtime"
"strconv"
"strings"
)
const (
defaultSkip = 3
)
// Frame represents a program counter inside a stack frame.
// For historical reasons if Frame is interpreted as a uintptr
// its value represents the program counter + 1.
type Frame uintptr
// pc returns the program counter for this frame;
// multiple frames may have the same PC value.
func (f Frame) pc() uintptr { return uintptr(f) - 1 }
// file returns the full path to the file that contains the
// function for this Frame's pc.
func (f Frame) file() string {
fn := runtime.FuncForPC(f.pc())
if fn == nil {
return "unknown"
}
file, _ := fn.FileLine(f.pc())
return file
}
// line returns the line number of source code of the
// function for this Frame's pc.
func (f Frame) line() int {
fn := runtime.FuncForPC(f.pc())
if fn == nil {
return 0
}
_, line := fn.FileLine(f.pc())
return line
}
// name returns the name of this function, if known.
func (f Frame) name() string {
fn := runtime.FuncForPC(f.pc())
if fn == nil {
return "unknown"
}
return fn.Name()
}
// Format formats the frame according to the fmt.Formatter interface.
//
// %s source file
// %d source line
// %n function name
// %v equivalent to %s:%d
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
// %+s function name and path of source file relative to the compile time
// GOPATH separated by \n\t (<funcname>\n\t<path>)
// %+v equivalent to %+s:%d
func (f Frame) Format(s fmt.State, verb rune) {
switch verb {
case 's':
switch {
case s.Flag('+'):
_, _ = io.WriteString(s, f.name())
_, _ = io.WriteString(s, "\n\t")
_, _ = io.WriteString(s, f.file())
default:
_, _ = io.WriteString(s, path.Base(f.file()))
}
case 'd':
_, _ = io.WriteString(s, strconv.Itoa(f.line()))
case 'n':
_, _ = io.WriteString(s, funcname(f.name()))
case 'v':
f.Format(s, 's')
_, _ = io.WriteString(s, ":")
f.Format(s, 'd')
}
}
// MarshalText formats a stacktrace Frame as a text string. The output is the
// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs.
func (f Frame) MarshalText() ([]byte, error) {
name := f.name()
if name == "unknown" {
return []byte(name), nil
}
return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil
}
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
type StackTrace []Frame
// Format formats the stack of Frames according to the fmt.Formatter interface.
//
// %s lists source files for each Frame in the stack
// %v lists the source file and line number for each Frame in the stack
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
// %+v Prints filename, function, and line number for each Frame in the stack.
func (st StackTrace) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
switch {
case s.Flag('+'):
for _, f := range st {
_, _ = io.WriteString(s, "\n")
f.Format(s, verb)
}
case s.Flag('#'):
fmt.Fprintf(s, "%#v", []Frame(st))
default:
st.formatSlice(s, verb)
}
case 's':
st.formatSlice(s, verb)
}
}
// formatSlice will format this StackTrace into the given buffer as a slice of
// Frame, only valid when called with '%s' or '%v'.
func (st StackTrace) formatSlice(s fmt.State, verb rune) {
_, _ = io.WriteString(s, "[")
for i, f := range st {
if i > 0 {
_, _ = io.WriteString(s, " ")
}
f.Format(s, verb)
}
_, _ = io.WriteString(s, "]")
}
// Stack represents a Stack of program counters.
type Stack []uintptr
func (s *Stack) Format(st fmt.State, verb rune) {
switch verb {
case 'v':
switch {
case st.Flag('+'):
for _, pc := range *s {
f := Frame(pc)
fmt.Fprintf(st, "\n%+v", f)
}
}
}
}
func (s *Stack) StackTrace() StackTrace {
f := make([]Frame, len(*s))
for i := 0; i < len(f); i++ {
f[i] = Frame((*s)[i])
}
return f
}
func Callers(additionalSkip int) *Stack {
const depth = 32
var pcs [depth]uintptr
n := runtime.Callers(defaultSkip+additionalSkip, pcs[:])
var st Stack = pcs[0:n]
return &st
}
// funcname removes the path prefix component of a function's name reported by func.Name().
func funcname(name string) string {
i := strings.LastIndex(name, "/")
name = name[i+1:]
i = strings.Index(name, ".")
return name[i+1:]
}

View File

@ -0,0 +1,63 @@
package errors
import (
"encoding/json"
"fmt"
"strings"
)
// copied from zerolog console writer since they aren't exported
//nolint
const (
colorBlack = iota + 30
colorRed
colorGreen
colorYellow
colorBlue
colorMagenta
colorCyan
colorWhite
)
// colorize returns the string s wrapped in ANSI code c, unless disabled is true.
func colorize(s interface{}, c int, disabled bool) string {
if disabled {
return fmt.Sprintf("%s", s)
}
return fmt.Sprintf("\x1b[%dm%v\x1b[0m", c, s)
}
type errorFormat = struct {
Error string
Details []string
}
func FormatErrFieldValue(i interface{}) string {
switch d := i.(type) {
case []byte:
var ed errorFormat
if err := json.Unmarshal(d, &ed); err != nil {
return fmt.Sprintf("error: %v", err)
}
var sb strings.Builder
sb.WriteString(fmt.Sprintf("%s\n", ed.Error))
if len(ed.Details) > 0 {
sb.WriteString("error details:\n")
for _, l := range ed.Details {
sb.WriteString(fmt.Sprintf("%s\n", l))
}
}
return colorize(sb.String(), colorRed, false)
default:
return colorize(fmt.Sprintf("%s", d), colorRed, false)
}
}
func ErrorMarshalFunc(err error) interface{} {
ef := errorFormat{
Error: err.Error(),
Details: PrintErrorDetails(err),
}
return ef
}

View File

@ -22,6 +22,7 @@ import (
"strings"
"time"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util"
"github.com/rs/zerolog"
@ -29,7 +30,6 @@ import (
etcdclientv3 "go.etcd.io/etcd/clientv3"
"go.etcd.io/etcd/clientv3/namespace"
"go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
errors "golang.org/x/xerrors"
)
var (
@ -65,7 +65,7 @@ func FromEtcdError(err error) error {
if errors.Is(err, rpctypes.ErrKeyNotFound) {
return ErrKeyNotFound
}
return err
return errors.WithStack(err)
}
type Store struct {
@ -90,7 +90,7 @@ func New(cfg Config) (*Store, error) {
for _, e := range endpoints {
u, err := url.Parse(e)
if err != nil {
return nil, errors.Errorf("cannot parse endpoint %q: %w", e, err)
return nil, errors.Wrapf(err, "cannot parse endpoint %q", e)
}
if scheme == "" {
scheme = u.Scheme
@ -108,7 +108,7 @@ func New(cfg Config) (*Store, error) {
var err error
tlsConfig, err = util.NewTLSConfig(cfg.CertFile, cfg.KeyFile, cfg.CAFile, cfg.SkipTLSVerify)
if err != nil {
return nil, errors.Errorf("cannot create tls config: %w", err)
return nil, errors.Wrapf(err, "cannot create tls config")
}
}
@ -119,7 +119,7 @@ func New(cfg Config) (*Store, error) {
c, err := etcdclientv3.New(config)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
c.KV = namespace.NewKV(c.KV, prefix)
@ -150,7 +150,7 @@ func (s *Store) Put(ctx context.Context, key string, value []byte, options *Writ
if options.TTL > 0 {
lease, err := s.c.Grant(ctx, int64(options.TTL.Seconds()))
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
etcdv3Options = append(etcdv3Options, etcdclientv3.WithLease(lease.ID))
}
@ -252,7 +252,7 @@ func (s *Store) AtomicPut(ctx context.Context, key string, value []byte, prevRev
if options.TTL > 0 {
lease, err := s.c.Grant(ctx, int64(options.TTL))
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
etcdv3Options = append(etcdv3Options, etcdclientv3.WithLease(lease.ID))
}
@ -282,7 +282,7 @@ func (s *Store) AtomicPut(ctx context.Context, key string, value []byte, prevRev
func (s *Store) Delete(ctx context.Context, key string) error {
_, err := s.c.Delete(ctx, key)
return err
return errors.WithStack(err)
}
func (s *Store) DeletePrefix(ctx context.Context, prefix string) error {
@ -298,7 +298,7 @@ func (s *Store) DeletePrefix(ctx context.Context, prefix string) error {
_, err := s.c.Delete(ctx, key, etcdv3Options...)
return err
return errors.WithStack(err)
}
func (s *Store) AtomicDelete(ctx context.Context, key string, revision int64) (*etcdclientv3.TxnResponse, error) {
@ -333,7 +333,7 @@ func (s *Store) Watch(ctx context.Context, prefix string, revision int64) etcdcl
}
func (s *Store) Close() error {
return s.c.Close()
return errors.WithStack(s.c.Close())
}
func (s *Store) compactor(ctx context.Context, interval time.Duration) {
@ -364,7 +364,7 @@ func (s *Store) compact(ctx context.Context, version, rev int64) (int64, int64,
).Commit()
if err != nil {
return version, rev, err
return version, rev, errors.WithStack(err)
}
curRev := resp.Header.Revision
@ -380,7 +380,7 @@ func (s *Store) compact(ctx context.Context, version, rev int64) (int64, int64,
}
if _, err = s.c.Compact(ctx, rev); err != nil {
s.log.Warn().Msgf("compact error: %v", err)
return curVersion, curRev, err
return curVersion, curRev, errors.WithStack(err)
}
s.log.Info().Msgf("compacted revision: %d", rev)
return curVersion, curRev, nil

View File

@ -16,6 +16,7 @@
// have the TryLock function not yet available on stable v3.4 client
// Remove this when updating the client to a version providing TryLock
//nolint:wrapcheck
package etcd
import (

View File

@ -24,10 +24,10 @@ import (
"regexp"
"strings"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util"
"github.com/rs/zerolog"
errors "golang.org/x/xerrors"
)
var (
@ -109,21 +109,21 @@ func InfoRefsResponse(ctx context.Context, repoPath, serviceName string) ([]byte
git := &util.Git{}
out, err := git.Output(ctx, nil, serviceName, "--stateless-rpc", "--advertise-refs", repoPath)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
buf.Write(out)
return buf.Bytes(), err
return buf.Bytes(), errors.WithStack(err)
}
func gitService(ctx context.Context, w io.Writer, r io.Reader, repoPath, serviceName string) error {
git := &util.Git{GitDir: repoPath}
return git.Pipe(ctx, w, r, serviceName, "--stateless-rpc", repoPath)
return errors.WithStack(git.Pipe(ctx, w, r, serviceName, "--stateless-rpc", repoPath))
}
func gitFetchFile(ctx context.Context, w io.Writer, r io.Reader, repoPath, ref, path string) error {
git := &util.Git{GitDir: repoPath}
return git.Pipe(ctx, w, r, "show", fmt.Sprintf("%s:%s", ref, path))
return errors.WithStack(git.Pipe(ctx, w, r, "show", fmt.Sprintf("%s:%s", ref, path)))
}
var ErrWrongRepoPath = errors.New("wrong repository path")

View File

@ -20,11 +20,11 @@ import (
"os"
"path/filepath"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util"
"github.com/gofrs/uuid"
"github.com/rs/zerolog"
errors "golang.org/x/xerrors"
)
const (
@ -35,24 +35,24 @@ const (
func copyFile(src, dest string) error {
srcf, err := os.Open(src)
if err != nil {
return err
return errors.WithStack(err)
}
defer srcf.Close()
destf, err := os.Create(dest)
if err != nil {
return err
return errors.WithStack(err)
}
defer destf.Close()
_, err = io.Copy(destf, srcf)
return err
return errors.WithStack(err)
}
func fileExists(path string) (bool, error) {
_, err := os.Stat(path)
if err != nil && !os.IsNotExist(err) {
return false, err
return false, errors.WithStack(err)
}
return !os.IsNotExist(err), nil
}
@ -62,24 +62,24 @@ func GitDir() (string, error) {
git := &util.Git{}
lines, err := git.OutputLines(context.Background(), nil, "rev-parse", "--git-dir")
if err != nil {
return "", err
return "", errors.WithStack(err)
}
if len(lines) != 1 {
return "", errors.Errorf("received %d lines, expected one line", len(lines))
}
return lines[0], err
return lines[0], errors.WithStack(err)
}
func currentGitBranch() (string, error) {
git := &util.Git{}
lines, err := git.OutputLines(context.Background(), nil, "symbolic-ref", "--short", "HEAD")
if err != nil {
return "", err
return "", errors.WithStack(err)
}
if len(lines) != 1 {
return "", errors.Errorf("received %d lines, expected one line", len(lines))
}
return lines[0], err
return lines[0], errors.WithStack(err)
}
// gitDir returns the git dir relative to the working dir
@ -87,60 +87,60 @@ func gitWriteTree(indexPath string) (string, error) {
git := &util.Git{Env: []string{"GIT_INDEX_FILE=" + indexPath}}
lines, err := git.OutputLines(context.Background(), nil, "write-tree")
if err != nil {
return "", err
return "", errors.WithStack(err)
}
if len(lines) != 1 {
return "", errors.Errorf("received %d lines, expected one line", len(lines))
}
return lines[0], err
return lines[0], errors.WithStack(err)
}
func gitCommitTree(message, treeSHA string) (string, error) {
git := &util.Git{}
lines, err := git.OutputLines(context.Background(), nil, "commit-tree", "-m", message, treeSHA)
if err != nil {
return "", err
return "", errors.WithStack(err)
}
if len(lines) != 1 {
return "", errors.Errorf("received %d lines, expected one line", len(lines))
}
return lines[0], err
return lines[0], errors.WithStack(err)
}
func gitUpdateRef(message, ref, commitSHA string) error {
git := &util.Git{}
_, err := git.Output(context.Background(), nil, "update-ref", "-m", message, ref, commitSHA)
return err
return errors.WithStack(err)
}
func gitUpdateFiles(indexPath string) error {
git := &util.Git{Env: []string{"GIT_INDEX_FILE=" + indexPath}}
_, err := git.Output(context.Background(), nil, "add", "-u")
return err
return errors.WithStack(err)
}
func gitAddUntrackedFiles(indexPath string) error {
git := &util.Git{Env: []string{"GIT_INDEX_FILE=" + indexPath}}
_, err := git.Output(context.Background(), nil, "add", ".")
return err
return errors.WithStack(err)
}
func gitAddIgnoredFiles(indexPath string) error {
git := &util.Git{Env: []string{"GIT_INDEX_FILE=" + indexPath}}
_, err := git.Output(context.Background(), nil, "add", "-f", "-A", ".")
return err
return errors.WithStack(err)
}
func GitAddRemote(configPath, name, url string) error {
git := &util.Git{}
_, err := git.Output(context.Background(), nil, "remote", "add", name, url)
return err
return errors.WithStack(err)
}
func GitPush(configPath, remote, branch string) error {
git := &util.Git{}
_, err := git.Output(context.Background(), nil, "push", remote, branch, "-f")
return err
return errors.WithStack(err)
}
type GitSaveConfig struct {
@ -178,7 +178,7 @@ func (s *GitSave) RefsPrefix() string {
func (s *GitSave) Save(message, branchName string) (string, error) {
gitdir, err := GitDir()
if err != nil {
return "", err
return "", errors.WithStack(err)
}
tmpIndexPath := filepath.Join(gitdir, "gitsave-index-"+uuid.Must(uuid.NewV4()).String())
@ -188,25 +188,25 @@ func (s *GitSave) Save(message, branchName string) (string, error) {
curBranch, err := currentGitBranch()
if err != nil {
return "", err
return "", errors.WithStack(err)
}
indexExists, err := fileExists(indexPath)
if err != nil {
return "", err
return "", errors.WithStack(err)
}
if indexExists {
// copy current git index to a temporary index
if err := copyFile(indexPath, tmpIndexPath); err != nil {
return "", err
return "", errors.WithStack(err)
}
s.log.Info().Msgf("created temporary index: %s", tmpIndexPath)
// read the current branch tree information into the index
git := &util.Git{Env: []string{"GIT_INDEX_FILE=" + tmpIndexPath}}
_, err = git.Output(context.Background(), nil, "read-tree", curBranch)
if err != nil {
return "", err
return "", errors.WithStack(err)
}
} else {
s.log.Info().Msgf("index %s does not exist", indexPath)
@ -214,40 +214,40 @@ func (s *GitSave) Save(message, branchName string) (string, error) {
s.log.Info().Msgf("updating files already in the index")
if err := gitUpdateFiles(tmpIndexPath); err != nil {
return "", err
return "", errors.WithStack(err)
}
if s.conf.AddUntracked {
s.log.Info().Msgf("adding untracked files")
if err := gitAddUntrackedFiles(tmpIndexPath); err != nil {
return "", err
return "", errors.WithStack(err)
}
}
if s.conf.AddIgnored {
s.log.Info().Msgf("adding ignored files")
if err := gitAddIgnoredFiles(tmpIndexPath); err != nil {
return "", err
return "", errors.WithStack(err)
}
}
s.log.Info().Msgf("writing tree file")
treeSHA, err := gitWriteTree(tmpIndexPath)
if err != nil {
return "", err
return "", errors.WithStack(err)
}
s.log.Info().Msgf("tree: %s", treeSHA)
s.log.Info().Msgf("committing tree")
commitSHA, err := gitCommitTree(message, treeSHA)
if err != nil {
return "", err
return "", errors.WithStack(err)
}
s.log.Info().Msgf("commit: %s", commitSHA)
s.log.Info().Msgf("updating ref")
if err = gitUpdateRef("git-save", filepath.Join(s.refsPrefix, branchName), commitSHA); err != nil {
return "", err
return "", errors.WithStack(err)
}
return commitSHA, nil

View File

@ -26,6 +26,7 @@ import (
"strings"
"time"
"agola.io/agola/internal/errors"
gitsource "agola.io/agola/internal/gitsources"
"agola.io/agola/internal/services/types"
"agola.io/agola/internal/util"
@ -75,29 +76,31 @@ func (c *Client) SetHTTPClient(client *http.Client) {
func (c *Client) doRequest(method, path string, query url.Values, header http.Header, ibody io.Reader) (*http.Response, error) {
u, err := url.Parse(c.url + "/" + path)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
u.RawQuery = query.Encode()
req, err := http.NewRequest(method, u.String(), ibody)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
for k, v := range header {
req.Header[k] = v
}
return c.client.Do(req)
res, err := c.client.Do(req)
return res, errors.WithStack(err)
}
func (c *Client) getResponse(method, path string, query url.Values, header http.Header, ibody io.Reader) (*http.Response, error) {
resp, err := c.doRequest(method, path, query, header, ibody)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if err := util.ErrFromRemote(resp); err != nil {
return resp, err
return resp, errors.WithStack(err)
}
return resp, nil
@ -114,12 +117,12 @@ func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
resp, err := c.getResponse("GET", fmt.Sprintf("%s.git/raw/%s/%s", repopath, commit, file), nil, nil, nil)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
return data, err
return data, errors.WithStack(err)
}
func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool) error {
@ -174,7 +177,7 @@ func (c *Client) RefType(ref string) (gitsource.RefType, string, error) {
}
}
return -1, "", fmt.Errorf("unsupported ref: %s", ref)
return -1, "", errors.Errorf("unsupported ref: %s", ref)
}
func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {

View File

@ -28,11 +28,11 @@ import (
"strings"
"time"
"agola.io/agola/internal/errors"
gitsource "agola.io/agola/internal/gitsources"
"code.gitea.io/sdk/gitea"
"golang.org/x/oauth2"
errors "golang.org/x/xerrors"
)
const (
@ -146,7 +146,7 @@ func (c *Client) RequestOauth2Token(callbackURL, code string) (*oauth2.Token, er
var config = c.oauth2Config(callbackURL)
token, err := config.Exchange(ctx, code)
if err != nil {
return nil, errors.Errorf("cannot get oauth2 token: %w", err)
return nil, errors.Wrapf(err, "cannot get oauth2 token")
}
return token, nil
}
@ -158,7 +158,9 @@ func (c *Client) RefreshOauth2Token(refreshToken string) (*oauth2.Token, error)
var config = c.oauth2Config("")
token := &oauth2.Token{RefreshToken: refreshToken}
ts := config.TokenSource(ctx, token)
return ts.Token()
ntoken, err := ts.Token()
return ntoken, errors.WithStack(err)
}
func (c *Client) LoginPassword(username, password, tokenName string) (string, error) {
@ -172,16 +174,16 @@ func (c *Client) LoginPassword(username, password, tokenName string) (string, er
tokens := make([]*gitea.AccessToken, 0, 10)
req, err := http.NewRequest("GET", c.APIURL+"/api/v1"+fmt.Sprintf("/users/%s/tokens", username), nil)
if err != nil {
return "", err
return "", errors.WithStack(err)
}
req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(username+":"+password)))
resp, err := c.oauth2HTTPClient.Do(req)
if err != nil {
return "", err
return "", errors.WithStack(err)
}
if resp.StatusCode == http.StatusUnauthorized {
return "", gitsource.ErrUnauthorized
return "", errors.WithStack(gitsource.ErrUnauthorized)
}
if resp.StatusCode/100 != 2 {
return "", errors.Errorf("gitea api status code %d", resp.StatusCode)
@ -190,7 +192,7 @@ func (c *Client) LoginPassword(username, password, tokenName string) (string, er
dec := json.NewDecoder(resp.Body)
if err := dec.Decode(&tokens); err != nil {
return "", err
return "", errors.WithStack(err)
}
for _, token := range tokens {
if token.Name == tokenName {
@ -206,7 +208,7 @@ func (c *Client) LoginPassword(username, password, tokenName string) (string, er
gitea.CreateAccessTokenOption{Name: tokenName},
)
if terr != nil {
return "", terr
return "", errors.WithStack(terr)
}
accessToken = token.Token
}
@ -217,7 +219,7 @@ func (c *Client) LoginPassword(username, password, tokenName string) (string, er
func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
user, err := c.client.GetMyUserInfo()
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return &gitsource.UserInfo{
ID: strconv.FormatInt(user.ID, 10),
@ -229,11 +231,11 @@ func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
rr, err := c.client.GetRepo(owner, reponame)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return fromGiteaRepo(rr), nil
}
@ -241,23 +243,23 @@ func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
data, err := c.client.GetFile(owner, reponame, commit, file)
return data, err
return data, errors.WithStack(err)
}
func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool) error {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return err
return errors.WithStack(err)
}
if _, err = c.client.CreateDeployKey(owner, reponame, gitea.CreateKeyOption{
Title: title,
Key: pubKey,
ReadOnly: readonly,
}); err != nil {
return errors.Errorf("error creating deploy key: %w", err)
return errors.Wrapf(err, "error creating deploy key")
}
return nil
@ -266,7 +268,7 @@ func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool)
func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool) error {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return err
return errors.WithStack(err)
}
// NOTE(sgotti) gitea has a bug where if we delete and remove the same key with
// the same value it is correctly readded and the admin must force a
@ -274,7 +276,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
// when the public key value has changed
keys, err := c.client.ListDeployKeys(owner, reponame, gitea.ListDeployKeysOptions{})
if err != nil {
return errors.Errorf("error retrieving existing deploy keys: %w", err)
return errors.Wrapf(err, "error retrieving existing deploy keys")
}
for _, key := range keys {
@ -283,7 +285,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
return nil
}
if err := c.client.DeleteDeployKey(owner, reponame, key.ID); err != nil {
return errors.Errorf("error removing existing deploy key: %w", err)
return errors.Wrapf(err, "error removing existing deploy key")
}
}
}
@ -293,7 +295,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
Key: pubKey,
ReadOnly: readonly,
}); err != nil {
return errors.Errorf("error creating deploy key: %w", err)
return errors.Wrapf(err, "error creating deploy key")
}
return nil
@ -302,17 +304,17 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
func (c *Client) DeleteDeployKey(repopath, title string) error {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return err
return errors.WithStack(err)
}
keys, err := c.client.ListDeployKeys(owner, reponame, gitea.ListDeployKeysOptions{})
if err != nil {
return errors.Errorf("error retrieving existing deploy keys: %w", err)
return errors.Wrapf(err, "error retrieving existing deploy keys")
}
for _, key := range keys {
if key.Title == title {
if err := c.client.DeleteDeployKey(owner, reponame, key.ID); err != nil {
return errors.Errorf("error removing existing deploy key: %w", err)
return errors.Wrapf(err, "error removing existing deploy key")
}
}
}
@ -323,7 +325,7 @@ func (c *Client) DeleteDeployKey(repopath, title string) error {
func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return err
return errors.WithStack(err)
}
opts := gitea.CreateHookOption{
@ -338,7 +340,7 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
}
if _, err = c.client.CreateRepoHook(owner, reponame, opts); err != nil {
return errors.Errorf("error creating repository webhook: %w", err)
return errors.Wrapf(err, "error creating repository webhook")
}
return nil
@ -347,11 +349,11 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
func (c *Client) DeleteRepoWebhook(repopath, u string) error {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return err
return errors.WithStack(err)
}
hooks, err := c.client.ListRepoHooks(owner, reponame, gitea.ListHooksOptions{})
if err != nil {
return errors.Errorf("error retrieving repository webhooks: %w", err)
return errors.Wrapf(err, "error retrieving repository webhooks")
}
// match the full url so we can have multiple webhooks for different agola
@ -359,7 +361,7 @@ func (c *Client) DeleteRepoWebhook(repopath, u string) error {
for _, hook := range hooks {
if hook.Config["url"] == u {
if err := c.client.DeleteRepoHook(owner, reponame, hook.ID); err != nil {
return errors.Errorf("error deleting existing repository webhook: %w", err)
return errors.Wrapf(err, "error deleting existing repository webhook")
}
}
}
@ -370,7 +372,7 @@ func (c *Client) DeleteRepoWebhook(repopath, u string) error {
func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource.CommitStatus, targetURL, description, context string) error {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return err
return errors.WithStack(err)
}
_, err = c.client.CreateStatus(owner, reponame, commitSHA, gitea.CreateStatusOption{
State: fromCommitStatus(status),
@ -378,7 +380,7 @@ func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource
Description: description,
Context: context,
})
return err
return errors.WithStack(err)
}
func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
@ -396,7 +398,7 @@ func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
)
if err != nil {
return []*gitsource.RepoInfo{}, err
return []*gitsource.RepoInfo{}, errors.WithStack(err)
}
for _, repo := range remoteRepos {
@ -429,12 +431,12 @@ func fromGiteaRepo(rr *gitea.Repository) *gitsource.RepoInfo {
func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
remoteRefs, err := c.client.GetRepoRefs(owner, reponame, ref)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if len(remoteRefs) == 0 {
return nil, errors.Errorf("no ref %q for repository %q", ref, repopath)
@ -480,12 +482,12 @@ func (c *Client) RefType(ref string) (gitsource.RefType, string, error) {
func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
commit, err := c.client.GetSingleCommit(owner, reponame, commitSHA)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return &gitsource.Commit{

View File

@ -27,9 +27,8 @@ import (
"strconv"
"strings"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/services/types"
errors "golang.org/x/xerrors"
)
const (
@ -48,7 +47,7 @@ const (
func (c *Client) ParseWebhook(r *http.Request, secret string) (*types.WebhookData, error) {
data, err := ioutil.ReadAll(io.LimitReader(r.Body, 10*1024*1024))
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
// verify signature
@ -83,7 +82,7 @@ func parsePushHook(data []byte) (*types.WebhookData, error) {
push := new(pushHook)
err := json.Unmarshal(data, push)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return webhookDataFromPush(push)
@ -93,7 +92,7 @@ func parsePullRequestHook(data []byte) (*types.WebhookData, error) {
prhook := new(pullRequestHook)
err := json.Unmarshal(data, prhook)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
// skip non open pull requests
@ -144,7 +143,7 @@ func webhookDataFromPush(hook *pushHook) (*types.WebhookData, error) {
whd.Message = fmt.Sprintf("Tag %s", whd.Tag)
default:
// ignore received webhook since it doesn't have a ref we're interested in
return nil, fmt.Errorf("unsupported webhook ref %q", hook.Ref)
return nil, errors.Errorf("unsupported webhook ref %q", hook.Ref)
}
return whd, nil

View File

@ -28,11 +28,11 @@ import (
"strings"
"time"
"agola.io/agola/internal/errors"
gitsource "agola.io/agola/internal/gitsources"
"github.com/google/go-github/v29/github"
"golang.org/x/oauth2"
errors "golang.org/x/xerrors"
)
var (
@ -81,7 +81,7 @@ func fromCommitStatus(status gitsource.CommitStatus) string {
case gitsource.CommitStatusFailed:
return "failure"
default:
panic(fmt.Errorf("unknown commit status %q", status))
panic(errors.Errorf("unknown commit status %q", status))
}
}
@ -102,6 +102,8 @@ func (t *TokenTransport) RoundTrip(r *http.Request) (*http.Response, error) {
if t.token != "" {
r.Header.Set("Authorization", "Bearer "+t.token)
}
//nolint:wrapcheck
return t.rt.RoundTrip(r)
}
@ -184,7 +186,7 @@ func (c *Client) RequestOauth2Token(callbackURL, code string) (*oauth2.Token, er
var config = c.oauth2Config(callbackURL)
token, err := config.Exchange(ctx, code)
if err != nil {
return nil, errors.Errorf("cannot get oauth2 token: %w", err)
return nil, errors.Wrapf(err, "cannot get oauth2 token")
}
return token, nil
}
@ -196,13 +198,15 @@ func (c *Client) RefreshOauth2Token(refreshToken string) (*oauth2.Token, error)
var config = c.oauth2Config("")
token := &oauth2.Token{RefreshToken: refreshToken}
ts := config.TokenSource(ctx, token)
return ts.Token()
ntoken, err := ts.Token()
return ntoken, errors.WithStack(err)
}
func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
user, _, err := c.client.Users.Get(context.TODO(), "")
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
userInfo := &gitsource.UserInfo{
@ -219,11 +223,11 @@ func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
rr, _, err := c.client.Repositories.Get(context.TODO(), owner, reponame)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return fromGithubRepo(rr), nil
}
@ -231,28 +235,29 @@ func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
r, err := c.client.Repositories.DownloadContents(context.TODO(), owner, reponame, file, &github.RepositoryContentGetOptions{Ref: commit})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
defer r.Close()
return ioutil.ReadAll(r)
d, err := ioutil.ReadAll(r)
return d, errors.WithStack(err)
}
func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool) error {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return err
return errors.WithStack(err)
}
if _, _, err = c.client.Repositories.CreateKey(context.TODO(), owner, reponame, &github.Key{
Title: github.String(title),
Key: github.String(pubKey),
ReadOnly: github.Bool(readonly),
}); err != nil {
return errors.Errorf("error creating deploy key: %w", err)
return errors.Wrapf(err, "error creating deploy key")
}
return nil
}
@ -260,7 +265,7 @@ func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool)
func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool) error {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return err
return errors.WithStack(err)
}
// NOTE(sgotti) gitea has a bug where if we delete and remove the same key with
// the same value it is correctly readded and the admin must force a
@ -268,7 +273,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
// when the public key value has changed
keys, _, err := c.client.Repositories.ListKeys(context.TODO(), owner, reponame, nil)
if err != nil {
return errors.Errorf("error retrieving existing deploy keys: %w", err)
return errors.Wrapf(err, "error retrieving existing deploy keys")
}
for _, key := range keys {
@ -277,7 +282,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
return nil
}
if _, err := c.client.Repositories.DeleteKey(context.TODO(), owner, reponame, *key.ID); err != nil {
return errors.Errorf("error removing existing deploy key: %w", err)
return errors.Wrapf(err, "error removing existing deploy key")
}
}
}
@ -287,7 +292,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
Key: github.String(pubKey),
ReadOnly: github.Bool(readonly),
}); err != nil {
return errors.Errorf("error creating deploy key: %w", err)
return errors.Wrapf(err, "error creating deploy key")
}
return nil
@ -296,17 +301,17 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
func (c *Client) DeleteDeployKey(repopath, title string) error {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return err
return errors.WithStack(err)
}
keys, _, err := c.client.Repositories.ListKeys(context.TODO(), owner, reponame, nil)
if err != nil {
return errors.Errorf("error retrieving existing deploy keys: %w", err)
return errors.Wrapf(err, "error retrieving existing deploy keys")
}
for _, key := range keys {
if *key.Title == title {
if _, err := c.client.Repositories.DeleteKey(context.TODO(), owner, reponame, *key.ID); err != nil {
return errors.Errorf("error removing existing deploy key: %w", err)
return errors.Wrapf(err, "error removing existing deploy key")
}
}
}
@ -317,7 +322,7 @@ func (c *Client) DeleteDeployKey(repopath, title string) error {
func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return err
return errors.WithStack(err)
}
hook := &github.Hook{
@ -331,7 +336,7 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
}
if _, _, err = c.client.Repositories.CreateHook(context.TODO(), owner, reponame, hook); err != nil {
return errors.Errorf("error creating repository webhook: %w", err)
return errors.Wrapf(err, "error creating repository webhook")
}
return nil
@ -340,7 +345,7 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
func (c *Client) DeleteRepoWebhook(repopath, u string) error {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return err
return errors.WithStack(err)
}
hooks := []*github.Hook{}
@ -349,7 +354,7 @@ func (c *Client) DeleteRepoWebhook(repopath, u string) error {
for {
pHooks, resp, err := c.client.Repositories.ListHooks(context.TODO(), owner, reponame, opt)
if err != nil {
return errors.Errorf("error retrieving repository webhooks: %w", err)
return errors.Wrapf(err, "error retrieving repository webhooks")
}
hooks = append(hooks, pHooks...)
if resp.NextPage == 0 {
@ -363,7 +368,7 @@ func (c *Client) DeleteRepoWebhook(repopath, u string) error {
for _, hook := range hooks {
if hook.Config["url"] == u {
if _, err := c.client.Repositories.DeleteHook(context.TODO(), owner, reponame, *hook.ID); err != nil {
return errors.Errorf("error deleting existing repository webhook: %w", err)
return errors.Wrapf(err, "error deleting existing repository webhook")
}
}
}
@ -374,7 +379,7 @@ func (c *Client) DeleteRepoWebhook(repopath, u string) error {
func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource.CommitStatus, targetURL, description, statusContext string) error {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return err
return errors.WithStack(err)
}
_, _, err = c.client.Repositories.CreateStatus(context.TODO(), owner, reponame, commitSHA, &github.RepoStatus{
State: github.String(fromCommitStatus(status)),
@ -382,7 +387,7 @@ func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource
Description: github.String(description),
Context: github.String(statusContext),
})
return err
return errors.WithStack(err)
}
func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
@ -392,7 +397,7 @@ func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
for {
pRemoteRepos, resp, err := c.client.Repositories.List(context.TODO(), "", opt)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
remoteRepos = append(remoteRepos, pRemoteRepos...)
if resp.NextPage == 0 {
@ -429,12 +434,12 @@ func fromGithubRepo(rr *github.Repository) *gitsource.RepoInfo {
func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
remoteRef, _, err := c.client.Git.GetRef(context.TODO(), owner, reponame, ref)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return fromGithubRef(remoteRef)
@ -445,7 +450,7 @@ func fromGithubRef(remoteRef *github.Reference) (*gitsource.Ref, error) {
switch t {
case "commit":
default:
return nil, fmt.Errorf("unsupported object type: %s", t)
return nil, errors.Errorf("unsupported object type: %s", t)
}
return &gitsource.Ref{
@ -467,19 +472,19 @@ func (c *Client) RefType(ref string) (gitsource.RefType, string, error) {
return gitsource.RefTypePullRequest, m[1], nil
default:
return -1, "", fmt.Errorf("unsupported ref: %s", ref)
return -1, "", errors.Errorf("unsupported ref: %s", ref)
}
}
func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {
owner, reponame, err := parseRepoPath(repopath)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
commit, _, err := c.client.Git.GetCommit(context.TODO(), owner, reponame, commitSHA)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return &gitsource.Commit{

View File

@ -21,10 +21,10 @@ import (
"strconv"
"strings"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/services/types"
"github.com/google/go-github/v29/github"
errors "golang.org/x/xerrors"
)
const (
@ -37,12 +37,12 @@ const (
func (c *Client) ParseWebhook(r *http.Request, secret string) (*types.WebhookData, error) {
payload, err := github.ValidatePayload(r, []byte(secret))
if err != nil {
return nil, errors.Errorf("wrong webhook signature: %w", err)
return nil, errors.Wrapf(err, "wrong webhook signature")
}
webHookType := github.WebHookType(r)
event, err := github.ParseWebHook(webHookType, payload)
if err != nil {
return nil, errors.Errorf("failed to parse webhook: %w", err)
return nil, errors.Wrapf(err, "failed to parse webhook")
}
switch event := event.(type) {
case *github.PushEvent:
@ -96,7 +96,7 @@ func webhookDataFromPush(hook *github.PushEvent) (*types.WebhookData, error) {
default:
// ignore received webhook since it doesn't have a ref we're interested in
return nil, fmt.Errorf("unsupported webhook ref %q", *hook.Ref)
return nil, errors.Errorf("unsupported webhook ref %q", *hook.Ref)
}
return whd, nil

View File

@ -26,11 +26,11 @@ import (
"strings"
"time"
"agola.io/agola/internal/errors"
gitsource "agola.io/agola/internal/gitsources"
gitlab "github.com/xanzy/go-gitlab"
"golang.org/x/oauth2"
errors "golang.org/x/xerrors"
)
var (
@ -70,7 +70,7 @@ func fromCommitStatus(status gitsource.CommitStatus) gitlab.BuildStateValue {
case gitsource.CommitStatusFailed:
return gitlab.Failed
default:
panic(fmt.Errorf("unknown commit status %q", status))
panic(errors.Errorf("unknown commit status %q", status))
}
}
@ -93,7 +93,7 @@ func New(opts Opts) (*Client, error) {
client := gitlab.NewOAuthClient(httpClient, opts.Token)
if err := client.SetBaseURL(opts.APIURL); err != nil {
return nil, errors.Errorf("failed to set gitlab client base url: %w", err)
return nil, errors.Wrapf(err, "failed to set gitlab client base url")
}
return &Client{
@ -130,7 +130,7 @@ func (c *Client) RequestOauth2Token(callbackURL, code string) (*oauth2.Token, er
var config = c.oauth2Config(callbackURL)
token, err := config.Exchange(ctx, code)
if err != nil {
return nil, errors.Errorf("cannot get oauth2 token: %w", err)
return nil, errors.Wrapf(err, "cannot get oauth2 token")
}
return token, nil
}
@ -142,13 +142,15 @@ func (c *Client) RefreshOauth2Token(refreshToken string) (*oauth2.Token, error)
var config = c.oauth2Config("")
token := &oauth2.Token{RefreshToken: refreshToken}
ts := config.TokenSource(ctx, token)
return ts.Token()
ntoken, err := ts.Token()
return ntoken, errors.WithStack(err)
}
func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
rr, _, err := c.client.Projects.GetProject(repopath, nil)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return fromGitlabRepo(rr), nil
}
@ -156,7 +158,7 @@ func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
user, _, err := c.client.Users.CurrentUser()
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return &gitsource.UserInfo{
ID: strconv.Itoa(user.ID),
@ -168,13 +170,13 @@ func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
f, _, err := c.client.RepositoryFiles.GetFile(repopath, file, &gitlab.GetFileOptions{Ref: gitlab.String(commit)})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
data, err := base64.StdEncoding.DecodeString(f.Content)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return data, err
return data, errors.WithStack(err)
}
func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool) error {
@ -182,7 +184,7 @@ func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool)
Title: gitlab.String(title),
Key: gitlab.String(pubKey),
}); err != nil {
return errors.Errorf("error creating deploy key: %w", err)
return errors.Wrapf(err, "error creating deploy key")
}
return nil
@ -191,7 +193,7 @@ func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool)
func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool) error {
keys, _, err := c.client.DeployKeys.ListProjectDeployKeys(repopath, nil)
if err != nil {
return errors.Errorf("error retrieving existing deploy keys: %w", err)
return errors.Wrapf(err, "error retrieving existing deploy keys")
}
for _, key := range keys {
@ -200,7 +202,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
return nil
}
if _, err := c.client.DeployKeys.DeleteDeployKey(repopath, key.ID); err != nil {
return errors.Errorf("error removing existing deploy key: %w", err)
return errors.Wrapf(err, "error removing existing deploy key")
}
}
}
@ -209,7 +211,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
Title: &title,
Key: &pubKey,
}); err != nil {
return errors.Errorf("error creating deploy key: %w", err)
return errors.Wrapf(err, "error creating deploy key")
}
return nil
@ -218,13 +220,13 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
func (c *Client) DeleteDeployKey(repopath, title string) error {
keys, _, err := c.client.DeployKeys.ListProjectDeployKeys(repopath, nil)
if err != nil {
return errors.Errorf("error retrieving existing deploy keys: %w", err)
return errors.Wrapf(err, "error retrieving existing deploy keys")
}
for _, key := range keys {
if key.Title == title {
if _, err := c.client.DeployKeys.DeleteDeployKey(repopath, key.ID); err != nil {
return errors.Errorf("error removing existing deploy key: %w", err)
return errors.Wrapf(err, "error removing existing deploy key")
}
}
}
@ -241,7 +243,7 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
Token: gitlab.String(secret),
}
if _, _, err := c.client.Projects.AddProjectHook(repopath, opts); err != nil {
return errors.Errorf("error creating repository webhook: %w", err)
return errors.Wrapf(err, "error creating repository webhook")
}
return nil
@ -250,7 +252,7 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
func (c *Client) DeleteRepoWebhook(repopath, u string) error {
hooks, _, err := c.client.Projects.ListProjectHooks(repopath, nil)
if err != nil {
return errors.Errorf("error retrieving repository webhooks: %w", err)
return errors.Wrapf(err, "error retrieving repository webhooks")
}
// match the full url so we can have multiple webhooks for different agola
@ -258,7 +260,7 @@ func (c *Client) DeleteRepoWebhook(repopath, u string) error {
for _, hook := range hooks {
if hook.URL == u {
if _, err := c.client.Projects.DeleteProjectHook(repopath, hook.ID); err != nil {
return errors.Errorf("error deleting existing repository webhook: %w", err)
return errors.Wrapf(err, "error deleting existing repository webhook")
}
}
}
@ -273,7 +275,7 @@ func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource
Description: gitlab.String(description),
Context: gitlab.String(context),
})
return err
return errors.WithStack(err)
}
func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
@ -281,7 +283,7 @@ func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
opts := &gitlab.ListProjectsOptions{MinAccessLevel: gitlab.AccessLevel(gitlab.MaintainerPermissions)}
remoteRepos, _, err := c.client.Projects.ListProjects(opts)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
repos := []*gitsource.RepoInfo{}
@ -311,7 +313,7 @@ func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
branch := strings.TrimPrefix(ref, "refs/heads/")
remoteBranch, _, err := c.client.Branches.GetBranch(repopath, branch)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return &gitsource.Ref{
@ -323,7 +325,7 @@ func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
tag := strings.TrimPrefix(ref, "refs/heads/")
remoteTag, _, err := c.client.Tags.GetTag(repopath, tag)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return &gitsource.Ref{
@ -331,7 +333,7 @@ func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
CommitSHA: remoteTag.Commit.ID,
}, nil
default:
return nil, fmt.Errorf("unsupported ref: %s", ref)
return nil, errors.Errorf("unsupported ref: %s", ref)
}
}
@ -348,14 +350,14 @@ func (c *Client) RefType(ref string) (gitsource.RefType, string, error) {
return gitsource.RefTypePullRequest, m[1], nil
default:
return -1, "", fmt.Errorf("unsupported ref: %s", ref)
return -1, "", errors.Errorf("unsupported ref: %s", ref)
}
}
func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {
commit, _, err := c.client.Commits.GetCommit(repopath, commitSHA, nil)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return &gitsource.Commit{

View File

@ -23,9 +23,8 @@ import (
"strconv"
"strings"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/services/types"
errors "golang.org/x/xerrors"
)
const (
@ -40,7 +39,7 @@ const (
func (c *Client) ParseWebhook(r *http.Request, secret string) (*types.WebhookData, error) {
data, err := ioutil.ReadAll(io.LimitReader(r.Body, 10*1024*1024))
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
// verify token (gitlab doesn't sign the payload but just returns the provided
@ -68,7 +67,7 @@ func parsePushHook(data []byte) (*types.WebhookData, error) {
push := new(pushHook)
err := json.Unmarshal(data, push)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
// skip push events with 0 commits. i.e. a tag deletion.
@ -83,7 +82,7 @@ func parsePullRequestHook(data []byte) (*types.WebhookData, error) {
prhook := new(pullRequestHook)
err := json.Unmarshal(data, prhook)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
// TODO(sgotti) skip non open pull requests
@ -127,7 +126,7 @@ func webhookDataFromPush(hook *pushHook) (*types.WebhookData, error) {
whd.Message = fmt.Sprintf("Tag %s", whd.Tag)
default:
// ignore received webhook since it doesn't have a ref we're interested in
return nil, fmt.Errorf("unsupported webhook ref %q", hook.Ref)
return nil, errors.Errorf("unsupported webhook ref %q", hook.Ref)
}
return whd, nil

View File

@ -15,10 +15,11 @@
package gitsource
import (
"errors"
"net/http"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/services/types"
"golang.org/x/oauth2"
)

View File

@ -20,6 +20,8 @@ import (
"os"
"path/filepath"
"strings"
"agola.io/agola/internal/errors"
)
// writeFileAtomicFunc atomically writes a file, it achieves this by creating a
@ -30,7 +32,7 @@ import (
func writeFileAtomicFunc(p, baseDir, tmpDir string, perm os.FileMode, persist bool, writeFunc func(f io.Writer) error) error {
f, err := ioutil.TempFile(tmpDir, "tmpfile")
if err != nil {
return err
return errors.WithStack(err)
}
err = writeFunc(f)
if persist && err == nil {
@ -47,7 +49,7 @@ func writeFileAtomicFunc(p, baseDir, tmpDir string, perm os.FileMode, persist bo
}
if err != nil {
os.Remove(f.Name())
return err
return errors.WithStack(err)
}
if !persist {
@ -80,7 +82,7 @@ func writeFileAtomic(filename, baseDir, tmpDir string, perm os.FileMode, persist
return writeFileAtomicFunc(filename, baseDir, tmpDir, perm, persist,
func(f io.Writer) error {
_, err := f.Write(data)
return err
return errors.WithStack(err)
})
}
*/

View File

@ -18,7 +18,7 @@ import (
"io"
"time"
errors "golang.org/x/xerrors"
"agola.io/agola/internal/errors"
)
type Storage interface {
@ -36,10 +36,12 @@ type Storage interface {
type ErrNotExist struct {
err error
*errors.Stack
}
func NewErrNotExist(err error) error {
return &ErrNotExist{err: err}
return &ErrNotExist{err: err, Stack: errors.Callers(0)}
}
func (e *ErrNotExist) Error() string {

View File

@ -21,7 +21,7 @@ import (
"path/filepath"
"strings"
errors "golang.org/x/xerrors"
"agola.io/agola/internal/errors"
)
const (
@ -36,15 +36,15 @@ type PosixStorage struct {
func NewPosix(baseDir string) (*PosixStorage, error) {
if err := os.MkdirAll(baseDir, 0770); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
dataDir := filepath.Join(baseDir, dataDirName)
tmpDir := filepath.Join(baseDir, tmpDirName)
if err := os.MkdirAll(dataDir, 0770); err != nil {
return nil, errors.Errorf("failed to create data dir: %w", err)
return nil, errors.Wrapf(err, "failed to create data dir")
}
if err := os.MkdirAll(tmpDir, 0770); err != nil {
return nil, errors.Errorf("failed to create tmp dir: %w", err)
return nil, errors.Wrapf(err, "failed to create tmp dir")
}
return &PosixStorage{
dataDir: dataDir,
@ -59,7 +59,7 @@ func (s *PosixStorage) fsPath(p string) (string, error) {
func (s *PosixStorage) Stat(p string) (*ObjectInfo, error) {
fspath, err := s.fsPath(p)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
fi, err := os.Stat(fspath)
@ -67,7 +67,7 @@ func (s *PosixStorage) Stat(p string) (*ObjectInfo, error) {
if os.IsNotExist(err) {
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
}
return nil, err
return nil, errors.WithStack(err)
}
return &ObjectInfo{Path: p, LastModified: fi.ModTime(), Size: fi.Size()}, nil
@ -76,24 +76,24 @@ func (s *PosixStorage) Stat(p string) (*ObjectInfo, error) {
func (s *PosixStorage) ReadObject(p string) (ReadSeekCloser, error) {
fspath, err := s.fsPath(p)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
f, err := os.Open(fspath)
if err != nil && os.IsNotExist(err) {
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
}
return f, err
return f, errors.WithStack(err)
}
func (s *PosixStorage) WriteObject(p string, data io.Reader, size int64, persist bool) error {
fspath, err := s.fsPath(p)
if err != nil {
return err
return errors.WithStack(err)
}
if err := os.MkdirAll(path.Dir(fspath), 0770); err != nil {
return err
return errors.WithStack(err)
}
r := data
@ -102,21 +102,21 @@ func (s *PosixStorage) WriteObject(p string, data io.Reader, size int64, persist
}
return writeFileAtomicFunc(fspath, s.dataDir, s.tmpDir, 0660, persist, func(f io.Writer) error {
_, err := io.Copy(f, r)
return err
return errors.WithStack(err)
})
}
func (s *PosixStorage) DeleteObject(p string) error {
fspath, err := s.fsPath(p)
if err != nil {
return err
return errors.WithStack(err)
}
if err := os.Remove(fspath); err != nil {
if os.IsNotExist(err) {
return NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
}
return err
return errors.WithStack(err)
}
// try to remove parent empty dirs
@ -179,7 +179,7 @@ func (s *PosixStorage) List(prefix, startWith, delimiter string, doneCh <-chan s
defer close(objectCh)
err := filepath.Walk(root, func(ep string, info os.FileInfo, err error) error {
if err != nil && !os.IsNotExist(err) {
return err
return errors.WithStack(err)
}
if os.IsNotExist(err) {
return nil
@ -191,7 +191,7 @@ func (s *PosixStorage) List(prefix, startWith, delimiter string, doneCh <-chan s
p, err = filepath.Rel(s.dataDir, p)
if err != nil {
return err
return errors.WithStack(err)
}
if !recursive && len(p) > len(prefix) {
rel := strings.TrimPrefix(p, prefix)

View File

@ -23,7 +23,7 @@ import (
"strings"
"unicode/utf8"
errors "golang.org/x/xerrors"
"agola.io/agola/internal/errors"
)
const (
@ -207,15 +207,15 @@ type PosixFlatStorage struct {
func NewPosixFlat(baseDir string) (*PosixFlatStorage, error) {
if err := os.MkdirAll(baseDir, 0770); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
dataDir := filepath.Join(baseDir, dataDirName)
tmpDir := filepath.Join(baseDir, tmpDirName)
if err := os.MkdirAll(dataDir, 0770); err != nil {
return nil, errors.Errorf("failed to create data dir: %w", err)
return nil, errors.Wrapf(err, "failed to create data dir")
}
if err := os.MkdirAll(tmpDir, 0770); err != nil {
return nil, errors.Errorf("failed to create tmp dir: %w", err)
return nil, errors.Wrapf(err, "failed to create tmp dir")
}
return &PosixFlatStorage{
dataDir: dataDir,
@ -233,7 +233,7 @@ func (s *PosixFlatStorage) fsPath(p string) (string, error) {
func (s *PosixFlatStorage) Stat(p string) (*ObjectInfo, error) {
fspath, err := s.fsPath(p)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
fi, err := os.Stat(fspath)
@ -241,7 +241,7 @@ func (s *PosixFlatStorage) Stat(p string) (*ObjectInfo, error) {
if os.IsNotExist(err) {
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
}
return nil, err
return nil, errors.WithStack(err)
}
return &ObjectInfo{Path: p, LastModified: fi.ModTime(), Size: fi.Size()}, nil
@ -250,24 +250,24 @@ func (s *PosixFlatStorage) Stat(p string) (*ObjectInfo, error) {
func (s *PosixFlatStorage) ReadObject(p string) (ReadSeekCloser, error) {
fspath, err := s.fsPath(p)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
f, err := os.Open(fspath)
if err != nil && os.IsNotExist(err) {
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
}
return f, err
return f, errors.WithStack(err)
}
func (s *PosixFlatStorage) WriteObject(p string, data io.Reader, size int64, persist bool) error {
fspath, err := s.fsPath(p)
if err != nil {
return err
return errors.WithStack(err)
}
if err := os.MkdirAll(path.Dir(fspath), 0770); err != nil {
return err
return errors.WithStack(err)
}
r := data
@ -276,21 +276,21 @@ func (s *PosixFlatStorage) WriteObject(p string, data io.Reader, size int64, per
}
return writeFileAtomicFunc(fspath, s.dataDir, s.tmpDir, 0660, persist, func(f io.Writer) error {
_, err := io.Copy(f, r)
return err
return errors.WithStack(err)
})
}
func (s *PosixFlatStorage) DeleteObject(p string) error {
fspath, err := s.fsPath(p)
if err != nil {
return err
return errors.WithStack(err)
}
if err := os.Remove(fspath); err != nil {
if os.IsNotExist(err) {
return NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
}
return err
return errors.WithStack(err)
}
// try to remove parent empty dirs
@ -354,7 +354,7 @@ func (s *PosixFlatStorage) List(prefix, startWith, delimiter string, doneCh <-ch
defer close(objectCh)
err := filepath.Walk(root, func(ep string, info os.FileInfo, err error) error {
if err != nil && !os.IsNotExist(err) {
return err
return errors.WithStack(err)
}
if os.IsNotExist(err) {
return nil
@ -366,11 +366,11 @@ func (s *PosixFlatStorage) List(prefix, startWith, delimiter string, doneCh <-ch
p, err = filepath.Rel(s.dataDir, p)
if err != nil {
return err
return errors.WithStack(err)
}
p, _, err = unescape(p)
if err != nil {
return err
return errors.WithStack(err)
}
if !recursive && len(p) > len(prefix) {
rel := strings.TrimPrefix(p, prefix)
@ -390,7 +390,7 @@ func (s *PosixFlatStorage) List(prefix, startWith, delimiter string, doneCh <-ch
hasFile := true
_, err = os.Stat(ep + ".f")
if err != nil && !os.IsNotExist(err) {
return err
return errors.WithStack(err)
}
if os.IsNotExist(err) {
hasFile = false

View File

@ -21,7 +21,7 @@ import (
"path/filepath"
"testing"
errors "golang.org/x/xerrors"
"agola.io/agola/internal/errors"
)
func TestEscapeUnescape(t *testing.T) {

View File

@ -21,8 +21,8 @@ import (
"os"
"strings"
"agola.io/agola/internal/errors"
minio "github.com/minio/minio-go/v6"
errors "golang.org/x/xerrors"
)
type S3Storage struct {
@ -35,21 +35,21 @@ type S3Storage struct {
func NewS3(bucket, location, endpoint, accessKeyID, secretAccessKey string, secure bool) (*S3Storage, error) {
minioClient, err := minio.New(endpoint, accessKeyID, secretAccessKey, secure)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
minioCore, err := minio.NewCore(endpoint, accessKeyID, secretAccessKey, secure)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
exists, err := minioClient.BucketExists(bucket)
if err != nil {
return nil, errors.Errorf("cannot check if bucket %q in location %q exits: %w", bucket, location, err)
return nil, errors.Wrapf(err, "cannot check if bucket %q in location %q exits", bucket, location)
}
if !exists {
if err := minioClient.MakeBucket(bucket, location); err != nil {
return nil, errors.Errorf("cannot create bucket %q in location %q: %w", bucket, location, err)
return nil, errors.Wrapf(err, "cannot create bucket %q in location %q", bucket, location)
}
}
@ -67,7 +67,7 @@ func (s *S3Storage) Stat(p string) (*ObjectInfo, error) {
if merr.StatusCode == http.StatusNotFound {
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p))
}
return nil, merr
return nil, errors.WithStack(merr)
}
return &ObjectInfo{Path: p, LastModified: oi.LastModified, Size: oi.Size}, nil
@ -79,9 +79,12 @@ func (s *S3Storage) ReadObject(filepath string) (ReadSeekCloser, error) {
if merr.StatusCode == http.StatusNotFound {
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", filepath))
}
return nil, merr
return nil, errors.WithStack(merr)
}
return s.minioClient.GetObject(s.bucket, filepath, minio.GetObjectOptions{})
o, err := s.minioClient.GetObject(s.bucket, filepath, minio.GetObjectOptions{})
return o, errors.WithStack(err)
}
func (s *S3Storage) WriteObject(filepath string, data io.Reader, size int64, persist bool) error {
@ -92,30 +95,30 @@ func (s *S3Storage) WriteObject(filepath string, data io.Reader, size int64, per
if size >= 0 {
lr := io.LimitReader(data, size)
_, err := s.minioClient.PutObject(s.bucket, filepath, lr, size, minio.PutObjectOptions{ContentType: "application/octet-stream"})
return err
return errors.WithStack(err)
}
// hack to know the real file size or minio will do this in memory with big memory usage since s3 doesn't support real streaming of unknown sizes
// TODO(sgotti) wait for minio client to expose an api to provide the max object size so we can remove this
tmpfile, err := ioutil.TempFile(os.TempDir(), "s3")
if err != nil {
return err
return errors.WithStack(err)
}
defer tmpfile.Close()
defer os.Remove(tmpfile.Name())
size, err = io.Copy(tmpfile, data)
if err != nil {
return err
return errors.WithStack(err)
}
if _, err := tmpfile.Seek(0, 0); err != nil {
return err
return errors.WithStack(err)
}
_, err = s.minioClient.PutObject(s.bucket, filepath, tmpfile, size, minio.PutObjectOptions{ContentType: "application/octet-stream"})
return err
return errors.WithStack(err)
}
func (s *S3Storage) DeleteObject(filepath string) error {
return s.minioClient.RemoveObject(s.bucket, filepath)
return errors.WithStack(s.minioClient.RemoveObject(s.bucket, filepath))
}
func (s *S3Storage) List(prefix, startWith, delimiter string, doneCh <-chan struct{}) <-chan ObjectInfo {

View File

@ -19,12 +19,11 @@ import (
"strings"
"agola.io/agola/internal/config"
"agola.io/agola/internal/errors"
itypes "agola.io/agola/internal/services/types"
"agola.io/agola/internal/util"
rstypes "agola.io/agola/services/runservice/types"
"agola.io/agola/services/types"
errors "golang.org/x/xerrors"
)
const (
@ -192,7 +191,7 @@ fi
return rws
default:
panic(fmt.Errorf("unknown config step type: %s", util.Dump(cs)))
panic(errors.Errorf("unknown config step type: %s", util.Dump(cs)))
}
}
@ -461,7 +460,7 @@ func genValue(val config.Value, variables map[string]string) string {
case config.ValueTypeFromVariable:
return variables[val.Value]
default:
panic(fmt.Errorf("wrong value type: %q", val.Value))
panic(errors.Errorf("wrong value type: %q", val.Value))
}
}

View File

@ -20,13 +20,13 @@ import (
"testing"
"agola.io/agola/internal/config"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util"
rstypes "agola.io/agola/services/runservice/types"
"agola.io/agola/services/types"
"k8s.io/apimachinery/pkg/api/resource"
"github.com/google/go-cmp/cmp"
errors "golang.org/x/xerrors"
)
var uuid = &util.TestUUIDGenerator{}
@ -128,7 +128,7 @@ func TestGenTasksLevels(t *testing.T) {
},
},
},
err: fmt.Errorf("circular dependency detected"),
err: errors.Errorf("circular dependency detected"),
},
{
name: "Test circular dependency between 3 tasks: a -> b -> c -> a",
@ -155,7 +155,7 @@ func TestGenTasksLevels(t *testing.T) {
},
},
},
err: fmt.Errorf("circular dependency detected"),
err: errors.Errorf("circular dependency detected"),
},
{
name: "Test circular dependency between 3 tasks: a -> b -> c -> b",
@ -182,7 +182,7 @@ func TestGenTasksLevels(t *testing.T) {
},
},
},
err: fmt.Errorf("circular dependency detected"),
err: errors.Errorf("circular dependency detected"),
},
}
for _, tt := range tests {

View File

@ -23,8 +23,8 @@ import (
"strings"
"time"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/etcd"
errors "golang.org/x/xerrors"
)
type Sequence struct {
@ -55,11 +55,11 @@ func Parse(s string) (*Sequence, error) {
}
epoch, err := strconv.ParseUint(parts[0], 32, 64)
if err != nil {
return nil, errors.Errorf("cannot parse sequence epoch %q: %w", epoch, err)
return nil, errors.Wrapf(err, "cannot parse sequence epoch %q", epoch)
}
c, err := strconv.ParseUint(parts[1], 32, 64)
if err != nil {
return nil, errors.Errorf("cannot parse sequence count %q: %w", c, err)
return nil, errors.Wrapf(err, "cannot parse sequence count %q", c)
}
return &Sequence{
Epoch: epoch,
@ -74,7 +74,7 @@ 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 && !errors.Is(err, etcd.ErrKeyNotFound) {
return nil, false, err
return nil, false, errors.WithStack(err)
}
if errors.Is(err, etcd.ErrKeyNotFound) {
return nil, false, nil
@ -84,7 +84,7 @@ func CurSequence(ctx context.Context, e *etcd.Store, key string) (*Sequence, boo
if !errors.Is(err, etcd.ErrKeyNotFound) {
kv := resp.Kvs[0]
if err := json.Unmarshal(kv.Value, &seq); err != nil {
return nil, false, err
return nil, false, errors.WithStack(err)
}
}
return seq, true, nil
@ -93,7 +93,7 @@ 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 && !errors.Is(err, etcd.ErrKeyNotFound) {
return nil, err
return nil, errors.WithStack(err)
}
var revision int64
@ -101,7 +101,7 @@ func IncSequence(ctx context.Context, e *etcd.Store, key string) (*Sequence, err
if !errors.Is(err, etcd.ErrKeyNotFound) {
kv := resp.Kvs[0]
if err := json.Unmarshal(kv.Value, &seq); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
revision = kv.ModRevision
}
@ -120,12 +120,12 @@ func IncSequence(ctx context.Context, e *etcd.Store, key string) (*Sequence, err
seqj, err := json.Marshal(seq)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
_, err = e.AtomicPut(ctx, key, seqj, revision, nil)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return seq, nil

View File

@ -15,10 +15,11 @@
package sequence
import (
"errors"
"math"
"testing"
"agola.io/agola/internal/errors"
"github.com/google/go-cmp/cmp"
)

View File

@ -15,43 +15,48 @@
package common
import (
"agola.io/agola/internal/errors"
gitsource "agola.io/agola/internal/gitsources"
"agola.io/agola/internal/gitsources/gitea"
"agola.io/agola/internal/gitsources/github"
"agola.io/agola/internal/gitsources/gitlab"
cstypes "agola.io/agola/services/configstore/types"
errors "golang.org/x/xerrors"
)
func newGitea(rs *cstypes.RemoteSource, accessToken string) (*gitea.Client, error) {
return gitea.New(gitea.Opts{
c, err := gitea.New(gitea.Opts{
APIURL: rs.APIURL,
SkipVerify: rs.SkipVerify,
Token: accessToken,
Oauth2ClientID: rs.Oauth2ClientID,
Oauth2Secret: rs.Oauth2ClientSecret,
})
return c, errors.WithStack(err)
}
func newGitlab(rs *cstypes.RemoteSource, accessToken string) (*gitlab.Client, error) {
return gitlab.New(gitlab.Opts{
c, err := gitlab.New(gitlab.Opts{
APIURL: rs.APIURL,
SkipVerify: rs.SkipVerify,
Token: accessToken,
Oauth2ClientID: rs.Oauth2ClientID,
Oauth2Secret: rs.Oauth2ClientSecret,
})
return c, errors.WithStack(err)
}
func newGithub(rs *cstypes.RemoteSource, accessToken string) (*github.Client, error) {
return github.New(github.Opts{
c, err := github.New(github.Opts{
APIURL: rs.APIURL,
SkipVerify: rs.SkipVerify,
Token: accessToken,
Oauth2ClientID: rs.Oauth2ClientID,
Oauth2Secret: rs.Oauth2ClientSecret,
})
return c, errors.WithStack(err)
}
func GetAccessToken(rs *cstypes.RemoteSource, userAccessToken, oauth2AccessToken string) (string, error) {
@ -71,7 +76,7 @@ func GetGitSource(rs *cstypes.RemoteSource, la *cstypes.LinkedAccount) (gitsourc
var err error
accessToken, err = GetAccessToken(rs, la.UserAccessToken, la.Oauth2AccessToken)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
}
@ -88,7 +93,7 @@ func GetGitSource(rs *cstypes.RemoteSource, la *cstypes.LinkedAccount) (gitsourc
return nil, errors.Errorf("remote source %s isn't a valid git source", rs.Name)
}
return gitSource, err
return gitSource, errors.WithStack(err)
}
func GetUserSource(rs *cstypes.RemoteSource, accessToken string) (gitsource.UserSource, error) {
@ -103,7 +108,7 @@ func GetUserSource(rs *cstypes.RemoteSource, accessToken string) (gitsource.User
return nil, errors.Errorf("unknown remote source auth type")
}
return userSource, err
return userSource, errors.WithStack(err)
}
func GetOauth2Source(rs *cstypes.RemoteSource, accessToken string) (gitsource.Oauth2Source, error) {
@ -120,7 +125,7 @@ func GetOauth2Source(rs *cstypes.RemoteSource, accessToken string) (gitsource.Oa
return nil, errors.Errorf("remote source %s isn't a valid oauth2 source", rs.Name)
}
return oauth2Source, err
return oauth2Source, errors.WithStack(err)
}
func GetPasswordSource(rs *cstypes.RemoteSource, accessToken string) (gitsource.PasswordSource, error) {
@ -133,5 +138,5 @@ func GetPasswordSource(rs *cstypes.RemoteSource, accessToken string) (gitsource.
return nil, errors.Errorf("remote source %s isn't a valid oauth2 source", rs.Name)
}
return passwordSource, err
return passwordSource, errors.WithStack(err)
}

View File

@ -19,8 +19,8 @@ import (
"encoding/json"
"time"
"agola.io/agola/internal/errors"
"github.com/golang-jwt/jwt/v4"
errors "golang.org/x/xerrors"
)
type TokenSigningData struct {
@ -44,13 +44,14 @@ func GenerateGenericJWTToken(sd *TokenSigningData, claims jwt.Claims) (string, e
return "", errors.Errorf("unsupported signing method %q", sd.Method.Alg())
}
// Sign and get the complete encoded token as a string
return token.SignedString(key)
ts, err := token.SignedString(key)
return ts, errors.WithStack(err)
}
func GenerateOauth2JWTToken(sd *TokenSigningData, remoteSourceName, requestType string, request interface{}) (string, error) {
requestj, err := json.Marshal(request)
if err != nil {
return "", err
return "", errors.WithStack(err)
}
return GenerateGenericJWTToken(sd, jwt.MapClaims{

View File

@ -15,13 +15,12 @@
package common
import (
"fmt"
"net/url"
"path"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/services/types"
"agola.io/agola/internal/util"
errors "golang.org/x/xerrors"
)
type GroupType string
@ -49,7 +48,7 @@ func WebHookEventToRunRefType(we types.WebhookEvent) types.RunRefType {
return types.RunRefTypePullRequest
}
panic(fmt.Errorf("invalid webhook event type: %q", we))
panic(errors.Errorf("invalid webhook event type: %q", we))
}
func GenRunGroup(baseGroupType GroupType, baseGroupID string, groupType GroupType, group string) string {

View File

@ -18,9 +18,9 @@ import (
"io/ioutil"
"time"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util"
errors "golang.org/x/xerrors"
yaml "gopkg.in/yaml.v2"
)
@ -273,12 +273,12 @@ var defaultConfig = Config{
func Parse(configFile string, componentsNames []string) (*Config, error) {
configData, err := ioutil.ReadFile(configFile)
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
c := &defaultConfig
if err := yaml.Unmarshal(configData, &c); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return c, Validate(c, componentsNames)
@ -333,7 +333,7 @@ func Validate(c *Config, componentsNames []string) error {
return errors.Errorf("gateway runserviceURL is empty")
}
if err := validateWeb(&c.Gateway.Web); err != nil {
return errors.Errorf("gateway web configuration error: %w", err)
return errors.Wrapf(err, "gateway web configuration error")
}
}
@ -343,7 +343,7 @@ func Validate(c *Config, componentsNames []string) error {
return errors.Errorf("configstore dataDir is empty")
}
if err := validateWeb(&c.Configstore.Web); err != nil {
return errors.Errorf("configstore web configuration error: %w", err)
return errors.Wrapf(err, "configstore web configuration error")
}
}
@ -353,7 +353,7 @@ func Validate(c *Config, componentsNames []string) error {
return errors.Errorf("runservice dataDir is empty")
}
if err := validateWeb(&c.Runservice.Web); err != nil {
return errors.Errorf("runservice web configuration error: %w", err)
return errors.Wrapf(err, "runservice web configuration error")
}
}
@ -379,7 +379,7 @@ func Validate(c *Config, componentsNames []string) error {
}
if err := validateInitImage(&c.Executor.InitImage); err != nil {
return errors.Errorf("executor initImage configuration error: %w", err)
return errors.Wrapf(err, "executor initImage configuration error")
}
}

View File

@ -20,7 +20,7 @@ import (
"path"
"testing"
errors "golang.org/x/xerrors"
"agola.io/agola/internal/errors"
)
func TestParseConfig(t *testing.T) {

View File

@ -17,13 +17,13 @@ package action
import (
"agola.io/agola/internal/datamanager"
"agola.io/agola/internal/db"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/etcd"
"agola.io/agola/internal/services/configstore/readdb"
"agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types"
"github.com/rs/zerolog"
errors "golang.org/x/xerrors"
)
type ActionHandler struct {
@ -53,7 +53,7 @@ func (h *ActionHandler) ResolveConfigID(tx *db.Tx, configType types.ConfigType,
case types.ConfigTypeProjectGroup:
group, err := h.readDB.GetProjectGroup(tx, ref)
if err != nil {
return "", err
return "", errors.WithStack(err)
}
if group == nil {
return "", util.NewAPIError(util.ErrBadRequest, errors.Errorf("group with ref %q doesn't exists", ref))
@ -63,7 +63,7 @@ func (h *ActionHandler) ResolveConfigID(tx *db.Tx, configType types.ConfigType,
case types.ConfigTypeProject:
project, err := h.readDB.GetProject(tx, ref)
if err != nil {
return "", err
return "", errors.WithStack(err)
}
if project == nil {
return "", util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with ref %q doesn't exists", ref))

View File

@ -18,17 +18,16 @@ import (
"context"
"io"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/etcd"
"agola.io/agola/internal/services/configstore/common"
"agola.io/agola/internal/util"
errors "golang.org/x/xerrors"
)
func (h *ActionHandler) MaintenanceMode(ctx context.Context, enable bool) error {
resp, err := h.e.Get(ctx, common.EtcdMaintenanceKey, 0)
if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) {
return err
return errors.WithStack(err)
}
if enable && len(resp.Kvs) > 0 {
@ -41,7 +40,7 @@ func (h *ActionHandler) MaintenanceMode(ctx context.Context, enable bool) error
if enable {
txResp, err := h.e.AtomicPut(ctx, common.EtcdMaintenanceKey, []byte{}, 0, nil)
if err != nil {
return err
return errors.WithStack(err)
}
if !txResp.Succeeded {
return errors.Errorf("failed to create maintenance mode key due to concurrent update")
@ -51,7 +50,7 @@ func (h *ActionHandler) MaintenanceMode(ctx context.Context, enable bool) error
if !enable {
txResp, err := h.e.AtomicDelete(ctx, common.EtcdMaintenanceKey, resp.Kvs[0].ModRevision)
if err != nil {
return err
return errors.WithStack(err)
}
if !txResp.Succeeded {
return errors.Errorf("failed to delete maintenance mode key due to concurrent update")
@ -62,12 +61,12 @@ func (h *ActionHandler) MaintenanceMode(ctx context.Context, enable bool) error
}
func (h *ActionHandler) Export(ctx context.Context, w io.Writer) error {
return h.dm.Export(ctx, w)
return errors.WithStack(h.dm.Export(ctx, w))
}
func (h *ActionHandler) Import(ctx context.Context, r io.Reader) error {
if !h.maintenanceMode {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("not in maintenance mode"))
}
return h.dm.Import(ctx, r)
return errors.WithStack(h.dm.Import(ctx, r))
}

View File

@ -22,12 +22,13 @@ import (
"agola.io/agola/internal/datamanager"
"agola.io/agola/internal/db"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/services/configstore/readdb"
"agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types"
"github.com/gofrs/uuid"
errors "golang.org/x/xerrors"
)
type OrgMemberResponse struct {
@ -48,17 +49,17 @@ func (h *ActionHandler) GetOrgMembers(ctx context.Context, orgRef string) ([]*Or
var err error
org, err := h.readDB.GetOrg(tx, orgRef)
if err != nil {
return err
return errors.WithStack(err)
}
if org == nil {
return util.NewAPIError(util.ErrNotExist, errors.Errorf("org %q doesn't exist", orgRef))
}
orgUsers, err = h.readDB.GetOrgUsers(tx, org.ID)
return err
return errors.WithStack(err)
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
res := make([]*OrgMemberResponse, len(orgUsers))
@ -89,13 +90,13 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
var err error
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
// check duplicate org name
o, err := h.readDB.GetOrgByName(tx, org.Name)
if err != nil {
return err
return errors.WithStack(err)
}
if o != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q already exists", o.Name))
@ -104,7 +105,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
if org.CreatorUserID != "" {
user, err := h.readDB.GetUser(tx, org.CreatorUserID)
if err != nil {
return err
return errors.WithStack(err)
}
if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("creator user %q doesn't exist", org.CreatorUserID))
@ -114,7 +115,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
actions := []*datamanager.Action{}
@ -123,7 +124,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
org.CreatedAt = time.Now()
orgj, err := json.Marshal(org)
if err != nil {
return nil, errors.Errorf("failed to marshal org: %w", err)
return nil, errors.Wrapf(err, "failed to marshal org")
}
actions = append(actions, &datamanager.Action{
ActionType: datamanager.ActionTypePut,
@ -142,7 +143,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
}
orgmemberj, err := json.Marshal(orgmember)
if err != nil {
return nil, errors.Errorf("failed to marshal project group: %w", err)
return nil, errors.Wrapf(err, "failed to marshal project group")
}
actions = append(actions, &datamanager.Action{
ActionType: datamanager.ActionTypePut,
@ -164,7 +165,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
}
pgj, err := json.Marshal(pg)
if err != nil {
return nil, errors.Errorf("failed to marshal project group: %w", err)
return nil, errors.Wrapf(err, "failed to marshal project group")
}
actions = append(actions, &datamanager.Action{
ActionType: datamanager.ActionTypePut,
@ -174,7 +175,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
})
_, err = h.dm.WriteWal(ctx, actions, cgt)
return org, err
return org, errors.WithStack(err)
}
func (h *ActionHandler) DeleteOrg(ctx context.Context, orgRef string) error {
@ -187,7 +188,7 @@ func (h *ActionHandler) DeleteOrg(ctx context.Context, orgRef string) error {
// check org existance
org, err = h.readDB.GetOrgByName(tx, orgRef)
if err != nil {
return err
return errors.WithStack(err)
}
if org == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q doesn't exist", orgRef))
@ -197,13 +198,13 @@ func (h *ActionHandler) DeleteOrg(ctx context.Context, orgRef string) error {
cgNames := []string{util.EncodeSha256Hex("orgid-" + org.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return err
return errors.WithStack(err)
}
// TODO(sgotti) delete all project groups, projects etc...
@ -216,7 +217,7 @@ func (h *ActionHandler) DeleteOrg(ctx context.Context, orgRef string) error {
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return err
return errors.WithStack(err)
}
// AddOrgMember add/updates an org member.
@ -237,7 +238,7 @@ func (h *ActionHandler) AddOrgMember(ctx context.Context, orgRef, userRef string
// check existing org
org, err = h.readDB.GetOrg(tx, orgRef)
if err != nil {
return err
return errors.WithStack(err)
}
if org == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q doesn't exists", orgRef))
@ -245,7 +246,7 @@ func (h *ActionHandler) AddOrgMember(ctx context.Context, orgRef, userRef string
// check existing user
user, err = h.readDB.GetUser(tx, userRef)
if err != nil {
return err
return errors.WithStack(err)
}
if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exists", userRef))
@ -254,19 +255,19 @@ func (h *ActionHandler) AddOrgMember(ctx context.Context, orgRef, userRef string
// fetch org member if it already exist
orgmember, err = h.readDB.GetOrgMemberByOrgUserID(tx, org.ID, user.ID)
if err != nil {
return err
return errors.WithStack(err)
}
cgNames := []string{util.EncodeSha256Hex(fmt.Sprintf("orgmember-%s-%s", org.ID, user.ID))}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
// update if role changed
@ -287,7 +288,7 @@ func (h *ActionHandler) AddOrgMember(ctx context.Context, orgRef, userRef string
actions := []*datamanager.Action{}
orgmemberj, err := json.Marshal(orgmember)
if err != nil {
return nil, errors.Errorf("failed to marshal project group: %w", err)
return nil, errors.Wrapf(err, "failed to marshal project group")
}
actions = append(actions, &datamanager.Action{
ActionType: datamanager.ActionTypePut,
@ -297,7 +298,7 @@ func (h *ActionHandler) AddOrgMember(ctx context.Context, orgRef, userRef string
})
_, err = h.dm.WriteWal(ctx, actions, cgt)
return orgmember, err
return orgmember, errors.WithStack(err)
}
// RemoveOrgMember removes an org member.
@ -313,7 +314,7 @@ func (h *ActionHandler) RemoveOrgMember(ctx context.Context, orgRef, userRef str
// check existing org
org, err = h.readDB.GetOrg(tx, orgRef)
if err != nil {
return err
return errors.WithStack(err)
}
if org == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q doesn't exists", orgRef))
@ -321,7 +322,7 @@ func (h *ActionHandler) RemoveOrgMember(ctx context.Context, orgRef, userRef str
// check existing user
user, err = h.readDB.GetUser(tx, userRef)
if err != nil {
return err
return errors.WithStack(err)
}
if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exists", userRef))
@ -330,7 +331,7 @@ func (h *ActionHandler) RemoveOrgMember(ctx context.Context, orgRef, userRef str
// check that org member exists
orgmember, err = h.readDB.GetOrgMemberByOrgUserID(tx, org.ID, user.ID)
if err != nil {
return err
return errors.WithStack(err)
}
if orgmember == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("orgmember for org %q, user %q doesn't exists", orgRef, userRef))
@ -339,13 +340,13 @@ func (h *ActionHandler) RemoveOrgMember(ctx context.Context, orgRef, userRef str
cgNames := []string{util.EncodeSha256Hex(fmt.Sprintf("orgmember-%s-%s", org.ID, user.ID))}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return err
return errors.WithStack(err)
}
actions := []*datamanager.Action{}
@ -356,5 +357,5 @@ func (h *ActionHandler) RemoveOrgMember(ctx context.Context, orgRef, userRef str
})
_, err = h.dm.WriteWal(ctx, actions, cgt)
return err
return errors.WithStack(err)
}

View File

@ -21,11 +21,12 @@ import (
"agola.io/agola/internal/datamanager"
"agola.io/agola/internal/db"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types"
"github.com/gofrs/uuid"
errors "golang.org/x/xerrors"
)
func (h *ActionHandler) ValidateProject(ctx context.Context, project *types.Project) error {
@ -69,10 +70,10 @@ func (h *ActionHandler) GetProject(ctx context.Context, projectRef string) (*typ
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
var err error
project, err = h.readDB.GetProject(tx, projectRef)
return err
return errors.WithStack(err)
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if project == nil {
@ -84,7 +85,7 @@ func (h *ActionHandler) GetProject(ctx context.Context, projectRef string) (*typ
func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Project) (*types.Project, error) {
if err := h.ValidateProject(ctx, project); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
var cgt *datamanager.ChangeGroupsUpdateToken
@ -94,7 +95,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
var err error
group, err := h.readDB.GetProjectGroup(tx, project.Parent.ID)
if err != nil {
return err
return errors.WithStack(err)
}
if group == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", project.Parent.ID))
@ -103,7 +104,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
groupPath, err := h.readDB.GetProjectGroupPath(tx, group)
if err != nil {
return err
return errors.WithStack(err)
}
pp := path.Join(groupPath, project.Name)
@ -112,13 +113,13 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
cgNames := []string{util.EncodeSha256Hex("projectpath-" + pp)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
// check duplicate project name
p, err := h.readDB.GetProjectByName(tx, project.Parent.ID, project.Name)
if err != nil {
return err
return errors.WithStack(err)
}
if p != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with name %q, path %q already exists", p.Name, pp))
@ -128,7 +129,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
// check that the linked account matches the remote source
user, err := h.readDB.GetUserByLinkedAccount(tx, project.LinkedAccountID)
if err != nil {
return errors.Errorf("failed to get user with linked account id %q: %w", project.LinkedAccountID, err)
return errors.Wrapf(err, "failed to get user with linked account id %q", project.LinkedAccountID)
}
if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user for linked account %q doesn't exist", project.LinkedAccountID))
@ -145,7 +146,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
project.ID = uuid.Must(uuid.NewV4()).String()
@ -156,7 +157,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
pcj, err := json.Marshal(project)
if err != nil {
return nil, errors.Errorf("failed to marshal project: %w", err)
return nil, errors.Wrapf(err, "failed to marshal project")
}
actions := []*datamanager.Action{
{
@ -168,7 +169,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return project, err
return project, errors.WithStack(err)
}
type UpdateProjectRequest struct {
@ -179,7 +180,7 @@ type UpdateProjectRequest struct {
func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectRequest) (*types.Project, error) {
if err := h.ValidateProject(ctx, req.Project); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
var cgt *datamanager.ChangeGroupsUpdateToken
@ -190,7 +191,7 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
// check project exists
p, err := h.readDB.GetProject(tx, req.ProjectRef)
if err != nil {
return err
return errors.WithStack(err)
}
if p == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with ref %q doesn't exist", req.ProjectRef))
@ -203,7 +204,7 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
// check parent project group exists
group, err := h.readDB.GetProjectGroup(tx, req.Project.Parent.ID)
if err != nil {
return err
return errors.WithStack(err)
}
if group == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", req.Project.Parent.ID))
@ -212,7 +213,7 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
groupPath, err := h.readDB.GetProjectGroupPath(tx, group)
if err != nil {
return err
return errors.WithStack(err)
}
pp := path.Join(groupPath, req.Project.Name)
@ -220,7 +221,7 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
// check duplicate project name
ap, err := h.readDB.GetProjectByName(tx, req.Project.Parent.ID, req.Project.Name)
if err != nil {
return err
return errors.WithStack(err)
}
if ap != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with name %q, path %q already exists", req.Project.Name, pp))
@ -236,14 +237,14 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
// get old parent project group
curGroup, err := h.readDB.GetProjectGroup(tx, p.Parent.ID)
if err != nil {
return err
return errors.WithStack(err)
}
if curGroup == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", p.Parent.ID))
}
curGroupPath, err := h.readDB.GetProjectGroupPath(tx, curGroup)
if err != nil {
return err
return errors.WithStack(err)
}
pp := path.Join(curGroupPath, req.Project.Name)
@ -252,14 +253,14 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
if req.Project.RemoteRepositoryConfigType == types.RemoteRepositoryConfigTypeRemoteSource {
// check that the linked account matches the remote source
user, err := h.readDB.GetUserByLinkedAccount(tx, req.Project.LinkedAccountID)
if err != nil {
return errors.Errorf("failed to get user with linked account id %q: %w", req.Project.LinkedAccountID, err)
return errors.Wrapf(err, "failed to get user with linked account id %q", req.Project.LinkedAccountID)
}
if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user for linked account %q doesn't exist", req.Project.LinkedAccountID))
@ -276,12 +277,12 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
pcj, err := json.Marshal(req.Project)
if err != nil {
return nil, errors.Errorf("failed to marshal project: %w", err)
return nil, errors.Wrapf(err, "failed to marshal project")
}
actions := []*datamanager.Action{
{
@ -293,7 +294,7 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return req.Project, err
return req.Project, errors.WithStack(err)
}
func (h *ActionHandler) DeleteProject(ctx context.Context, projectRef string) error {
@ -308,7 +309,7 @@ func (h *ActionHandler) DeleteProject(ctx context.Context, projectRef string) er
// check project existance
project, err = h.readDB.GetProject(tx, projectRef)
if err != nil {
return err
return errors.WithStack(err)
}
if project == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project %q doesn't exist", projectRef))
@ -318,13 +319,13 @@ func (h *ActionHandler) DeleteProject(ctx context.Context, projectRef string) er
cgNames := []string{util.EncodeSha256Hex(project.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return err
return errors.WithStack(err)
}
// TODO(sgotti) implement childs garbage collection
@ -337,5 +338,5 @@ func (h *ActionHandler) DeleteProject(ctx context.Context, projectRef string) er
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return err
return errors.WithStack(err)
}

View File

@ -22,11 +22,12 @@ import (
"agola.io/agola/internal/datamanager"
"agola.io/agola/internal/db"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types"
"github.com/gofrs/uuid"
errors "golang.org/x/xerrors"
)
func (h *ActionHandler) GetProjectGroup(ctx context.Context, projectGroupRef string) (*types.ProjectGroup, error) {
@ -34,10 +35,10 @@ func (h *ActionHandler) GetProjectGroup(ctx context.Context, projectGroupRef str
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
var err error
projectGroup, err = h.readDB.GetProjectGroup(tx, projectGroupRef)
return err
return errors.WithStack(err)
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if projectGroup == nil {
@ -53,7 +54,7 @@ func (h *ActionHandler) GetProjectGroupSubgroups(ctx context.Context, projectGro
var err error
projectGroup, err := h.readDB.GetProjectGroup(tx, projectGroupRef)
if err != nil {
return err
return errors.WithStack(err)
}
if projectGroup == nil {
@ -61,10 +62,10 @@ func (h *ActionHandler) GetProjectGroupSubgroups(ctx context.Context, projectGro
}
projectGroups, err = h.readDB.GetProjectGroupSubgroups(tx, projectGroup.ID)
return err
return errors.WithStack(err)
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return projectGroups, nil
@ -76,7 +77,7 @@ func (h *ActionHandler) GetProjectGroupProjects(ctx context.Context, projectGrou
var err error
projectGroup, err := h.readDB.GetProjectGroup(tx, projectGroupRef)
if err != nil {
return err
return errors.WithStack(err)
}
if projectGroup == nil {
@ -84,10 +85,10 @@ func (h *ActionHandler) GetProjectGroupProjects(ctx context.Context, projectGrou
}
projects, err = h.readDB.GetProjectGroupProjects(tx, projectGroup.ID)
return err
return errors.WithStack(err)
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return projects, nil
}
@ -125,7 +126,7 @@ func (h *ActionHandler) ValidateProjectGroup(ctx context.Context, projectGroup *
func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *types.ProjectGroup) (*types.ProjectGroup, error) {
if err := h.ValidateProjectGroup(ctx, projectGroup); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if projectGroup.Parent.Type != types.ConfigTypeProjectGroup {
@ -138,7 +139,7 @@ func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *ty
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
parentProjectGroup, err := h.readDB.GetProjectGroup(tx, projectGroup.Parent.ID)
if err != nil {
return err
return errors.WithStack(err)
}
if parentProjectGroup == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", projectGroup.Parent.ID))
@ -150,7 +151,7 @@ func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *ty
groupPath, err := h.readDB.GetProjectGroupPath(tx, parentProjectGroup)
if err != nil {
return err
return errors.WithStack(err)
}
pp := path.Join(groupPath, projectGroup.Name)
@ -159,13 +160,13 @@ func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *ty
cgNames := []string{util.EncodeSha256Hex("projectpath-" + pp)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
// check duplicate project group name
pg, err := h.readDB.GetProjectGroupByName(tx, projectGroup.Parent.ID, projectGroup.Name)
if err != nil {
return err
return errors.WithStack(err)
}
if pg != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with name %q, path %q already exists", pg.Name, pp))
@ -173,7 +174,7 @@ func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *ty
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
projectGroup.ID = uuid.Must(uuid.NewV4()).String()
@ -181,7 +182,7 @@ func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *ty
pgj, err := json.Marshal(projectGroup)
if err != nil {
return nil, errors.Errorf("failed to marshal projectGroup: %w", err)
return nil, errors.Wrapf(err, "failed to marshal projectGroup")
}
actions := []*datamanager.Action{
{
@ -193,7 +194,7 @@ func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *ty
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return projectGroup, err
return projectGroup, errors.WithStack(err)
}
type UpdateProjectGroupRequest struct {
@ -204,7 +205,7 @@ type UpdateProjectGroupRequest struct {
func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProjectGroupRequest) (*types.ProjectGroup, error) {
if err := h.ValidateProjectGroup(ctx, req.ProjectGroup); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
var cgt *datamanager.ChangeGroupsUpdateToken
@ -215,7 +216,7 @@ func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProje
// check project exists
pg, err := h.readDB.GetProjectGroup(tx, req.ProjectGroupRef)
if err != nil {
return err
return errors.WithStack(err)
}
if pg == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with ref %q doesn't exist", req.ProjectGroupRef))
@ -244,7 +245,7 @@ func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProje
// check parent exists
group, err := h.readDB.GetProjectGroup(tx, req.ProjectGroup.Parent.ID)
if err != nil {
return err
return errors.WithStack(err)
}
if group == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", req.ProjectGroup.Parent.ID))
@ -257,13 +258,13 @@ func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProje
curPGParentPath, err := h.readDB.GetPath(tx, pg.Parent.Type, pg.Parent.ID)
if err != nil {
return err
return errors.WithStack(err)
}
curPGP := path.Join(curPGParentPath, pg.Name)
pgParentPath, err := h.readDB.GetPath(tx, req.ProjectGroup.Parent.Type, req.ProjectGroup.Parent.ID)
if err != nil {
return err
return errors.WithStack(err)
}
pgp := path.Join(pgParentPath, req.ProjectGroup.Name)
@ -271,7 +272,7 @@ func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProje
// check duplicate project group name
ap, err := h.readDB.GetProjectGroupByName(tx, req.ProjectGroup.Parent.ID, req.ProjectGroup.Name)
if err != nil {
return err
return errors.WithStack(err)
}
if ap != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with name %q, path %q already exists", req.ProjectGroup.Name, pgp))
@ -293,18 +294,18 @@ func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProje
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
pgj, err := json.Marshal(req.ProjectGroup)
if err != nil {
return nil, errors.Errorf("failed to marshal project: %w", err)
return nil, errors.Wrapf(err, "failed to marshal project")
}
actions := []*datamanager.Action{
{
@ -316,7 +317,7 @@ func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProje
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return req.ProjectGroup, err
return req.ProjectGroup, errors.WithStack(err)
}
func (h *ActionHandler) DeleteProjectGroup(ctx context.Context, projectGroupRef string) error {
@ -331,7 +332,7 @@ func (h *ActionHandler) DeleteProjectGroup(ctx context.Context, projectGroupRef
// check project group existance
projectGroup, err = h.readDB.GetProjectGroup(tx, projectGroupRef)
if err != nil {
return err
return errors.WithStack(err)
}
if projectGroup == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group %q doesn't exist", projectGroupRef))
@ -347,13 +348,13 @@ func (h *ActionHandler) DeleteProjectGroup(ctx context.Context, projectGroupRef
cgNames := []string{util.EncodeSha256Hex(projectGroup.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return err
return errors.WithStack(err)
}
// TODO(sgotti) implement childs garbage collection
@ -366,5 +367,5 @@ func (h *ActionHandler) DeleteProjectGroup(ctx context.Context, projectGroupRef
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return err
return errors.WithStack(err)
}

View File

@ -20,11 +20,12 @@ import (
"agola.io/agola/internal/datamanager"
"agola.io/agola/internal/db"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types"
"github.com/gofrs/uuid"
errors "golang.org/x/xerrors"
)
func (h *ActionHandler) ValidateRemoteSource(ctx context.Context, remoteSource *types.RemoteSource) error {
@ -66,7 +67,7 @@ func (h *ActionHandler) ValidateRemoteSource(ctx context.Context, remoteSource *
func (h *ActionHandler) CreateRemoteSource(ctx context.Context, remoteSource *types.RemoteSource) (*types.RemoteSource, error) {
if err := h.ValidateRemoteSource(ctx, remoteSource); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
var cgt *datamanager.ChangeGroupsUpdateToken
@ -78,13 +79,13 @@ func (h *ActionHandler) CreateRemoteSource(ctx context.Context, remoteSource *ty
var err error
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
// check duplicate remoteSource name
u, err := h.readDB.GetRemoteSourceByName(tx, remoteSource.Name)
if err != nil {
return err
return errors.WithStack(err)
}
if u != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource %q already exists", u.Name))
@ -92,14 +93,14 @@ func (h *ActionHandler) CreateRemoteSource(ctx context.Context, remoteSource *ty
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
remoteSource.ID = uuid.Must(uuid.NewV4()).String()
rsj, err := json.Marshal(remoteSource)
if err != nil {
return nil, errors.Errorf("failed to marshal remotesource: %w", err)
return nil, errors.Wrapf(err, "failed to marshal remotesource")
}
actions := []*datamanager.Action{
{
@ -111,7 +112,7 @@ func (h *ActionHandler) CreateRemoteSource(ctx context.Context, remoteSource *ty
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return remoteSource, err
return remoteSource, errors.WithStack(err)
}
type UpdateRemoteSourceRequest struct {
@ -122,7 +123,7 @@ type UpdateRemoteSourceRequest struct {
func (h *ActionHandler) UpdateRemoteSource(ctx context.Context, req *UpdateRemoteSourceRequest) (*types.RemoteSource, error) {
if err := h.ValidateRemoteSource(ctx, req.RemoteSource); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
var curRemoteSource *types.RemoteSource
@ -135,7 +136,7 @@ func (h *ActionHandler) UpdateRemoteSource(ctx context.Context, req *UpdateRemot
// check remotesource exists
curRemoteSource, err = h.readDB.GetRemoteSourceByName(tx, req.RemoteSourceRef)
if err != nil {
return err
return errors.WithStack(err)
}
if curRemoteSource == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource with ref %q doesn't exist", req.RemoteSourceRef))
@ -145,7 +146,7 @@ func (h *ActionHandler) UpdateRemoteSource(ctx context.Context, req *UpdateRemot
// check duplicate remoteSource name
u, err := h.readDB.GetRemoteSourceByName(tx, req.RemoteSource.Name)
if err != nil {
return err
return errors.WithStack(err)
}
if u != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource %q already exists", u.Name))
@ -160,17 +161,17 @@ func (h *ActionHandler) UpdateRemoteSource(ctx context.Context, req *UpdateRemot
cgNames := []string{util.EncodeSha256Hex("remotesourcename-" + req.RemoteSource.Name), util.EncodeSha256Hex("remotesourceid-" + req.RemoteSource.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
rsj, err := json.Marshal(req.RemoteSource)
if err != nil {
return nil, errors.Errorf("failed to marshal remotesource: %w", err)
return nil, errors.Wrapf(err, "failed to marshal remotesource")
}
actions := []*datamanager.Action{
{
@ -182,7 +183,7 @@ func (h *ActionHandler) UpdateRemoteSource(ctx context.Context, req *UpdateRemot
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return req.RemoteSource, err
return req.RemoteSource, errors.WithStack(err)
}
func (h *ActionHandler) DeleteRemoteSource(ctx context.Context, remoteSourceName string) error {
@ -196,7 +197,7 @@ func (h *ActionHandler) DeleteRemoteSource(ctx context.Context, remoteSourceName
// check remoteSource existance
remoteSource, err = h.readDB.GetRemoteSourceByName(tx, remoteSourceName)
if err != nil {
return err
return errors.WithStack(err)
}
if remoteSource == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource %q doesn't exist", remoteSourceName))
@ -206,13 +207,13 @@ func (h *ActionHandler) DeleteRemoteSource(ctx context.Context, remoteSourceName
cgNames := []string{util.EncodeSha256Hex("remotesourceid-" + remoteSource.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return err
return errors.WithStack(err)
}
actions := []*datamanager.Action{
@ -225,5 +226,5 @@ func (h *ActionHandler) DeleteRemoteSource(ctx context.Context, remoteSourceName
// changegroup is all the remotesources
_, err = h.dm.WriteWal(ctx, actions, cgt)
return err
return errors.WithStack(err)
}

View File

@ -20,11 +20,12 @@ import (
"agola.io/agola/internal/datamanager"
"agola.io/agola/internal/db"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types"
"github.com/gofrs/uuid"
errors "golang.org/x/xerrors"
)
func (h *ActionHandler) GetSecret(ctx context.Context, secretID string) (*types.Secret, error) {
@ -32,10 +33,10 @@ func (h *ActionHandler) GetSecret(ctx context.Context, secretID string) (*types.
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
var err error
secret, err = h.readDB.GetSecretByID(tx, secretID)
return err
return errors.WithStack(err)
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if secret == nil {
@ -50,17 +51,17 @@ func (h *ActionHandler) GetSecrets(ctx context.Context, parentType types.ConfigT
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
if err != nil {
return err
return errors.WithStack(err)
}
if tree {
secrets, err = h.readDB.GetSecretsTree(tx, parentType, parentID)
} else {
secrets, err = h.readDB.GetSecrets(tx, parentID)
}
return err
return errors.WithStack(err)
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return secrets, nil
@ -97,7 +98,7 @@ func (h *ActionHandler) ValidateSecret(ctx context.Context, secret *types.Secret
func (h *ActionHandler) CreateSecret(ctx context.Context, secret *types.Secret) (*types.Secret, error) {
if err := h.ValidateSecret(ctx, secret); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
var cgt *datamanager.ChangeGroupsUpdateToken
@ -109,19 +110,19 @@ func (h *ActionHandler) CreateSecret(ctx context.Context, secret *types.Secret)
var err error
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
parentID, err := h.ResolveConfigID(tx, secret.Parent.Type, secret.Parent.ID)
if err != nil {
return err
return errors.WithStack(err)
}
secret.Parent.ID = parentID
// check duplicate secret name
s, err := h.readDB.GetSecretByName(tx, secret.Parent.ID, secret.Name)
if err != nil {
return err
return errors.WithStack(err)
}
if s != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("secret with name %q for %s with id %q already exists", secret.Name, secret.Parent.Type, secret.Parent.ID))
@ -130,14 +131,14 @@ func (h *ActionHandler) CreateSecret(ctx context.Context, secret *types.Secret)
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
secret.ID = uuid.Must(uuid.NewV4()).String()
secretj, err := json.Marshal(secret)
if err != nil {
return nil, errors.Errorf("failed to marshal secret: %w", err)
return nil, errors.Wrapf(err, "failed to marshal secret")
}
actions := []*datamanager.Action{
{
@ -149,7 +150,7 @@ func (h *ActionHandler) CreateSecret(ctx context.Context, secret *types.Secret)
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return secret, err
return secret, errors.WithStack(err)
}
type UpdateSecretRequest struct {
@ -160,7 +161,7 @@ type UpdateSecretRequest struct {
func (h *ActionHandler) UpdateSecret(ctx context.Context, req *UpdateSecretRequest) (*types.Secret, error) {
if err := h.ValidateSecret(ctx, req.Secret); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
var curSecret *types.Secret
@ -173,14 +174,14 @@ func (h *ActionHandler) UpdateSecret(ctx context.Context, req *UpdateSecretReque
parentID, err := h.ResolveConfigID(tx, req.Secret.Parent.Type, req.Secret.Parent.ID)
if err != nil {
return err
return errors.WithStack(err)
}
req.Secret.Parent.ID = parentID
// check secret exists
curSecret, err = h.readDB.GetSecretByName(tx, req.Secret.Parent.ID, req.SecretName)
if err != nil {
return err
return errors.WithStack(err)
}
if curSecret == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("secret with name %q for %s with id %q doesn't exists", req.SecretName, req.Secret.Parent.Type, req.Secret.Parent.ID))
@ -190,7 +191,7 @@ func (h *ActionHandler) UpdateSecret(ctx context.Context, req *UpdateSecretReque
// check duplicate secret name
u, err := h.readDB.GetSecretByName(tx, req.Secret.Parent.ID, req.Secret.Name)
if err != nil {
return err
return errors.WithStack(err)
}
if u != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("secret with name %q for %s with id %q already exists", req.Secret.Name, req.Secret.Parent.Type, req.Secret.Parent.ID))
@ -206,18 +207,18 @@ func (h *ActionHandler) UpdateSecret(ctx context.Context, req *UpdateSecretReque
}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
secretj, err := json.Marshal(req.Secret)
if err != nil {
return nil, errors.Errorf("failed to marshal secret: %w", err)
return nil, errors.Wrapf(err, "failed to marshal secret")
}
actions := []*datamanager.Action{
{
@ -229,7 +230,7 @@ func (h *ActionHandler) UpdateSecret(ctx context.Context, req *UpdateSecretReque
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return req.Secret, err
return req.Secret, errors.WithStack(err)
}
func (h *ActionHandler) DeleteSecret(ctx context.Context, parentType types.ConfigType, parentRef, secretName string) error {
@ -242,13 +243,13 @@ func (h *ActionHandler) DeleteSecret(ctx context.Context, parentType types.Confi
var err error
parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
if err != nil {
return err
return errors.WithStack(err)
}
// check secret existance
secret, err = h.readDB.GetSecretByName(tx, parentID, secretName)
if err != nil {
return err
return errors.WithStack(err)
}
if secret == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("secret with name %q doesn't exist", secretName))
@ -258,13 +259,13 @@ func (h *ActionHandler) DeleteSecret(ctx context.Context, parentType types.Confi
cgNames := []string{util.EncodeSha256Hex("secretid-" + secret.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return err
return errors.WithStack(err)
}
actions := []*datamanager.Action{
@ -276,5 +277,5 @@ func (h *ActionHandler) DeleteSecret(ctx context.Context, parentType types.Confi
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return err
return errors.WithStack(err)
}

View File

@ -21,12 +21,13 @@ import (
"agola.io/agola/internal/datamanager"
"agola.io/agola/internal/db"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/services/configstore/readdb"
"agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types"
"github.com/gofrs/uuid"
errors "golang.org/x/xerrors"
)
type CreateUserRequest struct {
@ -54,13 +55,13 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
var err error
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
// check duplicate user name
u, err := h.readDB.GetUserByName(tx, req.UserName)
if err != nil {
return err
return errors.WithStack(err)
}
if u != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user with name %q already exists", u.Name))
@ -69,14 +70,14 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
if req.CreateUserLARequest != nil {
rs, err = h.readDB.GetRemoteSourceByName(tx, req.CreateUserLARequest.RemoteSourceName)
if err != nil {
return err
return errors.WithStack(err)
}
if rs == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remote source %q doesn't exist", req.CreateUserLARequest.RemoteSourceName))
}
user, err := h.readDB.GetUserByLinkedAccountRemoteUserIDandSource(tx, req.CreateUserLARequest.RemoteUserID, rs.ID)
if err != nil {
return errors.Errorf("failed to get user for remote user id %q and remote source %q: %w", req.CreateUserLARequest.RemoteUserID, rs.ID, err)
return errors.Wrapf(err, "failed to get user for remote user id %q and remote source %q", req.CreateUserLARequest.RemoteUserID, rs.ID)
}
if user != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user for remote user id %q for remote source %q already exists", req.CreateUserLARequest.RemoteUserID, req.CreateUserLARequest.RemoteSourceName))
@ -85,7 +86,7 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
user := &types.User{
@ -114,7 +115,7 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
userj, err := json.Marshal(user)
if err != nil {
return nil, errors.Errorf("failed to marshal user: %w", err)
return nil, errors.Wrapf(err, "failed to marshal user")
}
// create root user project group
@ -129,7 +130,7 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
}
pgj, err := json.Marshal(pg)
if err != nil {
return nil, errors.Errorf("failed to marshal project group: %w", err)
return nil, errors.Wrapf(err, "failed to marshal project group")
}
actions := []*datamanager.Action{
@ -148,7 +149,7 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return user, err
return user, errors.WithStack(err)
}
func (h *ActionHandler) DeleteUser(ctx context.Context, userRef string) error {
@ -162,7 +163,7 @@ func (h *ActionHandler) DeleteUser(ctx context.Context, userRef string) error {
// check user existance
user, err = h.readDB.GetUser(tx, userRef)
if err != nil {
return err
return errors.WithStack(err)
}
if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef))
@ -172,13 +173,13 @@ func (h *ActionHandler) DeleteUser(ctx context.Context, userRef string) error {
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return err
return errors.WithStack(err)
}
actions := []*datamanager.Action{
@ -190,7 +191,7 @@ func (h *ActionHandler) DeleteUser(ctx context.Context, userRef string) error {
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return err
return errors.WithStack(err)
}
type UpdateUserRequest struct {
@ -210,7 +211,7 @@ func (h *ActionHandler) UpdateUser(ctx context.Context, req *UpdateUserRequest)
var err error
user, err = h.readDB.GetUser(tx, req.UserRef)
if err != nil {
return err
return errors.WithStack(err)
}
if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", req.UserRef))
@ -218,14 +219,14 @@ func (h *ActionHandler) UpdateUser(ctx context.Context, req *UpdateUserRequest)
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
if req.UserName != "" {
// check duplicate user name
u, err := h.readDB.GetUserByName(tx, req.UserName)
if err != nil {
return err
return errors.WithStack(err)
}
if u != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user with name %q already exists", u.Name))
@ -238,7 +239,7 @@ func (h *ActionHandler) UpdateUser(ctx context.Context, req *UpdateUserRequest)
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if req.UserName != "" {
@ -247,7 +248,7 @@ func (h *ActionHandler) UpdateUser(ctx context.Context, req *UpdateUserRequest)
userj, err := json.Marshal(user)
if err != nil {
return nil, errors.Errorf("failed to marshal user: %w", err)
return nil, errors.Wrapf(err, "failed to marshal user")
}
actions := []*datamanager.Action{
@ -260,7 +261,7 @@ func (h *ActionHandler) UpdateUser(ctx context.Context, req *UpdateUserRequest)
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return user, err
return user, errors.WithStack(err)
}
type CreateUserLARequest struct {
@ -293,7 +294,7 @@ func (h *ActionHandler) CreateUserLA(ctx context.Context, req *CreateUserLAReque
var err error
user, err = h.readDB.GetUser(tx, req.UserRef)
if err != nil {
return err
return errors.WithStack(err)
}
if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", req.UserRef))
@ -303,12 +304,12 @@ func (h *ActionHandler) CreateUserLA(ctx context.Context, req *CreateUserLAReque
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
rs, err = h.readDB.GetRemoteSourceByName(tx, req.RemoteSourceName)
if err != nil {
return err
return errors.WithStack(err)
}
if rs == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remote source %q doesn't exist", req.RemoteSourceName))
@ -316,7 +317,7 @@ func (h *ActionHandler) CreateUserLA(ctx context.Context, req *CreateUserLAReque
user, err := h.readDB.GetUserByLinkedAccountRemoteUserIDandSource(tx, req.RemoteUserID, rs.ID)
if err != nil {
return errors.Errorf("failed to get user for remote user id %q and remote source %q: %w", req.RemoteUserID, rs.ID, err)
return errors.Wrapf(err, "failed to get user for remote user id %q and remote source %q", req.RemoteUserID, rs.ID)
}
if user != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user for remote user id %q for remote source %q already exists", req.RemoteUserID, req.RemoteSourceName))
@ -324,7 +325,7 @@ func (h *ActionHandler) CreateUserLA(ctx context.Context, req *CreateUserLAReque
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
if user.LinkedAccounts == nil {
@ -346,7 +347,7 @@ func (h *ActionHandler) CreateUserLA(ctx context.Context, req *CreateUserLAReque
userj, err := json.Marshal(user)
if err != nil {
return nil, errors.Errorf("failed to marshal user: %w", err)
return nil, errors.Wrapf(err, "failed to marshal user")
}
actions := []*datamanager.Action{
{
@ -358,7 +359,7 @@ func (h *ActionHandler) CreateUserLA(ctx context.Context, req *CreateUserLAReque
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return la, err
return la, errors.WithStack(err)
}
func (h *ActionHandler) DeleteUserLA(ctx context.Context, userRef, laID string) error {
@ -378,7 +379,7 @@ func (h *ActionHandler) DeleteUserLA(ctx context.Context, userRef, laID string)
var err error
user, err = h.readDB.GetUser(tx, userRef)
if err != nil {
return err
return errors.WithStack(err)
}
if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef))
@ -388,13 +389,13 @@ func (h *ActionHandler) DeleteUserLA(ctx context.Context, userRef, laID string)
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return err
return errors.WithStack(err)
}
_, ok := user.LinkedAccounts[laID]
@ -406,7 +407,7 @@ func (h *ActionHandler) DeleteUserLA(ctx context.Context, userRef, laID string)
userj, err := json.Marshal(user)
if err != nil {
return errors.Errorf("failed to marshal user: %w", err)
return errors.Wrapf(err, "failed to marshal user")
}
actions := []*datamanager.Action{
{
@ -418,7 +419,7 @@ func (h *ActionHandler) DeleteUserLA(ctx context.Context, userRef, laID string)
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return err
return errors.WithStack(err)
}
type UpdateUserLARequest struct {
@ -448,7 +449,7 @@ func (h *ActionHandler) UpdateUserLA(ctx context.Context, req *UpdateUserLAReque
var err error
user, err = h.readDB.GetUser(tx, req.UserRef)
if err != nil {
return err
return errors.WithStack(err)
}
if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", req.UserRef))
@ -458,7 +459,7 @@ func (h *ActionHandler) UpdateUserLA(ctx context.Context, req *UpdateUserLAReque
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
la, ok := user.LinkedAccounts[req.LinkedAccountID]
@ -468,7 +469,7 @@ func (h *ActionHandler) UpdateUserLA(ctx context.Context, req *UpdateUserLAReque
rs, err = h.readDB.GetRemoteSource(tx, la.RemoteSourceID)
if err != nil {
return err
return errors.WithStack(err)
}
if rs == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remote source with id %q doesn't exist", la.RemoteSourceID))
@ -476,7 +477,7 @@ func (h *ActionHandler) UpdateUserLA(ctx context.Context, req *UpdateUserLAReque
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
la := user.LinkedAccounts[req.LinkedAccountID]
@ -490,7 +491,7 @@ func (h *ActionHandler) UpdateUserLA(ctx context.Context, req *UpdateUserLAReque
userj, err := json.Marshal(user)
if err != nil {
return nil, errors.Errorf("failed to marshal user: %w", err)
return nil, errors.Wrapf(err, "failed to marshal user")
}
actions := []*datamanager.Action{
{
@ -502,7 +503,7 @@ func (h *ActionHandler) UpdateUserLA(ctx context.Context, req *UpdateUserLAReque
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return la, err
return la, errors.WithStack(err)
}
func (h *ActionHandler) CreateUserToken(ctx context.Context, userRef, tokenName string) (string, error) {
@ -522,7 +523,7 @@ func (h *ActionHandler) CreateUserToken(ctx context.Context, userRef, tokenName
var err error
user, err = h.readDB.GetUser(tx, userRef)
if err != nil {
return err
return errors.WithStack(err)
}
if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef))
@ -532,13 +533,13 @@ func (h *ActionHandler) CreateUserToken(ctx context.Context, userRef, tokenName
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return "", err
return "", errors.WithStack(err)
}
if user.Tokens != nil {
if _, ok := user.Tokens[tokenName]; ok {
@ -555,7 +556,7 @@ func (h *ActionHandler) CreateUserToken(ctx context.Context, userRef, tokenName
userj, err := json.Marshal(user)
if err != nil {
return "", errors.Errorf("failed to marshal user: %w", err)
return "", errors.Wrapf(err, "failed to marshal user")
}
actions := []*datamanager.Action{
{
@ -567,7 +568,7 @@ func (h *ActionHandler) CreateUserToken(ctx context.Context, userRef, tokenName
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return token, err
return token, errors.WithStack(err)
}
func (h *ActionHandler) DeleteUserToken(ctx context.Context, userRef, tokenName string) error {
@ -587,7 +588,7 @@ func (h *ActionHandler) DeleteUserToken(ctx context.Context, userRef, tokenName
var err error
user, err = h.readDB.GetUser(tx, userRef)
if err != nil {
return err
return errors.WithStack(err)
}
if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef))
@ -597,13 +598,13 @@ func (h *ActionHandler) DeleteUserToken(ctx context.Context, userRef, tokenName
cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return err
return errors.WithStack(err)
}
_, ok := user.Tokens[tokenName]
@ -615,7 +616,7 @@ func (h *ActionHandler) DeleteUserToken(ctx context.Context, userRef, tokenName
userj, err := json.Marshal(user)
if err != nil {
return errors.Errorf("failed to marshal user: %w", err)
return errors.Wrapf(err, "failed to marshal user")
}
actions := []*datamanager.Action{
{
@ -627,7 +628,7 @@ func (h *ActionHandler) DeleteUserToken(ctx context.Context, userRef, tokenName
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return err
return errors.WithStack(err)
}
type UserOrgsResponse struct {
@ -648,17 +649,17 @@ func (h *ActionHandler) GetUserOrgs(ctx context.Context, userRef string) ([]*Use
var err error
user, err := h.readDB.GetUser(tx, userRef)
if err != nil {
return err
return errors.WithStack(err)
}
if user == nil {
return util.NewAPIError(util.ErrNotExist, errors.Errorf("user %q doesn't exist", userRef))
}
userOrgs, err = h.readDB.GetUserOrgs(tx, user.ID)
return err
return errors.WithStack(err)
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
res := make([]*UserOrgsResponse, len(userOrgs))

View File

@ -20,11 +20,12 @@ import (
"agola.io/agola/internal/datamanager"
"agola.io/agola/internal/db"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types"
"github.com/gofrs/uuid"
errors "golang.org/x/xerrors"
)
func (h *ActionHandler) GetVariables(ctx context.Context, parentType types.ConfigType, parentRef string, tree bool) ([]*types.Variable, error) {
@ -32,17 +33,17 @@ func (h *ActionHandler) GetVariables(ctx context.Context, parentType types.Confi
err := h.readDB.Do(ctx, func(tx *db.Tx) error {
parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
if err != nil {
return err
return errors.WithStack(err)
}
if tree {
variables, err = h.readDB.GetVariablesTree(tx, parentType, parentID)
} else {
variables, err = h.readDB.GetVariables(tx, parentID)
}
return err
return errors.WithStack(err)
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
return variables, nil
@ -73,7 +74,7 @@ func (h *ActionHandler) ValidateVariable(ctx context.Context, variable *types.Va
func (h *ActionHandler) CreateVariable(ctx context.Context, variable *types.Variable) (*types.Variable, error) {
if err := h.ValidateVariable(ctx, variable); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
var cgt *datamanager.ChangeGroupsUpdateToken
@ -85,19 +86,19 @@ func (h *ActionHandler) CreateVariable(ctx context.Context, variable *types.Vari
var err error
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
parentID, err := h.ResolveConfigID(tx, variable.Parent.Type, variable.Parent.ID)
if err != nil {
return err
return errors.WithStack(err)
}
variable.Parent.ID = parentID
// check duplicate variable name
s, err := h.readDB.GetVariableByName(tx, variable.Parent.ID, variable.Name)
if err != nil {
return err
return errors.WithStack(err)
}
if s != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("variable with name %q for %s with id %q already exists", variable.Name, variable.Parent.Type, variable.Parent.ID))
@ -106,14 +107,14 @@ func (h *ActionHandler) CreateVariable(ctx context.Context, variable *types.Vari
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
variable.ID = uuid.Must(uuid.NewV4()).String()
variablej, err := json.Marshal(variable)
if err != nil {
return nil, errors.Errorf("failed to marshal variable: %w", err)
return nil, errors.Wrapf(err, "failed to marshal variable")
}
actions := []*datamanager.Action{
{
@ -125,7 +126,7 @@ func (h *ActionHandler) CreateVariable(ctx context.Context, variable *types.Vari
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return variable, err
return variable, errors.WithStack(err)
}
type UpdateVariableRequest struct {
@ -136,7 +137,7 @@ type UpdateVariableRequest struct {
func (h *ActionHandler) UpdateVariable(ctx context.Context, req *UpdateVariableRequest) (*types.Variable, error) {
if err := h.ValidateVariable(ctx, req.Variable); err != nil {
return nil, err
return nil, errors.WithStack(err)
}
var curVariable *types.Variable
@ -149,14 +150,14 @@ func (h *ActionHandler) UpdateVariable(ctx context.Context, req *UpdateVariableR
parentID, err := h.ResolveConfigID(tx, req.Variable.Parent.Type, req.Variable.Parent.ID)
if err != nil {
return err
return errors.WithStack(err)
}
req.Variable.Parent.ID = parentID
// check variable exists
curVariable, err = h.readDB.GetVariableByName(tx, req.Variable.Parent.ID, req.VariableName)
if err != nil {
return err
return errors.WithStack(err)
}
if curVariable == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("variable with name %q for %s with id %q doesn't exists", req.VariableName, req.Variable.Parent.Type, req.Variable.Parent.ID))
@ -166,7 +167,7 @@ func (h *ActionHandler) UpdateVariable(ctx context.Context, req *UpdateVariableR
// check duplicate variable name
u, err := h.readDB.GetVariableByName(tx, req.Variable.Parent.ID, req.Variable.Name)
if err != nil {
return err
return errors.WithStack(err)
}
if u != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("variable with name %q for %s with id %q already exists", req.Variable.Name, req.Variable.Parent.Type, req.Variable.Parent.ID))
@ -182,18 +183,18 @@ func (h *ActionHandler) UpdateVariable(ctx context.Context, req *UpdateVariableR
}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return nil, err
return nil, errors.WithStack(err)
}
variablej, err := json.Marshal(req.Variable)
if err != nil {
return nil, errors.Errorf("failed to marshal variable: %w", err)
return nil, errors.Wrapf(err, "failed to marshal variable")
}
actions := []*datamanager.Action{
{
@ -205,7 +206,7 @@ func (h *ActionHandler) UpdateVariable(ctx context.Context, req *UpdateVariableR
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return req.Variable, err
return req.Variable, errors.WithStack(err)
}
func (h *ActionHandler) DeleteVariable(ctx context.Context, parentType types.ConfigType, parentRef, variableName string) error {
@ -218,13 +219,13 @@ func (h *ActionHandler) DeleteVariable(ctx context.Context, parentType types.Con
var err error
parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
if err != nil {
return err
return errors.WithStack(err)
}
// check variable existance
variable, err = h.readDB.GetVariableByName(tx, parentID, variableName)
if err != nil {
return err
return errors.WithStack(err)
}
if variable == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("variable with name %q doesn't exist", variableName))
@ -234,12 +235,12 @@ func (h *ActionHandler) DeleteVariable(ctx context.Context, parentType types.Con
cgNames := []string{util.EncodeSha256Hex("variableid-" + variable.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil {
return err
return errors.WithStack(err)
}
return nil
})
if err != nil {
return err
return errors.WithStack(err)
}
actions := []*datamanager.Action{
@ -251,5 +252,5 @@ func (h *ActionHandler) DeleteVariable(ctx context.Context, parentType types.Con
}
_, err = h.dm.WriteWal(ctx, actions, cgt)
return err
return errors.WithStack(err)
}

View File

@ -18,11 +18,11 @@ import (
"net/http"
"net/url"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types"
"github.com/gorilla/mux"
errors "golang.org/x/xerrors"
)
type ErrorResponse struct {
@ -33,7 +33,7 @@ func GetConfigTypeRef(r *http.Request) (types.ConfigType, string, error) {
vars := mux.Vars(r)
projectRef, err := url.PathUnescape(vars["projectref"])
if err != nil {
return "", "", util.NewAPIError(util.ErrBadRequest, errors.Errorf("wrong projectref %q: %w", vars["projectref"], err))
return "", "", util.NewAPIError(util.ErrBadRequest, errors.Wrapf(err, "wrong projectref %q", vars["projectref"]))
}
if projectRef != "" {
return types.ConfigTypeProject, projectRef, nil
@ -41,7 +41,7 @@ func GetConfigTypeRef(r *http.Request) (types.ConfigType, string, error) {
projectGroupRef, err := url.PathUnescape(vars["projectgroupref"])
if err != nil {
return "", "", util.NewAPIError(util.ErrBadRequest, errors.Errorf("wrong projectgroupref %q: %w", vars["projectgroupref"], err))
return "", "", util.NewAPIError(util.ErrBadRequest, errors.Wrapf(err, "wrong projectgroupref %q", vars["projectgroupref"]))
}
if projectGroupRef != "" {
return types.ConfigTypeProjectGroup, projectGroupRef, nil

Some files were not shown because too many files have changed in this diff Show More