commit 4012f8db5e3d6e2a7ac235ec965cfe3c5680ed31
parent dc513233a9bbad659e3c0d8419bf9ead8844d959
Author: arjoonn <arjoonn@noreply.localhost>
Date: Thu, 22 Dec 2022 09:50:46 +0000
fix_bugs (!8)
Branch auto created by JayporeCI
<details>
<summary>JayporeCi: 🟢 7f6cbd4915</summary>
```mermaid
flowchart TB
subgraph Pipeline
direction TB
end
subgraph Docker
direction TB
s_Docker(( )) -.-> Docker_0(JciEnv):::passed
s_Docker(( )) -..-> Docker_1(Jci):::passed
end
subgraph Checks
direction TB
s_Checks(( )) -.-> Checks_0(pytest):::passed
s_Checks(( )) -..-> Checks_1(black):::passed
s_Checks(( )) -.-> Checks_2(pylint):::passed
end
Pipeline ---> Docker
Docker ---> Checks
classDef pending fill:#aaa, color:black, stroke:black,stroke-width:2px,stroke-dasharray: 5 5;
classDef skipped fill:#aaa, color:black, stroke:black,stroke-width:2px;
classDef assigned fill:#ddd, color:black, stroke:black,stroke-width:2px;
classDef running fill:#bae1ff,color:black,stroke:black,stroke-width:2px,stroke-dasharray: 5 5;
classDef passed fill:#88d8b0, color:black, stroke:black;
classDef failed fill:#ff6f69, color:black, stroke:black;
classDef timeout fill:#ffda9e, color:black, stroke:black;
```
Co-authored-by: arjoonn sharma <arjoonn@midpathsoftware.com>
Reviewed-on: https://gitea.midpathsoftware.com/midpath/jaypore_ci/pulls/8
Diffstat:
6 files changed, 51 insertions(+), 24 deletions(-)
diff --git a/README.md b/README.md
@@ -1,8 +1,7 @@
# Jaypore CI
- A CI system that sounds ancient and powerful.
- Like the city of Jaypore.
-
+> A CI system that sounds ancient and powerful.
+> Like the city of Jaypore.
## Expected usage
@@ -11,7 +10,7 @@ curl https://raw.githubusercontent.com/theSage21/jaypore_ci/main/setup.sh | bash
```
- Use the script to install this in any project.
-- Configure CI at `.jaypore_ci/cicd.py`
+- Configure CI at `cicd/cicd.py`
- Each git-push will trigger a CI job.
## Screenshot
@@ -105,7 +104,7 @@ curl https://raw.githubusercontent.com/theSage21/jaypore_ci/main/setup.sh | bash
<summary>TLDR: Running jobs on cloud</summary>
- We can get the remote machine's docker socket by using [ssh socket forwarding](https://medium.com/@dperny/forwarding-the-docker-socket-over-ssh-e6567cfab160)
- - Then we can set jaypore CI to use the remote docker socket by editing `.jaypore_ci/pre-push.githook`
+ - Then we can set jaypore CI to use the remote docker socket by editing `cicd/pre-push.githook`
</summary>
</details>
- <details>
diff --git a/cicd/cicd.py b/cicd/cicd.py
@@ -6,7 +6,7 @@ with jci.Pipeline() as p:
with p.stage("Docker"):
p.job("JciEnv", f"docker build --target jcienv -t {jcienv} .")
p.job("Jci", f"docker build --target jci -t jci:{p.remote.sha} .")
- with p.stage("Checks"):
+ with p.stage("Checks", image=jcienv):
p.job("black", "python3 -m black --check .")
p.job("pylint", "python3 -m pylint jaypore_ci/ tests/")
p.job("pytest", "python3 -m pytest tests/")
diff --git a/jaypore_ci/docker.py b/jaypore_ci/docker.py
@@ -2,7 +2,7 @@ import subprocess
from rich import print as rprint
-from jaypore_ci.interfaces import Executor
+from jaypore_ci.interfaces import Executor, TriggerFailed
from jaypore_ci.logging import logger
@@ -113,7 +113,17 @@ class Docker(Executor):
if not job.is_service:
assert job.command
rprint(trigger)
- return self.check_output(" ".join(t for t in trigger if t is not None))
+ trigger = " ".join(t for t in trigger if t is not None)
+ run_job = subprocess.run(
+ trigger,
+ shell=True,
+ check=False,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
+ if run_job.returncode == 0:
+ return run_job.stdout.decode().strip()
+ raise TriggerFailed(run_job)
def get_status(self, run_id: str) -> (str, str):
ps_out = self.check_output(f"docker ps -f 'id={run_id}' --no-trunc")
diff --git a/jaypore_ci/interfaces.py b/jaypore_ci/interfaces.py
@@ -1,3 +1,7 @@
+class TriggerFailed(Exception):
+ ...
+
+
class Executor:
"""
It can be docker / podman / shell etc.
diff --git a/jaypore_ci/jci.py b/jaypore_ci/jci.py
@@ -10,7 +10,7 @@ import structlog
import pendulum
from jaypore_ci import gitea, docker
-from jaypore_ci.interfaces import Remote, Executor
+from jaypore_ci.interfaces import Remote, Executor, TriggerFailed
from jaypore_ci.logging import logger, jaypore_logs
TZ = "UTC"
@@ -112,8 +112,19 @@ class Job: # pylint: disable=too-many-instance-attributes
self.logging().info("Trigger called")
self.status = Status.RUNNING
if isinstance(self.command, str):
- self.run_id = self.pipeline.executor.run(self)
- self.logging().info("Trigger done")
+ try:
+ self.run_id = self.pipeline.executor.run(self)
+ self.logging().info("Trigger done")
+ except TriggerFailed as e:
+ job_run = e.args[0]
+ self.logging().error(
+ "Trigger failed",
+ returncode=job_run.returncode,
+ job_name=self.name,
+ )
+ logs = job_run.stdout.decode()
+ self.logs["stdout"] = clean_logs(logs).split("\n")
+ self.status = Status.FAILED
else:
self.logging().info("Trigger called but job already running")
self.check_job()
@@ -263,26 +274,28 @@ class Pipeline: # pylint: disable=too-many-instance-attributes
flowchart {self.graph_direction}
"""
for stage in self.stages:
- mermaid += f"""
- subgraph {stage}
- direction {self.graph_direction}
- """
nodes, edges = set(), set()
for job in self.jobs.values():
if job.stage != stage:
continue
nodes.add(job.name)
edges |= {(p, job.name) for p in job.parents}
+ mermaid += f"""
+ subgraph {stage}
+ direction {self.graph_direction}
+ """
ref = {n: f"{stage}_{i}" for i, n in enumerate(nodes)}
arrow = "-.->"
- for n in nodes:
+ for i, n in enumerate(nodes):
n = self.jobs[n]
if n.parents:
continue
+ arrow = "-.->" if i % 2 == 0 else "-..->"
mermaid += f"""
s_{stage}(( )) {arrow} {ref[n.name]}({n.name}):::{st_map[n.status]}"""
- for (a, b) in edges:
+ for i, (a, b) in enumerate(edges):
a, b = self.jobs[a], self.jobs[b]
+ arrow = "-.->" if i % 2 == 0 else "-..->"
mermaid += f"""
{ref[a.name]}({a.name}):::{st_map[a.status]} {arrow} {ref[b.name]}({b.name}):::{st_map[b.status]}"""
mermaid += """
@@ -342,6 +355,7 @@ flowchart {self.graph_direction}
Define a job in this pipeline.
"""
depends_on = [] if depends_on is None else depends_on
+ depends_on = [depends_on] if isinstance(depends_on, str) else depends_on
assert name not in self.jobs
kwargs, job_kwargs = dict(self.pipe_kwargs), kwargs
kwargs.update(self.stage_kwargs if self.stage_kwargs is not None else {})
diff --git a/setup.sh b/setup.sh
@@ -7,8 +7,8 @@ main (){
LOCAL_HOOK=$(echo $REPO_ROOT/.git/hooks/pre-push)
IMAGE='arjoonn/jci:latest'
echo "Working in repo: $REPO_ROOT"
- mkdir $REPO_ROOT/.jaypore_ci || echo 'Moving on..'
- cat > $REPO_ROOT/.jaypore_ci/cicd.py << EOF
+ mkdir $REPO_ROOT/cicd || echo 'Moving on..'
+ cat > $REPO_ROOT/cicd/cicd.py << EOF
from jaypore_ci import jci
with jci.Pipeline(
@@ -24,7 +24,7 @@ with jci.Pipeline(
).should_pass()
EOF
- cat > $REPO_ROOT/.jaypore_ci/pre-push.githook << EOF
+ cat > $REPO_ROOT/cicd/pre-push.githook << EOF
#! /bin/bash
#
set -o errexit
@@ -53,13 +53,13 @@ main() {
-v /tmp/jaypore_\$SHA:/jaypore_ci/run \\
--workdir /jaypore_ci/run \\
$IMAGE \\
- bash -c 'cp -r /jaypore_ci/repo/. /jaypore_ci/run && cd /jaypore_ci/run/ && git clean -fdx && python .jaypore_ci/cicd.py'
+ bash -c 'cp -r /jaypore_ci/repo/. /jaypore_ci/run && cd /jaypore_ci/run/ && git clean -fdx && python cicd/cicd.py'
echo '----------------------------------------------'
}
(main)
EOF
echo "Creating git hook for pre-commit"
- chmod u+x $REPO_ROOT/.jaypore_ci/pre-push.githook
+ chmod u+x $REPO_ROOT/cicd/pre-push.githook
if test -f "$LOCAL_HOOK"; then
if test -f "$LOCAL_HOOK.local"; then
@@ -67,7 +67,7 @@ EOF
echo $LOCAL_HOOK
echo $LOCAL_HOOK.local
echo "Please link"
- echo " Jaypore hook : $REPO_ROOT/.jaypore_ci/pre-push.githook"
+ echo " Jaypore hook : $REPO_ROOT/cicd/pre-push.githook"
echo "with"
echo " Existing hook: $LOCAL_HOOK"
echo "manually by editing the existing hook file"
@@ -80,7 +80,7 @@ EOF
echo "$REPO_ROOT/.git/hooks/pre-push.local" >> $REPO_ROOT/.git/hooks/pre-push
fi
fi
- echo "$REPO_ROOT/.jaypore_ci/pre-push.githook" >> $REPO_ROOT/.git/hooks/pre-push
+ echo "$REPO_ROOT/cicd/pre-push.githook" >> $REPO_ROOT/.git/hooks/pre-push
chmod u+x $LOCAL_HOOK
}