Jaypore CI

> Jaypore CI: Minimal, Offline, Local CI system.
Log | Files | Refs | README

commit f1861496fc97def686d28cb28881ad10cd277bf5
parent 60e443116a9448df49c8f032329c1355e97df7a5
Author: arjoonn <arjoonn@noreply.localhost>
Date:   Tue, 21 Mar 2023 04:39:56 +0000

Ensure that JayporeCI once installed will continue to work in a repo (!67)

Reviewed-on: https://gitea.midpathsoftware.com/midpath/jaypore_ci/pulls/67

Diffstat:
MREADME.md | 1+
Mcicd/Dockerfile | 3++-
Mcicd/build_and_publish_docs.sh | 19++++++++++++++++++-
Mcicd/build_and_push_docker.sh | 3+++
Mcicd/pre-push.sh | 11++++++++---
Ajaypore_ci/changelog.py | 25+++++++++++++++++++++++++
Ajaypore_ci/config.py | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ajaypore_ci/exceptions.py | 5+++++
Mjaypore_ci/jci.py | 42+++++++++++++++++++++++++++++++++++++++++-
Mpyproject.toml | 2+-
Msetup.sh | 12+++++++++---
Mtests/test_jaypore_ci.py | 6++++++
12 files changed, 178 insertions(+), 10 deletions(-)

diff --git a/README.md b/README.md @@ -1,5 +1,6 @@ # ![JayporeCI](docs/source/_static/logo80.png) Jaypore CI + Documentation is at : https://www.jayporeci.in ## If you are reading this on GitHub diff --git a/cicd/Dockerfile b/cicd/Dockerfile @@ -1,2 +1,3 @@ -FROM arjoonn/jci:latest +ARG JAYPORECI_VERSION +FROM arjoonn/jci:$JAYPORECI_VERSION COPY ../ /jaypore_ci/repo/ diff --git a/cicd/build_and_publish_docs.sh b/cicd/build_and_publish_docs.sh @@ -8,7 +8,22 @@ build() { echo "Building docs" sphinx-apidoc -o docs/source/reference ./jaypore_ci sphinx-build docs/source/ docs/build - cp cicd/pre-push.sh docs/build + + # Create pre-push for repo + PREPUSH=docs/build/pre-push.sh + cp cicd/pre-push.sh $PREPUSH + sed -i '$ d' $PREPUSH + # add expected version of Jci + echo "" >> $PREPUSH + echo "# Change the version in the next line to whatever you want if you" >> $PREPUSH + echo "# would like to upgrade to a different version of JayporeCI." >> $PREPUSH + echo -n "EXPECTED_JAYPORECI_" >> $PREPUSH + grep version pyproject.toml | python3 -c 'print(input().upper().replace(" ", "").replace("\"", ""))' >> $PREPUSH + + echo "" >> $PREPUSH + echo '("$@")' >> $PREPUSH + + # Copy other files cp cicd/Dockerfile docs/build cp setup.sh docs/build cp -r htmlcov /jaypore_ci/run/docs/build/ @@ -16,6 +31,8 @@ build() { wget -O docs/build/sops https://github.com/mozilla/sops/releases/download/v3.7.3/sops-v3.7.3.linux wget -O ./age.tar.gz https://github.com/FiloSottile/age/releases/download/v1.0.0/age-v1.0.0-linux-amd64.tar.gz tar xf ./age.tar.gz && mv ./age/age docs/build/bin && mv ./age/age-keygen docs/build/bin && rm -rf ./age + + # Create docs bundle (cd docs/build && zip -r ../../website.zip ./) } diff --git a/cicd/build_and_push_docker.sh b/cicd/build_and_push_docker.sh @@ -8,3 +8,6 @@ docker login -u arjoonn -p=$DOCKER_PWD docker build --target $1 -t $1:latest . docker tag $1:latest arjoonn/$1:latest docker push arjoonn/$1:latest +VERSION=$(grep version pyproject.toml | python3 -c 'print(input().split("=")[1].upper().replace(" ", "").replace("\"", ""))') +docker tag $1:latest arjoonn/$1:$VERSION +docker push arjoonn/$1:$VERSION diff --git a/cicd/pre-push.sh b/cicd/pre-push.sh @@ -13,12 +13,11 @@ run() { echo "---" source /jaypore_ci/repo/secrets/bin/set_env.sh $ENV fi - env | awk -F\= '{print $1}' cp -r /jaypore_ci/repo/. /jaypore_ci/run cd /jaypore_ci/run/ git clean -fdx # Change the name of the file if this is not cicd.py - echo "---- Run container ID:" + echo "---- Container ID:" cat /jaypore_ci/cidfiles/$SHA echo echo "---- =======" @@ -40,11 +39,14 @@ hook() { # jaypore_ci can create docker containers mkdir -p /tmp/jayporeci__cidfiles &> /dev/null echo '----------------------------------------------' - echo "JayporeCi: " + echo "Jaypore CI" + echo "Building image : " docker build \ + --build-arg JAYPORECI_VERSION=$EXPECTED_JAYPORECI_VERSION \ -t im_jayporeci__pipe__$SHA \ -f $REPO_ROOT/$JAYPORE_CODE_DIR/Dockerfile \ $REPO_ROOT + echo "Running container : " docker run \ -d \ --name jayporeci__pipe__$SHA \ @@ -59,4 +61,7 @@ hook() { bash -c "ENV=$ENV bash /jaypore_ci/repo/$JAYPORE_CODE_DIR/pre-push.sh run" echo '----------------------------------------------' } +EXPECTED_JAYPORECI_VERSION=latest + +# --------- runner ("$@") diff --git a/jaypore_ci/changelog.py b/jaypore_ci/changelog.py @@ -0,0 +1,25 @@ +from jaypore_ci.config import Version + +V = Version.parse +version_map = { + V("0.2.26"): { + "changes": [ + ( + "The Dockerfile inside `cicd/Dockerfile` now requires a build arg " + "that specifies the version of Jaypore CI to install." + ), + ], + "instructions": [ + "Please run the Jaypore CI setup once again.", + ], + }, + V("0.2.25"): { + "changes": [ + ( + "A dockerfile is now used to send context of the codebase to " + "the docker daemon instead of directly mounting the code." + ) + ], + "instructions": [], + }, +} diff --git a/jaypore_ci/config.py b/jaypore_ci/config.py @@ -0,0 +1,59 @@ +import os +import tomllib +from typing import NamedTuple +import importlib.metadata +from pathlib import Path + + +class Version(NamedTuple): + major: int + minor: int + patch: int + trail: str = None + + def __repr__(self): + if self.trail: + return f"{self.major}.{self.minor}.{self.patch}-{self.trail}" + return f"{self.major}.{self.minor}.{self.patch}" + + def __str__(self): + return self.__repr__() + + @classmethod + def parse(cls, inp: str) -> "Version": + if inp is None or inp == "": + return None + trail = None + major, minor, patch = inp.split(".") + major = major[1:] if major[0].lower() == "v" else major + assert major.isdigit() + assert minor.isdigit() + if "-" in patch: + patch, trail = patch.split("-", 1) + assert patch.isdigit() + return cls(major=int(major), minor=int(minor), patch=int(patch), trail=trail) + + +def get_version() -> Version: + try: + return Version.parse(importlib.metadata.version(__package__ or __name__)) + except importlib.metadata.PackageNotFoundError: + try: + with open( + (Path(__file__) / "../../pyproject.toml").resolve(), + "rb", + ) as fl: + data = tomllib.load(fl) + return Version.parse(data["tool"]["poetry"]["version"]) + except FileNotFoundError: + return None + + +class Const(NamedTuple): + expected_version: Version = Version.parse( + os.environ.get("EXPECTED_JAYPORECI_VERSION") + ) + version: Version = get_version() + + +const = Const() diff --git a/jaypore_ci/exceptions.py b/jaypore_ci/exceptions.py @@ -0,0 +1,5 @@ +class BadConfig(Exception): + """ + Raised when a given configuration for a pipeline will cause errors / + unexpected behaviour if it is allowed to run. + """ diff --git a/jaypore_ci/jci.py b/jaypore_ci/jci.py @@ -11,6 +11,9 @@ from contextlib import contextmanager import structlog import pendulum +from jaypore_ci.exceptions import BadConfig +from jaypore_ci.config import const +from jaypore_ci.changelog import version_map from jaypore_ci import remotes, executors, reporters, repos, clean from jaypore_ci.interfaces import ( Remote, @@ -31,6 +34,42 @@ __all__ = ["Pipeline", "Job"] FIN_STATUSES = (Status.FAILED, Status.PASSED, Status.TIMEOUT, Status.SKIPPED) PREFIX = "JAYPORE_" +# Check if we need to upgrade Jaypore CI +def ensure_version_is_correct(): + """ + Ensure that the version of Jaypore CI that is running, the code inside + cicd.py, and pre-push.sh are at compatible versions. + + If versions do not match then this function will print out instructions on + what to do in order to upgrade. + + Downgrades are not allowed, you need to re-install that specific version. + """ + if ( + const.expected_version is not None + and const.version is not None + and const.expected_version != const.version + ): + print("Expected : ", const.expected_version) + print("Got : ", const.version) + if const.version > const.expected_version: + print( + "Your current version is higher than the expected one. Please " + "re-install Jaypore CI in this repo as downgrades are not " + "supported." + ) + if const.version < const.expected_version: + print("--- Upgrade Instructions ---") + for version in sorted(version_map.keys()): + if version < const.version or version > const.expected_version: + continue + for line in version_map[version]["instructions"]: + print(line) + print("--- -------------------- ---") + raise BadConfig( + "Version mismatch between arjoonn/jci:<tag> docker container and pre-push.sh script" + ) + class Job: # pylint: disable=too-many-instance-attributes """ @@ -244,7 +283,7 @@ class Pipeline: # pylint: disable=too-many-instance-attributes self.__pipe_id__ = None self.executor.set_pipeline(self) # --- - kwargs["image"] = kwargs.get("image", "arjoonn/jci:latest") + kwargs["image"] = kwargs.get("image", "arjoonn/jci") kwargs["timeout"] = kwargs.get("timeout", 15 * 60) kwargs["env"] = kwargs.get("env", {}) kwargs["stage"] = "Pipeline" @@ -279,6 +318,7 @@ class Pipeline: # pylint: disable=too-many-instance-attributes ) def __enter__(self): + ensure_version_is_correct() self.executor.__enter__() self.remote.__enter__() return self diff --git a/pyproject.toml b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "jaypore_ci" -version = "0.2.25" +version = "0.2.26" description = "" authors = ["arjoonn sharma <arjoonn.94@gmail.com>"] homepage = "https://www.jayporeci.in/" diff --git a/setup.sh b/setup.sh @@ -53,7 +53,6 @@ getfile(){ main (){ REPO_ROOT=$(git rev-parse --show-toplevel) LOCAL_HOOK=$(echo $REPO_ROOT/.git/hooks/pre-push) - IMAGE='arjoonn/jci:latest' CICD_ROOT=cicd echo "--------------------" echo "Installing JayporeCI" @@ -84,11 +83,11 @@ EOF then mkdir -p secrets/bin PATH="$REPO_ROOT/secrets/bin:$PATH" - echo "Downloading age/sops binaries" + BINLOC=$HOME/.local/jayporeci_bin + echo "Downloading age/sops binaries to: $BINLOC" if should_continue then echo "Downloading age/ binaries" - BINLOC=$HOME/.local/bin mkdir -p $BINLOC &> /dev/null getfile /bin/age $BINLOC/age & getfile /bin/age-keygen $BINLOC/age-keygen & @@ -96,6 +95,13 @@ EOF wait chmod u+x $BINLOC/age $BINLOC/age-keygen $BINLOC/sops fi + echo "Adding line to .bashrc:" + echo " \$PATH=$BINLOC:\$PATH" + if should_continue + then + echo "export PATH=$BINLOC:\$PATH" >> $HOME/.bashrc + source $HOME/.bashrc + fi echo "Downloading edit/set env scripts" getfile /bin/edit_env.sh secrets/bin/edit_env.sh & getfile /bin/set_env.sh secrets/bin/set_env.sh & diff --git a/tests/test_jaypore_ci.py b/tests/test_jaypore_ci.py @@ -1,10 +1,16 @@ import pytest +from jaypore_ci.changelog import version_map +from jaypore_ci.config import const def test_sanity(): assert 4 == 2 + 2 +def test_version_has_entry_in_version_map(): + assert const.version in version_map, const + + def test_simple_linear_jobs(pipeline): pipeline = pipeline() with pipeline as p: