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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -17,12 +17,12 @@ package cmd
import ( import (
"context" "context"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types" gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client" gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
errors "golang.org/x/xerrors"
) )
var cmdOrgMemberAdd = &cobra.Command{ 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) 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)) _, _, err := gwclient.AddOrgMember(context.TODO(), orgMemberAddOpts.orgname, orgMemberAddOpts.username, gwapitypes.MemberRole(orgMemberAddOpts.role))
if err != nil { 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 return nil

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -18,6 +18,7 @@ import (
"context" "context"
"fmt" "fmt"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types" gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client" 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) projects, _, err := gwclient.GetProjectGroupProjects(context.TODO(), projectListOpts.parentPath)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
printProjects(projects) printProjects(projects)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -18,6 +18,7 @@ import (
"context" "context"
"fmt" "fmt"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types" gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client" 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) remouteSources, _, err := gwclient.GetRemoteSources(context.TODO(), remoteSourceListOpts.start, remoteSourceListOpts.limit, false)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
printRemoteSources(remouteSources) printRemoteSources(remouteSources)

View File

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

View File

@ -16,8 +16,8 @@ package cmd
import ( import (
"context" "context"
"fmt"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types" gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client" gwclient "agola.io/agola/services/gateway/client"
@ -76,7 +76,7 @@ func runCreate(cmd *cobra.Command, args []string) error {
set++ set++
} }
if set != 1 { 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{ req := &gwapitypes.ProjectCreateRunRequest{
@ -88,5 +88,5 @@ func runCreate(cmd *cobra.Command, args []string) error {
_, err := gwclient.ProjectCreateRun(context.TODO(), runCreateOpts.projectRef, req) _, err := gwclient.ProjectCreateRun(context.TODO(), runCreateOpts.projectRef, req)
return err return errors.WithStack(err)
} }

View File

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

View File

@ -19,6 +19,7 @@ import (
"fmt" "fmt"
"agola.io/agola/cmd" "agola.io/agola/cmd"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/services/config" "agola.io/agola/internal/services/config"
"agola.io/agola/internal/services/configstore" "agola.io/agola/internal/services/configstore"
"agola.io/agola/internal/services/executor" "agola.io/agola/internal/services/executor"
@ -33,7 +34,6 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"go.etcd.io/etcd/embed" "go.etcd.io/etcd/embed"
errors "golang.org/x/xerrors"
) )
var ( var (
@ -96,7 +96,7 @@ func embeddedEtcd(ctx context.Context) error {
log.Info().Msgf("starting embedded etcd server") log.Info().Msgf("starting embedded etcd server")
e, err := embed.StartEtcd(cfg) e, err := embed.StartEtcd(cfg)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
go func() { go func() {
@ -132,12 +132,12 @@ func serve(cmd *cobra.Command, args []string) error {
c, err := config.Parse(serveOpts.config, serveOpts.components) c, err := config.Parse(serveOpts.config, serveOpts.components)
if err != nil { if err != nil {
return errors.Errorf("config error: %w", err) return errors.Wrapf(err, "config error")
} }
if serveOpts.embeddedEtcd { if serveOpts.embeddedEtcd {
if err := embeddedEtcd(ctx); err != nil { 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") { if isComponentEnabled("runservice") {
rs, err = rsscheduler.NewRunservice(ctx, log.Logger, &c.Runservice) rs, err = rsscheduler.NewRunservice(ctx, log.Logger, &c.Runservice)
if err != nil { 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") { if isComponentEnabled("executor") {
ex, err = executor.NewExecutor(ctx, log.Logger, &c.Executor) ex, err = executor.NewExecutor(ctx, log.Logger, &c.Executor)
if err != nil { 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") { if isComponentEnabled("configstore") {
cs, err = configstore.NewConfigstore(ctx, log.Logger, &c.Configstore) cs, err = configstore.NewConfigstore(ctx, log.Logger, &c.Configstore)
if err != nil { 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") { if isComponentEnabled("scheduler") {
sched, err = scheduler.NewScheduler(ctx, log.Logger, &c.Scheduler) sched, err = scheduler.NewScheduler(ctx, log.Logger, &c.Scheduler)
if err != nil { 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") { if isComponentEnabled("notification") {
ns, err = notification.NewNotificationService(ctx, log.Logger, c) ns, err = notification.NewNotificationService(ctx, log.Logger, c)
if err != nil { 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") { if isComponentEnabled("gateway") {
gw, err = gateway.NewGateway(ctx, log.Logger, c) gw, err = gateway.NewGateway(ctx, log.Logger, c)
if err != nil { 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") { if isComponentEnabled("gitserver") {
gs, err = gitserver.NewGitserver(ctx, log.Logger, &c.Gitserver) gs, err = gitserver.NewGitserver(ctx, log.Logger, &c.Gitserver)
if err != nil { 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 ( import (
"context" "context"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types" gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client" gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
errors "golang.org/x/xerrors"
) )
var cmdUserCreate = &cobra.Command{ var cmdUserCreate = &cobra.Command{
@ -63,7 +63,7 @@ func userCreate(cmd *cobra.Command, args []string) error {
log.Info().Msgf("creating user") log.Info().Msgf("creating user")
user, _, err := gwclient.CreateUser(context.TODO(), req) user, _, err := gwclient.CreateUser(context.TODO(), req)
if err != nil { 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) log.Info().Msgf("user %q created, ID: %q", user.UserName, user.ID)

View File

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

View File

@ -17,12 +17,12 @@ package cmd
import ( import (
"context" "context"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types" gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client" gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
errors "golang.org/x/xerrors"
) )
var cmdUserLACreate = &cobra.Command{ 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) log.Info().Msgf("creating linked account for user %q", userLACreateOpts.username)
resp, _, err := gwclient.CreateUserLA(context.TODO(), userLACreateOpts.username, req) resp, _, err := gwclient.CreateUserLA(context.TODO(), userLACreateOpts.username, req)
if err != nil { 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 != "" { if resp.Oauth2Redirect != "" {
log.Info().Msgf("visit %s to continue", resp.Oauth2Redirect) log.Info().Msgf("visit %s to continue", resp.Oauth2Redirect)

View File

@ -17,11 +17,11 @@ package cmd
import ( import (
"context" "context"
"agola.io/agola/internal/errors"
gwclient "agola.io/agola/services/gateway/client" gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
errors "golang.org/x/xerrors"
) )
var cmdUserLADelete = &cobra.Command{ 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) log.Info().Msgf("deleting linked account %q for user %q", laID, userName)
_, err := gwclient.DeleteUserLA(context.TODO(), userName, laID) _, err := gwclient.DeleteUserLA(context.TODO(), userName, laID)
if err != nil { 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) log.Info().Msgf("linked account %q for user %q deleted", laID, userName)

View File

@ -18,6 +18,7 @@ import (
"context" "context"
"fmt" "fmt"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types" gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client" 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) users, _, err := gwclient.GetUsers(context.TODO(), userListOpts.start, userListOpts.limit, false)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
printUsers(users) printUsers(users)

View File

@ -18,12 +18,12 @@ import (
"context" "context"
"fmt" "fmt"
"agola.io/agola/internal/errors"
gwapitypes "agola.io/agola/services/gateway/api/types" gwapitypes "agola.io/agola/services/gateway/api/types"
gwclient "agola.io/agola/services/gateway/client" gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
errors "golang.org/x/xerrors"
) )
var cmdUserTokenCreate = &cobra.Command{ 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) log.Info().Msgf("creating token for user %q", userTokenCreateOpts.username)
resp, _, err := gwclient.CreateUserToken(context.TODO(), userTokenCreateOpts.username, req) resp, _, err := gwclient.CreateUserToken(context.TODO(), userTokenCreateOpts.username, req)
if err != nil { 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) log.Info().Msgf("token for user %q created: %s", userTokenCreateOpts.username, resp.Token)
fmt.Println(resp.Token) fmt.Println(resp.Token)

View File

@ -17,11 +17,11 @@ package cmd
import ( import (
"context" "context"
"agola.io/agola/internal/errors"
gwclient "agola.io/agola/services/gateway/client" gwclient "agola.io/agola/services/gateway/client"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
errors "golang.org/x/xerrors"
) )
var cmdUserTokenDelete = &cobra.Command{ 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) log.Info().Msgf("deleting token %q for user %q", tokenName, userName)
_, err := gwclient.DeleteUserToken(context.TODO(), userName, tokenName) _, err := gwclient.DeleteUserToken(context.TODO(), userName, tokenName)
if err != nil { 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) log.Info().Msgf("token %q for user %q deleted", tokenName, userName)

View File

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

View File

@ -21,6 +21,7 @@ import (
"log" "log"
"os" "os"
"agola.io/agola/internal/errors"
"github.com/spf13/cobra" "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 // create a temp dir if the image doesn't have one
tmpDir := os.TempDir() tmpDir := os.TempDir()
if err := os.MkdirAll(tmpDir, 0777); err != nil { 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("", "") file, err := ioutil.TempFile("", "")
if err != nil { if err != nil {
return "", err return "", errors.WithStack(err)
} }
filename := file.Name() filename := file.Name()
if _, err := io.Copy(file, r); err != nil { if _, err := io.Copy(file, r); err != nil {
file.Close() file.Close()
return "", err return "", errors.WithStack(err)
} }
file.Close() file.Close()

View File

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

View File

@ -2,7 +2,7 @@
#### Start the web interface #### 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: 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 ### 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 ./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 ./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 go.starlark.net v0.0.0-20200203144150-6677ee5c7211
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d 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-billy.v4 v4.3.2
gopkg.in/src-d/go-git.v4 v4.13.1 gopkg.in/src-d/go-git.v4 v4.13.1
gopkg.in/yaml.v2 v2.2.8 gopkg.in/yaml.v2 v2.2.8

View File

@ -21,12 +21,12 @@ import (
"os" "os"
"path" "path"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/etcd" "agola.io/agola/internal/etcd"
"agola.io/agola/internal/objectstorage" "agola.io/agola/internal/objectstorage"
"agola.io/agola/internal/services/config" "agola.io/agola/internal/services/config"
"github.com/rs/zerolog" "github.com/rs/zerolog"
errors "golang.org/x/xerrors"
) )
const ( const (
@ -43,7 +43,7 @@ func WriteFileAtomicFunc(filename string, perm os.FileMode, writeFunc func(f io.
dir, name := path.Split(filename) dir, name := path.Split(filename)
f, err := ioutil.TempFile(dir, name) f, err := ioutil.TempFile(dir, name)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
err = writeFunc(f) err = writeFunc(f)
if err == nil { if err == nil {
@ -62,7 +62,7 @@ func WriteFileAtomicFunc(filename string, perm os.FileMode, writeFunc func(f io.
if err != nil { if err != nil {
os.Remove(f.Name()) os.Remove(f.Name())
} }
return err return errors.WithStack(err)
} }
// WriteFileAtomic atomically writes a file // WriteFileAtomic atomically writes a file
@ -70,7 +70,7 @@ func WriteFileAtomic(filename string, data []byte, perm os.FileMode) error {
return WriteFileAtomicFunc(filename, perm, return WriteFileAtomicFunc(filename, perm,
func(f io.Writer) error { func(f io.Writer) error {
_, err := f.Write(data) _, 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: case config.ObjectStorageTypePosix:
ost, err = objectstorage.NewPosix(c.Path) ost, err = objectstorage.NewPosix(c.Path)
if err != nil { 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: case config.ObjectStorageTypeS3:
// minio golang client doesn't accept an url as an endpoint // 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) ost, err = objectstorage.NewS3(c.Bucket, c.Location, endpoint, c.AccessKey, c.SecretAccessKey, secure)
if err != nil { 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, SkipTLSVerify: c.TLSSkipVerify,
}) })
if err != nil { 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 return e, nil

View File

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

View File

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

View File

@ -17,21 +17,21 @@ package config
import ( import (
"encoding/json" "encoding/json"
"agola.io/agola/internal/errors"
"github.com/google/go-jsonnet" "github.com/google/go-jsonnet"
errors "golang.org/x/xerrors"
) )
func execJsonnet(configData []byte, configContext *ConfigContext) ([]byte, error) { func execJsonnet(configData []byte, configContext *ConfigContext) ([]byte, error) {
vm := jsonnet.MakeVM() vm := jsonnet.MakeVM()
cj, err := json.Marshal(configContext) cj, err := json.Marshal(configContext)
if err != nil { 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)) vm.TLACode("ctx", string(cj))
out, err := vm.EvaluateSnippet("", string(configData)) out, err := vm.EvaluateSnippet("", string(configData))
if err != nil { 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 return []byte(out), nil

View File

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

View File

@ -16,10 +16,10 @@ package config
import ( import (
"bytes" "bytes"
"fmt"
"math" "math"
"testing" "testing"
"agola.io/agola/internal/errors"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"go.starlark.net/starlark" "go.starlark.net/starlark"
) )
@ -48,7 +48,7 @@ func TestStarlarkJSON(t *testing.T) {
_ = s.SetKey(starlark.MakeInt(10), starlark.String("string01")) _ = s.SetKey(starlark.MakeInt(10), starlark.String("string01"))
return starlark.Value(s) 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", name: "test list",

View File

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

View File

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

View File

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

View File

@ -29,12 +29,12 @@ import (
"testing" "testing"
"time" "time"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/objectstorage" "agola.io/agola/internal/objectstorage"
"agola.io/agola/internal/testutil" "agola.io/agola/internal/testutil"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/rs/zerolog" "github.com/rs/zerolog"
errors "golang.org/x/xerrors"
) )
func setupEtcd(t *testing.T, log zerolog.Logger, dir string) *testutil.TestEmbeddedEtcd { 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 // populate with a wal
_, err := dm.WriteWal(ctx, actionGroup, nil) _, err := dm.WriteWal(ctx, actionGroup, nil)
if err != 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 // do a checkpoint
if err := dm.checkpoint(ctx, true); err != nil { 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 { if err := checkDataFiles(ctx, t, dm, expectedEntries); err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return expectedEntries, nil return expectedEntries, nil
@ -635,7 +635,7 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
// read the data file // read the data file
curDataStatus, err := dm.GetLastDataStatus() curDataStatus, err := dm.GetLastDataStatus()
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
allEntriesMap := map[string]*DataEntry{} 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] { for i, file := range curDataStatus.Files[dataType] {
dataFileIndexf, err := dm.ost.ReadObject(dm.DataFileIndexPath(dataType, file.ID)) dataFileIndexf, err := dm.ost.ReadObject(dm.DataFileIndexPath(dataType, file.ID))
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
var dataFileIndex *DataFileIndex var dataFileIndex *DataFileIndex
dec := json.NewDecoder(dataFileIndexf) dec := json.NewDecoder(dataFileIndexf)
err = dec.Decode(&dataFileIndex) err = dec.Decode(&dataFileIndex)
if err != nil { if err != nil {
dataFileIndexf.Close() dataFileIndexf.Close()
return err return errors.WithStack(err)
} }
dataFileIndexf.Close() dataFileIndexf.Close()
@ -660,7 +660,7 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
dataEntries := []*DataEntry{} dataEntries := []*DataEntry{}
dataf, err := dm.ost.ReadObject(dm.DataFilePath(dataType, file.ID)) dataf, err := dm.ost.ReadObject(dm.DataFilePath(dataType, file.ID))
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
dec = json.NewDecoder(dataf) dec = json.NewDecoder(dataf)
var prevEntryID string var prevEntryID string
@ -674,15 +674,15 @@ func checkDataFiles(ctx context.Context, t *testing.T, dm *DataManager, expected
} }
if err != nil { if err != nil {
dataf.Close() dataf.Close()
return err return errors.WithStack(err)
} }
// check that there are no duplicate entries // check that there are no duplicate entries
if _, ok := allEntriesMap[de.ID]; ok { 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 // check that the entries are in order
if de.ID < prevEntryID { 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 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 // check that the index matches the entries
if len(dataFileIndex.Index) != len(dataEntriesMap) { 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)) indexIDs := make([]string, len(dataFileIndex.Index))
entriesIDs := make([]string, len(dataEntriesMap)) 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(indexIDs)
sort.Strings(entriesIDs) sort.Strings(entriesIDs)
if !reflect.DeepEqual(indexIDs, 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 { 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 // check that all the files are in order
if file.LastEntryID == prevLastEntryID { 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 { 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 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 // check that the number of entries is right
if len(allEntriesMap) != len(expectedEntriesMap) { 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) { 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 return nil

View File

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

View File

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

View File

@ -20,8 +20,8 @@ import (
"regexp" "regexp"
"time" "time"
"agola.io/agola/internal/errors"
"github.com/mattn/go-sqlite3" "github.com/mattn/go-sqlite3"
errors "golang.org/x/xerrors"
) )
type Type string type Type string
@ -128,7 +128,7 @@ func NewDB(dbType Type, dbConnString string) (*DB, error) {
sqldb, err := sql.Open(driverName, dbConnString) sqldb, err := sql.Open(driverName, dbConnString)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
db := &DB{ db := &DB{
@ -151,11 +151,12 @@ type Tx struct {
} }
func (db *DB) Close() error { 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) { 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 { func (db *DB) NewUnstartedTx() *Tx {
@ -167,7 +168,7 @@ func (db *DB) NewUnstartedTx() *Tx {
func (db *DB) NewTx(ctx context.Context) (*Tx, error) { func (db *DB) NewTx(ctx context.Context) (*Tx, error) {
tx := db.NewUnstartedTx() tx := db.NewUnstartedTx()
if err := tx.Start(ctx); err != nil { if err := tx.Start(ctx); err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return tx, nil 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 { func (db *DB) do(ctx context.Context, f func(tx *Tx) error) error {
tx, err := db.NewTx(ctx) tx, err := db.NewTx(ctx)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
defer func() { defer func() {
if p := recover(); p != nil { 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 { if err = f(tx); err != nil {
_ = tx.Rollback() _ = tx.Rollback()
return err return errors.WithStack(err)
} }
return tx.Commit() 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 { func (tx *Tx) Start(ctx context.Context) error {
wtx, err := tx.db.db.Begin() wtx, err := tx.db.db.Begin()
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
switch tx.db.data.t { switch tx.db.data.t {
case Postgres: case Postgres:
if _, err := wtx.Exec("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"); err != nil { if _, err := wtx.Exec("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"); err != nil {
return err return errors.WithStack(err)
} }
} }
tx.tx = wtx tx.tx = wtx
@ -230,26 +231,26 @@ func (tx *Tx) Commit() error {
if tx.tx == nil { if tx.tx == nil {
return nil return nil
} }
return tx.tx.Commit() return errors.WithStack(tx.tx.Commit())
} }
func (tx *Tx) Rollback() error { func (tx *Tx) Rollback() error {
if tx.tx == nil { if tx.tx == nil {
return nil return nil
} }
return tx.tx.Rollback() return errors.WithStack(tx.tx.Rollback())
} }
func (tx *Tx) Exec(query string, args ...interface{}) (sql.Result, error) { func (tx *Tx) Exec(query string, args ...interface{}) (sql.Result, error) {
query = tx.db.data.translate(query) query = tx.db.data.translate(query)
r, err := tx.tx.ExecContext(tx.ctx, query, tx.db.data.translateArgs(args)...) 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) { func (tx *Tx) Query(query string, args ...interface{}) (*sql.Rows, error) {
query = tx.db.data.translate(query) query = tx.db.data.translate(query)
r, err := tx.tx.QueryContext(tx.ctx, query, tx.db.data.translateArgs(args)...) 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 { func (tx *Tx) QueryRow(query string, args ...interface{}) *sql.Row {
@ -262,13 +263,14 @@ func (tx *Tx) CurTime() (time.Time, error) {
case Sqlite3: case Sqlite3:
var timestring string var timestring string
if err := tx.QueryRow("select now()").Scan(&timestring); err != nil { 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: case Postgres:
var now time.Time var now time.Time
if err := tx.QueryRow("select now()").Scan(&now); err != nil { if err := tx.QueryRow("select now()").Scan(&now); err != nil {
return time.Time{}, err return time.Time{}, errors.WithStack(err)
} }
return now, nil 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" "strings"
"time" "time"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util" "agola.io/agola/internal/util"
"github.com/rs/zerolog" "github.com/rs/zerolog"
@ -29,7 +30,6 @@ import (
etcdclientv3 "go.etcd.io/etcd/clientv3" etcdclientv3 "go.etcd.io/etcd/clientv3"
"go.etcd.io/etcd/clientv3/namespace" "go.etcd.io/etcd/clientv3/namespace"
"go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes" "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
errors "golang.org/x/xerrors"
) )
var ( var (
@ -65,7 +65,7 @@ func FromEtcdError(err error) error {
if errors.Is(err, rpctypes.ErrKeyNotFound) { if errors.Is(err, rpctypes.ErrKeyNotFound) {
return ErrKeyNotFound return ErrKeyNotFound
} }
return err return errors.WithStack(err)
} }
type Store struct { type Store struct {
@ -90,7 +90,7 @@ func New(cfg Config) (*Store, error) {
for _, e := range endpoints { for _, e := range endpoints {
u, err := url.Parse(e) u, err := url.Parse(e)
if err != nil { 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 == "" { if scheme == "" {
scheme = u.Scheme scheme = u.Scheme
@ -108,7 +108,7 @@ func New(cfg Config) (*Store, error) {
var err error var err error
tlsConfig, err = util.NewTLSConfig(cfg.CertFile, cfg.KeyFile, cfg.CAFile, cfg.SkipTLSVerify) tlsConfig, err = util.NewTLSConfig(cfg.CertFile, cfg.KeyFile, cfg.CAFile, cfg.SkipTLSVerify)
if err != nil { 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) c, err := etcdclientv3.New(config)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
c.KV = namespace.NewKV(c.KV, prefix) 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 { if options.TTL > 0 {
lease, err := s.c.Grant(ctx, int64(options.TTL.Seconds())) lease, err := s.c.Grant(ctx, int64(options.TTL.Seconds()))
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
etcdv3Options = append(etcdv3Options, etcdclientv3.WithLease(lease.ID)) 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 { if options.TTL > 0 {
lease, err := s.c.Grant(ctx, int64(options.TTL)) lease, err := s.c.Grant(ctx, int64(options.TTL))
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
etcdv3Options = append(etcdv3Options, etcdclientv3.WithLease(lease.ID)) 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 { func (s *Store) Delete(ctx context.Context, key string) error {
_, err := s.c.Delete(ctx, key) _, err := s.c.Delete(ctx, key)
return err return errors.WithStack(err)
} }
func (s *Store) DeletePrefix(ctx context.Context, prefix string) error { 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...) _, 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) { 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 { 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) { 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() ).Commit()
if err != nil { if err != nil {
return version, rev, err return version, rev, errors.WithStack(err)
} }
curRev := resp.Header.Revision 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 { if _, err = s.c.Compact(ctx, rev); err != nil {
s.log.Warn().Msgf("compact error: %v", err) 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) s.log.Info().Msgf("compacted revision: %d", rev)
return curVersion, curRev, nil return curVersion, curRev, nil

View File

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

View File

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

View File

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

View File

@ -26,6 +26,7 @@ import (
"strings" "strings"
"time" "time"
"agola.io/agola/internal/errors"
gitsource "agola.io/agola/internal/gitsources" gitsource "agola.io/agola/internal/gitsources"
"agola.io/agola/internal/services/types" "agola.io/agola/internal/services/types"
"agola.io/agola/internal/util" "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) { 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) u, err := url.Parse(c.url + "/" + path)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
u.RawQuery = query.Encode() u.RawQuery = query.Encode()
req, err := http.NewRequest(method, u.String(), ibody) req, err := http.NewRequest(method, u.String(), ibody)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
for k, v := range header { for k, v := range header {
req.Header[k] = v 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) { 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) resp, err := c.doRequest(method, path, query, header, ibody)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
if err := util.ErrFromRemote(resp); err != nil { if err := util.ErrFromRemote(resp); err != nil {
return resp, err return resp, errors.WithStack(err)
} }
return resp, nil 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) { 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) resp, err := c.getResponse("GET", fmt.Sprintf("%s.git/raw/%s/%s", repopath, commit, file), nil, nil, nil)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
defer resp.Body.Close() defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body) 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 { 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) { func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {

View File

@ -28,11 +28,11 @@ import (
"strings" "strings"
"time" "time"
"agola.io/agola/internal/errors"
gitsource "agola.io/agola/internal/gitsources" gitsource "agola.io/agola/internal/gitsources"
"code.gitea.io/sdk/gitea" "code.gitea.io/sdk/gitea"
"golang.org/x/oauth2" "golang.org/x/oauth2"
errors "golang.org/x/xerrors"
) )
const ( const (
@ -146,7 +146,7 @@ func (c *Client) RequestOauth2Token(callbackURL, code string) (*oauth2.Token, er
var config = c.oauth2Config(callbackURL) var config = c.oauth2Config(callbackURL)
token, err := config.Exchange(ctx, code) token, err := config.Exchange(ctx, code)
if err != nil { 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 return token, nil
} }
@ -158,7 +158,9 @@ func (c *Client) RefreshOauth2Token(refreshToken string) (*oauth2.Token, error)
var config = c.oauth2Config("") var config = c.oauth2Config("")
token := &oauth2.Token{RefreshToken: refreshToken} token := &oauth2.Token{RefreshToken: refreshToken}
ts := config.TokenSource(ctx, token) 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) { 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) tokens := make([]*gitea.AccessToken, 0, 10)
req, err := http.NewRequest("GET", c.APIURL+"/api/v1"+fmt.Sprintf("/users/%s/tokens", username), nil) req, err := http.NewRequest("GET", c.APIURL+"/api/v1"+fmt.Sprintf("/users/%s/tokens", username), nil)
if err != nil { if err != nil {
return "", err return "", errors.WithStack(err)
} }
req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(username+":"+password))) req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(username+":"+password)))
resp, err := c.oauth2HTTPClient.Do(req) resp, err := c.oauth2HTTPClient.Do(req)
if err != nil { if err != nil {
return "", err return "", errors.WithStack(err)
} }
if resp.StatusCode == http.StatusUnauthorized { if resp.StatusCode == http.StatusUnauthorized {
return "", gitsource.ErrUnauthorized return "", errors.WithStack(gitsource.ErrUnauthorized)
} }
if resp.StatusCode/100 != 2 { if resp.StatusCode/100 != 2 {
return "", errors.Errorf("gitea api status code %d", resp.StatusCode) 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) dec := json.NewDecoder(resp.Body)
if err := dec.Decode(&tokens); err != nil { if err := dec.Decode(&tokens); err != nil {
return "", err return "", errors.WithStack(err)
} }
for _, token := range tokens { for _, token := range tokens {
if token.Name == tokenName { if token.Name == tokenName {
@ -206,7 +208,7 @@ func (c *Client) LoginPassword(username, password, tokenName string) (string, er
gitea.CreateAccessTokenOption{Name: tokenName}, gitea.CreateAccessTokenOption{Name: tokenName},
) )
if terr != nil { if terr != nil {
return "", terr return "", errors.WithStack(terr)
} }
accessToken = token.Token accessToken = token.Token
} }
@ -217,7 +219,7 @@ func (c *Client) LoginPassword(username, password, tokenName string) (string, er
func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) { func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
user, err := c.client.GetMyUserInfo() user, err := c.client.GetMyUserInfo()
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return &gitsource.UserInfo{ return &gitsource.UserInfo{
ID: strconv.FormatInt(user.ID, 10), 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) { func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
rr, err := c.client.GetRepo(owner, reponame) rr, err := c.client.GetRepo(owner, reponame)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return fromGiteaRepo(rr), nil 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) { func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
data, err := c.client.GetFile(owner, reponame, commit, file) 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 { func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool) error {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if _, err = c.client.CreateDeployKey(owner, reponame, gitea.CreateKeyOption{ if _, err = c.client.CreateDeployKey(owner, reponame, gitea.CreateKeyOption{
Title: title, Title: title,
Key: pubKey, Key: pubKey,
ReadOnly: readonly, ReadOnly: readonly,
}); err != nil { }); err != nil {
return errors.Errorf("error creating deploy key: %w", err) return errors.Wrapf(err, "error creating deploy key")
} }
return nil 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 { func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool) error {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { 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 // 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 // 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 // when the public key value has changed
keys, err := c.client.ListDeployKeys(owner, reponame, gitea.ListDeployKeysOptions{}) keys, err := c.client.ListDeployKeys(owner, reponame, gitea.ListDeployKeysOptions{})
if err != 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 { for _, key := range keys {
@ -283,7 +285,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
return nil return nil
} }
if err := c.client.DeleteDeployKey(owner, reponame, key.ID); err != 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, Key: pubKey,
ReadOnly: readonly, ReadOnly: readonly,
}); err != nil { }); err != nil {
return errors.Errorf("error creating deploy key: %w", err) return errors.Wrapf(err, "error creating deploy key")
} }
return nil return nil
@ -302,17 +304,17 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
func (c *Client) DeleteDeployKey(repopath, title string) error { func (c *Client) DeleteDeployKey(repopath, title string) error {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
keys, err := c.client.ListDeployKeys(owner, reponame, gitea.ListDeployKeysOptions{}) keys, err := c.client.ListDeployKeys(owner, reponame, gitea.ListDeployKeysOptions{})
if err != 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 { for _, key := range keys {
if key.Title == title { if key.Title == title {
if err := c.client.DeleteDeployKey(owner, reponame, key.ID); err != 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")
} }
} }
} }
@ -323,7 +325,7 @@ func (c *Client) DeleteDeployKey(repopath, title string) error {
func (c *Client) CreateRepoWebhook(repopath, url, secret string) error { func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
opts := gitea.CreateHookOption{ 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 { 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 return nil
@ -347,11 +349,11 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
func (c *Client) DeleteRepoWebhook(repopath, u string) error { func (c *Client) DeleteRepoWebhook(repopath, u string) error {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
hooks, err := c.client.ListRepoHooks(owner, reponame, gitea.ListHooksOptions{}) hooks, err := c.client.ListRepoHooks(owner, reponame, gitea.ListHooksOptions{})
if err != 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 // 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 { for _, hook := range hooks {
if hook.Config["url"] == u { if hook.Config["url"] == u {
if err := c.client.DeleteRepoHook(owner, reponame, hook.ID); err != nil { 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 { func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource.CommitStatus, targetURL, description, context string) error {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
_, err = c.client.CreateStatus(owner, reponame, commitSHA, gitea.CreateStatusOption{ _, err = c.client.CreateStatus(owner, reponame, commitSHA, gitea.CreateStatusOption{
State: fromCommitStatus(status), State: fromCommitStatus(status),
@ -378,7 +380,7 @@ func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource
Description: description, Description: description,
Context: context, Context: context,
}) })
return err return errors.WithStack(err)
} }
func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) { func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
@ -396,7 +398,7 @@ func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
) )
if err != nil { if err != nil {
return []*gitsource.RepoInfo{}, err return []*gitsource.RepoInfo{}, errors.WithStack(err)
} }
for _, repo := range remoteRepos { 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) { func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
remoteRefs, err := c.client.GetRepoRefs(owner, reponame, ref) remoteRefs, err := c.client.GetRepoRefs(owner, reponame, ref)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
if len(remoteRefs) == 0 { if len(remoteRefs) == 0 {
return nil, errors.Errorf("no ref %q for repository %q", ref, repopath) 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) { func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
commit, err := c.client.GetSingleCommit(owner, reponame, commitSHA) commit, err := c.client.GetSingleCommit(owner, reponame, commitSHA)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return &gitsource.Commit{ return &gitsource.Commit{

View File

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

View File

@ -28,11 +28,11 @@ import (
"strings" "strings"
"time" "time"
"agola.io/agola/internal/errors"
gitsource "agola.io/agola/internal/gitsources" gitsource "agola.io/agola/internal/gitsources"
"github.com/google/go-github/v29/github" "github.com/google/go-github/v29/github"
"golang.org/x/oauth2" "golang.org/x/oauth2"
errors "golang.org/x/xerrors"
) )
var ( var (
@ -81,7 +81,7 @@ func fromCommitStatus(status gitsource.CommitStatus) string {
case gitsource.CommitStatusFailed: case gitsource.CommitStatusFailed:
return "failure" return "failure"
default: 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 != "" { if t.token != "" {
r.Header.Set("Authorization", "Bearer "+t.token) r.Header.Set("Authorization", "Bearer "+t.token)
} }
//nolint:wrapcheck
return t.rt.RoundTrip(r) return t.rt.RoundTrip(r)
} }
@ -184,7 +186,7 @@ func (c *Client) RequestOauth2Token(callbackURL, code string) (*oauth2.Token, er
var config = c.oauth2Config(callbackURL) var config = c.oauth2Config(callbackURL)
token, err := config.Exchange(ctx, code) token, err := config.Exchange(ctx, code)
if err != nil { 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 return token, nil
} }
@ -196,13 +198,15 @@ func (c *Client) RefreshOauth2Token(refreshToken string) (*oauth2.Token, error)
var config = c.oauth2Config("") var config = c.oauth2Config("")
token := &oauth2.Token{RefreshToken: refreshToken} token := &oauth2.Token{RefreshToken: refreshToken}
ts := config.TokenSource(ctx, token) ts := config.TokenSource(ctx, token)
return ts.Token() ntoken, err := ts.Token()
return ntoken, errors.WithStack(err)
} }
func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) { func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
user, _, err := c.client.Users.Get(context.TODO(), "") user, _, err := c.client.Users.Get(context.TODO(), "")
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
userInfo := &gitsource.UserInfo{ userInfo := &gitsource.UserInfo{
@ -219,11 +223,11 @@ func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) { func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
rr, _, err := c.client.Repositories.Get(context.TODO(), owner, reponame) rr, _, err := c.client.Repositories.Get(context.TODO(), owner, reponame)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return fromGithubRepo(rr), nil 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) { func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { 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}) r, err := c.client.Repositories.DownloadContents(context.TODO(), owner, reponame, file, &github.RepositoryContentGetOptions{Ref: commit})
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
defer r.Close() 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 { func (c *Client) CreateDeployKey(repopath, title, pubKey string, readonly bool) error {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if _, _, err = c.client.Repositories.CreateKey(context.TODO(), owner, reponame, &github.Key{ if _, _, err = c.client.Repositories.CreateKey(context.TODO(), owner, reponame, &github.Key{
Title: github.String(title), Title: github.String(title),
Key: github.String(pubKey), Key: github.String(pubKey),
ReadOnly: github.Bool(readonly), ReadOnly: github.Bool(readonly),
}); err != nil { }); err != nil {
return errors.Errorf("error creating deploy key: %w", err) return errors.Wrapf(err, "error creating deploy key")
} }
return nil 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 { func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool) error {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { 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 // 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 // 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 // when the public key value has changed
keys, _, err := c.client.Repositories.ListKeys(context.TODO(), owner, reponame, nil) keys, _, err := c.client.Repositories.ListKeys(context.TODO(), owner, reponame, nil)
if err != 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 { for _, key := range keys {
@ -277,7 +282,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
return nil return nil
} }
if _, err := c.client.Repositories.DeleteKey(context.TODO(), owner, reponame, *key.ID); err != 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), Key: github.String(pubKey),
ReadOnly: github.Bool(readonly), ReadOnly: github.Bool(readonly),
}); err != nil { }); err != nil {
return errors.Errorf("error creating deploy key: %w", err) return errors.Wrapf(err, "error creating deploy key")
} }
return nil return nil
@ -296,17 +301,17 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
func (c *Client) DeleteDeployKey(repopath, title string) error { func (c *Client) DeleteDeployKey(repopath, title string) error {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
keys, _, err := c.client.Repositories.ListKeys(context.TODO(), owner, reponame, nil) keys, _, err := c.client.Repositories.ListKeys(context.TODO(), owner, reponame, nil)
if err != 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 { for _, key := range keys {
if *key.Title == title { if *key.Title == title {
if _, err := c.client.Repositories.DeleteKey(context.TODO(), owner, reponame, *key.ID); err != 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")
} }
} }
} }
@ -317,7 +322,7 @@ func (c *Client) DeleteDeployKey(repopath, title string) error {
func (c *Client) CreateRepoWebhook(repopath, url, secret string) error { func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
hook := &github.Hook{ 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 { 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 return nil
@ -340,7 +345,7 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
func (c *Client) DeleteRepoWebhook(repopath, u string) error { func (c *Client) DeleteRepoWebhook(repopath, u string) error {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
hooks := []*github.Hook{} hooks := []*github.Hook{}
@ -349,7 +354,7 @@ func (c *Client) DeleteRepoWebhook(repopath, u string) error {
for { for {
pHooks, resp, err := c.client.Repositories.ListHooks(context.TODO(), owner, reponame, opt) pHooks, resp, err := c.client.Repositories.ListHooks(context.TODO(), owner, reponame, opt)
if err != nil { if err != nil {
return errors.Errorf("error retrieving repository webhooks: %w", err) return errors.Wrapf(err, "error retrieving repository webhooks")
} }
hooks = append(hooks, pHooks...) hooks = append(hooks, pHooks...)
if resp.NextPage == 0 { if resp.NextPage == 0 {
@ -363,7 +368,7 @@ func (c *Client) DeleteRepoWebhook(repopath, u string) error {
for _, hook := range hooks { for _, hook := range hooks {
if hook.Config["url"] == u { if hook.Config["url"] == u {
if _, err := c.client.Repositories.DeleteHook(context.TODO(), owner, reponame, *hook.ID); err != nil { 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 { func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource.CommitStatus, targetURL, description, statusContext string) error {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
_, _, err = c.client.Repositories.CreateStatus(context.TODO(), owner, reponame, commitSHA, &github.RepoStatus{ _, _, err = c.client.Repositories.CreateStatus(context.TODO(), owner, reponame, commitSHA, &github.RepoStatus{
State: github.String(fromCommitStatus(status)), State: github.String(fromCommitStatus(status)),
@ -382,7 +387,7 @@ func (c *Client) CreateCommitStatus(repopath, commitSHA string, status gitsource
Description: github.String(description), Description: github.String(description),
Context: github.String(statusContext), Context: github.String(statusContext),
}) })
return err return errors.WithStack(err)
} }
func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) { func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
@ -392,7 +397,7 @@ func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {
for { for {
pRemoteRepos, resp, err := c.client.Repositories.List(context.TODO(), "", opt) pRemoteRepos, resp, err := c.client.Repositories.List(context.TODO(), "", opt)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
remoteRepos = append(remoteRepos, pRemoteRepos...) remoteRepos = append(remoteRepos, pRemoteRepos...)
if resp.NextPage == 0 { 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) { func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
remoteRef, _, err := c.client.Git.GetRef(context.TODO(), owner, reponame, ref) remoteRef, _, err := c.client.Git.GetRef(context.TODO(), owner, reponame, ref)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return fromGithubRef(remoteRef) return fromGithubRef(remoteRef)
@ -445,7 +450,7 @@ func fromGithubRef(remoteRef *github.Reference) (*gitsource.Ref, error) {
switch t { switch t {
case "commit": case "commit":
default: default:
return nil, fmt.Errorf("unsupported object type: %s", t) return nil, errors.Errorf("unsupported object type: %s", t)
} }
return &gitsource.Ref{ return &gitsource.Ref{
@ -467,19 +472,19 @@ func (c *Client) RefType(ref string) (gitsource.RefType, string, error) {
return gitsource.RefTypePullRequest, m[1], nil return gitsource.RefTypePullRequest, m[1], nil
default: 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) { func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {
owner, reponame, err := parseRepoPath(repopath) owner, reponame, err := parseRepoPath(repopath)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
commit, _, err := c.client.Git.GetCommit(context.TODO(), owner, reponame, commitSHA) commit, _, err := c.client.Git.GetCommit(context.TODO(), owner, reponame, commitSHA)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return &gitsource.Commit{ return &gitsource.Commit{

View File

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

View File

@ -26,11 +26,11 @@ import (
"strings" "strings"
"time" "time"
"agola.io/agola/internal/errors"
gitsource "agola.io/agola/internal/gitsources" gitsource "agola.io/agola/internal/gitsources"
gitlab "github.com/xanzy/go-gitlab" gitlab "github.com/xanzy/go-gitlab"
"golang.org/x/oauth2" "golang.org/x/oauth2"
errors "golang.org/x/xerrors"
) )
var ( var (
@ -70,7 +70,7 @@ func fromCommitStatus(status gitsource.CommitStatus) gitlab.BuildStateValue {
case gitsource.CommitStatusFailed: case gitsource.CommitStatusFailed:
return gitlab.Failed return gitlab.Failed
default: 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) client := gitlab.NewOAuthClient(httpClient, opts.Token)
if err := client.SetBaseURL(opts.APIURL); err != nil { 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{ return &Client{
@ -130,7 +130,7 @@ func (c *Client) RequestOauth2Token(callbackURL, code string) (*oauth2.Token, er
var config = c.oauth2Config(callbackURL) var config = c.oauth2Config(callbackURL)
token, err := config.Exchange(ctx, code) token, err := config.Exchange(ctx, code)
if err != nil { 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 return token, nil
} }
@ -142,13 +142,15 @@ func (c *Client) RefreshOauth2Token(refreshToken string) (*oauth2.Token, error)
var config = c.oauth2Config("") var config = c.oauth2Config("")
token := &oauth2.Token{RefreshToken: refreshToken} token := &oauth2.Token{RefreshToken: refreshToken}
ts := config.TokenSource(ctx, token) 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) { func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
rr, _, err := c.client.Projects.GetProject(repopath, nil) rr, _, err := c.client.Projects.GetProject(repopath, nil)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return fromGitlabRepo(rr), nil return fromGitlabRepo(rr), nil
} }
@ -156,7 +158,7 @@ func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) { func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
user, _, err := c.client.Users.CurrentUser() user, _, err := c.client.Users.CurrentUser()
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return &gitsource.UserInfo{ return &gitsource.UserInfo{
ID: strconv.Itoa(user.ID), 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) { func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
f, _, err := c.client.RepositoryFiles.GetFile(repopath, file, &gitlab.GetFileOptions{Ref: gitlab.String(commit)}) f, _, err := c.client.RepositoryFiles.GetFile(repopath, file, &gitlab.GetFileOptions{Ref: gitlab.String(commit)})
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
data, err := base64.StdEncoding.DecodeString(f.Content) data, err := base64.StdEncoding.DecodeString(f.Content)
if err != nil { 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 { 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), Title: gitlab.String(title),
Key: gitlab.String(pubKey), Key: gitlab.String(pubKey),
}); err != nil { }); err != nil {
return errors.Errorf("error creating deploy key: %w", err) return errors.Wrapf(err, "error creating deploy key")
} }
return nil 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 { func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool) error {
keys, _, err := c.client.DeployKeys.ListProjectDeployKeys(repopath, nil) keys, _, err := c.client.DeployKeys.ListProjectDeployKeys(repopath, nil)
if err != 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 { for _, key := range keys {
@ -200,7 +202,7 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
return nil return nil
} }
if _, err := c.client.DeployKeys.DeleteDeployKey(repopath, key.ID); err != 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, Title: &title,
Key: &pubKey, Key: &pubKey,
}); err != nil { }); err != nil {
return errors.Errorf("error creating deploy key: %w", err) return errors.Wrapf(err, "error creating deploy key")
} }
return nil return nil
@ -218,13 +220,13 @@ func (c *Client) UpdateDeployKey(repopath, title, pubKey string, readonly bool)
func (c *Client) DeleteDeployKey(repopath, title string) error { func (c *Client) DeleteDeployKey(repopath, title string) error {
keys, _, err := c.client.DeployKeys.ListProjectDeployKeys(repopath, nil) keys, _, err := c.client.DeployKeys.ListProjectDeployKeys(repopath, nil)
if err != 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 { for _, key := range keys {
if key.Title == title { if key.Title == title {
if _, err := c.client.DeployKeys.DeleteDeployKey(repopath, key.ID); err != 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")
} }
} }
} }
@ -241,7 +243,7 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
Token: gitlab.String(secret), Token: gitlab.String(secret),
} }
if _, _, err := c.client.Projects.AddProjectHook(repopath, opts); err != nil { 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 return nil
@ -250,7 +252,7 @@ func (c *Client) CreateRepoWebhook(repopath, url, secret string) error {
func (c *Client) DeleteRepoWebhook(repopath, u string) error { func (c *Client) DeleteRepoWebhook(repopath, u string) error {
hooks, _, err := c.client.Projects.ListProjectHooks(repopath, nil) hooks, _, err := c.client.Projects.ListProjectHooks(repopath, nil)
if err != 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 // 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 { for _, hook := range hooks {
if hook.URL == u { if hook.URL == u {
if _, err := c.client.Projects.DeleteProjectHook(repopath, hook.ID); err != nil { 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), Description: gitlab.String(description),
Context: gitlab.String(context), Context: gitlab.String(context),
}) })
return err return errors.WithStack(err)
} }
func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) { 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)} opts := &gitlab.ListProjectsOptions{MinAccessLevel: gitlab.AccessLevel(gitlab.MaintainerPermissions)}
remoteRepos, _, err := c.client.Projects.ListProjects(opts) remoteRepos, _, err := c.client.Projects.ListProjects(opts)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
repos := []*gitsource.RepoInfo{} repos := []*gitsource.RepoInfo{}
@ -311,7 +313,7 @@ func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
branch := strings.TrimPrefix(ref, "refs/heads/") branch := strings.TrimPrefix(ref, "refs/heads/")
remoteBranch, _, err := c.client.Branches.GetBranch(repopath, branch) remoteBranch, _, err := c.client.Branches.GetBranch(repopath, branch)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return &gitsource.Ref{ return &gitsource.Ref{
@ -323,7 +325,7 @@ func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
tag := strings.TrimPrefix(ref, "refs/heads/") tag := strings.TrimPrefix(ref, "refs/heads/")
remoteTag, _, err := c.client.Tags.GetTag(repopath, tag) remoteTag, _, err := c.client.Tags.GetTag(repopath, tag)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return &gitsource.Ref{ return &gitsource.Ref{
@ -331,7 +333,7 @@ func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
CommitSHA: remoteTag.Commit.ID, CommitSHA: remoteTag.Commit.ID,
}, nil }, nil
default: 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 return gitsource.RefTypePullRequest, m[1], nil
default: 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) { func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {
commit, _, err := c.client.Commits.GetCommit(repopath, commitSHA, nil) commit, _, err := c.client.Commits.GetCommit(repopath, commitSHA, nil)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return &gitsource.Commit{ return &gitsource.Commit{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -21,8 +21,8 @@ import (
"os" "os"
"strings" "strings"
"agola.io/agola/internal/errors"
minio "github.com/minio/minio-go/v6" minio "github.com/minio/minio-go/v6"
errors "golang.org/x/xerrors"
) )
type S3Storage struct { type S3Storage struct {
@ -35,21 +35,21 @@ type S3Storage struct {
func NewS3(bucket, location, endpoint, accessKeyID, secretAccessKey string, secure bool) (*S3Storage, error) { func NewS3(bucket, location, endpoint, accessKeyID, secretAccessKey string, secure bool) (*S3Storage, error) {
minioClient, err := minio.New(endpoint, accessKeyID, secretAccessKey, secure) minioClient, err := minio.New(endpoint, accessKeyID, secretAccessKey, secure)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
minioCore, err := minio.NewCore(endpoint, accessKeyID, secretAccessKey, secure) minioCore, err := minio.NewCore(endpoint, accessKeyID, secretAccessKey, secure)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
exists, err := minioClient.BucketExists(bucket) exists, err := minioClient.BucketExists(bucket)
if err != nil { 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 !exists {
if err := minioClient.MakeBucket(bucket, location); err != nil { 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 { if merr.StatusCode == http.StatusNotFound {
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", p)) 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 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 { if merr.StatusCode == http.StatusNotFound {
return nil, NewErrNotExist(errors.Errorf("object %q doesn't exist", filepath)) 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 { 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 { if size >= 0 {
lr := io.LimitReader(data, size) lr := io.LimitReader(data, size)
_, err := s.minioClient.PutObject(s.bucket, filepath, lr, size, minio.PutObjectOptions{ContentType: "application/octet-stream"}) _, 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 // 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 // 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") tmpfile, err := ioutil.TempFile(os.TempDir(), "s3")
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
defer tmpfile.Close() defer tmpfile.Close()
defer os.Remove(tmpfile.Name()) defer os.Remove(tmpfile.Name())
size, err = io.Copy(tmpfile, data) size, err = io.Copy(tmpfile, data)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if _, err := tmpfile.Seek(0, 0); err != nil { 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"}) _, 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 { 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 { func (s *S3Storage) List(prefix, startWith, delimiter string, doneCh <-chan struct{}) <-chan ObjectInfo {

View File

@ -19,12 +19,11 @@ import (
"strings" "strings"
"agola.io/agola/internal/config" "agola.io/agola/internal/config"
"agola.io/agola/internal/errors"
itypes "agola.io/agola/internal/services/types" itypes "agola.io/agola/internal/services/types"
"agola.io/agola/internal/util" "agola.io/agola/internal/util"
rstypes "agola.io/agola/services/runservice/types" rstypes "agola.io/agola/services/runservice/types"
"agola.io/agola/services/types" "agola.io/agola/services/types"
errors "golang.org/x/xerrors"
) )
const ( const (
@ -192,7 +191,7 @@ fi
return rws return rws
default: 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: case config.ValueTypeFromVariable:
return variables[val.Value] return variables[val.Value]
default: 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" "testing"
"agola.io/agola/internal/config" "agola.io/agola/internal/config"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util" "agola.io/agola/internal/util"
rstypes "agola.io/agola/services/runservice/types" rstypes "agola.io/agola/services/runservice/types"
"agola.io/agola/services/types" "agola.io/agola/services/types"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
errors "golang.org/x/xerrors"
) )
var uuid = &util.TestUUIDGenerator{} 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", 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", 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 { for _, tt := range tests {

View File

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

View File

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

View File

@ -15,43 +15,48 @@
package common package common
import ( import (
"agola.io/agola/internal/errors"
gitsource "agola.io/agola/internal/gitsources" gitsource "agola.io/agola/internal/gitsources"
"agola.io/agola/internal/gitsources/gitea" "agola.io/agola/internal/gitsources/gitea"
"agola.io/agola/internal/gitsources/github" "agola.io/agola/internal/gitsources/github"
"agola.io/agola/internal/gitsources/gitlab" "agola.io/agola/internal/gitsources/gitlab"
cstypes "agola.io/agola/services/configstore/types" cstypes "agola.io/agola/services/configstore/types"
errors "golang.org/x/xerrors"
) )
func newGitea(rs *cstypes.RemoteSource, accessToken string) (*gitea.Client, error) { func newGitea(rs *cstypes.RemoteSource, accessToken string) (*gitea.Client, error) {
return gitea.New(gitea.Opts{ c, err := gitea.New(gitea.Opts{
APIURL: rs.APIURL, APIURL: rs.APIURL,
SkipVerify: rs.SkipVerify, SkipVerify: rs.SkipVerify,
Token: accessToken, Token: accessToken,
Oauth2ClientID: rs.Oauth2ClientID, Oauth2ClientID: rs.Oauth2ClientID,
Oauth2Secret: rs.Oauth2ClientSecret, Oauth2Secret: rs.Oauth2ClientSecret,
}) })
return c, errors.WithStack(err)
} }
func newGitlab(rs *cstypes.RemoteSource, accessToken string) (*gitlab.Client, error) { func newGitlab(rs *cstypes.RemoteSource, accessToken string) (*gitlab.Client, error) {
return gitlab.New(gitlab.Opts{ c, err := gitlab.New(gitlab.Opts{
APIURL: rs.APIURL, APIURL: rs.APIURL,
SkipVerify: rs.SkipVerify, SkipVerify: rs.SkipVerify,
Token: accessToken, Token: accessToken,
Oauth2ClientID: rs.Oauth2ClientID, Oauth2ClientID: rs.Oauth2ClientID,
Oauth2Secret: rs.Oauth2ClientSecret, Oauth2Secret: rs.Oauth2ClientSecret,
}) })
return c, errors.WithStack(err)
} }
func newGithub(rs *cstypes.RemoteSource, accessToken string) (*github.Client, error) { func newGithub(rs *cstypes.RemoteSource, accessToken string) (*github.Client, error) {
return github.New(github.Opts{ c, err := github.New(github.Opts{
APIURL: rs.APIURL, APIURL: rs.APIURL,
SkipVerify: rs.SkipVerify, SkipVerify: rs.SkipVerify,
Token: accessToken, Token: accessToken,
Oauth2ClientID: rs.Oauth2ClientID, Oauth2ClientID: rs.Oauth2ClientID,
Oauth2Secret: rs.Oauth2ClientSecret, Oauth2Secret: rs.Oauth2ClientSecret,
}) })
return c, errors.WithStack(err)
} }
func GetAccessToken(rs *cstypes.RemoteSource, userAccessToken, oauth2AccessToken string) (string, error) { 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 var err error
accessToken, err = GetAccessToken(rs, la.UserAccessToken, la.Oauth2AccessToken) accessToken, err = GetAccessToken(rs, la.UserAccessToken, la.Oauth2AccessToken)
if err != nil { 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 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) { 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 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) { 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 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) { 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 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" "encoding/json"
"time" "time"
"agola.io/agola/internal/errors"
"github.com/golang-jwt/jwt/v4" "github.com/golang-jwt/jwt/v4"
errors "golang.org/x/xerrors"
) )
type TokenSigningData struct { 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()) return "", errors.Errorf("unsupported signing method %q", sd.Method.Alg())
} }
// Sign and get the complete encoded token as a string // 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) { func GenerateOauth2JWTToken(sd *TokenSigningData, remoteSourceName, requestType string, request interface{}) (string, error) {
requestj, err := json.Marshal(request) requestj, err := json.Marshal(request)
if err != nil { if err != nil {
return "", err return "", errors.WithStack(err)
} }
return GenerateGenericJWTToken(sd, jwt.MapClaims{ return GenerateGenericJWTToken(sd, jwt.MapClaims{

View File

@ -15,13 +15,12 @@
package common package common
import ( import (
"fmt"
"net/url" "net/url"
"path" "path"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/services/types" "agola.io/agola/internal/services/types"
"agola.io/agola/internal/util" "agola.io/agola/internal/util"
errors "golang.org/x/xerrors"
) )
type GroupType string type GroupType string
@ -49,7 +48,7 @@ func WebHookEventToRunRefType(we types.WebhookEvent) types.RunRefType {
return types.RunRefTypePullRequest 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 { func GenRunGroup(baseGroupType GroupType, baseGroupID string, groupType GroupType, group string) string {

View File

@ -18,9 +18,9 @@ import (
"io/ioutil" "io/ioutil"
"time" "time"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util" "agola.io/agola/internal/util"
errors "golang.org/x/xerrors"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )
@ -273,12 +273,12 @@ var defaultConfig = Config{
func Parse(configFile string, componentsNames []string) (*Config, error) { func Parse(configFile string, componentsNames []string) (*Config, error) {
configData, err := ioutil.ReadFile(configFile) configData, err := ioutil.ReadFile(configFile)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
c := &defaultConfig c := &defaultConfig
if err := yaml.Unmarshal(configData, &c); err != nil { if err := yaml.Unmarshal(configData, &c); err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return c, Validate(c, componentsNames) return c, Validate(c, componentsNames)
@ -333,7 +333,7 @@ func Validate(c *Config, componentsNames []string) error {
return errors.Errorf("gateway runserviceURL is empty") return errors.Errorf("gateway runserviceURL is empty")
} }
if err := validateWeb(&c.Gateway.Web); err != nil { 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") return errors.Errorf("configstore dataDir is empty")
} }
if err := validateWeb(&c.Configstore.Web); err != nil { 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") return errors.Errorf("runservice dataDir is empty")
} }
if err := validateWeb(&c.Runservice.Web); err != nil { 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 { 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" "path"
"testing" "testing"
errors "golang.org/x/xerrors" "agola.io/agola/internal/errors"
) )
func TestParseConfig(t *testing.T) { func TestParseConfig(t *testing.T) {

View File

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

View File

@ -18,17 +18,16 @@ import (
"context" "context"
"io" "io"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/etcd" "agola.io/agola/internal/etcd"
"agola.io/agola/internal/services/configstore/common" "agola.io/agola/internal/services/configstore/common"
"agola.io/agola/internal/util" "agola.io/agola/internal/util"
errors "golang.org/x/xerrors"
) )
func (h *ActionHandler) MaintenanceMode(ctx context.Context, enable bool) error { func (h *ActionHandler) MaintenanceMode(ctx context.Context, enable bool) error {
resp, err := h.e.Get(ctx, common.EtcdMaintenanceKey, 0) resp, err := h.e.Get(ctx, common.EtcdMaintenanceKey, 0)
if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) { if err != nil && !errors.Is(err, etcd.ErrKeyNotFound) {
return err return errors.WithStack(err)
} }
if enable && len(resp.Kvs) > 0 { if enable && len(resp.Kvs) > 0 {
@ -41,7 +40,7 @@ func (h *ActionHandler) MaintenanceMode(ctx context.Context, enable bool) error
if enable { if enable {
txResp, err := h.e.AtomicPut(ctx, common.EtcdMaintenanceKey, []byte{}, 0, nil) txResp, err := h.e.AtomicPut(ctx, common.EtcdMaintenanceKey, []byte{}, 0, nil)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if !txResp.Succeeded { if !txResp.Succeeded {
return errors.Errorf("failed to create maintenance mode key due to concurrent update") 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 { if !enable {
txResp, err := h.e.AtomicDelete(ctx, common.EtcdMaintenanceKey, resp.Kvs[0].ModRevision) txResp, err := h.e.AtomicDelete(ctx, common.EtcdMaintenanceKey, resp.Kvs[0].ModRevision)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if !txResp.Succeeded { if !txResp.Succeeded {
return errors.Errorf("failed to delete maintenance mode key due to concurrent update") 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 { 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 { func (h *ActionHandler) Import(ctx context.Context, r io.Reader) error {
if !h.maintenanceMode { if !h.maintenanceMode {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("not in maintenance mode")) 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/datamanager"
"agola.io/agola/internal/db" "agola.io/agola/internal/db"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/services/configstore/readdb" "agola.io/agola/internal/services/configstore/readdb"
"agola.io/agola/internal/util" "agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types" "agola.io/agola/services/configstore/types"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
errors "golang.org/x/xerrors"
) )
type OrgMemberResponse struct { type OrgMemberResponse struct {
@ -48,17 +49,17 @@ func (h *ActionHandler) GetOrgMembers(ctx context.Context, orgRef string) ([]*Or
var err error var err error
org, err := h.readDB.GetOrg(tx, orgRef) org, err := h.readDB.GetOrg(tx, orgRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if org == nil { if org == nil {
return util.NewAPIError(util.ErrNotExist, errors.Errorf("org %q doesn't exist", orgRef)) return util.NewAPIError(util.ErrNotExist, errors.Errorf("org %q doesn't exist", orgRef))
} }
orgUsers, err = h.readDB.GetOrgUsers(tx, org.ID) orgUsers, err = h.readDB.GetOrgUsers(tx, org.ID)
return err return errors.WithStack(err)
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
res := make([]*OrgMemberResponse, len(orgUsers)) res := make([]*OrgMemberResponse, len(orgUsers))
@ -89,13 +90,13 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
var err error var err error
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
// check duplicate org name // check duplicate org name
o, err := h.readDB.GetOrgByName(tx, org.Name) o, err := h.readDB.GetOrgByName(tx, org.Name)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if o != nil { if o != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q already exists", o.Name)) 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 != "" { if org.CreatorUserID != "" {
user, err := h.readDB.GetUser(tx, org.CreatorUserID) user, err := h.readDB.GetUser(tx, org.CreatorUserID)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if user == nil { if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("creator user %q doesn't exist", org.CreatorUserID)) 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 return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
actions := []*datamanager.Action{} actions := []*datamanager.Action{}
@ -123,7 +124,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
org.CreatedAt = time.Now() org.CreatedAt = time.Now()
orgj, err := json.Marshal(org) orgj, err := json.Marshal(org)
if err != nil { 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{ actions = append(actions, &datamanager.Action{
ActionType: datamanager.ActionTypePut, ActionType: datamanager.ActionTypePut,
@ -142,7 +143,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
} }
orgmemberj, err := json.Marshal(orgmember) orgmemberj, err := json.Marshal(orgmember)
if err != nil { 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{ actions = append(actions, &datamanager.Action{
ActionType: datamanager.ActionTypePut, ActionType: datamanager.ActionTypePut,
@ -164,7 +165,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
} }
pgj, err := json.Marshal(pg) pgj, err := json.Marshal(pg)
if err != nil { 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{ actions = append(actions, &datamanager.Action{
ActionType: datamanager.ActionTypePut, ActionType: datamanager.ActionTypePut,
@ -174,7 +175,7 @@ func (h *ActionHandler) CreateOrg(ctx context.Context, org *types.Organization)
}) })
_, err = h.dm.WriteWal(ctx, actions, cgt) _, 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 { 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 // check org existance
org, err = h.readDB.GetOrgByName(tx, orgRef) org, err = h.readDB.GetOrgByName(tx, orgRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if org == nil { if org == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q doesn't exist", orgRef)) 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)} cgNames := []string{util.EncodeSha256Hex("orgid-" + org.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
// TODO(sgotti) delete all project groups, projects etc... // 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) _, err = h.dm.WriteWal(ctx, actions, cgt)
return err return errors.WithStack(err)
} }
// AddOrgMember add/updates an org member. // AddOrgMember add/updates an org member.
@ -237,7 +238,7 @@ func (h *ActionHandler) AddOrgMember(ctx context.Context, orgRef, userRef string
// check existing org // check existing org
org, err = h.readDB.GetOrg(tx, orgRef) org, err = h.readDB.GetOrg(tx, orgRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if org == nil { if org == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q doesn't exists", orgRef)) 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 // check existing user
user, err = h.readDB.GetUser(tx, userRef) user, err = h.readDB.GetUser(tx, userRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if user == nil { if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exists", userRef)) 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 // fetch org member if it already exist
orgmember, err = h.readDB.GetOrgMemberByOrgUserID(tx, org.ID, user.ID) orgmember, err = h.readDB.GetOrgMemberByOrgUserID(tx, org.ID, user.ID)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
cgNames := []string{util.EncodeSha256Hex(fmt.Sprintf("orgmember-%s-%s", org.ID, user.ID))} cgNames := []string{util.EncodeSha256Hex(fmt.Sprintf("orgmember-%s-%s", org.ID, user.ID))}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
// update if role changed // update if role changed
@ -287,7 +288,7 @@ func (h *ActionHandler) AddOrgMember(ctx context.Context, orgRef, userRef string
actions := []*datamanager.Action{} actions := []*datamanager.Action{}
orgmemberj, err := json.Marshal(orgmember) orgmemberj, err := json.Marshal(orgmember)
if err != nil { 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{ actions = append(actions, &datamanager.Action{
ActionType: datamanager.ActionTypePut, ActionType: datamanager.ActionTypePut,
@ -297,7 +298,7 @@ func (h *ActionHandler) AddOrgMember(ctx context.Context, orgRef, userRef string
}) })
_, err = h.dm.WriteWal(ctx, actions, cgt) _, err = h.dm.WriteWal(ctx, actions, cgt)
return orgmember, err return orgmember, errors.WithStack(err)
} }
// RemoveOrgMember removes an org member. // RemoveOrgMember removes an org member.
@ -313,7 +314,7 @@ func (h *ActionHandler) RemoveOrgMember(ctx context.Context, orgRef, userRef str
// check existing org // check existing org
org, err = h.readDB.GetOrg(tx, orgRef) org, err = h.readDB.GetOrg(tx, orgRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if org == nil { if org == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("org %q doesn't exists", orgRef)) 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 // check existing user
user, err = h.readDB.GetUser(tx, userRef) user, err = h.readDB.GetUser(tx, userRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if user == nil { if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exists", userRef)) 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 // check that org member exists
orgmember, err = h.readDB.GetOrgMemberByOrgUserID(tx, org.ID, user.ID) orgmember, err = h.readDB.GetOrgMemberByOrgUserID(tx, org.ID, user.ID)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if orgmember == nil { if orgmember == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("orgmember for org %q, user %q doesn't exists", orgRef, userRef)) 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))} cgNames := []string{util.EncodeSha256Hex(fmt.Sprintf("orgmember-%s-%s", org.ID, user.ID))}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
actions := []*datamanager.Action{} actions := []*datamanager.Action{}
@ -356,5 +357,5 @@ func (h *ActionHandler) RemoveOrgMember(ctx context.Context, orgRef, userRef str
}) })
_, err = h.dm.WriteWal(ctx, actions, cgt) _, 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/datamanager"
"agola.io/agola/internal/db" "agola.io/agola/internal/db"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util" "agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types" "agola.io/agola/services/configstore/types"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
errors "golang.org/x/xerrors"
) )
func (h *ActionHandler) ValidateProject(ctx context.Context, project *types.Project) error { 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 { err := h.readDB.Do(ctx, func(tx *db.Tx) error {
var err error var err error
project, err = h.readDB.GetProject(tx, projectRef) project, err = h.readDB.GetProject(tx, projectRef)
return err return errors.WithStack(err)
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
if project == nil { 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) { func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Project) (*types.Project, error) {
if err := h.ValidateProject(ctx, project); err != nil { if err := h.ValidateProject(ctx, project); err != nil {
return nil, err return nil, errors.WithStack(err)
} }
var cgt *datamanager.ChangeGroupsUpdateToken var cgt *datamanager.ChangeGroupsUpdateToken
@ -94,7 +95,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
var err error var err error
group, err := h.readDB.GetProjectGroup(tx, project.Parent.ID) group, err := h.readDB.GetProjectGroup(tx, project.Parent.ID)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if group == nil { if group == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", project.Parent.ID)) 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) groupPath, err := h.readDB.GetProjectGroupPath(tx, group)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
pp := path.Join(groupPath, project.Name) 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)} cgNames := []string{util.EncodeSha256Hex("projectpath-" + pp)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
// check duplicate project name // check duplicate project name
p, err := h.readDB.GetProjectByName(tx, project.Parent.ID, project.Name) p, err := h.readDB.GetProjectByName(tx, project.Parent.ID, project.Name)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if p != nil { if p != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with name %q, path %q already exists", p.Name, pp)) 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 // check that the linked account matches the remote source
user, err := h.readDB.GetUserByLinkedAccount(tx, project.LinkedAccountID) user, err := h.readDB.GetUserByLinkedAccount(tx, project.LinkedAccountID)
if err != nil { 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 { if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user for linked account %q doesn't exist", project.LinkedAccountID)) 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 return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
project.ID = uuid.Must(uuid.NewV4()).String() 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) pcj, err := json.Marshal(project)
if err != nil { 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{ actions := []*datamanager.Action{
{ {
@ -168,7 +169,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, project *types.Projec
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, err = h.dm.WriteWal(ctx, actions, cgt)
return project, err return project, errors.WithStack(err)
} }
type UpdateProjectRequest struct { type UpdateProjectRequest struct {
@ -179,7 +180,7 @@ type UpdateProjectRequest struct {
func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectRequest) (*types.Project, error) { func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectRequest) (*types.Project, error) {
if err := h.ValidateProject(ctx, req.Project); err != nil { if err := h.ValidateProject(ctx, req.Project); err != nil {
return nil, err return nil, errors.WithStack(err)
} }
var cgt *datamanager.ChangeGroupsUpdateToken var cgt *datamanager.ChangeGroupsUpdateToken
@ -190,7 +191,7 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
// check project exists // check project exists
p, err := h.readDB.GetProject(tx, req.ProjectRef) p, err := h.readDB.GetProject(tx, req.ProjectRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if p == nil { if p == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with ref %q doesn't exist", req.ProjectRef)) 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 // check parent project group exists
group, err := h.readDB.GetProjectGroup(tx, req.Project.Parent.ID) group, err := h.readDB.GetProjectGroup(tx, req.Project.Parent.ID)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if group == nil { if group == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", req.Project.Parent.ID)) 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) groupPath, err := h.readDB.GetProjectGroupPath(tx, group)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
pp := path.Join(groupPath, req.Project.Name) pp := path.Join(groupPath, req.Project.Name)
@ -220,7 +221,7 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
// check duplicate project name // check duplicate project name
ap, err := h.readDB.GetProjectByName(tx, req.Project.Parent.ID, req.Project.Name) ap, err := h.readDB.GetProjectByName(tx, req.Project.Parent.ID, req.Project.Name)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if ap != nil { if ap != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project with name %q, path %q already exists", req.Project.Name, pp)) 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 // get old parent project group
curGroup, err := h.readDB.GetProjectGroup(tx, p.Parent.ID) curGroup, err := h.readDB.GetProjectGroup(tx, p.Parent.ID)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if curGroup == nil { if curGroup == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", p.Parent.ID)) 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) curGroupPath, err := h.readDB.GetProjectGroupPath(tx, curGroup)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
pp := path.Join(curGroupPath, req.Project.Name) 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) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if req.Project.RemoteRepositoryConfigType == types.RemoteRepositoryConfigTypeRemoteSource { if req.Project.RemoteRepositoryConfigType == types.RemoteRepositoryConfigTypeRemoteSource {
// check that the linked account matches the remote source // check that the linked account matches the remote source
user, err := h.readDB.GetUserByLinkedAccount(tx, req.Project.LinkedAccountID) user, err := h.readDB.GetUserByLinkedAccount(tx, req.Project.LinkedAccountID)
if err != nil { 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 { if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user for linked account %q doesn't exist", req.Project.LinkedAccountID)) 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 return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
pcj, err := json.Marshal(req.Project) pcj, err := json.Marshal(req.Project)
if err != nil { 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{ actions := []*datamanager.Action{
{ {
@ -293,7 +294,7 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, req *UpdateProjectReq
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, 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 { 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 // check project existance
project, err = h.readDB.GetProject(tx, projectRef) project, err = h.readDB.GetProject(tx, projectRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if project == nil { if project == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project %q doesn't exist", projectRef)) 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)} cgNames := []string{util.EncodeSha256Hex(project.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
// TODO(sgotti) implement childs garbage collection // 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) _, 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/datamanager"
"agola.io/agola/internal/db" "agola.io/agola/internal/db"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util" "agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types" "agola.io/agola/services/configstore/types"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
errors "golang.org/x/xerrors"
) )
func (h *ActionHandler) GetProjectGroup(ctx context.Context, projectGroupRef string) (*types.ProjectGroup, error) { 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 { err := h.readDB.Do(ctx, func(tx *db.Tx) error {
var err error var err error
projectGroup, err = h.readDB.GetProjectGroup(tx, projectGroupRef) projectGroup, err = h.readDB.GetProjectGroup(tx, projectGroupRef)
return err return errors.WithStack(err)
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
if projectGroup == nil { if projectGroup == nil {
@ -53,7 +54,7 @@ func (h *ActionHandler) GetProjectGroupSubgroups(ctx context.Context, projectGro
var err error var err error
projectGroup, err := h.readDB.GetProjectGroup(tx, projectGroupRef) projectGroup, err := h.readDB.GetProjectGroup(tx, projectGroupRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if projectGroup == nil { if projectGroup == nil {
@ -61,10 +62,10 @@ func (h *ActionHandler) GetProjectGroupSubgroups(ctx context.Context, projectGro
} }
projectGroups, err = h.readDB.GetProjectGroupSubgroups(tx, projectGroup.ID) projectGroups, err = h.readDB.GetProjectGroupSubgroups(tx, projectGroup.ID)
return err return errors.WithStack(err)
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return projectGroups, nil return projectGroups, nil
@ -76,7 +77,7 @@ func (h *ActionHandler) GetProjectGroupProjects(ctx context.Context, projectGrou
var err error var err error
projectGroup, err := h.readDB.GetProjectGroup(tx, projectGroupRef) projectGroup, err := h.readDB.GetProjectGroup(tx, projectGroupRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if projectGroup == nil { if projectGroup == nil {
@ -84,10 +85,10 @@ func (h *ActionHandler) GetProjectGroupProjects(ctx context.Context, projectGrou
} }
projects, err = h.readDB.GetProjectGroupProjects(tx, projectGroup.ID) projects, err = h.readDB.GetProjectGroupProjects(tx, projectGroup.ID)
return err return errors.WithStack(err)
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return projects, nil 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) { func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *types.ProjectGroup) (*types.ProjectGroup, error) {
if err := h.ValidateProjectGroup(ctx, projectGroup); err != nil { if err := h.ValidateProjectGroup(ctx, projectGroup); err != nil {
return nil, err return nil, errors.WithStack(err)
} }
if projectGroup.Parent.Type != types.ConfigTypeProjectGroup { 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 { err := h.readDB.Do(ctx, func(tx *db.Tx) error {
parentProjectGroup, err := h.readDB.GetProjectGroup(tx, projectGroup.Parent.ID) parentProjectGroup, err := h.readDB.GetProjectGroup(tx, projectGroup.Parent.ID)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if parentProjectGroup == nil { if parentProjectGroup == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", projectGroup.Parent.ID)) 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) groupPath, err := h.readDB.GetProjectGroupPath(tx, parentProjectGroup)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
pp := path.Join(groupPath, projectGroup.Name) 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)} cgNames := []string{util.EncodeSha256Hex("projectpath-" + pp)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
// check duplicate project group name // check duplicate project group name
pg, err := h.readDB.GetProjectGroupByName(tx, projectGroup.Parent.ID, projectGroup.Name) pg, err := h.readDB.GetProjectGroupByName(tx, projectGroup.Parent.ID, projectGroup.Name)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if pg != nil { if pg != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with name %q, path %q already exists", pg.Name, pp)) 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 return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
projectGroup.ID = uuid.Must(uuid.NewV4()).String() 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) pgj, err := json.Marshal(projectGroup)
if err != nil { 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{ actions := []*datamanager.Action{
{ {
@ -193,7 +194,7 @@ func (h *ActionHandler) CreateProjectGroup(ctx context.Context, projectGroup *ty
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, err = h.dm.WriteWal(ctx, actions, cgt)
return projectGroup, err return projectGroup, errors.WithStack(err)
} }
type UpdateProjectGroupRequest struct { type UpdateProjectGroupRequest struct {
@ -204,7 +205,7 @@ type UpdateProjectGroupRequest struct {
func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProjectGroupRequest) (*types.ProjectGroup, error) { func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProjectGroupRequest) (*types.ProjectGroup, error) {
if err := h.ValidateProjectGroup(ctx, req.ProjectGroup); err != nil { if err := h.ValidateProjectGroup(ctx, req.ProjectGroup); err != nil {
return nil, err return nil, errors.WithStack(err)
} }
var cgt *datamanager.ChangeGroupsUpdateToken var cgt *datamanager.ChangeGroupsUpdateToken
@ -215,7 +216,7 @@ func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProje
// check project exists // check project exists
pg, err := h.readDB.GetProjectGroup(tx, req.ProjectGroupRef) pg, err := h.readDB.GetProjectGroup(tx, req.ProjectGroupRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if pg == nil { if pg == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with ref %q doesn't exist", req.ProjectGroupRef)) 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 // check parent exists
group, err := h.readDB.GetProjectGroup(tx, req.ProjectGroup.Parent.ID) group, err := h.readDB.GetProjectGroup(tx, req.ProjectGroup.Parent.ID)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if group == nil { if group == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with id %q doesn't exist", req.ProjectGroup.Parent.ID)) 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) curPGParentPath, err := h.readDB.GetPath(tx, pg.Parent.Type, pg.Parent.ID)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
curPGP := path.Join(curPGParentPath, pg.Name) curPGP := path.Join(curPGParentPath, pg.Name)
pgParentPath, err := h.readDB.GetPath(tx, req.ProjectGroup.Parent.Type, req.ProjectGroup.Parent.ID) pgParentPath, err := h.readDB.GetPath(tx, req.ProjectGroup.Parent.Type, req.ProjectGroup.Parent.ID)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
pgp := path.Join(pgParentPath, req.ProjectGroup.Name) 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 // check duplicate project group name
ap, err := h.readDB.GetProjectGroupByName(tx, req.ProjectGroup.Parent.ID, req.ProjectGroup.Name) ap, err := h.readDB.GetProjectGroupByName(tx, req.ProjectGroup.Parent.ID, req.ProjectGroup.Name)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if ap != nil { if ap != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group with name %q, path %q already exists", req.ProjectGroup.Name, pgp)) 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) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
pgj, err := json.Marshal(req.ProjectGroup) pgj, err := json.Marshal(req.ProjectGroup)
if err != nil { 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{ actions := []*datamanager.Action{
{ {
@ -316,7 +317,7 @@ func (h *ActionHandler) UpdateProjectGroup(ctx context.Context, req *UpdateProje
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, 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 { 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 // check project group existance
projectGroup, err = h.readDB.GetProjectGroup(tx, projectGroupRef) projectGroup, err = h.readDB.GetProjectGroup(tx, projectGroupRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if projectGroup == nil { if projectGroup == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("project group %q doesn't exist", projectGroupRef)) 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)} cgNames := []string{util.EncodeSha256Hex(projectGroup.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
// TODO(sgotti) implement childs garbage collection // 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) _, 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/datamanager"
"agola.io/agola/internal/db" "agola.io/agola/internal/db"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util" "agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types" "agola.io/agola/services/configstore/types"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
errors "golang.org/x/xerrors"
) )
func (h *ActionHandler) ValidateRemoteSource(ctx context.Context, remoteSource *types.RemoteSource) error { 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) { func (h *ActionHandler) CreateRemoteSource(ctx context.Context, remoteSource *types.RemoteSource) (*types.RemoteSource, error) {
if err := h.ValidateRemoteSource(ctx, remoteSource); err != nil { if err := h.ValidateRemoteSource(ctx, remoteSource); err != nil {
return nil, err return nil, errors.WithStack(err)
} }
var cgt *datamanager.ChangeGroupsUpdateToken var cgt *datamanager.ChangeGroupsUpdateToken
@ -78,13 +79,13 @@ func (h *ActionHandler) CreateRemoteSource(ctx context.Context, remoteSource *ty
var err error var err error
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
// check duplicate remoteSource name // check duplicate remoteSource name
u, err := h.readDB.GetRemoteSourceByName(tx, remoteSource.Name) u, err := h.readDB.GetRemoteSourceByName(tx, remoteSource.Name)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if u != nil { if u != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource %q already exists", u.Name)) 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 return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
remoteSource.ID = uuid.Must(uuid.NewV4()).String() remoteSource.ID = uuid.Must(uuid.NewV4()).String()
rsj, err := json.Marshal(remoteSource) rsj, err := json.Marshal(remoteSource)
if err != nil { 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{ actions := []*datamanager.Action{
{ {
@ -111,7 +112,7 @@ func (h *ActionHandler) CreateRemoteSource(ctx context.Context, remoteSource *ty
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, err = h.dm.WriteWal(ctx, actions, cgt)
return remoteSource, err return remoteSource, errors.WithStack(err)
} }
type UpdateRemoteSourceRequest struct { type UpdateRemoteSourceRequest struct {
@ -122,7 +123,7 @@ type UpdateRemoteSourceRequest struct {
func (h *ActionHandler) UpdateRemoteSource(ctx context.Context, req *UpdateRemoteSourceRequest) (*types.RemoteSource, error) { func (h *ActionHandler) UpdateRemoteSource(ctx context.Context, req *UpdateRemoteSourceRequest) (*types.RemoteSource, error) {
if err := h.ValidateRemoteSource(ctx, req.RemoteSource); err != nil { if err := h.ValidateRemoteSource(ctx, req.RemoteSource); err != nil {
return nil, err return nil, errors.WithStack(err)
} }
var curRemoteSource *types.RemoteSource var curRemoteSource *types.RemoteSource
@ -135,7 +136,7 @@ func (h *ActionHandler) UpdateRemoteSource(ctx context.Context, req *UpdateRemot
// check remotesource exists // check remotesource exists
curRemoteSource, err = h.readDB.GetRemoteSourceByName(tx, req.RemoteSourceRef) curRemoteSource, err = h.readDB.GetRemoteSourceByName(tx, req.RemoteSourceRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if curRemoteSource == nil { if curRemoteSource == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource with ref %q doesn't exist", req.RemoteSourceRef)) 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 // check duplicate remoteSource name
u, err := h.readDB.GetRemoteSourceByName(tx, req.RemoteSource.Name) u, err := h.readDB.GetRemoteSourceByName(tx, req.RemoteSource.Name)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if u != nil { if u != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource %q already exists", u.Name)) 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)} cgNames := []string{util.EncodeSha256Hex("remotesourcename-" + req.RemoteSource.Name), util.EncodeSha256Hex("remotesourceid-" + req.RemoteSource.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
rsj, err := json.Marshal(req.RemoteSource) rsj, err := json.Marshal(req.RemoteSource)
if err != nil { 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{ actions := []*datamanager.Action{
{ {
@ -182,7 +183,7 @@ func (h *ActionHandler) UpdateRemoteSource(ctx context.Context, req *UpdateRemot
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, 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 { 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 // check remoteSource existance
remoteSource, err = h.readDB.GetRemoteSourceByName(tx, remoteSourceName) remoteSource, err = h.readDB.GetRemoteSourceByName(tx, remoteSourceName)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if remoteSource == nil { if remoteSource == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remotesource %q doesn't exist", remoteSourceName)) 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)} cgNames := []string{util.EncodeSha256Hex("remotesourceid-" + remoteSource.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
actions := []*datamanager.Action{ actions := []*datamanager.Action{
@ -225,5 +226,5 @@ func (h *ActionHandler) DeleteRemoteSource(ctx context.Context, remoteSourceName
// changegroup is all the remotesources // changegroup is all the remotesources
_, err = h.dm.WriteWal(ctx, actions, cgt) _, 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/datamanager"
"agola.io/agola/internal/db" "agola.io/agola/internal/db"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util" "agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types" "agola.io/agola/services/configstore/types"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
errors "golang.org/x/xerrors"
) )
func (h *ActionHandler) GetSecret(ctx context.Context, secretID string) (*types.Secret, error) { 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 { err := h.readDB.Do(ctx, func(tx *db.Tx) error {
var err error var err error
secret, err = h.readDB.GetSecretByID(tx, secretID) secret, err = h.readDB.GetSecretByID(tx, secretID)
return err return errors.WithStack(err)
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
if secret == nil { 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 { err := h.readDB.Do(ctx, func(tx *db.Tx) error {
parentID, err := h.ResolveConfigID(tx, parentType, parentRef) parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if tree { if tree {
secrets, err = h.readDB.GetSecretsTree(tx, parentType, parentID) secrets, err = h.readDB.GetSecretsTree(tx, parentType, parentID)
} else { } else {
secrets, err = h.readDB.GetSecrets(tx, parentID) secrets, err = h.readDB.GetSecrets(tx, parentID)
} }
return err return errors.WithStack(err)
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return secrets, nil 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) { func (h *ActionHandler) CreateSecret(ctx context.Context, secret *types.Secret) (*types.Secret, error) {
if err := h.ValidateSecret(ctx, secret); err != nil { if err := h.ValidateSecret(ctx, secret); err != nil {
return nil, err return nil, errors.WithStack(err)
} }
var cgt *datamanager.ChangeGroupsUpdateToken var cgt *datamanager.ChangeGroupsUpdateToken
@ -109,19 +110,19 @@ func (h *ActionHandler) CreateSecret(ctx context.Context, secret *types.Secret)
var err error var err error
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
parentID, err := h.ResolveConfigID(tx, secret.Parent.Type, secret.Parent.ID) parentID, err := h.ResolveConfigID(tx, secret.Parent.Type, secret.Parent.ID)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
secret.Parent.ID = parentID secret.Parent.ID = parentID
// check duplicate secret name // check duplicate secret name
s, err := h.readDB.GetSecretByName(tx, secret.Parent.ID, secret.Name) s, err := h.readDB.GetSecretByName(tx, secret.Parent.ID, secret.Name)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if s != nil { 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)) 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 return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
secret.ID = uuid.Must(uuid.NewV4()).String() secret.ID = uuid.Must(uuid.NewV4()).String()
secretj, err := json.Marshal(secret) secretj, err := json.Marshal(secret)
if err != nil { 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{ actions := []*datamanager.Action{
{ {
@ -149,7 +150,7 @@ func (h *ActionHandler) CreateSecret(ctx context.Context, secret *types.Secret)
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, err = h.dm.WriteWal(ctx, actions, cgt)
return secret, err return secret, errors.WithStack(err)
} }
type UpdateSecretRequest struct { type UpdateSecretRequest struct {
@ -160,7 +161,7 @@ type UpdateSecretRequest struct {
func (h *ActionHandler) UpdateSecret(ctx context.Context, req *UpdateSecretRequest) (*types.Secret, error) { func (h *ActionHandler) UpdateSecret(ctx context.Context, req *UpdateSecretRequest) (*types.Secret, error) {
if err := h.ValidateSecret(ctx, req.Secret); err != nil { if err := h.ValidateSecret(ctx, req.Secret); err != nil {
return nil, err return nil, errors.WithStack(err)
} }
var curSecret *types.Secret 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) parentID, err := h.ResolveConfigID(tx, req.Secret.Parent.Type, req.Secret.Parent.ID)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
req.Secret.Parent.ID = parentID req.Secret.Parent.ID = parentID
// check secret exists // check secret exists
curSecret, err = h.readDB.GetSecretByName(tx, req.Secret.Parent.ID, req.SecretName) curSecret, err = h.readDB.GetSecretByName(tx, req.Secret.Parent.ID, req.SecretName)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if curSecret == nil { 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)) 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 // check duplicate secret name
u, err := h.readDB.GetSecretByName(tx, req.Secret.Parent.ID, req.Secret.Name) u, err := h.readDB.GetSecretByName(tx, req.Secret.Parent.ID, req.Secret.Name)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if u != nil { 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)) 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) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
secretj, err := json.Marshal(req.Secret) secretj, err := json.Marshal(req.Secret)
if err != nil { 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{ actions := []*datamanager.Action{
{ {
@ -229,7 +230,7 @@ func (h *ActionHandler) UpdateSecret(ctx context.Context, req *UpdateSecretReque
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, 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 { 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 var err error
parentID, err := h.ResolveConfigID(tx, parentType, parentRef) parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
// check secret existance // check secret existance
secret, err = h.readDB.GetSecretByName(tx, parentID, secretName) secret, err = h.readDB.GetSecretByName(tx, parentID, secretName)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if secret == nil { if secret == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("secret with name %q doesn't exist", secretName)) 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)} cgNames := []string{util.EncodeSha256Hex("secretid-" + secret.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
actions := []*datamanager.Action{ actions := []*datamanager.Action{
@ -276,5 +277,5 @@ func (h *ActionHandler) DeleteSecret(ctx context.Context, parentType types.Confi
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, 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/datamanager"
"agola.io/agola/internal/db" "agola.io/agola/internal/db"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/services/configstore/readdb" "agola.io/agola/internal/services/configstore/readdb"
"agola.io/agola/internal/util" "agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types" "agola.io/agola/services/configstore/types"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
errors "golang.org/x/xerrors"
) )
type CreateUserRequest struct { type CreateUserRequest struct {
@ -54,13 +55,13 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
var err error var err error
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
// check duplicate user name // check duplicate user name
u, err := h.readDB.GetUserByName(tx, req.UserName) u, err := h.readDB.GetUserByName(tx, req.UserName)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if u != nil { if u != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user with name %q already exists", u.Name)) 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 { if req.CreateUserLARequest != nil {
rs, err = h.readDB.GetRemoteSourceByName(tx, req.CreateUserLARequest.RemoteSourceName) rs, err = h.readDB.GetRemoteSourceByName(tx, req.CreateUserLARequest.RemoteSourceName)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if rs == nil { if rs == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remote source %q doesn't exist", req.CreateUserLARequest.RemoteSourceName)) 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) user, err := h.readDB.GetUserByLinkedAccountRemoteUserIDandSource(tx, req.CreateUserLARequest.RemoteUserID, rs.ID)
if err != nil { 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 { 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)) 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 return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
user := &types.User{ user := &types.User{
@ -114,7 +115,7 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
userj, err := json.Marshal(user) userj, err := json.Marshal(user)
if err != nil { 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 // create root user project group
@ -129,7 +130,7 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
} }
pgj, err := json.Marshal(pg) pgj, err := json.Marshal(pg)
if err != nil { 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{ actions := []*datamanager.Action{
@ -148,7 +149,7 @@ func (h *ActionHandler) CreateUser(ctx context.Context, req *CreateUserRequest)
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, 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 { 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 // check user existance
user, err = h.readDB.GetUser(tx, userRef) user, err = h.readDB.GetUser(tx, userRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if user == nil { if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef)) 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)} cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
actions := []*datamanager.Action{ actions := []*datamanager.Action{
@ -190,7 +191,7 @@ func (h *ActionHandler) DeleteUser(ctx context.Context, userRef string) error {
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, err = h.dm.WriteWal(ctx, actions, cgt)
return err return errors.WithStack(err)
} }
type UpdateUserRequest struct { type UpdateUserRequest struct {
@ -210,7 +211,7 @@ func (h *ActionHandler) UpdateUser(ctx context.Context, req *UpdateUserRequest)
var err error var err error
user, err = h.readDB.GetUser(tx, req.UserRef) user, err = h.readDB.GetUser(tx, req.UserRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if user == nil { if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", req.UserRef)) 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) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if req.UserName != "" { if req.UserName != "" {
// check duplicate user name // check duplicate user name
u, err := h.readDB.GetUserByName(tx, req.UserName) u, err := h.readDB.GetUserByName(tx, req.UserName)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if u != nil { if u != nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user with name %q already exists", u.Name)) 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 return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
if req.UserName != "" { if req.UserName != "" {
@ -247,7 +248,7 @@ func (h *ActionHandler) UpdateUser(ctx context.Context, req *UpdateUserRequest)
userj, err := json.Marshal(user) userj, err := json.Marshal(user)
if err != nil { 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{ actions := []*datamanager.Action{
@ -260,7 +261,7 @@ func (h *ActionHandler) UpdateUser(ctx context.Context, req *UpdateUserRequest)
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, err = h.dm.WriteWal(ctx, actions, cgt)
return user, err return user, errors.WithStack(err)
} }
type CreateUserLARequest struct { type CreateUserLARequest struct {
@ -293,7 +294,7 @@ func (h *ActionHandler) CreateUserLA(ctx context.Context, req *CreateUserLAReque
var err error var err error
user, err = h.readDB.GetUser(tx, req.UserRef) user, err = h.readDB.GetUser(tx, req.UserRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if user == nil { if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", req.UserRef)) 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)} cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
rs, err = h.readDB.GetRemoteSourceByName(tx, req.RemoteSourceName) rs, err = h.readDB.GetRemoteSourceByName(tx, req.RemoteSourceName)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if rs == nil { if rs == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remote source %q doesn't exist", req.RemoteSourceName)) 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) user, err := h.readDB.GetUserByLinkedAccountRemoteUserIDandSource(tx, req.RemoteUserID, rs.ID)
if err != nil { 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 { 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)) 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 return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
if user.LinkedAccounts == nil { if user.LinkedAccounts == nil {
@ -346,7 +347,7 @@ func (h *ActionHandler) CreateUserLA(ctx context.Context, req *CreateUserLAReque
userj, err := json.Marshal(user) userj, err := json.Marshal(user)
if err != nil { 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{ actions := []*datamanager.Action{
{ {
@ -358,7 +359,7 @@ func (h *ActionHandler) CreateUserLA(ctx context.Context, req *CreateUserLAReque
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, 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 { 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 var err error
user, err = h.readDB.GetUser(tx, userRef) user, err = h.readDB.GetUser(tx, userRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if user == nil { if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef)) 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)} cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
_, ok := user.LinkedAccounts[laID] _, ok := user.LinkedAccounts[laID]
@ -406,7 +407,7 @@ func (h *ActionHandler) DeleteUserLA(ctx context.Context, userRef, laID string)
userj, err := json.Marshal(user) userj, err := json.Marshal(user)
if err != nil { if err != nil {
return errors.Errorf("failed to marshal user: %w", err) return errors.Wrapf(err, "failed to marshal user")
} }
actions := []*datamanager.Action{ actions := []*datamanager.Action{
{ {
@ -418,7 +419,7 @@ func (h *ActionHandler) DeleteUserLA(ctx context.Context, userRef, laID string)
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, err = h.dm.WriteWal(ctx, actions, cgt)
return err return errors.WithStack(err)
} }
type UpdateUserLARequest struct { type UpdateUserLARequest struct {
@ -448,7 +449,7 @@ func (h *ActionHandler) UpdateUserLA(ctx context.Context, req *UpdateUserLAReque
var err error var err error
user, err = h.readDB.GetUser(tx, req.UserRef) user, err = h.readDB.GetUser(tx, req.UserRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if user == nil { if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", req.UserRef)) 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)} cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
la, ok := user.LinkedAccounts[req.LinkedAccountID] 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) rs, err = h.readDB.GetRemoteSource(tx, la.RemoteSourceID)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if rs == nil { if rs == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("remote source with id %q doesn't exist", la.RemoteSourceID)) 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 return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
la := user.LinkedAccounts[req.LinkedAccountID] la := user.LinkedAccounts[req.LinkedAccountID]
@ -490,7 +491,7 @@ func (h *ActionHandler) UpdateUserLA(ctx context.Context, req *UpdateUserLAReque
userj, err := json.Marshal(user) userj, err := json.Marshal(user)
if err != nil { 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{ actions := []*datamanager.Action{
{ {
@ -502,7 +503,7 @@ func (h *ActionHandler) UpdateUserLA(ctx context.Context, req *UpdateUserLAReque
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, 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) { 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 var err error
user, err = h.readDB.GetUser(tx, userRef) user, err = h.readDB.GetUser(tx, userRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if user == nil { if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef)) 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)} cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return "", err return "", errors.WithStack(err)
} }
if user.Tokens != nil { if user.Tokens != nil {
if _, ok := user.Tokens[tokenName]; ok { if _, ok := user.Tokens[tokenName]; ok {
@ -555,7 +556,7 @@ func (h *ActionHandler) CreateUserToken(ctx context.Context, userRef, tokenName
userj, err := json.Marshal(user) userj, err := json.Marshal(user)
if err != nil { if err != nil {
return "", errors.Errorf("failed to marshal user: %w", err) return "", errors.Wrapf(err, "failed to marshal user")
} }
actions := []*datamanager.Action{ actions := []*datamanager.Action{
{ {
@ -567,7 +568,7 @@ func (h *ActionHandler) CreateUserToken(ctx context.Context, userRef, tokenName
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, 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 { 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 var err error
user, err = h.readDB.GetUser(tx, userRef) user, err = h.readDB.GetUser(tx, userRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if user == nil { if user == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("user %q doesn't exist", userRef)) 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)} cgNames := []string{util.EncodeSha256Hex("userid-" + user.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
_, ok := user.Tokens[tokenName] _, ok := user.Tokens[tokenName]
@ -615,7 +616,7 @@ func (h *ActionHandler) DeleteUserToken(ctx context.Context, userRef, tokenName
userj, err := json.Marshal(user) userj, err := json.Marshal(user)
if err != nil { if err != nil {
return errors.Errorf("failed to marshal user: %w", err) return errors.Wrapf(err, "failed to marshal user")
} }
actions := []*datamanager.Action{ actions := []*datamanager.Action{
{ {
@ -627,7 +628,7 @@ func (h *ActionHandler) DeleteUserToken(ctx context.Context, userRef, tokenName
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, err = h.dm.WriteWal(ctx, actions, cgt)
return err return errors.WithStack(err)
} }
type UserOrgsResponse struct { type UserOrgsResponse struct {
@ -648,17 +649,17 @@ func (h *ActionHandler) GetUserOrgs(ctx context.Context, userRef string) ([]*Use
var err error var err error
user, err := h.readDB.GetUser(tx, userRef) user, err := h.readDB.GetUser(tx, userRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if user == nil { if user == nil {
return util.NewAPIError(util.ErrNotExist, errors.Errorf("user %q doesn't exist", userRef)) return util.NewAPIError(util.ErrNotExist, errors.Errorf("user %q doesn't exist", userRef))
} }
userOrgs, err = h.readDB.GetUserOrgs(tx, user.ID) userOrgs, err = h.readDB.GetUserOrgs(tx, user.ID)
return err return errors.WithStack(err)
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
res := make([]*UserOrgsResponse, len(userOrgs)) res := make([]*UserOrgsResponse, len(userOrgs))

View File

@ -20,11 +20,12 @@ import (
"agola.io/agola/internal/datamanager" "agola.io/agola/internal/datamanager"
"agola.io/agola/internal/db" "agola.io/agola/internal/db"
"agola.io/agola/internal/errors"
"agola.io/agola/internal/util" "agola.io/agola/internal/util"
"agola.io/agola/services/configstore/types" "agola.io/agola/services/configstore/types"
"github.com/gofrs/uuid" "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) { 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 { err := h.readDB.Do(ctx, func(tx *db.Tx) error {
parentID, err := h.ResolveConfigID(tx, parentType, parentRef) parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if tree { if tree {
variables, err = h.readDB.GetVariablesTree(tx, parentType, parentID) variables, err = h.readDB.GetVariablesTree(tx, parentType, parentID)
} else { } else {
variables, err = h.readDB.GetVariables(tx, parentID) variables, err = h.readDB.GetVariables(tx, parentID)
} }
return err return errors.WithStack(err)
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
return variables, nil 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) { func (h *ActionHandler) CreateVariable(ctx context.Context, variable *types.Variable) (*types.Variable, error) {
if err := h.ValidateVariable(ctx, variable); err != nil { if err := h.ValidateVariable(ctx, variable); err != nil {
return nil, err return nil, errors.WithStack(err)
} }
var cgt *datamanager.ChangeGroupsUpdateToken var cgt *datamanager.ChangeGroupsUpdateToken
@ -85,19 +86,19 @@ func (h *ActionHandler) CreateVariable(ctx context.Context, variable *types.Vari
var err error var err error
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
parentID, err := h.ResolveConfigID(tx, variable.Parent.Type, variable.Parent.ID) parentID, err := h.ResolveConfigID(tx, variable.Parent.Type, variable.Parent.ID)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
variable.Parent.ID = parentID variable.Parent.ID = parentID
// check duplicate variable name // check duplicate variable name
s, err := h.readDB.GetVariableByName(tx, variable.Parent.ID, variable.Name) s, err := h.readDB.GetVariableByName(tx, variable.Parent.ID, variable.Name)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if s != nil { 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)) 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 return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
variable.ID = uuid.Must(uuid.NewV4()).String() variable.ID = uuid.Must(uuid.NewV4()).String()
variablej, err := json.Marshal(variable) variablej, err := json.Marshal(variable)
if err != nil { 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{ actions := []*datamanager.Action{
{ {
@ -125,7 +126,7 @@ func (h *ActionHandler) CreateVariable(ctx context.Context, variable *types.Vari
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, err = h.dm.WriteWal(ctx, actions, cgt)
return variable, err return variable, errors.WithStack(err)
} }
type UpdateVariableRequest struct { type UpdateVariableRequest struct {
@ -136,7 +137,7 @@ type UpdateVariableRequest struct {
func (h *ActionHandler) UpdateVariable(ctx context.Context, req *UpdateVariableRequest) (*types.Variable, error) { func (h *ActionHandler) UpdateVariable(ctx context.Context, req *UpdateVariableRequest) (*types.Variable, error) {
if err := h.ValidateVariable(ctx, req.Variable); err != nil { if err := h.ValidateVariable(ctx, req.Variable); err != nil {
return nil, err return nil, errors.WithStack(err)
} }
var curVariable *types.Variable 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) parentID, err := h.ResolveConfigID(tx, req.Variable.Parent.Type, req.Variable.Parent.ID)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
req.Variable.Parent.ID = parentID req.Variable.Parent.ID = parentID
// check variable exists // check variable exists
curVariable, err = h.readDB.GetVariableByName(tx, req.Variable.Parent.ID, req.VariableName) curVariable, err = h.readDB.GetVariableByName(tx, req.Variable.Parent.ID, req.VariableName)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if curVariable == nil { 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)) 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 // check duplicate variable name
u, err := h.readDB.GetVariableByName(tx, req.Variable.Parent.ID, req.Variable.Name) u, err := h.readDB.GetVariableByName(tx, req.Variable.Parent.ID, req.Variable.Name)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if u != nil { 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)) 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) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, errors.WithStack(err)
} }
variablej, err := json.Marshal(req.Variable) variablej, err := json.Marshal(req.Variable)
if err != nil { 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{ actions := []*datamanager.Action{
{ {
@ -205,7 +206,7 @@ func (h *ActionHandler) UpdateVariable(ctx context.Context, req *UpdateVariableR
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, 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 { 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 var err error
parentID, err := h.ResolveConfigID(tx, parentType, parentRef) parentID, err := h.ResolveConfigID(tx, parentType, parentRef)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
// check variable existance // check variable existance
variable, err = h.readDB.GetVariableByName(tx, parentID, variableName) variable, err = h.readDB.GetVariableByName(tx, parentID, variableName)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
if variable == nil { if variable == nil {
return util.NewAPIError(util.ErrBadRequest, errors.Errorf("variable with name %q doesn't exist", variableName)) 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)} cgNames := []string{util.EncodeSha256Hex("variableid-" + variable.ID)}
cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames) cgt, err = h.readDB.GetChangeGroupsUpdateTokens(tx, cgNames)
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return err return errors.WithStack(err)
} }
actions := []*datamanager.Action{ actions := []*datamanager.Action{
@ -251,5 +252,5 @@ func (h *ActionHandler) DeleteVariable(ctx context.Context, parentType types.Con
} }
_, err = h.dm.WriteWal(ctx, actions, cgt) _, err = h.dm.WriteWal(ctx, actions, cgt)
return err return errors.WithStack(err)
} }

View File

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

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