diff --git a/.gitea/pkgdashcli.yaml b/.gitea/pkgdashcli.yaml index aa426c2..fe0f9e9 100644 --- a/.gitea/pkgdashcli.yaml +++ b/.gitea/pkgdashcli.yaml @@ -3,8 +3,9 @@ branches: source: type: gitea apiurl: git.unistack.org + repository: pkgdash update_opt: pre: false major: false up_major: false - cached: true + cached: true \ No newline at end of file diff --git a/internal/source/gitea/gitea.go b/internal/source/gitea/gitea.go index b318fd6..ca32dbe 100644 --- a/internal/source/gitea/gitea.go +++ b/internal/source/gitea/gitea.go @@ -35,6 +35,7 @@ type Gitea struct { Repository string Owner string pulls []*giteaPull + baseRef *plumbing.Reference } func NewGitea(cfg configcli.Config) *Gitea { @@ -105,13 +106,21 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod } //извлекаем ссылки с объектами из удаленного объекта?? if err = repo.FetchContext(ctx, &git.FetchOptions{ - // Auth: &httpauth.BasicAuth{Username: g.Username, Password: g.Password}, + 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)) } //обновляем репозиторий 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)) + } + } + refIter, err := repo.Branches() //получение веток if err != nil { logger.Fatal(ctx, fmt.Sprintf("failed to get branches: %v", err)) @@ -140,10 +149,10 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod if err != nil { logger.Fatal(ctx, fmt.Sprintf("failed to get worktree: %v", err)) } - defer checkout(wtree, *headRef) + defer checkout(*wtree, *g.baseRef) g.pulls, err = GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Password) - if err != nil && err != ErrPRNotExist { + if err != nil { logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err)) return err } @@ -270,7 +279,7 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod } req.Header.Add("Accept", "application/json") req.Header.Add("Content-Type", "application/json") - req.Header.Add("Authorization", g.Password) + req.Header.Add("Authorization", "Bearer "+g.Password) rsp, err := http.DefaultClient.Do(req) if err != nil { @@ -293,8 +302,9 @@ func (g *Gitea) RequestOpen(ctx context.Context, branch string, path string, mod func (g *Gitea) RequestClose(ctx context.Context, branch string, path string) error { logger.Debug(ctx, fmt.Sprintf("RequestClose start, mod title: %s", path)) + var err error - pulls, err := GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Password) + 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)) return err @@ -302,7 +312,7 @@ func (g *Gitea) RequestClose(ctx context.Context, branch string, path string) er prExist := false var b string // Name of the branch to be deleted - for _, pull := range pulls { + 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)) prExist = true @@ -333,12 +343,10 @@ func (g *Gitea) RequestUpdate(ctx context.Context, branch string, path string, m logger.Debug(ctx, fmt.Sprintf("RequestUpdate start, mod title: %s", path)) var err error - if len(g.pulls) == 0 { - 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)) - return err - } + 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)) + return err } prExist := false @@ -379,6 +387,7 @@ func (g *Gitea) RequestList(ctx context.Context, branch string) (map[string]stri 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)) return nil, err } @@ -411,7 +420,7 @@ func DeleteBranch(ctx context.Context, url, owner, repo, branch, password string } req.Header.Add("Accept", "application/json") req.Header.Add("Content-Type", "application/json") - req.Header.Add("Authorization", password) + req.Header.Add("Authorization", "Bearer "+password) return req, err } @@ -432,7 +441,7 @@ func GetPulls(ctx context.Context, url, owner, repo, password string) ([]*giteaP req.Header.Add("Accept", "application/json") req.Header.Add("Content-Type", "application/json") - req.Header.Add("Authorization", password) + req.Header.Add("Authorization", "Bearer "+password) rsp, err := http.DefaultClient.Do(req) // выполнение запроса if err != nil { @@ -464,9 +473,16 @@ func GetPulls(ctx context.Context, url, owner, repo, password string) ([]*giteaP return pullsAll, nil } -func checkout(w *git.Worktree, ref plumbing.Reference) { +func checkout(w git.Worktree, ref plumbing.Reference) { ctx := context.Background() - if err := w.Reset(&git.ResetOptions{Commit: ref.Hash(), Mode: git.HardReset}); err != nil { - logger.Fatal(ctx, fmt.Sprintf("failed to reset: %v", err)) + logger.Debug(ctx, fmt.Sprintf("Checkout: %s", ref.Name().Short())) + + if err := w.Checkout(&git.CheckoutOptions{ + Branch: ref.Name(), + Create: false, + Force: true, + Keep: false, + }); err != nil { + logger.Error(ctx, fmt.Sprintf("failed to reset: %v", err)) } } diff --git a/internal/source/github/github.go b/internal/source/github/github.go index 22b355b..972457e 100644 --- a/internal/source/github/github.go +++ b/internal/source/github/github.go @@ -34,6 +34,7 @@ type Github struct { Repository string Owner string pulls []*githubPull + baseRef *plumbing.Reference } func NewGithub(cfg configcli.Config) *Github { @@ -111,6 +112,14 @@ func (g *Github) RequestOpen(ctx context.Context, branch string, path string, mo } //обновляем репозиторий 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)) + } + } + refIter, err := repo.Branches() //получение веток if err != nil { logger.Fatal(ctx, fmt.Sprintf("failed to get branches: %v", err)) @@ -139,9 +148,10 @@ func (g *Github) RequestOpen(ctx context.Context, branch string, path string, mo if err != nil { logger.Fatal(ctx, fmt.Sprintf("failed to get worktree: %v", err)) } + defer checkout(*wtree, *g.baseRef) g.pulls, err = GetPulls(ctx, g.URL, g.Owner, g.Repository, g.Password) - if err != nil && err != ErrPRNotExist { + if err != nil { logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err)) return err } @@ -268,7 +278,7 @@ func (g *Github) RequestOpen(ctx context.Context, branch string, path string, mo } req.Header.Add("Accept", "application/json") req.Header.Add("Content-Type", "application/json") - req.Header.Add("Authorization", g.Password) + req.Header.Add("Authorization", "Bearer "+g.Password) rsp, err := http.DefaultClient.Do(req) if err != nil { @@ -295,7 +305,26 @@ func (g *Github) RequestUpdate(ctx context.Context, branch string, path string, return fmt.Errorf("implement me") } func (g *Github) RequestList(ctx context.Context, branch string) (map[string]string, error) { - return nil, fmt.Errorf("implement me") + 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) + if err != nil { + logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err)) + return nil, err + } + + var path string + rMap := make(map[string]string) + + for _, pull := range g.pulls { + if !strings.HasPrefix(pull.Title, "Bump ") || pull.Base.Ref != branch { //добавляем только реквесты бота по обновлению модулей + continue + } + path = strings.Split(pull.Title, " ")[1] //todo Работет только для дефолтного шаблона + rMap[path] = pull.Title + } + return rMap, nil } func GetPulls(ctx context.Context, url, owner, repo, password string) ([]*githubPull, error) { @@ -315,7 +344,7 @@ func GetPulls(ctx context.Context, url, owner, repo, password string) ([]*github req.Header.Add("Accept", "application/json") req.Header.Add("Content-Type", "application/json") - req.Header.Add("Authorization", password) + req.Header.Add("Authorization", "Bearer "+password) rsp, err := http.DefaultClient.Do(req) // выполнение запроса if err != nil { @@ -346,3 +375,17 @@ func GetPulls(ctx context.Context, url, owner, repo, password string) ([]*github return pullsAll, nil } + +func checkout(w git.Worktree, ref plumbing.Reference) { + ctx := context.Background() + logger.Debug(ctx, fmt.Sprintf("Checkout: %s", ref.Name().Short())) + + if err := w.Checkout(&git.CheckoutOptions{ + Branch: ref.Name(), + Create: false, + Force: true, + Keep: false, + }); err != nil { + logger.Error(ctx, fmt.Sprintf("failed to reset: %v", err)) + } +} diff --git a/internal/source/gitlab/gitlab.go b/internal/source/gitlab/gitlab.go index a096eeb..88fc2be 100644 --- a/internal/source/gitlab/gitlab.go +++ b/internal/source/gitlab/gitlab.go @@ -10,7 +10,6 @@ import ( "net/http" "os/exec" "regexp" - "strconv" "strings" "text/template" "time" @@ -37,6 +36,7 @@ type Gitlab struct { RepositoryId string Owner string pulls []*gitlabPull + baseRef *plumbing.Reference } func NewGitlab(cfg configcli.Config) *Gitlab { @@ -59,11 +59,6 @@ type gitlabPull struct { ID int64 `json:"id"` } -type gitlabProject struct { - Id int64 `json:"id"` - Name string `json:"name"` -} - func (g *Gitlab) Name() string { return "gitlab" } @@ -116,10 +111,16 @@ func (g *Gitlab) RequestOpen(ctx context.Context, branch string, path string, mo 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)) + } + } + refIter, err := repo.Branches() //получение веток if err != nil { logger.Fatal(ctx, fmt.Sprintf("failed to get branches: %v", err)) - return err } for { ref, err := refIter.Next() @@ -144,15 +145,10 @@ func (g *Gitlab) RequestOpen(ctx context.Context, branch string, path string, mo if err != nil { logger.Fatal(ctx, fmt.Sprintf("failed to get worktree: %v", err)) } - defer checkout(wtree, *headRef) + defer checkout(*wtree, *g.baseRef) - g.RepositoryId, err = GetRepoID(ctx, g.URL, g.Owner, g.Repository, g.Password) - if err != nil || g.RepositoryId == "" { - return fmt.Errorf("project id is empty") - } - - g.pulls, err = GetPulls(ctx, g.URL, g.RepositoryId, branch, g.Password) - if err != nil && err != ErrPRNotExist { + 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)) return err } @@ -282,7 +278,7 @@ func (g *Gitlab) RequestOpen(ctx context.Context, branch string, path string, mo } req.Header.Add("Accept", "application/json") req.Header.Add("Content-Type", "application/json") - req.Header.Add("Authorization", g.Password) + req.Header.Add("Authorization", "Bearer "+g.Password) rsp, err := http.DefaultClient.Do(req) if err != nil { @@ -300,15 +296,9 @@ func (g *Gitlab) RequestOpen(ctx context.Context, branch string, path string, mo func (g *Gitlab) RequestClose(ctx context.Context, branch string, path string) error { logger.Debug(ctx, fmt.Sprintf("RequestClose start, mod title: %s", path)) - var err error - g.RepositoryId, err = GetRepoID(ctx, g.URL, g.Owner, g.Repository, g.Password) - if err != nil || g.RepositoryId == "" { - return fmt.Errorf("project id is empty") - } - - pulls, err := GetPulls(ctx, g.URL, g.RepositoryId, branch, g.Password) + 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)) return err @@ -316,7 +306,7 @@ func (g *Gitlab) RequestClose(ctx context.Context, branch string, path string) e prExist := false var b string // Name of the branch to be deleted - for _, pull := range pulls { + for _, pull := range g.pulls { if strings.Contains(pull.Title, path) { logger.Info(ctx, fmt.Sprintf("PR for %s exists: %s", path, pull.URL)) prExist = true @@ -347,17 +337,10 @@ func (g *Gitlab) RequestUpdate(ctx context.Context, branch string, path string, logger.Debug(ctx, fmt.Sprintf("RequestUpdate start, mod title: %s", path)) var err error - g.RepositoryId, err = GetRepoID(ctx, g.URL, g.Owner, g.Repository, g.Password) - if err != nil || g.RepositoryId == "" { - return fmt.Errorf("project id is empty") - } - - if len(g.pulls) == 0 { - g.pulls, err = GetPulls(ctx, g.URL, g.RepositoryId, branch, g.Password) - if err != nil { - logger.Error(ctx, fmt.Sprintf("GetPulls error: %s", err)) - return err - } + 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)) + return err } prExist := false @@ -396,13 +379,9 @@ func (g *Gitlab) RequestList(ctx context.Context, branch string) (map[string]str logger.Debug(ctx, fmt.Sprintf("RequestList for %s", branch)) var err error - g.RepositoryId, err = GetRepoID(ctx, g.URL, g.Owner, g.Repository, g.Password) - if err != nil || g.RepositoryId == "" { - return nil, fmt.Errorf("project id is empty") - } - - g.pulls, err = GetPulls(ctx, g.URL, g.RepositoryId, branch, g.Password) + 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)) return nil, err } @@ -435,7 +414,7 @@ func DeleteBranch(ctx context.Context, url, projectId, branch, password string) } req.Header.Add("Accept", "application/json") req.Header.Add("Content-Type", "application/json") - req.Header.Add("Authorization", password) + req.Header.Add("Authorization", "Bearer "+password) return req, err } @@ -452,7 +431,7 @@ func GetPulls(ctx context.Context, url, projectId, branch, password string) ([]* req.Header.Add("Accept", "application/json") req.Header.Add("Content-Type", "application/json") - req.Header.Add("Authorization", password) + req.Header.Add("Authorization", "Bearer "+password) rsp, err := http.DefaultClient.Do(req) // выполнение запроса if err != nil { @@ -476,43 +455,16 @@ func GetPulls(ctx context.Context, url, projectId, branch, password string) ([]* } } -func GetRepoID(ctx context.Context, url, owner, repo, password string) (rId string, err error) { - var buf []byte - projects := make([]*gitlabProject, 0, 10) - req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://%s/api/v4/users/%s/projects?owned=true", url, owner), nil) - if err != nil { - return - } - req.Header.Add("Accept", "application/json") - req.Header.Add("Content-Type", "application/json") - req.Header.Add("Authorization", password) - - rsp, err := http.DefaultClient.Do(req) - if err != nil { - return - } - - buf, _ = io.ReadAll(rsp.Body) - - switch rsp.StatusCode { - case http.StatusOK: - if err = json.Unmarshal(buf, &projects); err != nil { - logger.Error(ctx, fmt.Sprintf("failed to decode response %s err: %v", buf, err)) - } - for _, p := range projects { - if p.Name == repo { - rId = strconv.Itoa(int(p.Id)) - } - } - return - default: - return rId, fmt.Errorf("unknown error: %s", buf) - } -} - -func checkout(w *git.Worktree, ref plumbing.Reference) { +func checkout(w git.Worktree, ref plumbing.Reference) { ctx := context.Background() - if err := w.Reset(&git.ResetOptions{Commit: ref.Hash(), Mode: git.HardReset}); err != nil { - logger.Fatal(ctx, fmt.Sprintf("failed to reset: %v", err)) + logger.Debug(ctx, fmt.Sprintf("Checkout: %s", ref.Name().Short())) + + if err := w.Checkout(&git.CheckoutOptions{ + Branch: ref.Name(), + Create: false, + Force: true, + Keep: false, + }); err != nil { + logger.Error(ctx, fmt.Sprintf("failed to reset: %v", err)) } }