obs-staging-bot: allow forking projects and build-disabling their repositories #111
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
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"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user
there's a
common.PanicOnError(err)that could replace the if { panic }