Skip to content

Commit a9895bb

Browse files
committed
New git obs subcommand "testprj"
This new command is useful to create custom build projects with multiple packages in gitea repository. For example if you want to test several packages together you can just do it with one line: $ git obs testprj -p SUSE:SLFO:Main my-test-project python-pip python-fastapi#slfo-1.2
1 parent 08ad031 commit a9895bb

File tree

1 file changed

+186
-0
lines changed

1 file changed

+186
-0
lines changed

osc/commands_git/testprj.py

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
import re
2+
import sys
3+
import osc.commandline_git
4+
5+
6+
class TestPrjCommand(osc.commandline_git.GitObsCommand):
7+
"""
8+
Create test project in OBS linking git packages
9+
"""
10+
11+
name = "testprj"
12+
13+
def init_arguments(self):
14+
self.add_argument(
15+
"-a",
16+
"--api-url",
17+
help="OBS api url, defaults to api.opensuse.org",
18+
default="api.opensuse.org",
19+
)
20+
self.add_argument(
21+
"-p",
22+
"--prj",
23+
help="OBS base project to copy config from, defaults to openSUSE:Factory",
24+
)
25+
self.add_argument(
26+
"-b",
27+
"--branch",
28+
help="Git branch to use",
29+
)
30+
self.add_argument(
31+
"-f",
32+
"--fork",
33+
action="store_true",
34+
help="Fork gitea pkg repos in your user home, defaults to False",
35+
default=False,
36+
)
37+
self.add_argument(
38+
"prj_name",
39+
help="test project name to create in home:USER:$prj_name",
40+
)
41+
self.add_argument(
42+
"pkg_repo",
43+
nargs="*",
44+
help="pkg gitea ref, it should be [org/]repo[#branch]",
45+
)
46+
47+
def run(self, args):
48+
from osc import conf
49+
50+
self.output = []
51+
self.apiurl = conf.sanitize_apiurl(args.api_url)
52+
self.args = args
53+
self.weburl = self.apiurl.replace("api", "build", count=1)
54+
55+
c = conf.get_config()
56+
self.user = conf.get_apiurl_usr(self.apiurl)
57+
58+
project = f"home:{self.user}:{self.args.prj_name}"
59+
self.create_project(project)
60+
self.output.append(f"OBS test project created: {project}")
61+
self.output.append(f"{self.weburl}/project/show/{project}")
62+
self.output.append("")
63+
64+
self.num_entries = 0
65+
self.failed_entries = []
66+
for repo in args.pkg_repo:
67+
repo, branch = self.parse_repo(repo)
68+
package, scm = self.create_package(project, repo, branch)
69+
self.output.append(f" * Linked pkg: {package} <- {scm}")
70+
71+
print()
72+
for line in self.output:
73+
print(line, file=sys.stderr)
74+
75+
def create_project(self, project):
76+
from osc.util.xml import ET
77+
from osc.core import edit_meta, xml_fromstring, show_project_meta
78+
79+
# Get base project meta
80+
if self.args.prj:
81+
meta_data = b''.join(show_project_meta(self.apiurl, self.args.prj))
82+
root = xml_fromstring(meta_data)
83+
repos = "\n".join(ET.tostring(i).decode() for i in root.findall("repository"))
84+
else:
85+
repos = """
86+
<repository name="openSUSE_Tumbleweed">
87+
<path project="openSUSE:Tumbleweed" repository="standard"/>
88+
<arch>x86_64</arch>
89+
</repository>
90+
"""
91+
92+
data = f"""
93+
<project name="{project}">
94+
<title>Test project gitea</title>
95+
<description/>
96+
<person userid="{self.user}" role="maintainer"/>
97+
{repos}
98+
</project>
99+
"""
100+
101+
# Create the project in OBS
102+
edit_meta(metatype="prj",
103+
data=data,
104+
apiurl=self.apiurl,
105+
path_args=(project, ))
106+
107+
def create_package(self, project, repo, branch):
108+
from osc.core import edit_meta
109+
110+
package = repo.repo
111+
if self.args.fork:
112+
scm = self.fork(repo, branch, self.args.branch)
113+
else:
114+
scm = f"{repo.clone_url}#{branch}"
115+
116+
# Create the package in OBS
117+
data = f"""
118+
<package name="{package}" project="{project}">
119+
<title/>
120+
<description/>
121+
<person userid="{self.user}" role="maintainer"/>
122+
<scmsync>{scm}</scmsync>
123+
</package>
124+
"""
125+
126+
edit_meta(metatype="pkg",
127+
data=data,
128+
apiurl=self.apiurl,
129+
path_args=(project, package))
130+
131+
return package, scm
132+
133+
def fork(self, repo, base_branch, new_branch=None):
134+
from osc import gitea_api
135+
owner, repo = repo.owner, repo.repo
136+
print(f"Forking git repo {owner}/{repo} ...", file=sys.stderr)
137+
try:
138+
repo_obj = gitea_api.Fork.create(self.gitea_conn, owner, repo)
139+
fork_owner = repo_obj.owner
140+
fork_repo = repo_obj.repo
141+
print(f" * Fork created: {fork_owner}/{fork_repo}", file=sys.stderr)
142+
self.num_entries += 1
143+
except gitea_api.ForkExists as e:
144+
fork_owner = e.fork_owner
145+
fork_repo = e.fork_repo
146+
print(f" * Fork already exists: {fork_owner}/{fork_repo}", file=sys.stderr)
147+
self.num_entries += 1
148+
except gitea_api.GiteaException as e:
149+
if e.status == 404:
150+
print(f" * ERROR: Repo doesn't exist: {owner}/{repo}", file=sys.stderr)
151+
self.failed_entries.append(f"{owner}/{repo}")
152+
return None
153+
raise
154+
155+
r = gitea_api.Repo.get(self.gitea_conn, fork_owner, fork_repo)
156+
if new_branch:
157+
try:
158+
_branch = gitea_api.Branch.create(self.gitea_conn, fork_owner,
159+
fork_repo, new_branch_name=new_branch,
160+
old_ref_name=base_branch)
161+
except gitea_api.BranchExists:
162+
print(f" * Warning: Branch already exists, not creating it: {fork_owner}/{fork_repo}#{new_branch}", file=sys.stderr)
163+
164+
branch = new_branch or base_branch
165+
return f"{r.clone_url}#{branch}"
166+
167+
def parse_repo(self, repo):
168+
"""
169+
Convert org/repo#branch into gitea repo
170+
org and branch are optional, default org is "pool" and default
171+
branch is the default branch configured in gitea.
172+
173+
returns [Repo, branch]
174+
"""
175+
from osc import gitea_api
176+
177+
org = "pool"
178+
if "/" in repo:
179+
org, repo = repo.split("/", maxsplit=1)
180+
if "#" in repo:
181+
repo, branch = repo.split("#", maxsplit=1)
182+
else:
183+
branch = None
184+
185+
r = gitea_api.Repo.get(self.gitea_conn, org, repo)
186+
return r, branch or r.default_branch

0 commit comments

Comments
 (0)