obs-staging-bot: allow forking projects and build-disabling their repositories #111

Open
epaolantonio wants to merge 2 commits from epaolantonio/autogits:epaolantonio/pkglistgen into main
4 changed files with 74 additions and 7 deletions

View File

@@ -55,6 +55,8 @@ type QAConfig struct {
Name string
Origin string
BuildDisableRepos []string // which repos to build disable in the new project
ForkProject bool // whether to fork the Origin project and use that as scmsync
ForkOrganization string // which organization to use when forking
}
type Permissions struct {

View File

@@ -286,3 +286,13 @@ func TrimRemovedBranchSuffix(branchName string) string {
return branchName
}
func Slugify(orig string) string {
return strings.Map(func(r rune) rune {
if unicode.IsLetter(r) || unicode.IsDigit(r) {
return unicode.ToLower(r)
}
return '-'
}, orig)
}

View File

@@ -35,7 +35,9 @@ It's a JSON file with following syntax:
{
"Name": "SLES",
"Origin": "SUSE:SLFO:Products:SLES:16.0",
"BuildDisableRepos": ["product"]
"BuildDisableRepos": ["product"],
"ForkProject": false,
"ForkOrganization": "products-staging"
}
]
}
@@ -49,6 +51,8 @@ It's a JSON file with following syntax:
| *QA > Name* | Suffix for the QA OBS staging project. The project is named *StagingProject:<PR_Number>:Name*. | no | string | | |
| *QA > Origin* | OBS reference project | no | string | | |
| *QA > BuildDisableRepos* | The names of OBS repositories to build-disable, if any. | no | array of strings | | [] |
| *QA > ForkProject* | Whether to fork the project | no | boolean | true/false | false |
| *QA > ForkOrganization* | The organization where the fork project resiedes | yes (if using ForkProject) | string | `[a-zA-Z0-9-_:]+` | |
Details
@@ -67,6 +71,8 @@ Details
* **PrjGit PR - QA staging project**
* The QA staging project is meant for building the product; the relative build config is inherited from the `QA > Origin` project.
* In this case, the **scmsync** tag is inherited from the `QA > Origin` project.
* It is desirable in some cases to avoid building some specific build service repositories when not needed. In this case, `QA > BuildDisableRepos` can be specified.
* It is desirable in some cases to avoid building some specific build service repositories when not needed. In this case, `QA > BuildDisableRepos` can be specified.
These repositories would be disabled in the project meta when generating the QA project.
* When using the **ForkProject** setting, the current ref specified in the `scmsync` definition in the `QA > Origin` project's meta is pushed to a separate git project,
*`QA > ForkOrganization/QA > Name`*. `QA > ForkOrganization` must be specified in this case.
The target project and organization must already exist.

View File

@@ -376,13 +376,14 @@ func GenerateObsPrjMeta(git common.Git, gitea common.Gitea, pr *models.PullReque
return meta, nil
}
// buildProject
// ^- templateProject
//
// stagingProject:$buildProject
// ^- stagingProject:$buildProject:$subProjectName (based on templateProject)
func CreateQASubProject(stagingConfig *common.StagingConfig, git common.Git, gitea common.Gitea, pr *models.PullRequest, stagingProject, templateProject, subProjectName string, buildDisableRepos []string) error {
func CreateQASubProject(stagingConfig *common.StagingConfig, git common.Git, gitea common.Gitea, pr *models.PullRequest, stagingProject, templateProject, subProjectName string, buildDisableRepos []string, forkProject bool, forkOrganization string) error {
common.LogDebug("Setup QA sub projects")
templateMeta, err := ObsClient.GetProjectMeta(templateProject)
if err != nil {
@@ -408,8 +409,54 @@ func CreateQASubProject(stagingConfig *common.StagingConfig, git common.Git, git
panic(err)
}
// set expanded commit url
repository.Fragment = branch.SHA
if forkProject && len(forkOrganization) > 0 {
// Clone the original repository
origin_repo, err := gitea.GetRepository(org, repo)
if err != nil {
common.LogError("unable to get original repository details: ", org, repo, err)
return err
}
RemoteName, err := git.GitClone(subProjectName, repository.Fragment, origin_repo.SSHURL)
if err != nil {
common.LogError("unable to clone original repository: ", err)
return err
}
err = git.GitExec(subProjectName, "fetch", "--prune", RemoteName, branch.SHA)
if err != nil {
common.LogError("unable to fetch original repository: ", err)
return err
}
// Push the repository to the forked remote.
// We don't need to change the content.
forked_branch_name := "QA_"+common.Slugify(stagingProject)
if !IsDryRun {
forked_repo, err := gitea.GetRepository(forkOrganization, subProjectName)
if err != nil {
common.LogError("unable to get forked repository details: ", forkOrganization, subProjectName, err)
return err
}
repository, err = url.Parse(forked_repo.CloneURL)
common.PanicOnError(err)
err = git.GitExec(subProjectName, "push", "--force", forked_repo.SSHURL, branch.SHA+":refs/heads/"+forked_branch_name)
epaolantonio marked this conversation as resolved Outdated
Outdated
Review

there's a common.PanicOnError(err) that could replace the if { panic }

there's a `common.PanicOnError(err)` that could replace the if { panic }
if err != nil {
common.LogError("unable to push to the forked repository: ", err)
return err
}
}
// use the branch name
repository.Fragment = forked_branch_name
} else {
if forkProject && len(forkOrganization) == 0 {
// this is probably a misconfiguration, so complain
common.LogError("ForkProject specified without a ForkOrganization - the Origin scmsync branch will be used instead")
}
// set expanded commit url
repository.Fragment = branch.SHA
}
templateMeta.ScmSync = repository.String()
common.LogDebug("Setting scmsync url to ", templateMeta.ScmSync)
}
@@ -942,7 +989,9 @@ func ProcessPullRequest(gitea common.Gitea, org, repo string, id int64) (bool, e
stagingProject,
setup.Origin,
setup.Name,
setup.BuildDisableRepos)
setup.BuildDisableRepos,
setup.ForkProject,
setup.ForkOrganization)
msg = msg + ObsWebHost + "/project/show/" +
stagingProject + ":" + setup.Name + "\n"
}