forked from jzerebecki/autogits
Compare commits
5 Commits
testpr
...
fix-pr-lin
| Author | SHA256 | Date | |
|---|---|---|---|
|
|
933ca9a3db
|
||
| 6cbeaef6f2 | |||
| d146fb8c4e | |||
| 7e78ee83c1 | |||
| 17e925bfd7 |
@@ -1,26 +0,0 @@
|
||||
name: go-generate
|
||||
on:
|
||||
push:
|
||||
branches: ['main']
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**foo'
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
go-generate:
|
||||
name: go-generate
|
||||
container:
|
||||
image: registry.opensuse.org/home/jzerebecki/branches/devel/factory/git-workflow/containers/opensuse/bci/golang-extended:latest
|
||||
steps:
|
||||
- run: git clone --no-checkout --depth 1 ${{ gitea.server_url }}/${{ gitea.repository }} .
|
||||
- run: git fetch origin ${{ gitea.ref }}
|
||||
- run: git checkout FETCH_HEAD
|
||||
- run: go generate -C common; go generate -C workflow-pr
|
||||
- run: echo ${{ github.event.number }}
|
||||
- run: echo ${{ github.event.pull_request.author_association }}
|
||||
- name: Check access
|
||||
if: ${{ github.event.pull_request.author_association != 'MEMBER' }}
|
||||
run: exit 1
|
||||
- run: 'git status --short; git status --porcelain=2|grep --quiet -v . || ( git add .; git config user.name "Gitea Actions"; git config user.email "gitea_noreply@opensuse.org"; git commit -m "CI run result of: go generate"; git show; git show --numstat; git push origin ${{ gitea.ref }} )'
|
||||
- run: git diff --numstat FETCH_HEAD HEAD
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
mock
|
||||
node_modules
|
||||
*.obscpio
|
||||
autogits-tmp.tar.zst
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const PrPattern = "PR: %s/%s#%d"
|
||||
const PrPattern = "PR: %s/%s!%d"
|
||||
|
||||
type BasicPR struct {
|
||||
Org, Repo string
|
||||
@@ -36,10 +36,14 @@ func parsePrLine(line string) (BasicPR, error) {
|
||||
return ret, errors.New("missing / separator")
|
||||
}
|
||||
|
||||
repo := strings.SplitN(org[1], "#", 2)
|
||||
repo := strings.SplitN(org[1], "!", 2)
|
||||
ret.Repo = repo[0]
|
||||
if len(repo) != 2 {
|
||||
return ret, errors.New("Missing # separator")
|
||||
repo := strings.SplitN(org[1], "#", 2)
|
||||
ret.Repo = repo[0]
|
||||
}
|
||||
if len(repo) != 2 {
|
||||
return ret, errors.New("Missing ! or # separator")
|
||||
}
|
||||
|
||||
// Gitea requires that each org and repo be [A-Za-z0-9_-]+
|
||||
|
||||
@@ -274,12 +274,17 @@ func (e *GitHandlerImpl) GitClone(repo, branch, remoteUrl string) (string, error
|
||||
}
|
||||
|
||||
func (e *GitHandlerImpl) GitBranchHead(gitDir, branchName string) (string, error) {
|
||||
id, err := e.GitExecWithOutput(gitDir, "show-ref", "--hash", "--verify", "refs/heads/"+branchName)
|
||||
id, err := e.GitExecWithOutput(gitDir, "show-ref", "--branch", "--hash", branchName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Can't find default branch: %s", branchName)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(id), nil
|
||||
id = strings.TrimSpace(SplitLines(id)[0])
|
||||
if len(id) < 10 {
|
||||
return "", fmt.Errorf("Can't find branch: %s", branchName)
|
||||
}
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (e *GitHandlerImpl) GitRemoteHead(gitDir, remote, branchName string) (string, error) {
|
||||
@@ -345,6 +350,7 @@ func (e *GitHandlerImpl) GitExecWithOutput(cwd string, params ...string) (string
|
||||
"GIT_COMMITTER_NAME=" + e.GitCommiter,
|
||||
"EMAIL=not@exist@src.opensuse.org",
|
||||
"GIT_LFS_SKIP_SMUDGE=1",
|
||||
"GIT_LFS_SKIP_PUSH=1",
|
||||
"GIT_SSH_COMMAND=/usr/bin/ssh -o StrictHostKeyChecking=yes",
|
||||
}
|
||||
if len(ExtraGitParams) > 0 {
|
||||
|
||||
@@ -583,18 +583,36 @@ type PackageBuildStatus struct {
|
||||
Package string `xml:"package,attr"`
|
||||
Code string `xml:"code,attr"`
|
||||
Details string `xml:"details"`
|
||||
|
||||
LastUpdate time.Time
|
||||
}
|
||||
|
||||
func PackageBuildStatusComp(A, B *PackageBuildStatus) int {
|
||||
return strings.Compare(A.Package, B.Package)
|
||||
}
|
||||
|
||||
type BuildResult struct {
|
||||
Project string `xml:"project,attr"`
|
||||
Repository string `xml:"repository,attr"`
|
||||
Arch string `xml:"arch,attr"`
|
||||
Code string `xml:"code,attr"`
|
||||
Dirty bool `xml:"dirty,attr"`
|
||||
ScmSync string `xml:"scmsync"`
|
||||
ScmInfo string `xml:"scminfo"`
|
||||
Status []PackageBuildStatus `xml:"status"`
|
||||
Binaries []BinaryList `xml:"binarylist"`
|
||||
Project string `xml:"project,attr"`
|
||||
Repository string `xml:"repository,attr"`
|
||||
Arch string `xml:"arch,attr"`
|
||||
Code string `xml:"code,attr"`
|
||||
Dirty bool `xml:"dirty,attr"`
|
||||
ScmSync string `xml:"scmsync"`
|
||||
ScmInfo string `xml:"scminfo"`
|
||||
Status []*PackageBuildStatus `xml:"status"`
|
||||
Binaries []BinaryList `xml:"binarylist"`
|
||||
|
||||
LastUpdate time.Time
|
||||
}
|
||||
|
||||
func BuildResultComp(A, B *BuildResult) int {
|
||||
if cmp := strings.Compare(A.Project, B.Project); cmp != 0 {
|
||||
return cmp
|
||||
}
|
||||
if cmp := strings.Compare(A.Repository, B.Repository); cmp != 0 {
|
||||
return cmp
|
||||
}
|
||||
return strings.Compare(A.Arch, B.Arch)
|
||||
}
|
||||
|
||||
type Binary struct {
|
||||
@@ -611,7 +629,7 @@ type BinaryList struct {
|
||||
type BuildResultList struct {
|
||||
XMLName xml.Name `xml:"resultlist"`
|
||||
State string `xml:"state,attr"`
|
||||
Result []BuildResult `xml:"result"`
|
||||
Result []*BuildResult `xml:"result"`
|
||||
|
||||
isLastBuild bool
|
||||
}
|
||||
|
||||
@@ -273,7 +273,7 @@ func (rs *PRSet) AssignReviewers(gitea GiteaReviewFetcherAndRequester, maintaine
|
||||
if !IsDryRun {
|
||||
for _, r := range reviewers {
|
||||
if _, err := gitea.RequestReviews(pr.PR, r); err != nil {
|
||||
LogError("Cannot create reviews on", fmt.Sprintf("%s/%s#%d for [%s]", pr.PR.Base.Repo.Owner.UserName, pr.PR.Base.Repo.Name, pr.PR.Index, strings.Join(reviewers, ", ")), err)
|
||||
LogError("Cannot create reviews on", fmt.Sprintf("%s/%s!%d for [%s]", pr.PR.Base.Repo.Owner.UserName, pr.PR.Base.Repo.Name, pr.PR.Index, strings.Join(reviewers, ", ")), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -397,7 +397,7 @@ func (rs *PRSet) Merge(gitea GiteaReviewUnrequester, git Git) error {
|
||||
panic("FIXME")
|
||||
}
|
||||
*/
|
||||
msg := fmt.Sprintf("Merging\n\nPR: %s/%s#%d", prjgit.Base.Repo.Owner.UserName, prjgit.Base.Repo.Name, prjgit.Index)
|
||||
msg := fmt.Sprintf("Merging\n\nPR: %s/%s!%d", prjgit.Base.Repo.Owner.UserName, prjgit.Base.Repo.Name, prjgit.Index)
|
||||
|
||||
err = git.GitExec(DefaultGitPrj, "merge", "--no-ff", "-m", msg, prjgit.Head.Sha)
|
||||
if err != nil {
|
||||
|
||||
@@ -132,7 +132,7 @@ func PRtoString(pr *models.PullRequest) string {
|
||||
return "(null)"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s/%s#%d", pr.Base.Repo.Owner.UserName, pr.Base.Repo.Name, pr.Index)
|
||||
return fmt.Sprintf("%s/%s!%d", pr.Base.Repo.Owner.UserName, pr.Base.Repo.Name, pr.Index)
|
||||
}
|
||||
|
||||
type DevelProject struct {
|
||||
|
||||
@@ -146,7 +146,9 @@ func listMaintainers(obs *common.ObsClient, prj string, pkgs []string) {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
contact_email = append(contact_email, fmt.Sprintf("%s <%s>", user.Name, user.Email))
|
||||
if user != nil {
|
||||
contact_email = append(contact_email, fmt.Sprintf("%s <%s>", user.Name, user.Email))
|
||||
}
|
||||
}
|
||||
log.Println(strings.Join(contact_email, ", "))
|
||||
}
|
||||
@@ -241,14 +243,14 @@ func importFactoryRepoAndCheckHistory(pkg string, meta *common.PackageMeta) (fac
|
||||
}
|
||||
|
||||
roots := 0
|
||||
if _, err := git.GitBranchHead(pkg, "pool/devel"); err == nil {
|
||||
if _, err := git.GitRemoteHead(pkg, "pool", "devel"); err == nil {
|
||||
factory_roots := strings.TrimSpace(git.GitExecWithOutputOrPanic(pkg, "rev-list", "pool/factory", "--max-parents=0"))
|
||||
devel_roots := strings.TrimSpace(git.GitExecWithOutputOrPanic(pkg, "rev-list", "pool/devel", "--max-parents=0"))
|
||||
roots = len(common.SplitLines(factory_roots))
|
||||
if devel_roots != factory_roots || len(common.SplitLines(factory_roots)) != 1 {
|
||||
roots = 10
|
||||
}
|
||||
} else if _, err := git.GitBranchHead(pkg, "pool/factory"); err == nil {
|
||||
} else if _, err := git.GitRemoteHead(pkg, "pool", "factory"); err == nil {
|
||||
items := strings.TrimSpace(git.GitExecWithOutputOrPanic(pkg, "rev-list", "pool/factory", "--max-parents=0"))
|
||||
roots = len(common.SplitLines(items))
|
||||
} else {
|
||||
@@ -394,38 +396,38 @@ func PushRepository(factoryRepo, develRepo *models.Repository, pkg string) (repo
|
||||
SetRepoOptions(repo)
|
||||
git.GitExec(pkg, "push", "develorigin", "--delete", "factory")
|
||||
git.GitExec(pkg, "push", "develorigin", "--delete", "devel")
|
||||
git.GitExec(pkg, "push", "develorigin", "--delete", "leap-16.0")
|
||||
return repo
|
||||
}
|
||||
|
||||
func importDevelRepoAndCheckHistory(pkg string, meta *common.PackageMeta) *models.Repository {
|
||||
repo := CreateDevelOnlyPackage(pkg)
|
||||
|
||||
log.Println("setting main branch for devel package:", pkg)
|
||||
if meta == nil {
|
||||
log.Println(" **** pkg meta is nil? ****")
|
||||
} else if len(meta.ScmSync) > 0 {
|
||||
if _, err := os.Stat(path.Join(git.GetPath(), pkg)); os.IsNotExist(err) {
|
||||
u, _ := url.Parse(meta.ScmSync)
|
||||
if err2 := cloneDevel(git, "", pkg, meta.ScmSync, "origin", true); err2 != nil {
|
||||
log.Panicln(err2)
|
||||
}
|
||||
git.GitExecOrPanic(pkg, "checkout", "-B", "main", u.Fragment)
|
||||
}
|
||||
common.LogDebug("skip check for scmsync")
|
||||
return repo
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(git.GetPath(), pkg)); os.IsNotExist(err) {
|
||||
cloneDevel(git, "", pkg, repo.SSHURL, "develorigin", false) // in case we have imported
|
||||
}
|
||||
|
||||
if CloneScmsync(pkg, meta) {
|
||||
return repo
|
||||
}
|
||||
var p, dp string
|
||||
factory_branch, fhe := git.GitBranchHead(pkg, "factory")
|
||||
factory_branch, fhe := git.GitRemoteHead(pkg, "develorigin", "factory")
|
||||
if fhe == nil {
|
||||
p = strings.TrimSpace(git.GitExecWithOutputOrPanic(pkg, "rev-list", "--max-parents=0", "--count", factory_branch))
|
||||
} else {
|
||||
common.LogError(fhe)
|
||||
}
|
||||
devel_branch, dhe := git.GitBranchHead(pkg, "devel")
|
||||
devel_branch, dhe := git.GitRemoteHead(pkg, "develorigin", "devel")
|
||||
if dhe != nil {
|
||||
devel_project, err := devel_projects.GetDevelProject(pkg)
|
||||
common.LogDebug("Devel project:", devel_project, err)
|
||||
if err == common.DevelProjectNotFound {
|
||||
// assume it's this project, maybe removed from factory
|
||||
devel_project = prj
|
||||
}
|
||||
common.LogDebug("finding missing branches in", pkg, devel_project)
|
||||
findMissingDevelBranch(git, pkg, devel_project)
|
||||
devel_branch, dhe = git.GitBranchHead(pkg, "devel")
|
||||
}
|
||||
if dhe == nil {
|
||||
dp = strings.TrimSpace(git.GitExecWithOutputOrPanic(pkg, "rev-list", "--max-parents=0", "--count", devel_branch))
|
||||
} else {
|
||||
@@ -454,6 +456,32 @@ func importDevelRepoAndCheckHistory(pkg string, meta *common.PackageMeta) *model
|
||||
return repo
|
||||
}
|
||||
|
||||
return repo
|
||||
}
|
||||
|
||||
func SetMainBranch(pkg string, meta *common.PackageMeta) {
|
||||
// scnsync, follow that and don't care
|
||||
common.LogDebug("Setting main branch...")
|
||||
remotes := common.SplitStringNoEmpty(git.GitExecWithOutputOrPanic(pkg, "remote", "show"), "\n")
|
||||
if slices.Contains(remotes, "origin") {
|
||||
u, err := url.Parse(meta.ScmSync)
|
||||
common.PanicOnError(err)
|
||||
if len(u.Fragment) == 0 {
|
||||
u.Fragment = "HEAD"
|
||||
}
|
||||
if err := git.GitExec(pkg, "checkout", "-B", "main", u.Fragment); err != nil {
|
||||
git.GitExecOrPanic(pkg, "checkout", "-B", "main", "origin/"+u.Fragment)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// check if we have factory
|
||||
if _, err := git.GitBranchHead(pkg, "factory"); err != nil {
|
||||
if len(git.GitExecWithOutputOrPanic(pkg, "show-ref", "pool/factory")) > 20 {
|
||||
git.GitExecOrPanic(pkg, "branch", "factory", "pool/factory")
|
||||
}
|
||||
}
|
||||
|
||||
// mark newer branch as main
|
||||
branch := "factory"
|
||||
if len(common.SplitStringNoEmpty(git.GitExecWithOutputOrPanic(pkg, "rev-list", "^factory", "devel"), "\n")) > 0 {
|
||||
@@ -461,13 +489,66 @@ func importDevelRepoAndCheckHistory(pkg string, meta *common.PackageMeta) *model
|
||||
}
|
||||
common.LogInfo("setting main to", branch)
|
||||
git.GitExecOrPanic(pkg, "checkout", "-B", "main", branch)
|
||||
return repo
|
||||
}
|
||||
|
||||
func ObsToRepoName(obspkg string) string {
|
||||
return strings.ReplaceAll(obspkg, "+", "_")
|
||||
}
|
||||
|
||||
func ImportSha1Sync(pkg string, url *url.URL) {
|
||||
common.LogDebug("Converting SHA1", url.String())
|
||||
|
||||
branch := url.Fragment
|
||||
url.Fragment = ""
|
||||
p := path.Join(pkg, "sha1stuff")
|
||||
common.PanicOnError(os.RemoveAll(path.Join(git.GetPath(), p)))
|
||||
git.GitExecOrPanic(pkg, "clone", "--mirror", url.String(), "sha1stuff")
|
||||
git.GitExecOrPanic(p, "fetch", "origin", branch)
|
||||
|
||||
gitexport := exec.Command("/usr/bin/git", "fast-export", "--signed-tags=strip", "--tag-of-filtered-object=drop", "--all")
|
||||
gitexport.Dir = path.Join(git.GetPath(), p)
|
||||
gitexportData, err := gitexport.Output()
|
||||
common.LogDebug("Got export data size:", len(gitexportData))
|
||||
common.PanicOnError(err)
|
||||
gitimport := exec.Command("/usr/bin/git", "fast-import", "--allow-unsafe-features")
|
||||
gitimport.Dir = path.Join(git.GetPath(), pkg)
|
||||
gitimport.Stdin = bytes.NewReader(gitexportData)
|
||||
data, err := gitimport.CombinedOutput()
|
||||
common.LogError(string(data))
|
||||
common.PanicOnError(err)
|
||||
common.PanicOnError(os.RemoveAll(path.Join(git.GetPath(), p)))
|
||||
}
|
||||
|
||||
func LfsImport(pkg string) {
|
||||
git.GitExecOrPanic(pkg, "lfs", "migrate", "import", "--everything",
|
||||
"--include=*.7z,*.bsp,*.bz2,*.gem,*.gz,*.jar,*.lz,*.lzma,*.obscpio,*.oxt,*.pdf,*.png,*.rpm,*.tar,*.tbz,*.tbz2,*.tgz,*.ttf,*.txz,*.whl,*.xz,*.zip,*.zst")
|
||||
}
|
||||
|
||||
func CloneScmsync(pkg string, meta *common.PackageMeta) bool {
|
||||
if len(meta.ScmSync) > 0 {
|
||||
u, _ := url.Parse(meta.ScmSync)
|
||||
if remotes := common.SplitStringNoEmpty(git.GitExecWithOutputOrPanic(pkg, "remote", "show"), "\n"); !slices.Contains(remotes, "origin") {
|
||||
branch := u.Fragment
|
||||
if len(branch) == 0 {
|
||||
branch = "HEAD"
|
||||
}
|
||||
u.Fragment = ""
|
||||
git.GitExecOrPanic(pkg, "remote", "add", "origin", u.String())
|
||||
u.Fragment = branch
|
||||
}
|
||||
if err := git.GitExec(pkg, "fetch", "origin"); strings.Contains(err.Error(), "fatal: mismatched algorithms: client sha256; server sha1") {
|
||||
ImportSha1Sync(pkg, u)
|
||||
} else if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
LfsImport(pkg)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func importRepo(pkg string) (BrokenFactoryPackage, FailedImport bool) {
|
||||
BrokenFactoryPackage = false
|
||||
FailedImport = false
|
||||
@@ -487,6 +568,9 @@ func importRepo(pkg string) (BrokenFactoryPackage, FailedImport bool) {
|
||||
if err != nil {
|
||||
common.PanicOnError(err)
|
||||
}
|
||||
if meta == nil {
|
||||
panic("package meta is nil...")
|
||||
}
|
||||
|
||||
factoryRepo, err = importFactoryRepoAndCheckHistory(pkg, meta)
|
||||
if factoryRepo != nil && err != nil {
|
||||
@@ -498,8 +582,11 @@ func importRepo(pkg string) (BrokenFactoryPackage, FailedImport bool) {
|
||||
|
||||
if factoryRepo == nil || BrokenFactoryPackage {
|
||||
develRepo = importDevelRepoAndCheckHistory(pkg, meta)
|
||||
} else {
|
||||
CloneScmsync(pkg, meta)
|
||||
}
|
||||
|
||||
SetMainBranch(pkg, meta)
|
||||
PushRepository(factoryRepo, develRepo, pkg)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ func ProcessNotifications(notification *models.NotificationThread, gitea common.
|
||||
repo := match[2]
|
||||
id, _ := strconv.ParseInt(match[3], 10, 64)
|
||||
|
||||
common.LogInfo("processing:", fmt.Sprintf("%s/%s#%d", org, repo, id))
|
||||
common.LogInfo("processing:", fmt.Sprintf("%s/%s!%d", org, repo, id))
|
||||
pr, err := gitea.GetPullRequest(org, repo, id)
|
||||
if err != nil {
|
||||
common.LogError(" ** Cannot fetch PR associated with review:", subject.URL, "Error:", err)
|
||||
@@ -181,7 +181,7 @@ func ProcessNotifications(notification *models.NotificationThread, gitea common.
|
||||
|
||||
config := configs.GetPrjGitConfig(org, repo, pr.Base.Name)
|
||||
if config == nil {
|
||||
common.LogError("Cannot find config for:", fmt.Sprintf("%s/%s#%s", org, repo, pr.Base.Name))
|
||||
common.LogError("Cannot find config for:", fmt.Sprintf("%s/%s!%s", org, repo, pr.Base.Name))
|
||||
return
|
||||
}
|
||||
if pr.State == "closed" {
|
||||
|
||||
@@ -108,7 +108,7 @@ func ProcessNotification(notification *models.NotificationThread) {
|
||||
repo := match[2]
|
||||
id, _ := strconv.ParseInt(match[3], 10, 64)
|
||||
|
||||
common.LogInfo("processing:", fmt.Sprintf("%s/%s#%d", org, repo, id))
|
||||
common.LogInfo("processing:", fmt.Sprintf("%s/%s!%d", org, repo, id))
|
||||
pr, err := Gitea.GetPullRequest(org, repo, id)
|
||||
if err != nil {
|
||||
common.LogError(" ** Cannot fetch PR associated with review:", subject.URL, "Error:", err)
|
||||
|
||||
@@ -80,7 +80,7 @@ func AllocatePRProcessor(req *common.PullRequestWebhookEvent, configs common.Aut
|
||||
|
||||
branch := req.Pull_Request.Base.Ref
|
||||
|
||||
PRstr := fmt.Sprintf("%s/%s#%d", org, repo, id)
|
||||
PRstr := fmt.Sprintf("%s/%s!%d", org, repo, id)
|
||||
common.LogInfo("*** Starting processing PR:", PRstr, "branch:", branch)
|
||||
|
||||
config := configs.GetPrjGitConfig(org, repo, branch)
|
||||
|
||||
Reference in New Issue
Block a user