Skip to content

Commit

Permalink
scripts: add versionary.py to drive FCOS versioning
Browse files Browse the repository at this point in the history
This script implements the versioning scheme as described in:
coreos/fedora-coreos-tracker#211

The next step is to use this in the FCOS pipeline to drive versioning.
  • Loading branch information
jlebon committed Nov 11, 2019
1 parent 7e7ffb5 commit 5785b74
Showing 1 changed file with 140 additions and 0 deletions.
140 changes: 140 additions & 0 deletions scripts/versionary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#!/usr/bin/python3 -u

'''
Implements the Fedora CoreOS versioning scheme as per:
https://github.com/coreos/fedora-coreos-tracker/issues/81
https://github.com/coreos/fedora-coreos-tracker/issues/211
'''

import argparse
import json
import os
import re
import subprocess
import sys
import time
import yaml

from datetime import datetime


def main():
args = parse_args()
if args.workdir is not None:
os.chdir(args.workdir)
assert os.path.isfile('builds/builds.json'), 'Missing builds/builds.json!'

x, y, z = (get_x(), get_y(), get_z())
n = get_next_iteration(x, y, z)
new_version = f'{x}.{y}.{z}.{n}'

# sanity check the new version by trying to re-parse it
assert parse_version(new_version) is not None
print(new_version)


def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument('--workdir', help="path to cosa workdir")
return parser.parse_args()


def get_x():
"""
X is the Fedora release version on which we're based.
"""
manifest = get_flattened_manifest()
releasever = manifest['releasever']
eprint(f"Got releasever {releasever} from manifest")
return int(releasever)


def get_y():
"""
Y is the base snapshot date in YYYYMMDD format of Fedora. We derive
this using the timestamp in the base lockfile.
"""
# XXX: should sanity check that the lockfiles for all the basearches have
# matching timestamps
with open('src/config/manifest-lock.x86_64.json') as f:
lockfile = json.load(f)
generated = lockfile.get('metadata', {}).get('generated')
if not generated:
raise Exception(f"Missing 'metadata.generated' key from {lockfile}")
dt = datetime.strptime(generated, '%Y-%m-%dT%H:%M:%SZ')
ymd = dt.strftime('%Y%m%d')
eprint(f"Got lockfile timestamp {ymd}")
return int(ymd)


def get_z():
"""
Z is the stream indicator.
"""
# https://github.com/coreos/fedora-coreos-tracker/issues/211#issuecomment-543547587
stream_to_int = {
'next': 1,
'testing': 2,
'stable': 3,
'next-devel': 10,
'testing-devel': 20,
'rawhide': 91,
'branched': 92,
'bodhi-updates-testing': 93,
'bodhi-updates': 94,
}
manifest = get_flattened_manifest()
stream = manifest['add-commit-metadata']['fedora-coreos.stream']
eprint(f"Got stream {stream} from manifest")
assert stream in stream_to_int, f"Unknown stream: {stream}"
mapped = stream_to_int[stream]
eprint(f"Mapped stream {stream} to {mapped}")
return mapped


def get_next_iteration(x, y, z):
with open('builds/builds.json') as f:
builds = json.load(f)

if len(builds['builds']) == 0:
eprint(f"No previous builds")
return 0

last_buildid = builds['builds'][0]['id']
last_version = parse_version(last_buildid)
if not last_version:
eprint(f"Previous version {last_buildid} does not match scheme")
return 0

if (x, y, z) != last_version[:3]:
eprint(f"Previous version {last_buildid} x.y.z does not match")
return 0

return last_version[3] + 1


def get_flattened_manifest():
return yaml.safe_load(
subprocess.check_output(['rpm-ostree', 'compose', 'tree', '--repo',
'tmp/repo', '--print-only',
'src/config/manifest.yaml']))


def parse_version(version):
m = re.match(r'^([0-9]{2})\.([0-9]{8})\.([0-9]+)\.([0-9]+)$', version)
if m is None:
return None
# sanity-check date
try:
time.strptime(m.group(2), '%Y%m%d')
except ValueError:
return None
return tuple(map(int, m.groups()))


def eprint(*args):
print(*args, file=sys.stderr)


if __name__ == "__main__":
sys.exit(main())

0 comments on commit 5785b74

Please sign in to comment.