diff --git a/Makefile b/Makefile index 02b3010a..fcb84fd4 100644 --- a/Makefile +++ b/Makefile @@ -106,7 +106,7 @@ hook/%: ## run post-build hooks for an image DOCKER_REPO="$(OWNER)/$(notdir $@)" \ IMAGE_NAME="$(OWNER)/$(notdir $@):latest" \ IMAGE_SHORT_NAME="$(notdir $@)" \ - $(SHELL) $(notdir $@)/hooks/run_hook + ./tagging/apply_tags.py --short-image-name "$(notdir $@)" --owner "$(OWNER)" hook-all: $(foreach I,$(ALL_IMAGES),hook/$(I) ) ## run post-build hooks for all images diff --git a/tagging/apply_tags.py b/tagging/apply_tags.py new file mode 100755 index 00000000..b9848872 --- /dev/null +++ b/tagging/apply_tags.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +# Copyright (c) Jupyter Development Team. +# Distributed under the terms of the Modified BSD License. +import argparse +import logging +from tagger_interface import TaggerInterface +from dataclasses import dataclass, field +from typing import Optional, List +from taggers import SHATagger, PythonVersionTagger + + +# NB_VERSION_TAG="notebook-$(docker run --rm -a STDOUT ${IMAGE_NAME} jupyter-notebook --version | tr -d '\r')" +# docker tag $IMAGE_NAME "$DOCKER_REPO:${NB_VERSION_TAG%% }" +# LAB_VERSION_TAG="lab-$(docker run --rm -a STDOUT ${IMAGE_NAME} jupyter-lab --version | tr -d '\r')" +# docker tag $IMAGE_NAME "$DOCKER_REPO:${LAB_VERSION_TAG%%\r}" +# HUB_VERSION_TAG="hub-$(docker run --rm -a STDOUT ${IMAGE_NAME} jupyterhub --version | tr -d '\r')" +# docker tag $IMAGE_NAME "$DOCKER_REPO:${HUB_VERSION_TAG%%\r}" + + +@dataclass +class ImageDescription: + parent_image: Optional[str] + taggers: List[TaggerInterface] = field(default_factory=list) + + +ALL_IMAGES = { + "minimal-notebook": ImageDescription( + parent_image=None, + taggers=[SHATagger] + ), + "base-notebook": ImageDescription( + parent_image="minimal-notebook", + taggers=[PythonVersionTagger] + ) +} + + +def get_all_taggers(short_image_name): + taggers = [] + while short_image_name is not None: + image_description = ALL_IMAGES[short_image_name] + taggers = image_description.taggers + taggers + short_image_name = image_description.parent_image + return taggers + + +def apply_tags(short_image_name, owner): + logging.info(f"Applying tags for image: {short_image_name}") + taggers = get_all_taggers(short_image_name) + + for tagger in taggers: + tag_name, tag_value = tagger.tag_name(), tagger.tag_value(short_image_name, owner) + logging.info(f"Applying tag tag_name: {tag_name} tag_value: {tag_value}") + + +if __name__ == "__main__": + logging.basicConfig(level=logging.DEBUG) + arg_parser = argparse.ArgumentParser() + arg_parser.add_argument("--short-image-name", required=True, help="Short image name to apply tags for") + arg_parser.add_argument("--owner", required=True, help="Owner of the image") + args = arg_parser.parse_args() + apply_tags(args.short_image_name, args.owner) diff --git a/tagging/git_helper.py b/tagging/git_helper.py new file mode 100755 index 00000000..f0ea0f8a --- /dev/null +++ b/tagging/git_helper.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# Copyright (c) Jupyter Development Team. +# Distributed under the terms of the Modified BSD License. +from plumbum.cmd import git + + +class GitHelper: + @staticmethod + def commit_hash(): + return git['rev-parse', 'HEAD']().strip() + + @staticmethod + def commit_message(): + return git["log", -1, "--pretty=%B"]().strip() + + +if __name__ == '__main__': + print('Git hash:', GitHelper.commit_hash()) + print('Git message:', GitHelper.commit_message()) diff --git a/tagging/tagger_interface.py b/tagging/tagger_interface.py new file mode 100644 index 00000000..3020d3b3 --- /dev/null +++ b/tagging/tagger_interface.py @@ -0,0 +1,13 @@ +# Copyright (c) Jupyter Development Team. +# Distributed under the terms of the Modified BSD License. + + +class TaggerInterface: + """HooksInterface for all hooks common interface""" + @staticmethod + def tag_value(image): + raise NotImplementedError + + @staticmethod + def tag_name(): + raise NotImplementedError diff --git a/tagging/taggers.py b/tagging/taggers.py new file mode 100644 index 00000000..873a9895 --- /dev/null +++ b/tagging/taggers.py @@ -0,0 +1,39 @@ +# Copyright (c) Jupyter Development Team. +# Distributed under the terms of the Modified BSD License. +from tagger_interface import TaggerInterface +from git_helper import GitHelper +from plumbum.cmd import docker + + +def _get_full_name(short_image_name, owner): + return f"{owner}/{short_image_name}:latest" + + +def _get_program_version(short_image_name, owner, program): + return docker[ + "run", + "--rm", + "-a", "STDOUT", + _get_full_name(short_image_name, owner), + program, "--version" + ]().strip() + + +class SHATagger(TaggerInterface): + @staticmethod + def tag_value(short_image_name, owner): + return GitHelper.commit_hash()[:12] + + @staticmethod + def tag_name(): + return "git_sha" + + +class PythonVersionTagger(TaggerInterface): + @staticmethod + def tag_value(short_image_name, owner): + return "python-" + _get_program_version(short_image_name, owner, "python").split()[1] + + @staticmethod + def tag_name(): + return "python_version"