Skip to content

Commit 8ccdbb8

Browse files
Fix resolution of base job branch determination in .build/run-ci
patch by Mick Semb Wever; reviewed by Štefan Miklošovič for CASSANDRA-20875
1 parent b3cc1d0 commit 8ccdbb8

File tree

1 file changed

+49
-21
lines changed

1 file changed

+49
-21
lines changed

.build/run-ci

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -64,35 +64,53 @@ except OSError as import_jenkins_error:
6464
else:
6565
raise
6666

67-
def determine_job_name(cassandra_dir: Path) -> str:
67+
def base_job_name(args) -> str:
6868
"""
6969
Determines the default Jenkins job name based on the Cassandra version.
7070
Separate jobs are required because Jenkinsfiles are baked into the job configuration.
7171
ref: .jenkins/k8s/jenkins-deployment.yaml JCasC.configScripts.test-job
72-
TODO: add new version each release branching
7372
"""
74-
with open(cassandra_dir / "build.xml", "r", encoding="utf-8") as build_file:
75-
for line in build_file:
73+
if not hasattr(base_job_name, "_cached_result"):
74+
raw_url = args.repository.replace("https://github.com/", "https://raw.githubusercontent.com/").removesuffix(".git") + f"/{args.branch}/build.xml"
75+
if 200 != requests.head(raw_url).status_code:
76+
raise ValueError(f"GitHub unavailable, or this branch has not been pushed yet: {args.repository} @ {args.branch} (or remote tracking not setup up: `git config --get branch.{args.branch}.remote` and `git config --get branch.{args.branch}.merge`)")
77+
response = requests.get(raw_url)
78+
response.raise_for_status()
79+
for line in response.text.splitlines():
7680
if 'property' in line and 'name="base.version"' in line:
7781
version = line.split('value="')[1].split('"')[0]
82+
# TODO: add new version each release branching
7883
if version.startswith("5.0."):
79-
return "cassandra-5.0"
80-
return "cassandra"
84+
base_job_name._cached_result = "cassandra-5.0"
85+
else:
86+
base_job_name._cached_result = "cassandra"
87+
break
88+
return base_job_name._cached_result
8189

8290
def get_current_branch() -> str:
8391
"""Returns the current branch."""
8492
return subprocess.run(["git", "-C", str(CASSANDRA_DIR), "branch", "--show-current"],
8593
capture_output=True, text=True, check=True).stdout.strip()
8694

95+
def is_local_git_dirty(args) -> bool:
96+
"""Returns True if there are uncommitted/unpushed changes in the local git repository."""
97+
# use base_job_name to verify the remote branch exists
98+
base_job_name(args)
99+
# check if the working directory is clean
100+
clean = subprocess.run(["git", "-C", str(CASSANDRA_DIR), "diff-index", "--quiet", "HEAD", "--"]).returncode
101+
# check if there are unpushed committed changes
102+
unpushed_commits = bool(subprocess.run(["git", "-C", str(CASSANDRA_DIR), "log", "@{u}..HEAD", "--name-only"],
103+
capture_output=True, text=True, check=False).stdout.strip())
104+
return 0 != clean or unpushed_commits
105+
87106
def get_tracking_remote_url() -> str:
88107
"""
89108
Returns the tracking remote URL of the current branch, falling back to the 'origin' remote URL.
90109
"""
91110
try:
92111
# Get the tracking remote URL of the current branch
93-
remote_name = subprocess.run(
94-
["git", "-C", str(CASSANDRA_DIR), "config", "--get", f"branch.{DEFAULT_REPO_BRANCH}.remote"],
95-
capture_output=True, text=True, check=True).stdout.strip()
112+
remote_name = subprocess.run(["git", "-C", str(CASSANDRA_DIR), "config", "--get", f"branch.{DEFAULT_REPO_BRANCH}.remote"],
113+
capture_output=True, text=True, check=True).stdout.strip()
96114

97115
except subprocess.CalledProcessError:
98116
# Fallback to the 'origin' remote URL
@@ -102,7 +120,9 @@ def get_tracking_remote_url() -> str:
102120
capture_output=True, text=True, check=True).stdout.strip()
103121
if repo_url.startswith("[email protected]:"):
104122
repo_url = repo_url.replace("[email protected]:", "https://github.com/")
105-
return repo_url
123+
124+
# and change gitbox to github
125+
return repo_url.replace("https://gitbox.apache.org/repos/asf/cassandra.git", "https://github.com/apache/cassandra.git")
106126

107127
# Constants
108128
DEFAULT_KUBE_NS = "default"
@@ -113,7 +133,6 @@ DEFAULT_REPO_URL = get_tracking_remote_url()
113133
DEFAULT_DTEST_REPO_URL = "https://github.com/apache/cassandra-dtest.git"
114134
DEFAULT_DTEST_REPO_BRANCH = "trunk"
115135
DEFAULT_PROFILE = "skinny"
116-
DEFAULT_JOB_NAME = determine_job_name(CASSANDRA_DIR)
117136
DEFAULT_POD_NAME = "cassius-jenkins-0"
118137
DEFAULT_CONTAINER_NAME = "jenkins"
119138
LOCAL_RESULTS_BASEDIR = CASSANDRA_DIR / "build/ci/"
@@ -306,7 +325,7 @@ def trigger_jenkins_build(server: jenkins.Jenkins, job_name: str, **build_params
306325
print("Parameters should now be available.")
307326

308327
# Check and trigger non-parameter build if parameters are not visible
309-
check_for_parameter_build(server, DEFAULT_JOB_NAME)
328+
check_for_parameter_build(server, job_name)
310329
print("Triggering Jenkins build… ")
311330
return server.build_job(job_name, parameters=build_params)
312331

@@ -587,9 +606,9 @@ def node_cleaner(k8s_client: client.CoreV1Api, kubeconfig: Optional[str], kubeco
587606
time.sleep(10)
588607

589608

590-
def delete_remote_junit_files(k8s_client, pod_name: str, kube_ns: str, build_number: int):
609+
def delete_remote_junit_files(k8s_client, pod_name: str, kube_ns: str, base_job_name: str, build_number: int):
591610
debug("Cleaning remote individual JUnit XML files...")
592-
exec_command = ['rm', '-rf', f'/var/jenkins_home/jobs/{DEFAULT_JOB_NAME}/builds/{build_number}/archive/test/output']
611+
exec_command = ['rm', '-rf', f'/var/jenkins_home/jobs/{base_job_name}/builds/{build_number}/archive/test/output']
593612
stream.stream(k8s_client.connect_get_namespaced_pod_exec,
594613
pod_name, kube_ns, container=DEFAULT_CONTAINER_NAME, command=exec_command, stderr=True, stdin=False, stdout=True, tty=False, _preload_content=False)
595614
debug("Remote JUnit XML files cleaned.")
@@ -702,8 +721,8 @@ def download_results_and_print_summary(k8s_client, pod_name: str, kube_ns: str,
702721
ci_summary_file = local_results_dir / f"ci_summary_{repo_owner}_{args.branch.replace('/', '-')}_{build_number}.html"
703722
ci_details_file = local_results_dir / f"results_details_{repo_owner}_{args.branch.replace('/', '-')}_{build_number}.tar.xz"
704723
if args.url:
705-
download_url(f"http://{ip}/job/{DEFAULT_JOB_NAME}/{build_number}/artifact/ci_summary.html", ci_summary_file)
706-
download_url(f"http://{ip}/job/{DEFAULT_JOB_NAME}/{build_number}/artifact/results_details.tar.xz", ci_details_file)
724+
download_url(f"http://{ip}/job/{base_job_name(args)}/{build_number}/artifact/ci_summary.html", ci_summary_file)
725+
download_url(f"http://{ip}/job/{base_job_name(args)}/{build_number}/artifact/results_details.tar.xz", ci_details_file)
707726
if (ci_summary_file).exists():
708727
print(f"CI summary saved as {ci_summary_file}")
709728
if (ci_details_file).exists():
@@ -716,7 +735,7 @@ def download_results_and_print_summary(k8s_client, pod_name: str, kube_ns: str,
716735
kubecontext = args.kubecontext
717736
local_console_log = local_results_dir / "console_log.txt"
718737
local_archive_tar = local_results_dir / "archive.tar.gz"
719-
remote_build_dir = f"/var/jenkins_home/jobs/{DEFAULT_JOB_NAME}/builds/{build_number}"
738+
remote_build_dir = f"/var/jenkins_home/jobs/{base_job_name(args)}/builds/{build_number}"
720739
remote_console_log_path = f"{remote_build_dir}/log"
721740
remote_archive_dir = f"{remote_build_dir}/archive"
722741

@@ -822,14 +841,23 @@ def main():
822841
"dtest_branch": args.dtest_branch or ""
823842
}
824843

825-
queue_item = trigger_jenkins_build(server, DEFAULT_JOB_NAME, **build_params)
844+
if DEFAULT_REPO_URL == args.repository and DEFAULT_REPO_BRANCH == args.branch and is_local_git_dirty(args):
845+
print("Local uncommitted/unpushed changes.")
846+
print(f"CI only runs on what is pushed in {args.repository} @ {args.branch}")
847+
print(" See `git diff-index HEAD --` for uncommitted changes")
848+
print(" See `git log @{u}.. --name-only` for unpushed changes")
849+
print(" Do you want to continue anyway (y/N):")
850+
if "y" != input().strip().lower():
851+
return
852+
853+
queue_item = trigger_jenkins_build(server, base_job_name(args), **build_params)
826854
build_number = wait_for_build_number(server, queue_item)
827-
print(f"Jenkins UI at http://{ip}/job/{DEFAULT_JOB_NAME}/{build_number}/pipeline-overview/")
828-
wait_for_build_complete(server, DEFAULT_JOB_NAME, build_number)
855+
print(f"Jenkins UI at http://{ip}/job/{base_job_name(args)}/{build_number}/pipeline-overview/")
856+
wait_for_build_complete(server, base_job_name(args), build_number)
829857

830858
# Post-build processing and cleanup
831859
if not args.url:
832-
delete_remote_junit_files(k8s_client, DEFAULT_POD_NAME, DEFAULT_KUBE_NS, build_number)
860+
delete_remote_junit_files(k8s_client, DEFAULT_POD_NAME, DEFAULT_KUBE_NS, base_job_name(args), build_number)
833861
download_results_and_print_summary(k8s_client, DEFAULT_POD_NAME, DEFAULT_KUBE_NS, build_number, ip, args)
834862
cleanup_and_maybe_teardown(args.kubeconfig, args.kubecontext, DEFAULT_KUBE_NS, args.tear_down)
835863

0 commit comments

Comments
 (0)