Skip to content

Commit 9e3e2af

Browse files
committed
jenkins: always obey sandbox when calculating job graph
In contrast to the local build logic the Jenkins job generator has to eagerly create the whole job graph. In conjunction with the sandboxInvariant policy this might lead to cyclic jobs because the sandbox was not taken into account. If the same artifact (as in variant-id) is built inside *and* outside of the sanbox in the same project then a cycle was created. The Jenkins logic will now always take the configured sandbox into account. Steps with the same variant-id but different sandboxes are built separately. This might lead to duplicated checkout- and build-steps but is the simplest bullet-proof solution to the problem. Fixes #438.
1 parent 7bacb0c commit 9e3e2af

File tree

1 file changed

+25
-14
lines changed

1 file changed

+25
-14
lines changed

pym/bob/cmds/jenkins.py

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,23 @@ def verifyAuditMeta(meta):
181181
valid = re.compile(r"[0-9A-Za-z._-]+")
182182
return all(valid.fullmatch(k) for k in meta.keys())
183183

184+
def getJenkinsVariantId(step):
185+
"""Get the variant-id of a step with it's sandbox dependency.
186+
187+
Even though the sandbox is considered an invariant of the build
188+
(sandboxInvariant policy) it still needs to be respected when building the
189+
packages. Because the Jenkins logic cannot rely on lazy evaluation like the
190+
local builds we need to regard the sandbox as real dependency.
191+
192+
This is only relevant when calculating the job graph. The actual build
193+
result still uses the original variant- and build-id.
194+
"""
195+
vid = step.getVariantId()
196+
sandbox = step.getSandbox()
197+
if sandbox:
198+
vid += sandbox.getStep().getVariantId()
199+
return vid
200+
184201
class JenkinsJob:
185202
def __init__(self, name, displayName, nameCalculator, recipe, archiveBackend):
186203
self.__name = name
@@ -242,7 +259,7 @@ def getDescription(self, date, warnLazy):
242259
return "\n".join(description)
243260

244261
def addStep(self, step):
245-
vid = step.getVariantId()
262+
vid = getJenkinsVariantId(step)
246263
if step.isCheckoutStep():
247264
self.__checkoutSteps.setdefault(vid, step)
248265
elif step.isBuildStep():
@@ -262,7 +279,7 @@ def addStep(self, step):
262279
# add dependencies unless they are built by this job or invalid
263280
for dep in step.getAllDepSteps(True):
264281
if not dep.isValid(): continue
265-
vid = dep.getVariantId()
282+
vid = getJenkinsVariantId(dep)
266283
if vid in self.__steps: continue
267284
self.__deps.setdefault(vid, dep)
268285

@@ -1108,7 +1125,7 @@ def sanitize(self):
11081125
# Helper function that recursively adds the packages to the graph.
11091126
# Recursion stops at already known packages.
11101127
def addStep(step, parentJob):
1111-
sbxVariantId = step._getSandboxVariantId()
1128+
sbxVariantId = getJenkinsVariantId(step)
11121129
job = vidToJob.get(sbxVariantId)
11131130
if job is None:
11141131
if step.isPackageStep():
@@ -1207,9 +1224,9 @@ def longestPrefix(pkgs):
12071224

12081225
def getJobDisplayName(self, step):
12091226
if step.isPackageStep():
1210-
vid = step._getSandboxVariantId()
1227+
vid = getJenkinsVariantId(step)
12111228
else:
1212-
vid = step.getPackage().getPackageStep()._getSandboxVariantId()
1229+
vid = getJenkinsVariantId(step.getPackage().getPackageStep())
12131230
return self.__prefix + self.__packageName[vid]
12141231

12151232
def getJobInternalName(self, step):
@@ -1220,11 +1237,11 @@ def _genJenkinsJobs(step, jobs, nameCalculator, archiveBackend, seenPackages, al
12201237
shortdescription):
12211238

12221239
if step.isPackageStep() and shortdescription:
1223-
if step.getVariantId() in allVariantIds:
1240+
if getJenkinsVariantId(step) in allVariantIds:
12241241
name = nameCalculator.getJobInternalName(step)
12251242
return jobs[name]
12261243
else:
1227-
allVariantIds.add(step.getVariantId())
1244+
allVariantIds.add(getJenkinsVariantId(step))
12281245

12291246
name = nameCalculator.getJobInternalName(step)
12301247
if name in jobs:
@@ -1272,14 +1289,8 @@ def jenkinsNameFormatter(step, props):
12721289
def jenkinsNamePersister(jenkins, wrapFmt, uuid):
12731290

12741291
def persist(step, props):
1275-
vid = step.getVariantId()
1276-
# Make sure that build steps of sandboxed and non-sandboxed builds are
1277-
# not mixed. Does not apply to other steps because checkout steps must
1278-
# be self contained and package steps are always built clean.
1279-
if step.isBuildStep():
1280-
vid += b'\x00' if step.getSandbox() is None else b'\x01'
12811292
ret = BobState().getJenkinsByNameDirectory(
1282-
jenkins, wrapFmt(step, props), vid)
1293+
jenkins, wrapFmt(step, props), getJenkinsVariantId(step))
12831294
if uuid: ret = ret + "-" + uuid
12841295
return ret
12851296

0 commit comments

Comments
 (0)