Merge pull request #321 from sgotti/use_new_error_library

*: use new errors handling library
This commit is contained in:
Simone Gotti 2022-02-28 14:23:43 +01:00 committed by GitHub
commit 8fe9196101
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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