#8 implement interface Source and methods for gitea without Update #9

Merged
vtolstov merged 27 commits from kgorbunov/pkgdash:master into master 2024-03-24 20:52:34 +03:00
2 changed files with 51 additions and 52 deletions
Showing only changes of commit b83cbd9c8e - Show all commits

View File

@ -75,7 +75,7 @@ func main() {
logger.DefaultLogger = slog.NewLogger() logger.DefaultLogger = slog.NewLogger()
if err = logger.DefaultLogger.Init(logger.WithCallerSkipCount(3), logger.WithLevel(logger.DebugLevel)); err != nil { if err = logger.DefaultLogger.Init(logger.WithCallerSkipCount(3), logger.WithLevel(logger.DebugLevel)); err != nil {
logger.Error(ctx, "logger init error: %v", err) logger.Error(ctx, fmt.Sprintf("logger init error: %v", err))
} }
cfg := configcli.NewConfig() cfg := configcli.NewConfig()
@ -91,7 +91,7 @@ func main() {
}, },
config.LoadOverride(true), config.LoadOverride(true),
); err != nil { ); err != nil {
logger.Fatal(ctx, "failed to load config: %v", err) logger.Fatal(ctx, fmt.Sprintf("failed to load config: %v", err))
} }
for _, configDir := range configDirs { for _, configDir := range configDirs {
@ -103,23 +103,23 @@ func main() {
fileconfig.Path(filepath.Join(configDir, configFile)), fileconfig.Path(filepath.Join(configDir, configFile)),
) )
if err = c.Load(ctx, config.LoadOverride(true)); err != nil { if err = c.Load(ctx, config.LoadOverride(true)); err != nil {
logger.Fatal(ctx, "failed to load config: %v", err) logger.Fatal(ctx, fmt.Sprintf("failed to load config: %v", err))
} }
} }
} }
file, err := os.Open(".gitea/pkgdashcli.yaml") file, err := os.Open(".gitea/pkgdashcli.yaml")
if err != nil { if err != nil {
logger.Fatal(ctx, "file open: %s", err) logger.Fatal(ctx, fmt.Sprintf("file open: %s", err))
} }
defer file.Close() defer file.Close()
d := yaml.NewDecoder(file) d := yaml.NewDecoder(file)
if err = d.Decode(&cfg); err != nil { if err = d.Decode(&cfg); err != nil {
logger.Fatal(ctx, "Decode err: %s", d) logger.Fatal(ctx, fmt.Sprintf("Decode err: %s", d))
} }
logger.Info(ctx, "Load config... %s", cfg) logger.Info(ctx, fmt.Sprintf("Load config... %s", cfg))
if cfg.PullRequestBody == "" { if cfg.PullRequestBody == "" {
cfg.PullRequestBody = DefaultPullRequestBody cfg.PullRequestBody = DefaultPullRequestBody
@ -210,7 +210,7 @@ func main() {
} }
}*/ }*/
logger.Info(ctx, "cfg: %v", cfg) logger.Info(ctx, fmt.Sprintf("cfg: %v", cfg))
gitSource := source.NewSourceControl(*cfg) gitSource := source.NewSourceControl(*cfg)
for _, branch := range cfg.Branches { for _, branch := range cfg.Branches {
@ -221,10 +221,10 @@ func main() {
if err.Error() == "pull request exists" { if err.Error() == "pull request exists" {
err = gitSource.RequestUpdate(ctx, branch, pathMod, mod) err = gitSource.RequestUpdate(ctx, branch, pathMod, mod)
if err != nil { if err != nil {
logger.Error(ctx, "Update PR error: %s", err) logger.Error(ctx, fmt.Sprintf("Update PR error: %s", err))
} }
} }
logger.Error(ctx, "failed to create pr: %v", err) logger.Error(ctx, fmt.Sprintf("failed to create pr: %v", err))
} }
logger.Debugf(ctx, "Update successful for %s", pathMod) logger.Debugf(ctx, "Update successful for %s", pathMod)
} }

View File

@ -70,14 +70,14 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
// создания шаблона названия для пулл реквеста // создания шаблона названия для пулл реквеста
tplTitle, err := template.New("pull_request_title").Parse(g.PRTitle) tplTitle, err := template.New("pull_request_title").Parse(g.PRTitle)
if err != nil { if err != nil {
logger.Fatal(ctx, "failed to parse template: %v", err) logger.Fatal(ctx, fmt.Sprintf("failed to parse template: %v", err))
} }
wTitle := bytes.NewBuffer(nil) wTitle := bytes.NewBuffer(nil)
// создания шаблона тела для пулл реквеста // создания шаблона тела для пулл реквеста
tplBody, err := template.New("pull_request_body").Parse(g.PRTitle) tplBody, err := template.New("pull_request_body").Parse(g.PRTitle)
if err != nil { if err != nil {
logger.Fatal(ctx, "failed to parse template: %v", err) logger.Fatal(ctx, fmt.Sprintf("failed to parse template: %v", err))
} }
wBody := bytes.NewBuffer(nil) wBody := bytes.NewBuffer(nil)
@ -89,29 +89,29 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
} }
if err = tplTitle.Execute(wTitle, data); err != nil { if err = tplTitle.Execute(wTitle, data); err != nil {
logger.Fatal(ctx, "failed to execute template: %v", err) logger.Fatal(ctx, fmt.Sprintf("failed to execute template: %v", err))
} }
if err = tplBody.Execute(wBody, data); err != nil { if err = tplBody.Execute(wBody, data); err != nil {
logger.Fatal(ctx, "failed to execute template: %v", err) logger.Fatal(ctx, fmt.Sprintf("failed to execute template: %v", err))
} }
// открытие гит репозитория с опцией обхода репозитория для нахождения .git // открытие гит репозитория с опцией обхода репозитория для нахождения .git
repo, err := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{DetectDotGit: true}) repo, err := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{DetectDotGit: true})
if err != nil { if err != nil {
logger.Fatal(ctx, "failed to open repo: %v", err) logger.Fatal(ctx, fmt.Sprintf("failed to open repo: %v", err))
} }
//извлекаем ссылки с объектами из удаленного объекта?? //извлекаем ссылки с объектами из удаленного объекта??
if err = repo.FetchContext(ctx, &git.FetchOptions{ if err = repo.FetchContext(ctx, &git.FetchOptions{
Auth: &httpauth.BasicAuth{Username: g.Token, Password: g.Token}, Auth: &httpauth.BasicAuth{Username: g.Token, Password: g.Token},
Force: true, Force: true,
}); err != nil && err != git.NoErrAlreadyUpToDate { }); err != nil && err != git.NoErrAlreadyUpToDate {
logger.Fatal(ctx, "failed to fetch repo: %v", err) logger.Fatal(ctx, fmt.Sprintf("failed to fetch repo: %v", err))
} //обновляем репозиторий } //обновляем репозиторий
var headRef *plumbing.Reference // вроде ссылка на гит var headRef *plumbing.Reference // вроде ссылка на гит
refIter, err := repo.Branches() //получение веток refIter, err := repo.Branches() //получение веток
if err != nil { if err != nil {
logger.Fatal(ctx, "failed to get branches: %v", err) logger.Fatal(ctx, fmt.Sprintf("failed to get branches: %v", err))
} }
for { for {
ref, err := refIter.Next() ref, err := refIter.Next()
@ -133,27 +133,27 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
wtree, err := repo.Worktree() //todo вроде рабочее дерево не нужно wtree, err := repo.Worktree() //todo вроде рабочее дерево не нужно
if err != nil { if err != nil {
logger.Fatal(ctx, "failed to get worktree: %v", err) logger.Fatal(ctx, fmt.Sprintf("failed to get worktree: %v", err))
} }
pulls, err := GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Token) pulls, err := GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Token)
if err != nil && err != ErrPRNotExist { if err != nil && err != ErrPRNotExist {
logger.Error(ctx, "GetPulls error: %s", err) logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err))
return err return err
} }
for _, pull := range pulls { for _, pull := range pulls {
if strings.Contains(pull.Title, path) && strings.Contains(pull.Base.Ref, branch) { if strings.Contains(pull.Title, path) && strings.Contains(pull.Base.Ref, branch) {
logger.Info(ctx, "skip %s as pr already exists %s", path, pull.URL) logger.Info(ctx, fmt.Sprintf("skip %s as pr already exists %s", path, pull.URL))
return ErrPRExist return ErrPRExist
} // хотим проверить есть ли пулл реквест для этой ветки, если есть то выходим } // хотим проверить есть ли пулл реквест для этой ветки, если есть то выходим
} }
logger.Info(ctx, "update %s from %s to %s", path, mod.Module.Version, mod.Version) logger.Info(ctx, fmt.Sprintf("update %s from %s to %s", path, mod.Module.Version, mod.Version))
logger.Info(ctx, "reset worktree") logger.Info(ctx, "reset worktree")
if err = wtree.Reset(&git.ResetOptions{Mode: git.HardReset}); err != nil { if err = wtree.Reset(&git.ResetOptions{Mode: git.HardReset}); err != nil {
logger.Fatal(ctx, "failed to reset repo branch: %v", err) logger.Error(ctx, fmt.Sprintf("failed to reset repo branch: %v", err))
} //вроде меняем ветку todo вроде можно удалить } //вроде меняем ветку todo вроде можно удалить
if err = wtree.PullContext(ctx, &git.PullOptions{ if err = wtree.PullContext(ctx, &git.PullOptions{
@ -163,17 +163,17 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
Force: true, Force: true,
RemoteName: "origin", RemoteName: "origin",
}); err != nil && err != git.NoErrAlreadyUpToDate { }); err != nil && err != git.NoErrAlreadyUpToDate {
logger.Fatal(ctx, "failed to pull repo: %v", err) //подтягиваем изменения с удаленого репозитория logger.Error(ctx, fmt.Sprintf("failed to pull repo: %v", err)) //подтягиваем изменения с удаленого репозитория
} }
logger.Info(ctx, "checkout ref %s", headRef) logger.Info(ctx, fmt.Sprintf("checkout ref %s", headRef))
if err = wtree.Checkout(&git.CheckoutOptions{ if err = wtree.Checkout(&git.CheckoutOptions{
Hash: headRef.Hash(), Hash: headRef.Hash(),
Branch: plumbing.NewBranchReferenceName(fmt.Sprintf("pkgdash/go_modules/%s-%s", path, mod.Version)), Branch: plumbing.NewBranchReferenceName(fmt.Sprintf("pkgdash/go_modules/%s-%s", path, mod.Version)),
Create: true, Create: true,
Force: true, Force: true,
}); err != nil { }); err != nil {
logger.Fatal(ctx, "failed to checkout tree: %v", err) logger.Fatal(ctx, fmt.Sprintf("failed to checkout tree: %v", err))
} //создаем новую ветку } //создаем новую ветку
epath, err := exec.LookPath("go") epath, err := exec.LookPath("go")
@ -181,7 +181,7 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
err = nil err = nil
} }
if err != nil { if err != nil {
logger.Fatal(ctx, "failed to find go command: %v", err) logger.Fatal(ctx, fmt.Sprintf("failed to find go command: %v", err))
} // ищем go файл } // ищем go файл
var cmd *exec.Cmd var cmd *exec.Cmd
@ -189,27 +189,27 @@ 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)) cmd = exec.CommandContext(ctx, epath, "mod", "edit", fmt.Sprintf("-droprequire=%s", mod.Module.Path))
if out, err = cmd.CombinedOutput(); err != nil { if out, err = cmd.CombinedOutput(); err != nil {
logger.Fatal(ctx, "failed to run go mod edit: %s err: %v", out, err) 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)) cmd = exec.CommandContext(ctx, epath, "mod", "edit", fmt.Sprintf("-require=%s@%s", path, mod.Version))
if out, err = cmd.CombinedOutput(); err != nil { if out, err = cmd.CombinedOutput(); err != nil {
logger.Fatal(ctx, "failed to run go mod edit: %s err: %v", out, err) logger.Fatal(ctx, fmt.Sprintf("failed to run go mod edit: %s err: %v", out, err))
} // пытаемся выполнить команду go mod edit с новой версией модуля } // пытаемся выполнить команду go mod edit с новой версией модуля
cmd = exec.CommandContext(ctx, epath, "mod", "tidy") cmd = exec.CommandContext(ctx, epath, "mod", "tidy")
if out, err = cmd.CombinedOutput(); err != nil { if out, err = cmd.CombinedOutput(); err != nil {
logger.Fatal(ctx, "failed to run go mod tidy: %s err: %v", out, err) logger.Fatal(ctx, fmt.Sprintf("failed to run go mod tidy: %s err: %v", out, err))
} // пытаемся выполнить команду go mod tidy пытаемся подтянуть новую версию модуля } // пытаемся выполнить команду go mod tidy пытаемся подтянуть новую версию модуля
logger.Info(ctx, "worktree add go.mod") logger.Info(ctx, "worktree add go.mod")
if _, err = wtree.Add("go.mod"); err != nil { if _, err = wtree.Add("go.mod"); err != nil {
logger.Fatal(ctx, "failed to add file: %v", err) logger.Fatal(ctx, fmt.Sprintf("failed to add file: %v", err))
} }
logger.Info(ctx, "worktree add go.sum") logger.Info(ctx, "worktree add go.sum")
if _, err = wtree.Add("go.sum"); err != nil { if _, err = wtree.Add("go.sum"); err != nil {
logger.Fatal(ctx, "failed to add file: %v", err) logger.Fatal(ctx, fmt.Sprintf("failed to add file: %v", err))
} }
logger.Info(ctx, "worktree commit") logger.Info(ctx, "worktree commit")
@ -222,19 +222,19 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
}, },
}) // хотим за коммитить изменения }) // хотим за коммитить изменения
if err != nil { if err != nil {
logger.Fatal(ctx, "failed to commit: %v", err) 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, "try to push refspec %s", refspec) logger.Info(ctx, fmt.Sprintf("try to push refspec %s", refspec))
if err = repo.PushContext(ctx, &git.PushOptions{ if err = repo.PushContext(ctx, &git.PushOptions{
RefSpecs: []gitconfig.RefSpec{refspec}, RefSpecs: []gitconfig.RefSpec{refspec},
Auth: &httpauth.BasicAuth{Username: g.Token, Password: g.Token}, Auth: &httpauth.BasicAuth{Username: g.Token, Password: g.Token},
Force: true, Force: true,
}); err != nil { }); err != nil {
logger.Fatal(ctx, "failed to push repo branch: %v", err) logger.Fatal(ctx, fmt.Sprintf("failed to push repo branch: %v", err))
} // пытаемся за пушить изменения } // пытаемся за пушить изменения
body := map[string]string{ body := map[string]string{
@ -243,14 +243,14 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
"head": fmt.Sprintf("pkgdash/go_modules/%s-%s", path, mod.Version), "head": fmt.Sprintf("pkgdash/go_modules/%s-%s", path, mod.Version),
"title": wTitle.String(), "title": wTitle.String(),
} }
logger.Info(ctx, "raw body: %#+v", body) logger.Info(ctx, fmt.Sprintf("raw body: %#+v", body))
buf, err = json.Marshal(body) buf, err = json.Marshal(body)
if err != nil { if err != nil {
return err return err
} }
logger.Info(ctx, "marshal body: %s", buf) logger.Info(ctx, fmt.Sprintf("marshal body: %s", buf))
req, err := http.NewRequestWithContext( req, err := http.NewRequestWithContext(
ctx, ctx,
@ -273,7 +273,7 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod
return fmt.Errorf("unknown error: %s", buf) return fmt.Errorf("unknown error: %s", buf)
} }
logger.Info(ctx, "PR create for %s-%s", path, mod.Version) logger.Info(ctx, fmt.Sprintf("PR create for %s-%s", path, mod.Version))
return nil return nil
} }
@ -283,7 +283,7 @@ func (g *Gitea) RequestClose(ctx context.Context, branch string, path string) er
pulls, err := GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Token) pulls, err := GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Token)
if err != nil { if err != nil {
logger.Error(ctx, "GetPulls error: %s", err) logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err))
return err return err
} }
@ -291,28 +291,28 @@ func (g *Gitea) RequestClose(ctx context.Context, branch string, path string) er
var b string // Name of the branch to be deleted var b string // Name of the branch to be deleted
for _, pull := range pulls { for _, pull := range pulls {
if strings.Contains(pull.Title, path) && pull.Base.Ref == branch { if strings.Contains(pull.Title, path) && pull.Base.Ref == branch {
logger.Info(ctx, "PR for %s exists: %s", path, pull.URL) logger.Info(ctx, fmt.Sprintf("PR for %s exists: %s", path, pull.URL))
prExist = true prExist = true
b = pull.Head.Ref b = pull.Head.Ref
} }
} }
if !prExist { if !prExist {
logger.Error(ctx, " skip %s since pr does not exist", path) logger.Error(ctx, fmt.Sprintf("skip %s since pr does not exist", path))
return ErrPRNotExist return ErrPRNotExist
} }
req, err := DeleteBranch(ctx, g.URL, g.Owner, g.Repository, b, g.Token) req, err := DeleteBranch(ctx, g.URL, g.Owner, g.Repository, b, g.Token)
if err != nil { if err != nil {
logger.Error(ctx, "failed to create request for delete the branch: %s, err: %s", branch, err) logger.Error(ctx, fmt.Sprintf("failed to create request for delete the branch: %s, err: %s", branch, err))
return err return err
} }
rsp, err := http.DefaultClient.Do(req) rsp, err := http.DefaultClient.Do(req)
if err != nil { if err != nil {
logger.Error(ctx, "failed to do request for delete the branch: %s, err: %s, code: %s", branch, err, rsp.StatusCode) logger.Error(ctx, fmt.Sprintf("failed to do request for delete the branch: %s, err: %s, code: %s", branch, err, rsp.StatusCode))
return err return err
} }
logger.Info(ctx, "Delete branch for %s successful", path) logger.Info(ctx, fmt.Sprintf("Delete branch for %s successful", path))
return nil return nil
} }
@ -321,37 +321,37 @@ func (g *Gitea) RequestUpdate(ctx context.Context, branch string, path string, m
pulls, err := GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Token) pulls, err := GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Token)
if err != nil { if err != nil {
logger.Error(ctx, "GetPulls error: %s", err) logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err))
return err return err
} }
prExist := false prExist := false
for _, pull := range pulls { for _, pull := range pulls {
if strings.Contains(pull.Title, path) && pull.Base.Ref == branch { if strings.Contains(pull.Title, path) && pull.Base.Ref == branch {
logger.Info(ctx, "don't skip %s since pr exist %s", path, pull.URL) //todo logger.Info(ctx, fmt.Sprintf("don't skip %s since pr exist %s", path, pull.URL)) //todo
tVersion := getVersions(pull.Head.Ref) //Надо взять просто из названия ветки последнюю версию tVersion := getVersions(pull.Head.Ref) //Надо взять просто из названия ветки последнюю версию
if modules.IsNewerVersion(tVersion, mod.Version, false) { if modules.IsNewerVersion(tVersion, mod.Version, false) {
reqDel, err := DeleteBranch(ctx, g.URL, g.Owner, g.Repository, pull.Head.Ref, g.Token) reqDel, err := DeleteBranch(ctx, g.URL, g.Owner, g.Repository, pull.Head.Ref, g.Token)
if err != nil { if err != nil {
logger.Error(ctx, "Error with create request for branch: %s, err: %s", branch, err) logger.Error(ctx, fmt.Sprintf("Error with create request for branch: %s, err: %s", branch, err))
continue continue
} }
rsp, err := http.DefaultClient.Do(reqDel) rsp, err := http.DefaultClient.Do(reqDel)
if err != nil { if err != nil {
logger.Error(ctx, "Error with do request for branch: %s, err: %s, code: %v", branch, err, rsp.StatusCode) logger.Error(ctx, fmt.Sprintf("Error with do request for branch: %s, err: %s, code: %v", branch, err, rsp.StatusCode))
continue //думаю что если не можем удалить ветку не стоит заканчивать работу, а перейти к следующей итерации continue //думаю что если не можем удалить ветку не стоит заканчивать работу, а перейти к следующей итерации
} }
logger.Info(ctx, "Old pr %s successful delete", pull.Head.Ref) logger.Info(ctx, fmt.Sprintf("Old pr %s successful delete", pull.Head.Ref))
} }
prExist = true prExist = true
} }
} }
if !prExist { if !prExist {
logger.Error(ctx, " skip %s since pr does not exist", path) logger.Error(ctx, fmt.Sprintf("skip %s since pr does not exist", path))
return ErrPRNotExist return ErrPRNotExist
} }
logger.Info(ctx, "update %s from %s to %s", path, mod.Module.Version, mod.Version) logger.Info(ctx, fmt.Sprintf("update %s from %s to %s", path, mod.Module.Version, mod.Version))
return g.RequestOpen(ctx, branch, path, mod) return g.RequestOpen(ctx, branch, path, mod)
} }
@ -401,10 +401,9 @@ func GetPulls(ctx context.Context, url, owner, repo, token string) ([]*giteaPull
switch rsp.StatusCode { switch rsp.StatusCode {
case http.StatusOK: case http.StatusOK:
if err = json.Unmarshal(buf, &pulls); err != nil { if err = json.Unmarshal(buf, &pulls); err != nil {
logger.Fatal(ctx, "failed to decode response %s err: %v", buf, err) logger.Error(ctx, fmt.Sprintf("failed to decode response %s err: %v", buf, err))
return nil, err return nil, err
} }
return pulls, nil return pulls, nil
case http.StatusNotFound: case http.StatusNotFound:
logger.Info(ctx, "PL is not exist for %s", repo) logger.Info(ctx, "PL is not exist for %s", repo)