Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
2024-12-07 02:35:30 +03:00
parent 8729d0b88e
commit c5f3fa325e
42 changed files with 1316 additions and 2009 deletions

View File

@@ -14,19 +14,20 @@ import (
"text/template"
"time"
"git.unistack.org/unistack-org/pkgdash/internal/configcli"
"git.unistack.org/unistack-org/pkgdash/internal/modules"
"github.com/go-git/go-git/v5"
gitconfig "github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
httpauth "github.com/go-git/go-git/v5/plumbing/transport/http"
"go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/logger"
"go.unistack.org/pkgdash/internal/configcli"
"go.unistack.org/pkgdash/internal/modules"
)
var ErrPRNotExist = errors.New("pull request does not exist")
type Gitea struct {
logger logger.Logger
URL string
Username string
Password string
@@ -38,8 +39,9 @@ type Gitea struct {
baseRef *plumbing.Reference
}
func NewGitea(cfg configcli.Config) *Gitea {
func NewGitea(cfg configcli.Config, log logger.Logger) *Gitea {
return &Gitea{
logger: log,
URL: cfg.Source.APIURL,
Username: cfg.Source.Username,
Password: cfg.Source.Password,
@@ -67,21 +69,21 @@ func (g *Gitea) Name() string {
}
func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod modules.Update) error {
logger.Debug(ctx, fmt.Sprintf("RequestOpen start, mod title: %s", path))
g.logger.Debug(ctx, fmt.Sprintf("RequestOpen start, mod title: %s", path))
var buf []byte
var err error
// создания шаблона названия для пулл реквеста
tplTitle, err := template.New("pull_request_title").Parse(g.PRTitle)
if err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to parse template: %v", err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to parse template: %v", err))
}
wTitle := bytes.NewBuffer(nil)
// создания шаблона тела для пулл реквеста
tplBody, err := template.New("pull_request_body").Parse(g.PRTitle)
if err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to parse template: %v", err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to parse template: %v", err))
}
wBody := bytes.NewBuffer(nil)
@@ -93,37 +95,37 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
}
if err = tplTitle.Execute(wTitle, data); err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to execute template: %v", err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to execute template: %v", err))
}
if err = tplBody.Execute(wBody, data); err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to execute template: %v", err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to execute template: %v", err))
}
// открытие гит репозитория с опцией обхода репозитория для нахождения .git
repo, err := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{DetectDotGit: true})
if err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to open repo: %v", err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to open repo: %v", err))
}
//извлекаем ссылки с объектами из удаленного объекта??
// извлекаем ссылки с объектами из удаленного объекта??
if err = repo.FetchContext(ctx, &git.FetchOptions{
Auth: &httpauth.BasicAuth{Username: g.Username, Password: g.Password},
Force: true,
}); err != nil && err != git.NoErrAlreadyUpToDate {
logger.Fatal(ctx, fmt.Sprintf("failed to fetch repo : %v", err))
} //обновляем репозиторий
g.logger.Fatal(ctx, fmt.Sprintf("failed to fetch repo : %v", err))
} // обновляем репозиторий
var headRef *plumbing.Reference // вроде ссылка на гит
if g.baseRef == nil {
g.baseRef, err = repo.Head()
if err != nil {
logger.Fatal(ctx, fmt.Sprintf("Error head: %s", err))
g.logger.Fatal(ctx, fmt.Sprintf("Error head: %s", err))
}
}
refIter, err := repo.Branches() //получение веток
refIter, err := repo.Branches() // получение веток
if err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to get branches: %v", err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to get branches: %v", err))
return err
}
for {
@@ -131,45 +133,45 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
if err != nil {
break
}
if ref.Name().Short() == branch { //todo вот тут возможно нужно переделать
if ref.Name().Short() == branch { // todo вот тут возможно нужно переделать
headRef = ref
break
}
} //перебираем получение ветки и когда находим нужную выходим из цикла записав ветку в headRef
} // перебираем получение ветки и когда находим нужную выходим из цикла записав ветку в headRef
refIter.Close()
if headRef == nil {
logger.Fatal(ctx, "failed to get repo branch head")
g.logger.Fatal(ctx, "failed to get repo branch head")
return err
} // Не получили нужную ветку
logger.Info(ctx, fmt.Sprintf("repo head %s", headRef))
g.logger.Info(ctx, fmt.Sprintf("repo head %s", headRef))
wtree, err := repo.Worktree() //todo вроде рабочее дерево не нужно
wtree, err := repo.Worktree() // todo вроде рабочее дерево не нужно
if err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to get worktree: %v", err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to get worktree: %v", err))
}
defer checkout(*wtree, *g.baseRef)
defer g.checkout(*wtree, *g.baseRef)
g.pulls, err = GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Password)
if err != nil {
logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err))
g.pulls, err = g.GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Password)
if err != nil && err != ErrPRNotExist {
g.logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err))
return err
}
for _, pull := range g.pulls {
if strings.Contains(pull.Title, path) && strings.Contains(pull.Base.Ref, branch) {
logger.Info(ctx, fmt.Sprintf("PR for %s exists %s, call RequestUpdate", path, pull.URL))
g.logger.Info(ctx, fmt.Sprintf("PR for %s exists %s, call RequestUpdate", path, pull.URL))
return g.RequestUpdate(ctx, branch, path, mod)
} // хотим проверить есть ли пулл реквест для этой ветки, если есть то выходим
}
logger.Info(ctx, fmt.Sprintf("update %s from %s to %s", path, mod.Module.Version, mod.Version))
g.logger.Info(ctx, fmt.Sprintf("update %s from %s to %s", path, mod.Module.Version, mod.Version))
logger.Info(ctx, "reset worktree")
g.logger.Info(ctx, "reset worktree")
if err = wtree.Reset(&git.ResetOptions{Commit: headRef.Hash(), Mode: git.HardReset}); err != nil {
logger.Error(ctx, fmt.Sprintf("failed to reset repo branch: %v", err))
} //вроде меняем ветку todo вроде можно удалить
g.logger.Error(ctx, fmt.Sprintf("failed to reset repo branch: %v", err))
} // вроде меняем ветку todo вроде можно удалить
if err = wtree.PullContext(ctx, &git.PullOptions{
Auth: &httpauth.BasicAuth{Username: g.Username, Password: g.Password},
@@ -178,26 +180,26 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
Force: true,
RemoteName: "origin",
}); err != nil && err != git.NoErrAlreadyUpToDate {
logger.Error(ctx, fmt.Sprintf("failed to pull repo: %v", err)) //подтягиваем изменения с удаленого репозитория
g.logger.Error(ctx, fmt.Sprintf("failed to pull repo: %v", err)) // подтягиваем изменения с удаленого репозитория
}
logger.Info(ctx, fmt.Sprintf("checkout ref %s", headRef))
g.logger.Info(ctx, fmt.Sprintf("checkout ref %s", headRef))
if err = wtree.Checkout(&git.CheckoutOptions{
Hash: headRef.Hash(),
Branch: plumbing.NewBranchReferenceName(fmt.Sprintf("pkgdash/go_modules/%s-%s", path, mod.Version)),
Create: true,
Force: true,
}); err != nil {
logger.Error(ctx, fmt.Sprintf("failed to checkout tree: %v", err))
}); err != nil && err != git.ErrBranchExists && err != git.ErrInvalidReference {
g.logger.Error(ctx, fmt.Sprintf("failed to checkout tree: %v", err))
return err
} //создаем новую ветку
} // создаем новую ветку
epath, err := exec.LookPath("go")
if errors.Is(err, exec.ErrDot) {
err = nil
}
if err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to find go command: %v", err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to find go command: %v", err))
} // ищем go файл
var cmd *exec.Cmd
@@ -205,30 +207,30 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
cmd = exec.CommandContext(ctx, epath, "mod", "edit", fmt.Sprintf("-droprequire=%s", mod.Module.Path))
if out, err = cmd.CombinedOutput(); err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to run go mod edit: %s err: %v", out, err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to run go mod edit: %s err: %v", out, err))
}
cmd = exec.CommandContext(ctx, epath, "mod", "edit", fmt.Sprintf("-require=%s@%s", path, mod.Version))
if out, err = cmd.CombinedOutput(); err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to run go mod edit: %s err: %v", out, err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to run go mod edit: %s err: %v", out, err))
} // пытаемся выполнить команду go mod edit с новой версией модуля
cmd = exec.CommandContext(ctx, epath, "mod", "tidy")
if out, err = cmd.CombinedOutput(); err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to run go mod tidy: %s err: %v", out, err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to run go mod tidy: %s err: %v", out, err))
} // пытаемся выполнить команду go mod tidy пытаемся подтянуть новую версию модуля
logger.Info(ctx, "worktree add go.mod")
g.logger.Info(ctx, "worktree add go.mod")
if _, err = wtree.Add("go.mod"); err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to add file: %v", err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to add file: %v", err))
}
logger.Info(ctx, "worktree add go.sum")
g.logger.Info(ctx, "worktree add go.sum")
if _, err = wtree.Add("go.sum"); err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to add file: %v", err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to add file: %v", err))
}
logger.Info(ctx, "worktree commit")
g.logger.Info(ctx, "worktree commit")
_, err = wtree.Commit(wTitle.String(), &git.CommitOptions{
Parents: []plumbing.Hash{headRef.Hash()},
Author: &object.Signature{
@@ -238,19 +240,19 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
},
}) // хотим за коммитить изменения
if err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to commit: %v", err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to commit: %v", err))
}
refspec := gitconfig.RefSpec(fmt.Sprintf("+refs/heads/pkgdash/go_modules/%s-%s:refs/heads/pkgdash/go_modules/%s-%s", path, mod.Version, path, mod.Version)) //todo как будто нужно переделать
refspec := gitconfig.RefSpec(fmt.Sprintf("+refs/heads/pkgdash/go_modules/%s-%s:refs/heads/pkgdash/go_modules/%s-%s", path, mod.Version, path, mod.Version)) // todo как будто нужно переделать
logger.Info(ctx, fmt.Sprintf("try to push refspec %s", refspec))
g.logger.Info(ctx, fmt.Sprintf("try to push refspec %s", refspec))
if err = repo.PushContext(ctx, &git.PushOptions{
RefSpecs: []gitconfig.RefSpec{refspec},
Auth: &httpauth.BasicAuth{Username: g.Username, Password: g.Password},
Force: true,
}); err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to push repo branch: %v", err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to push repo branch: %v", err))
} // пытаемся за пушить изменения
body := map[string]string{
@@ -259,14 +261,14 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
"head": fmt.Sprintf("pkgdash/go_modules/%s-%s", path, mod.Version),
"title": wTitle.String(),
}
logger.Info(ctx, fmt.Sprintf("raw body: %#+v", body))
g.logger.Info(ctx, fmt.Sprintf("raw body: %#+v", body))
buf, err = json.Marshal(body)
if err != nil {
return err
}
logger.Info(ctx, fmt.Sprintf("marshal body: %s", buf))
g.logger.Info(ctx, fmt.Sprintf("marshal body: %s", buf))
req, err := http.NewRequestWithContext(
ctx,
@@ -284,29 +286,29 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
rsp, err := http.DefaultClient.Do(req)
if err != nil {
return err
} //Вроде создаем новый реквест на создание пулл реквеста
} // Вроде создаем новый реквест на создание пулл реквеста
if rsp.StatusCode != http.StatusCreated {
buf, _ = io.ReadAll(rsp.Body)
return fmt.Errorf("unknown error: %s", buf)
}
logger.Info(ctx, fmt.Sprintf("PR create for %s-%s", path, mod.Version))
g.logger.Info(ctx, fmt.Sprintf("PR create for %s-%s", path, mod.Version))
repo, err = git.PlainOpenWithOptions(".", &git.PlainOpenOptions{DetectDotGit: true})
if err != nil {
logger.Fatal(ctx, fmt.Sprintf("failed to open repo: %v", err))
g.logger.Fatal(ctx, fmt.Sprintf("failed to open repo: %v", err))
}
return nil
}
func (g *Gitea) RequestClose(ctx context.Context, branch string, path string) error {
logger.Debug(ctx, fmt.Sprintf("RequestClose start, mod title: %s", path))
g.logger.Debug(ctx, fmt.Sprintf("RequestClose start, mod title: %s", path))
var err error
g.pulls, err = GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Password)
g.pulls, err = g.GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Password)
if err != nil {
logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err))
g.logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err))
return err
}
@@ -314,67 +316,67 @@ func (g *Gitea) RequestClose(ctx context.Context, branch string, path string) er
var b string // Name of the branch to be deleted
for _, pull := range g.pulls {
if strings.Contains(pull.Title, path) && pull.Base.Ref == branch {
logger.Info(ctx, fmt.Sprintf("PR for %s exists: %s", path, pull.URL))
g.logger.Info(ctx, fmt.Sprintf("PR for %s exists: %s", path, pull.URL))
prExist = true
b = pull.Head.Ref
}
}
if !prExist {
logger.Error(ctx, fmt.Sprintf("skip %s since pr does not exist", path))
g.logger.Error(ctx, fmt.Sprintf("skip %s since pr does not exist", path))
return ErrPRNotExist
}
req, err := DeleteBranch(ctx, g.URL, g.Owner, g.Repository, b, g.Password)
req, err := g.DeleteBranch(ctx, g.URL, g.Owner, g.Repository, b, g.Password)
if err != nil {
logger.Error(ctx, fmt.Sprintf("failed to create request for delete the branch: %s, err: %s", branch, err))
g.logger.Error(ctx, fmt.Sprintf("failed to create request for delete the branch: %s, err: %s", branch, err))
return err
}
rsp, err := http.DefaultClient.Do(req)
if err != nil {
logger.Error(ctx, fmt.Sprintf("failed to do request for delete the branch: %s, err: %s, code: %v", branch, err, rsp.StatusCode))
g.logger.Error(ctx, fmt.Sprintf("failed to do request for delete the branch: %s, err: %s, code: %v", branch, err, rsp.StatusCode))
return err
}
logger.Info(ctx, fmt.Sprintf("Delete branch for %s successful", path))
g.logger.Info(ctx, fmt.Sprintf("Delete branch for %s successful", path))
return nil
}
func (g *Gitea) RequestUpdate(ctx context.Context, branch string, path string, mod modules.Update) error {
logger.Debug(ctx, fmt.Sprintf("RequestUpdate start, mod title: %s", path))
g.logger.Debug(ctx, fmt.Sprintf("RequestUpdate start, mod title: %s", path))
var err error
g.pulls, err = GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Password)
g.pulls, err = g.GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Password)
if err != nil {
logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err))
g.logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err))
return err
}
prExist := false
for _, pull := range g.pulls {
if strings.Contains(pull.Title, path) && pull.Base.Ref == branch {
logger.Info(ctx, fmt.Sprintf("don't skip %s since pr exist %s", path, pull.URL)) //todo
tVersion := getVersions(pull.Head.Ref) //Надо взять просто из названия ветки последнюю версию
g.logger.Info(ctx, fmt.Sprintf("don't skip %s since pr exist %s", path, pull.URL)) // todo
tVersion := getVersions(pull.Head.Ref) // Надо взять просто из названия ветки последнюю версию
if modules.IsNewerVersion(tVersion, mod.Version, false) {
reqDel, err := DeleteBranch(ctx, g.URL, g.Owner, g.Repository, pull.Head.Ref, g.Password)
reqDel, err := g.DeleteBranch(ctx, g.URL, g.Owner, g.Repository, pull.Head.Ref, g.Password)
if err != nil {
logger.Error(ctx, fmt.Sprintf("Error with create request for branch: %s, err: %s", branch, err))
g.logger.Error(ctx, fmt.Sprintf("Error with create request for branch: %s, err: %s", branch, err))
return err
}
rsp, err := http.DefaultClient.Do(reqDel)
if err != nil {
logger.Error(ctx, fmt.Sprintf("Error with do request for branch: %s, err: %s, code: %v", branch, err, rsp.StatusCode))
g.logger.Error(ctx, fmt.Sprintf("Error with do request for branch: %s, err: %s, code: %v", branch, err, rsp.StatusCode))
return err
}
logger.Info(ctx, fmt.Sprintf("Old pr %s successful delete", pull.Head.Ref))
g.logger.Info(ctx, fmt.Sprintf("Old pr %s successful delete", pull.Head.Ref))
} else {
logger.Debug(ctx, "The existing PR is relevant")
g.logger.Debug(ctx, "The existing PR is relevant")
return nil
}
prExist = true
}
}
if !prExist {
logger.Error(ctx, fmt.Sprintf("skip %s since pr does not exist", path))
g.logger.Error(ctx, fmt.Sprintf("skip %s since pr does not exist", path))
return ErrPRNotExist
}
@@ -382,12 +384,12 @@ func (g *Gitea) RequestUpdate(ctx context.Context, branch string, path string, m
}
func (g *Gitea) RequestList(ctx context.Context, branch string) (map[string]string, error) {
logger.Debug(ctx, fmt.Sprintf("RequestList for %s", branch))
g.logger.Debug(ctx, fmt.Sprintf("RequestList for %s", branch))
var err error
g.pulls, err = GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Password)
g.pulls, err = g.GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Password)
if err != nil {
logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err))
g.logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err))
return nil, err
}
@@ -395,10 +397,10 @@ func (g *Gitea) RequestList(ctx context.Context, branch string) (map[string]stri
rMap := make(map[string]string)
for _, pull := range g.pulls {
if !strings.HasPrefix(pull.Title, "Bump ") || pull.Base.Ref != branch { //добавляем только реквесты бота по обновлению модулей
if !strings.HasPrefix(pull.Title, "Bump ") || pull.Base.Ref != branch { // добавляем только реквесты бота по обновлению модулей
continue
}
path = strings.Split(pull.Title, " ")[1] //todo Работет только для дефолтного шаблона
path = strings.Split(pull.Title, " ")[1] // todo Работет только для дефолтного шаблона
rMap[path] = pull.Title
}
return rMap, nil
@@ -412,7 +414,7 @@ func getVersions(s string) string {
return version
}
func DeleteBranch(ctx context.Context, url, owner, repo, branch, password string) (*http.Request, error) {
func (g *Gitea) DeleteBranch(ctx context.Context, url, owner, repo, branch, password string) (*http.Request, error) {
var buf []byte
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, fmt.Sprintf("https://%s/api/v1/repos/%s/%s/branches/%s", url, owner, repo, branch), bytes.NewReader(buf))
if err != nil {
@@ -424,7 +426,7 @@ func DeleteBranch(ctx context.Context, url, owner, repo, branch, password string
return req, err
}
func GetPulls(ctx context.Context, url, owner, repo, password string) ([]*giteaPull, error) {
func (g *Gitea) GetPulls(ctx context.Context, url, owner, repo, password string) ([]*giteaPull, error) {
var pullsAll []*giteaPull
page := 1
@@ -437,7 +439,7 @@ func GetPulls(ctx context.Context, url, owner, repo, password string) ([]*giteaP
nil)
if err != nil {
return nil, err
} //вроде запроса к репозиторию
} // вроде запроса к репозиторию
req.Header.Add("Accept", "application/json")
req.Header.Add("Content-Type", "application/json")
@@ -453,13 +455,13 @@ func GetPulls(ctx context.Context, url, owner, repo, password string) ([]*giteaP
switch rsp.StatusCode {
case http.StatusOK:
if err = json.Unmarshal(buf, &pulls); err != nil {
logger.Error(ctx, fmt.Sprintf("failed to decode response %s err: %v", buf, err))
g.logger.Error(ctx, fmt.Sprintf("failed to decode response %s err: %v", buf, err))
return nil, err
}
pullsAll = append(pullsAll, pulls...)
page++
case http.StatusNotFound:
logger.Info(ctx, fmt.Sprintf("pull-request is not exist for %s", repo))
g.logger.Info(ctx, fmt.Sprintf("pull-request is not exist for %s", repo))
return nil, ErrPRNotExist
default:
return nil, fmt.Errorf("unknown error: %s", buf)
@@ -473,9 +475,9 @@ func GetPulls(ctx context.Context, url, owner, repo, password string) ([]*giteaP
return pullsAll, nil
}
func checkout(w git.Worktree, ref plumbing.Reference) {
func (g *Gitea) checkout(w git.Worktree, ref plumbing.Reference) {
ctx := context.Background()
logger.Debug(ctx, fmt.Sprintf("Checkout: %s", ref.Name().Short()))
g.logger.Debug(ctx, fmt.Sprintf("Checkout: %s", ref.Name().Short()))
if err := w.Checkout(&git.CheckoutOptions{
Branch: ref.Name(),
@@ -483,6 +485,6 @@ func checkout(w git.Worktree, ref plumbing.Reference) {
Force: true,
Keep: false,
}); err != nil {
logger.Error(ctx, fmt.Sprintf("failed to reset: %v", err))
g.logger.Error(ctx, fmt.Sprintf("failed to reset: %v", err))
}
}