initial commit
This commit is contained in:
87
src/archipelago_tester/pipeline/batch/version.py
Normal file
87
src/archipelago_tester/pipeline/batch/version.py
Normal file
@@ -0,0 +1,87 @@
|
||||
"""Which Archipelago version a run tests against."""
|
||||
|
||||
from archipelago_tester.core.state.keys import StateKeys
|
||||
from archipelago_tester.pipeline.build.archipelago import ArchipelagoBuild
|
||||
from archipelago_tester.pipeline.build.docker import Docker
|
||||
|
||||
|
||||
class Version:
|
||||
"""Resolve the version, and build it if this machine lacks it."""
|
||||
|
||||
def __init__(self, config, paths, store):
|
||||
self.paths = paths
|
||||
self.store = store
|
||||
self.build = ArchipelagoBuild(config, paths)
|
||||
|
||||
def resolve(self):
|
||||
"""The version to test, and where that choice came from.
|
||||
|
||||
A pin is a decision already made, so nothing else revisits it.
|
||||
Failing that the recorded version wins, then whichever image is
|
||||
on this machine - a test runs entirely inside the container, so
|
||||
an image already here is everything it needs.
|
||||
"""
|
||||
pinned = self.build.pinned_version
|
||||
if pinned:
|
||||
return pinned, "pinned in config.json"
|
||||
recorded = self.store.load().get(StateKeys.ARCHIPELAGO_TAG)
|
||||
if recorded:
|
||||
return recorded, "from state.json"
|
||||
local = next(iter(self.build.local_tags()), None)
|
||||
return (local, "newest image on this machine") if local else (None,
|
||||
None)
|
||||
|
||||
def ensure_built(self, tag):
|
||||
"""Build what this version needs, if anything is missing.
|
||||
|
||||
Building needs the Archipelago source, which is the one job the
|
||||
checkout has - so this is also the only path that clones.
|
||||
"""
|
||||
if tag is None:
|
||||
print("no Archipelago image on this machine - cloning the "
|
||||
"newest release to build one (several minutes) ...")
|
||||
built, _, _, _ = self.build.update_and_build(self.store)
|
||||
return built, "just built"
|
||||
if not Docker.image_exists(self.build.image_tag(tag)):
|
||||
print(f"Archipelago {tag} is not built on this machine - "
|
||||
"cloning and building it (several minutes) ...")
|
||||
self.build.build_version(tag)
|
||||
return tag, None
|
||||
|
||||
def note_others(self, tag, source):
|
||||
"""Say so when an unpinned run is not using the newest image.
|
||||
|
||||
An unpinned tag can come from an image that happens to be lying
|
||||
around, so a run can quietly answer for a version that is not
|
||||
the current one. A pinned tag was chosen deliberately.
|
||||
"""
|
||||
local = self.build.local_tags()
|
||||
if self.build.pinned_version or not local or tag == local[0]:
|
||||
return source
|
||||
return f"{source}, but {local[0]} is also built here"
|
||||
|
||||
def update(self):
|
||||
"""Resolve the newest release, build it, and record it.
|
||||
|
||||
Never automatic. A new version invalidates every cached result,
|
||||
so the full re-test it forces is the caller's decision, not a
|
||||
side effect of running. A pinned version stays pinned: the
|
||||
resolution behind this honours the pin, so an update then only
|
||||
ensures that version is built.
|
||||
"""
|
||||
tag, previous, changed, _ = self.build.update_and_build(self.store)
|
||||
if self.build.pinned_version:
|
||||
return tag, "pinned in config.json"
|
||||
if not changed:
|
||||
return tag, "already the newest release"
|
||||
if previous is None:
|
||||
return tag, "newest release, recorded for the first time"
|
||||
return tag, f"updated from {previous}"
|
||||
|
||||
def prepare(self, update=False):
|
||||
"""The version to test against, built if it is missing."""
|
||||
if update:
|
||||
return self.update()
|
||||
tag, source = self.resolve()
|
||||
tag, built = self.ensure_built(tag)
|
||||
return tag, built or self.note_others(tag, source)
|
||||
Reference in New Issue
Block a user