2024-02-14 23:03:30 +03:00
package gitea
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"os"
"os/exec"
2024-02-21 18:52:55 +03:00
"regexp"
2024-02-14 23:03:30 +03:00
"strings"
"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"
)
2024-03-15 21:18:58 +03:00
var (
ErrPRExist = errors . New ( "Pull request exists" )
ErrPRNotExist = errors . New ( "Pull request does not exist" )
)
2024-02-14 23:03:30 +03:00
type Gitea struct {
2024-03-15 21:18:58 +03:00
URL string
Token string
PRTitle string
PRBody string
Repository string
2024-03-15 23:12:39 +03:00
Owner string
2024-02-14 23:03:30 +03:00
}
2024-03-15 21:18:58 +03:00
func NewGitea ( cfg configcli . Config ) * Gitea {
2024-02-14 23:03:30 +03:00
return & Gitea {
2024-03-15 21:18:58 +03:00
URL : cfg . Source . APIURL ,
Token : cfg . Source . Token ,
PRTitle : cfg . PullRequestTitle ,
PRBody : cfg . PullRequestBody ,
Repository : cfg . Source . Repository ,
2024-03-15 23:12:39 +03:00
Owner : cfg . Source . Owner ,
2024-02-14 23:03:30 +03:00
}
}
type giteaPull struct {
URL string ` json:"url" `
Title string ` json:"title" `
Base struct {
Ref string ` json:"ref" `
} ` json:"base" `
ID int64 ` json:"id" `
}
2024-03-15 21:18:58 +03:00
func ( g * Gitea ) RequestOpen ( ctx context . Context , branch string , path string , mod modules . Update ) error {
2024-02-14 23:03:30 +03:00
logger . Debugf ( ctx , "RequestOpen start, mod title: %s" , path )
var buf [ ] byte
var err error
// создания шаблона названия для пулл реквеста
2024-03-15 21:18:58 +03:00
tplTitle , err := template . New ( "pull_request_title" ) . Parse ( g . PRTitle )
2024-02-14 23:03:30 +03:00
if err != nil {
logger . Fatalf ( ctx , "failed to parse template: %v" , err )
}
wTitle := bytes . NewBuffer ( nil )
// создания шаблона тела для пулл реквеста
2024-03-15 21:18:58 +03:00
tplBody , err := template . New ( "pull_request_body" ) . Parse ( g . PRTitle )
2024-02-14 23:03:30 +03:00
if err != nil {
logger . Fatalf ( ctx , "failed to parse template: %v" , err )
}
wBody := bytes . NewBuffer ( nil )
2024-03-15 23:12:39 +03:00
data := map [ string ] string {
"Name" : path ,
"VersionOld" : mod . Module . Version ,
"VersionNew" : mod . Version ,
}
if err = tplTitle . Execute ( wTitle , data ) ; err != nil {
logger . Fatalf ( ctx , "failed to execute template: %v" , err )
}
if err = tplBody . Execute ( wBody , data ) ; err != nil {
logger . Fatalf ( ctx , "failed to execute template: %v" , err )
}
2024-02-14 23:03:30 +03:00
// открытие гит репозитория с опцией обхода репозитория для нахождения .git
repo , err := git . PlainOpenWithOptions ( "." , & git . PlainOpenOptions { DetectDotGit : true } )
if err != nil {
logger . Fatalf ( ctx , "failed to open repo: %v" , err )
}
//извлекаем ссылки с объектами из удаленного объекта??
if err = repo . FetchContext ( ctx , & git . FetchOptions {
2024-03-15 21:18:58 +03:00
Auth : & httpauth . BasicAuth { Username : g . Token , Password : g . Token } ,
2024-02-14 23:03:30 +03:00
Force : true ,
} ) ; err != nil && err != git . NoErrAlreadyUpToDate {
logger . Fatalf ( ctx , "failed to fetch repo: %v" , err )
2024-02-21 18:52:55 +03:00
} //обновляем репозиторий
2024-02-14 23:03:30 +03:00
var headRef * plumbing . Reference // вроде ссылка на гит
refIter , err := repo . Branches ( ) //получение веток
if err != nil {
logger . Fatalf ( ctx , "failed to get branches: %v" , err )
}
for {
ref , err := refIter . Next ( )
if err != nil {
break
}
2024-03-15 21:59:29 +03:00
if strings . Contains ( ref . Name ( ) . String ( ) , branch ) { //todo вот тут возможно нужно переделать
2024-02-14 23:03:30 +03:00
headRef = ref
break
}
} //перебираем получение ветки и когда находим нужную выходим из цикла записав ветку в headRef
refIter . Close ( )
if headRef == nil {
logger . Fatalf ( ctx , "failed to get repo branch head" )
} // Н е получили нужную ветку
logger . Infof ( ctx , "repo head %s" , headRef )
2024-02-21 18:52:55 +03:00
wtree , err := repo . Worktree ( ) //todo вроде рабочее дерево не нужно
2024-02-14 23:03:30 +03:00
if err != nil {
logger . Fatalf ( ctx , "failed to get worktree: %v" , err )
}
var pulls [ ] * giteaPull
2024-03-16 01:05:37 +03:00
req , err := http . NewRequestWithContext (
ctx ,
http . MethodGet ,
fmt . Sprintf ( "%s/repos/%s/%s/pulls?state=open&token=%s" , g . URL , g . Owner , g . Repository , g . Token ) ,
nil )
2024-02-14 23:03:30 +03:00
if err != nil {
return err
2024-02-21 18:52:55 +03:00
} //Получаем список пулл реквестов
2024-02-14 23:03:30 +03:00
req . Header . Add ( "Accept" , "application/json" )
req . Header . Add ( "Content-Type" , "application/json" )
rsp , err := http . DefaultClient . Do ( req ) // выполнение запроса
if err != nil {
return err
}
buf , _ = io . ReadAll ( rsp . Body )
2024-03-15 21:59:29 +03:00
switch rsp . StatusCode {
case http . StatusOK :
if err = json . Unmarshal ( buf , & pulls ) ; err != nil {
logger . Fatalf ( ctx , "failed to decode response %s err: %v" , buf , err )
} // записываем ответ от гита по пулл реквестам, видимо существующим
// перебираем наши модификации и если они уже есть в гите удаляем их из mods
for _ , pull := range pulls {
if strings . Contains ( pull . Title , path ) && pull . Base . Ref == branch {
logger . Infof ( ctx , "skip %s as pr already exists %s" , path , pull . URL )
return ErrPRExist
} // хотим проверить есть ли пулл реквест для этой ветки, если есть то выходим
}
case http . StatusNotFound :
logger . Infof ( ctx , "PL is not exist for %s" , g . Repository )
default :
return fmt . Errorf ( "unknown error: %s" , buf )
2024-02-14 23:03:30 +03:00
}
logger . Infof ( ctx , "update %s from %s to %s" , path , mod . Module . Version , mod . Version )
logger . Infof ( ctx , "reset worktree" )
if err = wtree . Reset ( & git . ResetOptions { Mode : git . HardReset } ) ; err != nil {
logger . Fatalf ( ctx , "failed to reset repo branch: %v" , err )
2024-02-21 18:52:55 +03:00
} //вроде меняем ветку todo вроде можно удалить
2024-02-14 23:03:30 +03:00
if err = wtree . PullContext ( ctx , & git . PullOptions {
2024-03-15 21:18:58 +03:00
Auth : & httpauth . BasicAuth { Username : g . Token , Password : g . Token } ,
2024-02-14 23:03:30 +03:00
Depth : 1 ,
// RemoteURL :
Force : true ,
RemoteName : "origin" ,
} ) ; err != nil && err != git . NoErrAlreadyUpToDate {
2024-02-21 18:52:55 +03:00
logger . Fatalf ( ctx , "failed to pull repo: %v" , err ) //подтягиваем изменения с удаленого репозитория
2024-02-14 23:03:30 +03:00
}
logger . Infof ( ctx , "checkout ref %s" , headRef )
if err = wtree . Checkout ( & git . CheckoutOptions {
Hash : headRef . Hash ( ) ,
2024-02-21 18:52:55 +03:00
Branch : plumbing . NewBranchReferenceName ( fmt . Sprintf ( "pkgdash/go_modules/%s-%s" , path , mod . Version ) ) ,
2024-02-14 23:03:30 +03:00
Create : true ,
Force : true ,
} ) ; err != nil {
logger . Fatalf ( ctx , "failed to checkout tree: %v" , err )
2024-02-21 18:52:55 +03:00
} //создаем новую ветку
2024-02-14 23:03:30 +03:00
epath , err := exec . LookPath ( "go" )
if errors . Is ( err , exec . ErrDot ) {
err = nil
}
if err != nil {
logger . Fatalf ( ctx , "failed to find go command: %v" , err )
} // ищем go файл
var cmd * exec . Cmd
var out [ ] byte
cmd = exec . CommandContext ( ctx , epath , "mod" , "edit" , fmt . Sprintf ( "-require=%s@%s" , path , mod . Version ) )
if out , err = cmd . CombinedOutput ( ) ; err != nil {
logger . Fatalf ( ctx , "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 . Fatalf ( ctx , "failed to run go mod tidy: %s err: %v" , out , err )
} // пытаемся выполнить команду go mod tidy пытаемся подтянуть новую версию модуля
logger . Infof ( ctx , "worktree add go.mod" )
if _ , err = wtree . Add ( "go.mod" ) ; err != nil {
logger . Fatalf ( ctx , "failed to add file: %v" , err )
}
logger . Infof ( ctx , "worktree add go.sum" )
if _ , err = wtree . Add ( "go.sum" ) ; err != nil {
logger . Fatalf ( ctx , "failed to add file: %v" , err )
}
logger . Infof ( ctx , "worktree commit" )
_ , err = wtree . Commit ( wTitle . String ( ) , & git . CommitOptions {
Parents : [ ] plumbing . Hash { headRef . Hash ( ) } ,
Author : & object . Signature {
Name : "gitea-actions" ,
Email : "info@unistack.org" ,
When : time . Now ( ) ,
} ,
} ) // хотим за коммитить изменения
if err != nil {
logger . Fatalf ( ctx , "failed to commit: %v" , err )
}
// newref := plumbing.NewHashReference(plumbing.ReferenceName(fmt.Sprintf("refs/heads/pkgdash-1/go_modules/%s-%s", path, mod.Version)), headRef.Hash())
/ *
if err = repo . Storer . SetReference ( newref ) ; err != nil {
logger . Fatalf ( ctx , "failed to create repo branch: %v" , err )
}
* /
2024-03-15 21:59:29 +03:00
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 как будто нужно переделать
2024-02-14 23:03:30 +03:00
logger . Infof ( ctx , "try to push refspec %s" , refspec )
if err = repo . PushContext ( ctx , & git . PushOptions {
RefSpecs : [ ] gitconfig . RefSpec { refspec } ,
2024-03-15 21:18:58 +03:00
Auth : & httpauth . BasicAuth { Username : g . Token , Password : g . Token } ,
2024-02-14 23:03:30 +03:00
Force : true ,
} ) ; err != nil {
logger . Fatalf ( ctx , "failed to push repo branch: %v" , err )
} // пытаемся за пушить изменения
body := map [ string ] string {
2024-03-16 00:41:56 +03:00
"base" : "develop" ,
2024-02-14 23:03:30 +03:00
"body" : wBody . String ( ) ,
2024-03-15 21:59:29 +03:00
"head" : fmt . Sprintf ( "pkgdash/go_modules/%s-%s" , path , mod . Version ) ,
2024-02-14 23:03:30 +03:00
"title" : wTitle . String ( ) ,
}
logger . Infof ( ctx , "raw body: %#+v" , body )
buf , err = json . Marshal ( body )
if err != nil {
return err
}
logger . Infof ( ctx , "marshal body: %s" , buf )
2024-03-15 23:12:39 +03:00
req , err = http . NewRequestWithContext (
ctx ,
http . MethodPost ,
fmt . Sprintf ( "%s/repos/%s/%s/pulls?token=%s" , g . URL , g . Owner , g . Repository , g . Token ) ,
bytes . NewReader ( buf ) ,
)
2024-02-14 23:03:30 +03:00
if err != nil {
return err
}
req . Header . Add ( "Accept" , "application/json" )
req . Header . Add ( "Content-Type" , "application/json" )
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 )
}
return nil
}
func ( g * Gitea ) RequestClose ( ctx context . Context , cfg * configcli . Config , branch string , path string ) error {
logger . Debugf ( ctx , "RequestOpen start, mod title: %s" , path )
if cfg . Source == nil {
cfg . Source = & configcli . Source {
TypeGit : "gitea" ,
Token : os . Getenv ( "GITHUB_TOKEN" ) ,
APIURL : os . Getenv ( "GITHUB_API_URL" ) ,
Repository : os . Getenv ( "GITHUB_REPOSITORY" ) ,
}
}
2024-03-15 21:18:58 +03:00
fmt . Printf ( "cfg: %v" , cfg )
2024-02-14 23:03:30 +03:00
var buf [ ] byte
var err error
repo , err := git . PlainOpenWithOptions ( "." , & git . PlainOpenOptions { DetectDotGit : true } )
if err != nil {
logger . Fatalf ( ctx , "failed to open repo: %v" , err )
}
//извлекаем ссылки с объектами из удаленного объекта??
if err = repo . FetchContext ( ctx , & git . FetchOptions {
Auth : & httpauth . BasicAuth { Username : cfg . Source . Token , Password : cfg . Source . Token } ,
Force : true ,
} ) ; err != nil && err != git . NoErrAlreadyUpToDate {
logger . Fatalf ( ctx , "failed to fetch repo: %v" , err )
}
var headRef * plumbing . Reference // вроде ссылка на гит
refIter , err := repo . Branches ( ) //получение веток
if err != nil {
logger . Fatalf ( ctx , "failed to get branches: %v" , err )
}
for {
ref , err := refIter . Next ( )
if err != nil {
break
}
if ref . Name ( ) . String ( ) == branch {
headRef = ref
break
}
} //перебираем получение ветки и когда находим нужную выходим из цикла записав ветку в headRef
refIter . Close ( )
if headRef == nil {
logger . Fatalf ( ctx , "failed to get repo branch head" )
} // Н е получили нужную ветку
logger . Infof ( ctx , "repo head %s" , headRef )
var pulls [ ] * giteaPull
req , err := http . NewRequestWithContext ( ctx , http . MethodGet , cfg . Source . APIURL + "/repos/" + cfg . Source . Repository + "/pulls?state=open&token=" + cfg . Source . Token , nil )
if err != nil {
return err
} //вроде запроса к репозиторию
req . Header . Add ( "Accept" , "application/json" )
req . Header . Add ( "Content-Type" , "application/json" )
rsp , err := http . DefaultClient . Do ( req ) // выполнение запроса
if err != nil {
return err
}
buf , _ = io . ReadAll ( rsp . Body )
if rsp . StatusCode != http . StatusOK {
return fmt . Errorf ( "unknown error: %s" , buf )
}
if err = json . Unmarshal ( buf , & pulls ) ; err != nil {
logger . Fatalf ( ctx , "failed to decode response %s err: %v" , buf , err )
} // записываем ответ от гита по пулл реквестам, видимо существующим
// перебираем наши модификации и если они уже есть в гите удаляем их из mods
2024-02-21 18:52:55 +03:00
prExist := false
2024-02-14 23:03:30 +03:00
for _ , pull := range pulls {
2024-02-21 18:52:55 +03:00
if strings . Contains ( pull . Title , path ) && pull . Base . Ref == branch {
2024-02-14 23:03:30 +03:00
logger . Infof ( ctx , "skip %s since pr does not exist %s" , path , pull . URL )
2024-02-21 18:52:55 +03:00
prExist = true
2024-02-14 23:03:30 +03:00
}
}
2024-02-21 18:52:55 +03:00
if ! prExist {
logger . Errorf ( ctx , " skip %s since pr does not exist" , path )
2024-03-15 21:18:58 +03:00
return ErrPRNotExist
2024-02-21 18:52:55 +03:00
}
2024-02-14 23:03:30 +03:00
2024-02-21 18:52:55 +03:00
req , err = DeleteBranch ( ctx , cfg , branch )
if err != nil {
logger . Errorf ( ctx , "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 . Errorf ( ctx , "failed to do request for delete the branch: %s, err: %s, code: %s" , branch , err , rsp . StatusCode )
2024-02-14 23:03:30 +03:00
return err
}
2024-02-21 18:52:55 +03:00
logger . Infof ( ctx , "Delete branch %s successful" , branch )
2024-02-14 23:03:30 +03:00
return nil
}
func ( g * Gitea ) RequestUpdate ( ctx context . Context , cfg * configcli . Config , branch string , path string , mod modules . Update ) error {
logger . Debugf ( ctx , "RequestOpen start, mod title: %s" , path )
if cfg . Source == nil {
cfg . Source = & configcli . Source {
TypeGit : "gitea" ,
Token : os . Getenv ( "GITHUB_TOKEN" ) ,
APIURL : os . Getenv ( "GITHUB_API_URL" ) ,
Repository : os . Getenv ( "GITHUB_REPOSITORY" ) ,
}
}
var buf [ ] byte
var err error
// создания шаблона названия для пулл реквеста
tplTitle , err := template . New ( "pull_request_title" ) . Parse ( cfg . PullRequestTitle )
if err != nil {
logger . Fatalf ( ctx , "failed to parse template: %v" , err )
}
wTitle := bytes . NewBuffer ( nil )
// создания шаблона тела для пулл реквеста
tplBody , err := template . New ( "pull_request_body" ) . Parse ( cfg . PullRequestBody )
if err != nil {
logger . Fatalf ( ctx , "failed to parse template: %v" , err )
}
wBody := bytes . NewBuffer ( nil )
// открытие гит репозитория с опцией обхода репозитория для нахождения .git
repo , err := git . PlainOpenWithOptions ( "." , & git . PlainOpenOptions { DetectDotGit : true } )
if err != nil {
logger . Fatalf ( ctx , "failed to open repo: %v" , err )
}
//извлекаем ссылки с объектами из удаленного объекта??
if err = repo . FetchContext ( ctx , & git . FetchOptions {
Auth : & httpauth . BasicAuth { Username : cfg . Source . Token , Password : cfg . Source . Token } ,
Force : true ,
} ) ; err != nil && err != git . NoErrAlreadyUpToDate {
logger . Fatalf ( ctx , "failed to fetch repo: %v" , err )
}
var headRef * plumbing . Reference // вроде ссылка на гит
refIter , err := repo . Branches ( ) //получение веток
if err != nil {
logger . Fatalf ( ctx , "failed to get branches: %v" , err )
}
for {
ref , err := refIter . Next ( )
if err != nil {
break
}
if ref . Name ( ) . String ( ) == branch {
headRef = ref
break
}
} //перебираем получение ветки и когда находим нужную выходим из цикла записав ветку в headRef
refIter . Close ( )
if headRef == nil {
logger . Fatalf ( ctx , "failed to get repo branch head" )
} // Н е получили нужную ветку
logger . Infof ( ctx , "repo head %s" , headRef )
wtree , err := repo . Worktree ( )
if err != nil {
logger . Fatalf ( ctx , "failed to get worktree: %v" , err )
}
var pulls [ ] * giteaPull
req , err := http . NewRequestWithContext ( ctx , http . MethodGet , cfg . Source . APIURL + "/repos/" + cfg . Source . Repository + "/pulls?state=open&token=" + cfg . Source . Token , nil )
if err != nil {
return err
} //вроде запроса к репозиторию
req . Header . Add ( "Accept" , "application/json" )
req . Header . Add ( "Content-Type" , "application/json" )
rsp , err := http . DefaultClient . Do ( req ) // выполнение запроса
if err != nil {
return err
}
buf , _ = io . ReadAll ( rsp . Body )
if rsp . StatusCode != http . StatusOK {
return fmt . Errorf ( "unknown error: %s" , buf )
}
if err = json . Unmarshal ( buf , & pulls ) ; err != nil {
logger . Fatalf ( ctx , "failed to decode response %s err: %v" , buf , err )
} // записываем ответ от гита по пулл реквестам, видимо существующим
// перебираем наши модификации и если они уже есть в гите удаляем их из mods
2024-02-21 18:52:55 +03:00
prExist := false
2024-02-14 23:03:30 +03:00
for _ , pull := range pulls {
2024-02-21 18:52:55 +03:00
if strings . Contains ( pull . Title , path ) && pull . Base . Ref != branch {
logger . Infof ( ctx , "skip %s since pr does not exist %s" , path , pull . URL ) //todo
titleVersions := getVersions ( pull . Title )
if modules . IsNewerVersion ( titleVersions . NewV , mod . Version , false ) {
reqDel , err := DeleteBranch ( ctx , cfg , branch )
if err != nil {
logger . Errorf ( ctx , "Error with create request for branch: %s, err: %s" , branch , err )
continue
}
rsp , err := http . DefaultClient . Do ( reqDel )
if err != nil {
logger . Errorf ( ctx , "Error with do request for branch: %s, err: %s, code: %v" , branch , err , rsp . StatusCode )
continue //думаю что если не можем удалить ветку не стоит заканчивать работу, а перейти к следующей итерации
}
}
prExist = true
2024-02-14 23:03:30 +03:00
}
}
2024-02-21 18:52:55 +03:00
if ! prExist {
logger . Errorf ( ctx , " skip %s since pr does not exist" , path )
2024-03-15 21:18:58 +03:00
return ErrPRNotExist
2024-02-21 18:52:55 +03:00
}
2024-02-14 23:03:30 +03:00
logger . Infof ( ctx , "update %s from %s to %s" , path , mod . Module . Version , mod . Version )
logger . Infof ( ctx , "reset worktree" )
if err = wtree . Reset ( & git . ResetOptions { Mode : git . HardReset } ) ; err != nil {
logger . Fatalf ( ctx , "failed to reset repo branch: %v" , err )
} //вроде меняем ветку
if err = wtree . PullContext ( ctx , & git . PullOptions {
Auth : & httpauth . BasicAuth { Username : cfg . Source . Token , Password : cfg . Source . Token } ,
Depth : 1 ,
// RemoteURL :
Force : true ,
RemoteName : "origin" ,
} ) ; err != nil && err != git . NoErrAlreadyUpToDate {
logger . Fatalf ( ctx , "failed to pull repo: %v" , err )
}
logger . Infof ( ctx , "checkout ref %s" , headRef )
if err = wtree . Checkout ( & git . CheckoutOptions {
Hash : headRef . Hash ( ) ,
Branch : headRef . Name ( ) ,
Create : false ,
Force : true ,
} ) ; err != nil {
logger . Fatalf ( ctx , "failed to checkout tree: %v" , err )
} //вроде как переходим на другую ветку
epath , err := exec . LookPath ( "go" )
if errors . Is ( err , exec . ErrDot ) {
err = nil
}
if err != nil {
logger . Fatalf ( ctx , "failed to find go command: %v" , err )
} // ищем go файл
var cmd * exec . Cmd
var out [ ] byte
cmd = exec . CommandContext ( ctx , epath , "mod" , "edit" , fmt . Sprintf ( "-require=%s@%s" , path , mod . Version ) )
if out , err = cmd . CombinedOutput ( ) ; err != nil {
logger . Fatalf ( ctx , "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 . Fatalf ( ctx , "failed to run go mod tidy: %s err: %v" , out , err )
} // пытаемся выполнить команду go mod tidy пытаемся подтянуть новую версию модуля
logger . Infof ( ctx , "worktree add go.mod" )
if _ , err = wtree . Add ( "go.mod" ) ; err != nil {
logger . Fatalf ( ctx , "failed to add file: %v" , err )
}
logger . Infof ( ctx , "worktree add go.sum" )
if _ , err = wtree . Add ( "go.sum" ) ; err != nil {
logger . Fatalf ( ctx , "failed to add file: %v" , err )
}
logger . Infof ( ctx , "worktree commit" )
_ , err = wtree . Commit ( wTitle . String ( ) , & git . CommitOptions {
Parents : [ ] plumbing . Hash { headRef . Hash ( ) } ,
Author : & object . Signature {
Name : "gitea-actions" ,
Email : "info@unistack.org" ,
When : time . Now ( ) ,
} ,
} ) // хотим за коммитить изменения
if err != nil {
logger . Fatalf ( ctx , "failed to commit: %v" , err )
}
// newref := plumbing.NewHashReference(plumbing.ReferenceName(fmt.Sprintf("refs/heads/pkgdash-1/go_modules/%s-%s", path, mod.Version)), headRef.Hash())
/ *
if err = repo . Storer . SetReference ( newref ) ; err != nil {
logger . Fatalf ( ctx , "failed to create repo branch: %v" , err )
}
* /
refspec := gitconfig . RefSpec ( fmt . Sprintf ( "+refs/heads/pkgdash-1/go_modules/%s-%s:refs/heads/pkgdash-1/go_modules/%s-%s" , path , mod . Version , path , mod . Version ) )
logger . Infof ( ctx , "try to push refspec %s" , refspec )
if err = repo . PushContext ( ctx , & git . PushOptions {
RefSpecs : [ ] gitconfig . RefSpec { refspec } ,
Auth : & httpauth . BasicAuth { Username : cfg . Source . Token , Password : cfg . Source . Token } ,
Force : true ,
} ) ; err != nil {
logger . Fatalf ( ctx , "failed to push repo branch: %v" , err )
} // пытаемся за пушить изменения
data := map [ string ] string {
"Name" : path ,
"VersionOld" : mod . Module . Version ,
"VersionNew" : mod . Version ,
}
if err = tplTitle . Execute ( wTitle , data ) ; err != nil {
logger . Fatalf ( ctx , "failed to execute template: %v" , err )
}
if err = tplBody . Execute ( wBody , data ) ; err != nil {
logger . Fatalf ( ctx , "failed to execute template: %v" , err )
}
body := map [ string ] string {
"base" : branch ,
"body" : wBody . String ( ) ,
"head" : fmt . Sprintf ( "pkgdash-1/go_modules/%s-%s" , path , mod . Version ) ,
"title" : wTitle . String ( ) ,
}
logger . Infof ( ctx , "raw body: %#+v" , body )
buf , err = json . Marshal ( body )
if err != nil {
return err
}
logger . Infof ( ctx , "marshal body: %s" , buf )
req , err = http . NewRequestWithContext ( ctx , http . MethodPost , cfg . Source . APIURL + "/repos/" + cfg . Source . Repository + "/pulls?token=" + cfg . Source . Token , bytes . NewReader ( buf ) )
if err != nil {
return err
}
req . Header . Add ( "Accept" , "application/json" )
req . Header . Add ( "Content-Type" , "application/json" )
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 )
}
return nil
}
2024-02-21 18:52:55 +03:00
func getVersions ( s string ) * Tmod {
rsp := new ( Tmod )
re := regexp . MustCompile ( "[0-9]+\\.[0-9]+\\.[0-9]+" )
versions := re . FindAllString ( s , - 1 )
if len ( versions ) < 2 {
return nil
}
if modules . IsNewerVersion ( versions [ 0 ] , versions [ 1 ] , false ) {
rsp . OldV = versions [ 0 ]
rsp . NewV = versions [ 1 ]
return rsp
}
rsp . OldV = versions [ 1 ]
rsp . NewV = versions [ 0 ]
return rsp
}
type Tmod struct {
OldV string
NewV string
}
func DeleteBranch ( ctx context . Context , cfg * configcli . Config , branch string ) ( * http . Request , error ) {
var buf [ ] byte
req , err := http . NewRequestWithContext ( ctx , http . MethodDelete , cfg . Source . APIURL + "/repos/" + cfg . Source . Repository + "/branches/" + branch + "?token=" + cfg . Source . Token , bytes . NewReader ( buf ) )
if err != nil {
return nil , err
}
req . Header . Add ( "Accept" , "application/json" )
req . Header . Add ( "Content-Type" , "application/json" )
return req , err
}