add build timestamp to avoid useless image builds
* skip build if image timestamp is newer than config file
This commit is contained in:
		@@ -10,6 +10,8 @@ import os
 | 
			
		||||
import re
 | 
			
		||||
import xdg.BaseDirectory
 | 
			
		||||
import yaml
 | 
			
		||||
import datetime
 | 
			
		||||
import pytz
 | 
			
		||||
import subprocess
 | 
			
		||||
from pprint import pprint
 | 
			
		||||
 | 
			
		||||
@@ -33,6 +35,7 @@ def read_yaml(conf_file):
 | 
			
		||||
    try:
 | 
			
		||||
        with open(conf_file, 'r') as file:
 | 
			
		||||
            conf = yaml.safe_load(file)
 | 
			
		||||
            conf['stamp'] = datetime.datetime.fromtimestamp(os.path.getmtime(conf_file), tz=pytz.UTC)
 | 
			
		||||
        return conf
 | 
			
		||||
    except yaml.YAMLError as e:
 | 
			
		||||
        print(f'ERROR: bad configuration file:')
 | 
			
		||||
@@ -62,6 +65,7 @@ def load_config(conf_file, osname):
 | 
			
		||||
        print(f"ERROR: cannot find configuration for distribution {osname}")
 | 
			
		||||
        sys.exit(1)
 | 
			
		||||
 | 
			
		||||
    osconf['stamp'] = conf.get('stamp')
 | 
			
		||||
    osconf['osname'] = osname
 | 
			
		||||
    for k in [ 'dockerfile', 'packages', 'environment', 'binds' ]:
 | 
			
		||||
        if osconf.get(k):
 | 
			
		||||
@@ -83,6 +87,24 @@ def make_image_name(osname):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def build_image(client, conf, update, verbose):
 | 
			
		||||
    osname = conf.get('osname')
 | 
			
		||||
    image_name = 'runon-{}'.format(osname)
 | 
			
		||||
    tag = make_image_name(conf['osname'])
 | 
			
		||||
    cache_dir = os.path.join(xdg.BaseDirectory.xdg_cache_home, 'runon')
 | 
			
		||||
    cache_file = os.path.join(cache_dir, image_name)
 | 
			
		||||
 | 
			
		||||
    if not update and os.path.exists(cache_file):
 | 
			
		||||
        ts_image = datetime.datetime.fromtimestamp(os.path.getmtime(cache_file), tz=pytz.UTC)
 | 
			
		||||
        ts_conf = conf.get('stamp')
 | 
			
		||||
        if verbose:
 | 
			
		||||
            print('config: {}'.format(ts_conf))
 | 
			
		||||
            print('image:  {}'.format(ts_image))
 | 
			
		||||
        if ts_image and ts_image > ts_conf:
 | 
			
		||||
            if verbose:
 | 
			
		||||
                print('image: {} up-to-date'.format(image_name))
 | 
			
		||||
            image = client.images.get(tag)
 | 
			
		||||
            return image
 | 
			
		||||
 | 
			
		||||
    image = conf.get('image')
 | 
			
		||||
    packages = conf['packages']
 | 
			
		||||
    dockerfile = conf['dockerfile']
 | 
			
		||||
@@ -91,7 +113,6 @@ def build_image(client, conf, update, verbose):
 | 
			
		||||
        dockerfile.insert(0, 'FROM {}'.format(image))
 | 
			
		||||
    for p in packages:
 | 
			
		||||
        dockerfile.append(pkginstall.format(p))
 | 
			
		||||
    tag = make_image_name(conf['osname'])
 | 
			
		||||
    try:
 | 
			
		||||
        if verbose:
 | 
			
		||||
            # fallback to external command 'docker build' as there is
 | 
			
		||||
@@ -112,6 +133,14 @@ def build_image(client, conf, update, verbose):
 | 
			
		||||
                print('Built image {} / {}'.format(image.tags[0], image.short_id))
 | 
			
		||||
                for l in logs:
 | 
			
		||||
                    print(l.get('stream', '').strip('\n'))
 | 
			
		||||
 | 
			
		||||
        if not os.path.exists(cache_dir):
 | 
			
		||||
            os.mkdir(cache_dir)
 | 
			
		||||
        with open(cache_file, 'w') as file:
 | 
			
		||||
            if verbose:
 | 
			
		||||
                print('cache: {}'.format(cache_file))
 | 
			
		||||
            file.write('')
 | 
			
		||||
 | 
			
		||||
    except (docker.errors.BuildError, KeyboardInterrupt, subprocess.CalledProcessError, docker.errors.ImageNotFound) as e:
 | 
			
		||||
        print('Build Error: {}'.format(e))
 | 
			
		||||
        print()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user