Skip to content

Commit 302971e

Browse files
authored
Merge pull request #71 from sclorg/support_gitlab
Use GitLab for syncing upstream->downstream - gitlab_git_changes
2 parents 6fed0f1 + 36527b3 commit 302971e

File tree

12 files changed

+721
-90
lines changed

12 files changed

+721
-90
lines changed

container_workflow_tool/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
action_map = {}
22
action_map['git'] = {
3-
'pullupstream': 'dist_git_changes',
3+
'pullupstream': 'dist_git_merge_changes',
44
'clonedownstream': 'pull_downstream',
55
'cloneupstream': 'pull_upstream',
66
'rebase': 'dist_git_rebase',

container_workflow_tool/distgit.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from git import Repo
66
from git.exc import GitCommandError
77

8-
import container_workflow_tool.utility as u
8+
from container_workflow_tool import utility
99
from container_workflow_tool.utility import RebuilderError
1010
from container_workflow_tool.dockerfile import DockerfileHandler
1111
from container_workflow_tool.sync import SyncHandler
@@ -49,21 +49,22 @@ def check_script(self, component, script_path, component_path):
4949
self.logger.info(template.format(name=component, status="Affected"))
5050
err = ret.stderr.decode('utf-8').strip()
5151
if err:
52-
self.logger.error(u._2sp(err))
52+
self.logger.error(utility._2sp(err))
5353
else:
5454
self.logger.info(template.format(name=component, status="OK"))
5555

56-
def dist_git_changes(self, images, rebase=False):
56+
def dist_git_merge_changes(self, images, rebase=False):
5757
"""Method to merge changes from upstream into downstream
5858
5959
Pulls both downstream and upstream repositories into a temporary dir.
6060
Merge is done by copying tracked files from upstream into downstream.
6161
6262
Args:
63+
images (list): List of images to sync
6364
rebase (bool, optional): Specify if a rebase should be done instead
6465
"""
6566
try:
66-
for image in (images):
67+
for image in images:
6768
name = image["name"]
6869
component = image["component"]
6970
branch = image["git_branch"]
@@ -92,18 +93,17 @@ def dist_git_changes(self, images, rebase=False):
9293
ups_name = name.split('-')[0]
9394
# Clone upstream repository
9495
ups_path = os.path.join('upstreams/', ups_name)
95-
self._clone_upstream(url, ups_path, commands=commands)
96+
self.clone_upstream(url, ups_path, commands=commands)
9697
# Save the upstream commit hash
9798
ups_hash = Repo(ups_path).commit().hexsha
98-
self._pull_upstream(component, path, url, repo, ups_name, commands)
99+
self.pull_upstream(component, path, url, repo, ups_name, commands)
99100
self.df_handler.update_dockerfile(
100101
df_path, from_tag, downstream_from=downstream_from
101102
)
102103
repo.git.add("Dockerfile")
103104
# It is possible for the git repository to have no changes
104105
if repo.is_dirty():
105-
commit = self.get_commit_msg(rebase, image, ups_hash
106-
)
106+
commit = self.get_commit_msg(rebase, image, ups_hash)
107107
if commit:
108108
repo.git.commit("-m", commit)
109109
else:
@@ -122,8 +122,8 @@ def _clone_downstream(self, component, branch):
122122
self.logger.info("Using existing downstream repo: " + component)
123123
repo = Repo(component)
124124
else:
125-
hostname_url = u._get_hostname_url(self.conf)
126-
packager = u._get_packager(self.conf)
125+
hostname_url = utility._get_hostname_url(self.conf)
126+
packager = utility._get_packager(self.conf)
127127
# if packager is fedpkg then namespace is `container` else `containers`
128128
namespace = "container" if packager == "fedpkg" else "containers"
129129
component_path = f"{namespace}/{component}"
@@ -162,7 +162,7 @@ def push_changes(self, tmp, images):
162162
# commit_msg is set so it is always returned
163163
commit = self.get_commit_msg(None, image)
164164
repo.git.commit("-am", commit)
165-
if self._get_unpushed_commits(repo):
165+
if self.are_unpushed_commits_available(repo):
166166
self.logger.info("Pushing: " + component)
167167

168168
repo.git.push()
@@ -176,7 +176,7 @@ def push_changes(self, tmp, images):
176176
if failed:
177177
self.logger.error("Failed pushing images:")
178178
for image in failed:
179-
self.logger.error(u._2sp(image["component"]))
179+
self.logger.error(utility._2sp(image["component"]))
180180
self.logger.error("Please check the failures and push the changes manually.")
181181

182182
# TODO: Multiple future branches?
@@ -204,5 +204,5 @@ def merge_future_branches(self, images):
204204
if failed:
205205
self.logger.error("Failed merging images:")
206206
for image in failed:
207-
self.logger.error(u._2sp(image["component"]))
207+
self.logger.error(utility._2sp(image["component"]))
208208
self.logger.error("Please check the failures and push the changes manually.")

container_workflow_tool/git_operations.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# MIT License
22
#
3-
# Copyright (c) 2020 SCL team at Red Hat
3+
# Copyright (c) 2023 SCL team at Red Hat
44
#
55
# Permission is hereby granted, free of charge, to any person obtaining a copy
66
# of this software and associated documentation files (the "Software"), to deal
@@ -55,7 +55,7 @@ def set_commit_msg(self, msg):
5555
"""
5656
self.commit_msg = msg
5757

58-
def _do_git_reset(self, repo):
58+
def do_git_reset(self, repo):
5959
file_list = ['--', '.gitignore'] + self.conf.ignore_files
6060
repo.git.reset(file_list)
6161
# One file at a time to make sure all files get reset even on error
@@ -68,7 +68,7 @@ def _do_git_reset(self, repo):
6868
repo.git.clean('-xfd', f)
6969
self.logger.debug("Removing untracked ignored file: " + f)
7070

71-
def _clone_upstream(self, url, ups_path, commands=None):
71+
def clone_upstream(self, url, ups_path, commands=None):
7272
"""
7373
:params: url is URL to repofile from upstream. https://github.com/sclorg
7474
:param: ups_path is path where URL is cloned locally
@@ -113,20 +113,23 @@ def _clone_upstream(self, url, ups_path, commands=None):
113113
os.chdir(oldcwd)
114114
return repo
115115

116-
def are_unpushed_commits_available(self, repo) -> bool:
116+
def are_unpushed_commits_available(self, repo, branch_name="") -> bool:
117117
"""
118118
Get unpushed commits
119119
:param repo: repo object to check for unpushed commits
120+
:param branch_name: In case of gitlab, branch_name has to be defined.
121+
:param branch_name: In case of gitlab, branch_name has to be defined.
122+
branch_name is e.g. rhel-8.7.0 and 'repo.active_branch.name' is 'rhel-8.7.0-<ubi_name>'
120123
:return: List of commits or empty array
121124
"""
122125
branch = repo.active_branch.name
123126
# Get a list of commits that have not been pushed to remote
124127
select = "origin/" + branch + ".." + branch
125-
if len(list(repo.iter_commits(select))) == 0:
126-
return False
127-
return True
128+
if branch_name != "":
129+
select = "origin/" + branch_name + ".." + branch
130+
return bool(list(repo.iter_commits(select)))
128131

129-
def show_git_changes(self, tmp, components=None, diff=False):
132+
def show_git_changes(self, tmp, components=None, diff=False, branch_name=""):
130133
"""Shows changes made to tracked files in local downstream repositories
131134
132135
Walks through all repositories and calls 'git-show' or 'git-diff' on each of them.
@@ -135,6 +138,8 @@ def show_git_changes(self, tmp, components=None, diff=False):
135138
tmp (str): Path to the directory that is used to store git repositories
136139
components (list of str, optional): List of components to show changes for
137140
diff (boolean, optional): Controls whether the method calls git-show or git-diff
141+
branch_name (str, optional): In case of gitlab, branch_name has to be defined.
142+
branch_name is e.g. rhel-8.7.0 and 'repo.active_branch.name' is 'rhel-8.7.0-<ubi_name>'
138143
"""
139144
# Function to check if a path contains a git repository
140145
def is_git(x): return os.path.isdir(os.path.join(x, '.git'))
@@ -155,7 +160,7 @@ def is_git(x): return os.path.isdir(os.path.join(x, '.git'))
155160
repo = Repo(path)
156161
# Only show changes if there are unpushed commits to show
157162
# or we only want the diff of unstaged changes
158-
if self.are_unpushed_commits_available(repo) or diff:
163+
if self.are_unpushed_commits_available(repo, branch_name=branch_name) or diff:
159164
# Clears the screen
160165
print(chr(27) + "[2J")
161166
# Force pager for short git diffs
@@ -229,7 +234,7 @@ def get_commit_msg(self, rebase, image=None, ups_hash=None):
229234
commit += "\n created from upstream commit: " + ups_hash
230235
return commit
231236

232-
def _pull_upstream(self, component, path, url, repo, ups_name, commands):
237+
def pull_upstream(self, component, path, url, repo, ups_name, commands):
233238
"""Pulls an upstream repo and copies it into downstream"""
234239
ups_path = os.path.join('upstreams/', ups_name)
235240
cp_path = os.path.join(ups_path, path)
@@ -268,7 +273,7 @@ def _pull_upstream(self, component, path, url, repo, ups_name, commands):
268273
self.update_test_openshift_yaml(test_openshift_yaml_file, path, short_name=ups_name)
269274

270275
repo.git.add("*")
271-
self._do_git_reset(repo)
276+
self.do_git_reset(repo)
272277
# TODO: Configurable?
273278
df_ext = self.df_ext
274279
df_path = os.path.join(component, "Dockerfile")

container_workflow_tool/main.py

Lines changed: 48 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import re
1010
import tempfile
1111
import pprint
12-
import getpass
1312
import logging
1413

1514
from git import Repo, GitError
@@ -53,6 +52,7 @@ def __init__(self,
5352

5453
self.conf_name = config
5554
self.rebuild_reason = rebuild_reason
55+
self.gitlab_usage = None
5656
self.do_image = None
5757
self.exclude_image = None
5858
self.do_set = None
@@ -119,10 +119,8 @@ def _setup_args(self, args):
119119
self.rebuild_reason = args.rebuild_reason
120120
if getattr(args, 'check_script', None) is not None and args.check_script:
121121
self.check_script = args.check_script
122-
if getattr(args, 'disable_klist', None) is not None and args.disable_klist:
123-
self.disable_klist = args.disable_klist
124-
if getattr(args, 'latest_release', None) is not None and args.latest_release:
125-
self.latest_release = args.latest_release
122+
self.disable_klist = args.disable_klist
123+
self.latest_release = args.latest_release
126124
if getattr(args, 'output_file', None) is not None and args.output_file:
127125
self.output_file = args.output_file
128126

@@ -150,7 +148,7 @@ def git_ops(self):
150148
if not self._git_ops:
151149
self._git_ops = GitOperations(self.base_image, self.conf,
152150
self.rebuild_reason,
153-
self.logger.getChild("-git-ops"))
151+
self.logger.getChild("git-ops"))
154152
return self._git_ops
155153

156154
@property
@@ -449,16 +447,16 @@ def set_repo_url(self, repo_url):
449447

450448
def list_images(self):
451449
"""Prints list of images that we work with"""
452-
for i in self._get_images():
453-
self.logger.info(i["component"])
450+
for image in self._get_images():
451+
self.logger.info(image["component"])
454452

455453
def print_upstream(self):
456454
"""Prints the upstream name and url for images used in config"""
457-
for i in self._get_images():
455+
for image in self._get_images():
458456
ups_name = re.search(r".*\/([a-zA-Z0-9-]+).git",
459-
i["git_url"]).group(1)
460-
msg = f"{i.get('component')} {i.get('name')} {ups_name} " \
461-
f"{i.get('git_url')} {i.get('git_path')} {i.get('git_branch')}"
457+
image["git_url"]).group(1)
458+
msg = f"{image.get('component')} {image.get('name')} {ups_name} " \
459+
f"{image.get('git_url')} {image.get('git_path')} {image.get('git_branch')}"
462460
self.logger.info(msg)
463461

464462
def show_config_contents(self):
@@ -502,17 +500,14 @@ def pull_downstream(self):
502500
Additionally runs a script against each repository if check_script is set,
503501
checking its exit value.
504502
"""
505-
self._check_kerb_ticket()
506-
tmp = self._get_tmp_workdir()
507-
self._change_workdir(tmp)
508-
images = self._get_images()
509-
for i in images:
510-
self.distgit._clone_downstream(i["component"], i["git_branch"])
503+
tmp, images = self.preparation()
504+
for image in images:
505+
self.distgit._clone_downstream(image["component"], image["git_branch"])
511506
# If check script is set, run the script provided for each config entry
512507
if self.check_script:
513-
for i in images:
514-
self.distgit.check_script(i["component"], self.check_script,
515-
i["git_branch"])
508+
for image in images:
509+
self.distgit.check_script(image["component"], self.check_script,
510+
image["git_branch"])
516511

517512
def pull_upstream(self):
518513
"""
@@ -521,24 +516,19 @@ def pull_upstream(self):
521516
Additionally runs a script against each repository if check_script is set,
522517
checking its exit value.
523518
"""
524-
tmp = self._get_tmp_workdir()
525-
self._change_workdir(tmp)
526-
images = self._get_images()
527-
for i in images:
519+
tmp, images = self.preparation()
520+
for image in images:
528521
# Use unversioned name as a path for the repository
529-
ups_name = i["name"].split('-')[0]
530-
self.distgit._clone_upstream(i["git_url"],
531-
ups_name,
532-
commands=i["commands"])
522+
ups_name = image["name"].split('-')[0]
523+
self.git_ops.clone_upstream(image["git_url"], ups_name, commands=image["commands"])
533524
# If check script is set, run the script provided for each config entry
534525
if self.check_script:
535-
for i in images:
536-
ups_name = i["name"].split('-')[0]
537-
self.distgit.check_script(i["component"], self.check_script,
538-
os.path.join(ups_name, i["git_path"]))
526+
for image in images:
527+
ups_name = image["name"].split('-')[0]
528+
self.distgit.check_script(image["component"], self.check_script,
529+
os.path.join(ups_name, image["git_path"]))
539530

540-
def push_changes(self):
541-
"""Pushes changes for all components into downstream dist-git repository"""
531+
def preparation(self):
542532
# Check for kerberos ticket
543533
self._check_kerb_ticket()
544534
tmp = self._get_tmp_workdir(setup_dir=False)
@@ -547,31 +537,22 @@ def push_changes(self):
547537
raise RebuilderError(msg)
548538
self._change_workdir(tmp)
549539
images = self._get_images()
540+
return tmp, images
541+
542+
def push_changes(self):
543+
"""Pushes changes for all components into downstream dist-git repository"""
550544

545+
tmp, images = self.preparation()
551546
self.distgit.push_changes(tmp, images)
552547

553548
def dist_git_rebase(self):
554549
"""
555550
Do a rebase against a new base/s2i image.
556551
Does not pull in upstream changes of layered images.
557552
"""
558-
self.dist_git_changes(rebase=True)
559-
560-
def dist_git_changes(self, rebase: bool = False):
561-
"""Method to merge changes from upstream into downstream
553+
self.dist_git_merge_changes(rebase=True)
562554

563-
Pulls both downstream and upstream repositories into a temporary directory.
564-
Merge is done by copying tracked files from upstream into downstream.
565-
566-
Args:
567-
rebase (bool, optional): Specifies whether a rebase should be done instead.
568-
"""
569-
# Check for kerberos ticket
570-
self._check_kerb_ticket()
571-
tmp = self._get_tmp_workdir()
572-
self._change_workdir(tmp)
573-
images = self._get_images()
574-
self.distgit.dist_git_changes(images, rebase)
555+
def git_changes_report(self, tmp):
575556
self.logger.info("\nGit location: " + tmp)
576557
if self.args:
577558
tmp_str = ' --tmp ' + self.tmp_workdir if self.tmp_workdir else '"'
@@ -583,13 +564,23 @@ def dist_git_changes(self, rebase: bool = False):
583564
"cwt git push && cwt build"
584565
"[base/core/s2i] --repo-url link-to-repo-file")
585566

567+
def dist_git_merge_changes(self, rebase: bool = False):
568+
"""Method to merge changes from upstream into downstream
569+
570+
Pulls both downstream and upstream repositories into a temporary directory.
571+
Merge is done by copying tracked files from upstream into downstream.
572+
573+
Args:
574+
rebase (bool, optional): Specifies whether a rebase should be done instead.
575+
"""
576+
tmp, images = self.preparation()
577+
self.distgit.dist_git_merge_changes(images, rebase)
578+
self.git_changes_report(tmp=tmp)
579+
586580
def merge_future_branches(self):
587581
"""Merges current branch with future branches"""
588582
# Check for kerberos ticket
589-
self._check_kerb_ticket()
590-
tmp = self._get_tmp_workdir()
591-
self._change_workdir(tmp)
592-
images = self._get_images()
583+
tmp, images = self.preparation()
593584
self.distgit.merge_future_branches(images)
594585

595586
def show_git_changes(self, components: List = None):
@@ -599,9 +590,8 @@ def show_git_changes(self, components: List = None):
599590
components (list of str, optional): List of components to show changes for
600591
Walks through all downstream repositories and calls 'git-show' on each of them.
601592
"""
593+
tmp, _ = self.preparation()
602594
if not components:
603595
images = self._get_images()
604-
components = [i["component"] for i in images]
605-
tmp = self._get_tmp_workdir()
606-
self._change_workdir(tmp)
596+
components = [image["component"] for image in images]
607597
self.distgit.show_git_changes(tmp, components)

0 commit comments

Comments
 (0)