Jaypore CI

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

commit 4e84c70a7cbc1f2267f4c0a83565450ef4ba597a
parent 033ea779e2911e65f196b4d4f1b8c2cfb00b7e28
Author: arjoonn <arjoonn@noreply.localhost>
Date:   Wed, 18 Jan 2023 10:39:05 +0000

Add timing information to runs (!25)

Branch auto created by JayporeCI

```jayporeci
╔ 🟢 : JayporeCI       [sha 3af3387812]
┏━ Docker
┃
┃ 🟢 : JciEnv          [87c4250a]   0:55
┃ 🟢 : Jci             [c1c5ea5a]   1: 2
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
┏━ Jobs
┃
┃ 🟢 : black           [2989f3fd]   0: 0
┃ 🟢 : pytest          [cbbc1049]   0:33
┃ 🟢 : pylint          [ba2e620d]   0: 5
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
┏━ Publish
┃
┃ 🟢 : DockerHubJci    [f4d7ee2d]   1:20
┃ 🟢 : PublishDocs     [bfa21bdb]   0: 7
┃ 🟢 : DockerHubJcienv [790449dc]   0:51
┃ 🟢 : PublishPypi     [18424873]   0: 8
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
```

Co-authored-by: arjoonn sharma <arjoonn@midpathsoftware.com>
Reviewed-on: https://gitea.midpathsoftware.com/midpath/jaypore_ci/pulls/25

Diffstat:
MREADME.md | 6++++++
Mjaypore_ci/executors/docker.py | 7+++++--
Mjaypore_ci/executors/mock.py | 4++--
Mjaypore_ci/jci.py | 15+++++++++------
Mjaypore_ci/reporters/text.py | 33++++++++++++++++++++++++---------
Mpyproject.toml | 2+-
6 files changed, 47 insertions(+), 20 deletions(-)

diff --git a/README.md b/README.md @@ -2,6 +2,12 @@ Documentation is at : https://www.jayporeci.in +## If you are reading this on github + +- Github is only the mirror for this codebase. +- Actual development is on a personal gitea instance. +- Please use github to file issues / PRs and I'll get them merged when I have time. + ## Usage - Install : `curl https://get.jayporeci.in | bash` diff --git a/jaypore_ci/executors/docker.py b/jaypore_ci/executors/docker.py @@ -4,6 +4,7 @@ A docker executor for Jaypore CI. import json import subprocess +import pendulum from rich import print as rprint from jaypore_ci.interfaces import Executor, TriggerFailed, JobStatus @@ -182,8 +183,10 @@ class Docker(Executor): is_running=inspect["State"]["Running"], exit_code=int(inspect["State"]["ExitCode"]), logs="", - started_at=inspect["State"]["StartedAt"], - finished_at=inspect["State"]["FinishedAt"], + started_at=pendulum.parse(inspect["State"]["StartedAt"]), + finished_at=pendulum.parse(inspect["State"]["FinishedAt"]) + if inspect["State"]["FinishedAt"] != "0001-01-01T00:00:00Z" + else None, ) # --- logs self.logging().debug("Check status", status=status) diff --git a/jaypore_ci/executors/mock.py b/jaypore_ci/executors/mock.py @@ -129,9 +129,9 @@ class Mock(Executor): """ Given a run_id, it will get the status for that run. """ - status = JobStatus(True, None, "", "", "") + status = JobStatus(True, None, "", None, None) if run_id in self.__status__: - status = JobStatus(False, 0, "fake logs", "", "") + status = JobStatus(False, 0, "fake logs", None, None) return status def get_execution_order(self): diff --git a/jaypore_ci/jci.py b/jaypore_ci/jci.py @@ -52,6 +52,7 @@ class Job: # pylint: disable=too-many-instance-attributes self.command = command self.image = image self.status = status + self.run_state = None self.timeout = timeout self.pipeline = pipeline self.env = env @@ -133,18 +134,20 @@ class Job: # pylint: disable=too-many-instance-attributes """ if isinstance(self.command, str) and self.run_id is not None: self.logging().debug("Checking job run") - status = self.pipeline.executor.get_status(self.run_id) + self.run_state = self.pipeline.executor.get_status(self.run_id) self.last_check = pendulum.now(TZ) self.logging().debug( "Job run status found", - is_running=status.is_running, - exit_code=status.exit_code, + is_running=self.run_state.is_running, + exit_code=self.run_state.exit_code, ) - if status.is_running: + if self.run_state.is_running: self.status = Status.RUNNING if not self.is_service else Status.PASSED else: - self.status = Status.PASSED if status.exit_code == 0 else Status.FAILED - self.logs["stdout"] = reporters.gitea.clean_logs(status.logs) + self.status = ( + Status.PASSED if self.run_state.exit_code == 0 else Status.FAILED + ) + self.logs["stdout"] = reporters.gitea.clean_logs(self.run_state.logs) if with_update_report: self.update_report() diff --git a/jaypore_ci/reporters/text.py b/jaypore_ci/reporters/text.py @@ -1,16 +1,32 @@ +import pendulum from jaypore_ci.interfaces import Reporter, Status +def __get_time_format__(job): + time = " --:--" + if job.run_state is not None: + s = ( + (pendulum.now() - job.run_state.started_at) + if job.run_state.finished_at is None + else (job.run_state.finished_at - job.run_state.started_at) + ).in_seconds() + m = s // 60 + time = f"{m:>3}:{s % 60:>2}" + return time + + +__ST_MAP__ = { + Status.RUNNING: "🔵", + Status.FAILED: "🔴", + Status.PASSED: "🟢", +} + + class Text(Reporter): def render(self, pipeline): """ Returns a human readable report for a given pipeline. """ - st_map = { - Status.RUNNING: "🔵", - Status.FAILED: "🔴", - Status.PASSED: "🟢", - } max_name = max(len(job.name) for job in pipeline.jobs.values()) max_name = max(max_name, len("jayporeci")) name = ("JayporeCI" + " " * max_name)[:max_name] @@ -35,12 +51,11 @@ class Text(Reporter): ): # Fewer parents first n = pipeline.jobs[n] name = (n.name + " " * max_name)[:max_name] - status = st_map.get(n.status, "🟡") + status = __ST_MAP__.get(n.status, "🟡") run_id = f"{n.run_id}"[:8] if n.run_id is not None else "" + graph += [f"┃ {status} : {name} [{run_id:<8}] {__get_time_format__(n)}"] if n.parents: - graph += [f"┃ {status} : {name} [{run_id:<8}] ❮-- {n.parents}"] - else: - graph += [f"┃ {status} : {name} [{run_id:<8}]"] + graph[-1] += f" ❮-- {n.parents}" graph += [closer] graph += ["```"] graph = "\n".join(graph) diff --git a/pyproject.toml b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "jaypore_ci" -version = "0.1.10" +version = "0.1.11" description = "" authors = ["arjoonn sharma <arjoonn.94@gmail.com>"]