commit 8d52f98134c3069733081828f707d3f95c32d2e6
parent eba6687076924afb065aa98d7afcf38f15378781
Author: arjoonn <arjoonn@noreply.localhost>
Date: Fri, 24 Feb 2023 03:57:49 +0000
Use python docker client instead of binary install (!51)
Branch auto created by JayporeCI
```jayporeci
╔ 🟢 : JayporeCI [sha b1eb47c663]
┏━ build_and_test
┃
┃ 🟢 : JciEnv [eaf81975] 0:32
┃ 🟢 : Jci [9022a0e6] 0: 9 ❮-- ['JciEnv']
┃ 🟢 : black [dc689d56] 0: 0 ❮-- ['JciEnv']
┃ 🟢 : pylint [c7cd0e9e] 0: 7 ❮-- ['JciEnv']
┃ 🟢 : pytest [752cfbd8] 1: 3 Cov: 87% ❮-- ['JciEnv']
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
┏━ Publish
┃
┃ 🟢 : DockerHubJci [583c4c69] 5:38
┃ 🟢 : DockerHubJcienv [58baae70] 1: 8
┃ 🟢 : PublishDocs [9bf44ae9] 0:18
┃ 🟢 : PublishPypi [fbbe778b] 0: 6 v0.2.19
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
```
Co-authored-by: arjoonn sharma <arjoonn.94@gmail.com>
Reviewed-on: https://gitea.midpathsoftware.com/midpath/jaypore_ci/pulls/51
Diffstat:
17 files changed, 324 insertions(+), 320 deletions(-)
diff --git a/Dockerfile b/Dockerfile
@@ -1,7 +1,5 @@
from python:3.11 as jcienv
workdir /app
-add cicd/install_docker.sh .
-run bash install_docker.sh
run python3 -m pip install --upgrade pip
run python3 -m pip install poetry
add pyproject.toml .
diff --git a/cicd/run_tests.sh b/cicd/run_tests.sh
@@ -6,7 +6,7 @@ set -o pipefail
main() {
- python -m coverage run --branch --source=. -m pytest -vv
+ python -m coverage run --branch --source=. -m pytest -xl --full-trace -vv
coverage html
coverage report
echo "Cov: $(coverage report --format=total)%" > "/jaypore_ci/run/pytest.txt"
diff --git a/docs/source/conf.py b/docs/source/conf.py
@@ -34,7 +34,7 @@ html_sidebars = {
html_theme = "alabaster"
html_static_path = ["_static"]
html_theme_options = {
- "logo": "logo.png",
+ "nosidebar": True,
"logo_name": "Jaypore CI",
"touch_icon": "logo.png",
"github_user": "theSage21",
diff --git a/jaypore_ci/executors/__init__.py b/jaypore_ci/executors/__init__.py
@@ -1,2 +1 @@
-from .mock import Mock
from .docker import Docker
diff --git a/jaypore_ci/executors/docker.py b/jaypore_ci/executors/docker.py
@@ -1,30 +1,14 @@
"""
A docker executor for Jaypore CI.
"""
-import json
-import subprocess
-
import pendulum
+import docker
from rich import print as rprint
from jaypore_ci.interfaces import Executor, TriggerFailed, JobStatus
from jaypore_ci.logging import logger
-def __check_output__(cmd):
- """
- Common arguments that need to be provided while
- calling subprocess.check_output
- """
- proc = subprocess.run(
- cmd, check=False, shell=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE
- )
- if proc.returncode != 0:
- print(proc.stdout.decode())
- raise TriggerFailed(cmd)
- return proc.stdout.decode().strip()
-
-
class Docker(Executor):
"""
Run jobs via docker.
@@ -39,6 +23,9 @@ class Docker(Executor):
super().__init__()
self.pipe_id = None
self.pipeline = None
+ self.docker = docker.from_env()
+ self.client = docker.APIClient()
+ self.__execution_order__ = []
def logging(self):
"""
@@ -79,22 +66,13 @@ class Docker(Executor):
"""
assert self.pipe_id is not None, "Cannot create network if pipe is not set"
for _ in range(3):
- net_ls = subprocess.run(
- f"docker network ls | grep {self.get_net()}",
- shell=True,
- check=False,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT,
- )
- if net_ls.returncode == 0:
- self.logging().info(
- "Found network", network_name=self.get_net(), subprocess=net_ls
- )
- return net_ls
+ if len(self.docker.networks.list(names=[self.get_net()])) != 0:
+ self.logging().info("Found network", network_name=self.get_net())
+ return
self.logging().info(
"Create network",
- subprocess=__check_output__(
- f"docker network create -d bridge {self.get_net()}"
+ subprocess=self.docker.networks.create(
+ name=self.get_net(), driver="bridge"
),
)
raise TriggerFailed("Cannot create network")
@@ -110,10 +88,9 @@ class Docker(Executor):
job = None
for job in self.pipeline.jobs.values():
if job.run_id is not None and not job.run_id.startswith("pyrun_"):
- self.logging().info(
- "Stop job:",
- subprocess=__check_output__(f"docker stop -t 1 {job.run_id}"),
- )
+ container = self.docker.containers.get(job.run_id)
+ container.stop(timeout=1)
+ self.logging().info("Stop job:", run_id=job.run_id)
job.check_job(with_update_report=False)
if job is not None:
job.check_job()
@@ -124,14 +101,13 @@ class Docker(Executor):
Delete the network for this executor.
"""
assert self.pipe_id is not None, "Cannot delete network if pipe is not set"
- self.logging().info(
- "Delete network",
- subprocess=__check_output__(
- f"docker network rm {self.get_net()} || echo 'No such net'"
- ),
- )
+ try:
+ net = self.docker.networks.get(self.get_net())
+ net.remove()
+ except docker.errors.NotFound:
+ self.logging().error("Delete network: Not found", netid=self.get_net())
- def get_job_name(self, job):
+ def get_job_name(self, job, tail=False):
"""
Generates a clean job name slug.
"""
@@ -139,6 +115,8 @@ class Docker(Executor):
l if l in "abcdefghijklmnopqrstuvwxyz1234567890" else "-"
for l in job.name.lower()
)
+ if tail:
+ return name
return f"jayporeci__job__{self.pipe_id}__{name}"
def run(self, job: "Job") -> str:
@@ -147,39 +125,39 @@ class Docker(Executor):
In case something goes wrong it will raise TriggerFailed
"""
assert self.pipe_id is not None, "Cannot run job if pipe id is not set"
- env_vars = [f"--env {key}={val}" for key, val in job.get_env().items()]
- trigger = [
- "docker run -d",
- "-v /var/run/docker.sock:/var/run/docker.sock",
- "-v /usr/bin/docker:/usr/bin/docker:ro",
- f"-v /tmp/jayporeci__src__{self.pipeline.remote.sha}:/jaypore_ci/run",
- *["--workdir /jaypore_ci/run" if not job.is_service else None],
- f"--name {self.get_job_name(job)}",
- f"--network {self.get_net()}",
- *env_vars,
- job.image,
- job.command if not job.is_service else None,
- ]
+ trigger = {
+ "detach": True,
+ "environment": job.get_env(),
+ "volumes": [
+ "/var/run/docker.sock:/var/run/docker.sock",
+ "/usr/bin/docker:/usr/bin/docker:ro",
+ f"/tmp/jayporeci__src__{self.pipeline.remote.sha}:/jaypore_ci/run",
+ ],
+ "name": self.get_job_name(job),
+ "network": self.get_net(),
+ "image": job.image,
+ "command": job.command if not job.is_service else None,
+ }
+ if not job.is_service:
+ trigger["working_dir"] = "/jaypore_ci/run"
if not job.is_service:
assert job.command
rprint(trigger)
- 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)
+ try:
+ container = self.docker.containers.run(**trigger)
+ self.__execution_order__.append(
+ (self.get_job_name(job, tail=True), container.id, "Run")
+ )
+ return container.id
+ except docker.errors.APIError as e:
+ self.logging().exception(e)
+ raise TriggerFailed(e) from e
def get_status(self, run_id: str) -> JobStatus:
"""
Given a run_id, it will get the status for that run.
"""
- inspect = json.loads(__check_output__(f"docker inspect {run_id}"))[0]
+ inspect = self.client.inspect_container(run_id)
status = JobStatus(
is_running=inspect["State"]["Running"],
exit_code=int(inspect["State"]["ExitCode"]),
@@ -191,5 +169,8 @@ class Docker(Executor):
)
# --- logs
self.logging().debug("Check status", status=status)
- logs = __check_output__(f"docker logs {run_id}")
+ logs = self.docker.containers.get(run_id).logs().decode()
return status._replace(logs=logs)
+
+ def get_execution_order(self):
+ return {name: i for i, (name, *_) in enumerate(self.__execution_order__)}
diff --git a/jaypore_ci/executors/mock.py b/jaypore_ci/executors/mock.py
@@ -1,138 +0,0 @@
-"""
-A mock executor that actually does not run anything.
-"""
-import uuid
-
-from jaypore_ci.interfaces import Executor, JobStatus
-from jaypore_ci.logging import logger
-
-
-class Mock(Executor):
- """
- Run jobs via docker.
-
- This will:
- - Create a separate network for each run
- - Run jobs as part of the network
- - Clean up all jobs when the pipeline exits.
- """
-
- def __init__(self):
- super().__init__()
- self.pipe_id = None
- self.pipeline = None
- self.__log__ = []
- self.__status__ = {}
-
- def logging(self):
- """
- Returns a logging instance that has executor specific
- information bound to it.
- """
- return logger.bind(pipe_id=self.pipe_id, network_name=self.get_net())
-
- def set_pipeline(self, pipeline):
- """
- Set executor's pipeline to the given one.
-
- This will clean up old networks and create new ones.
- """
- if self.pipe_id is not None:
- self.delete_network()
- self.delete_all_jobs()
- self.pipe_id = id(pipeline)
- self.pipeline = pipeline
- self.create_network()
-
- def __exit__(self, exc_type, exc_value, traceback):
- self.delete_network()
- self.delete_all_jobs()
-
- def get_net(self):
- """
- Return a network name based on what the curent pipeline is.
- """
- return f"jaypore_{self.pipe_id}" if self.pipe_id is not None else None
-
- def create_network(self):
- """
- Will create a docker network.
-
- If it fails to do so in 3 attempts it will raise an
- exception and fail.
- """
- assert self.pipe_id is not None, "Cannot create network if pipe is not set"
- return self.get_net()
-
- def delete_all_jobs(self):
- """
- Deletes all jobs associated with the pipeline for this
- executor.
-
- It will stop any jobs that are still running.
- """
- assert self.pipe_id is not None, "Cannot delete jobs if pipe is not set"
- job = None
- for job in self.pipeline.jobs.values():
- if job.run_id is not None and not job.run_id.startswith("pyrun_"):
- self.logging().info("Stop job:", run_id=job.run_id)
- job.check_job(with_update_report=False)
- if job is not None:
- job.check_job()
- self.logging().info("All jobs stopped")
-
- def delete_network(self):
- """
- Delete the network for this executor.
- """
- assert self.pipe_id is not None, "Cannot delete network if pipe is not set"
- self.logging().info("Delete network", net=self.get_net())
-
- def get_job_name(self, job):
- """
- Generates a clean job name slug.
- """
- name = "".join(
- l
- for l in job.name.lower().replace(" ", "_")
- if l in "abcdefghijklmnopqrstuvwxyz_1234567890"
- )
- return name
-
- def run(self, job: "Job") -> str:
- """
- Run the given job and return a docker container ID.
- """
- assert self.pipe_id is not None, "Cannot run job if pipe id is not set"
- self.pipe_id = id(job.pipeline) if self.pipe_id is None else self.pipe_id
- if not job.is_service:
- assert job.command
- name = self.get_job_name(job)
- if name in self.__status__:
- return None
- run_id = uuid.uuid4().hex
- self.__log__.append((name, run_id, "Run"))
- self.__status__[name] = self.__status__[run_id] = True
- self.logging().info(
- "Run job",
- run_id=run_id,
- env_vars=job.get_env(),
- is_service=job.is_service,
- name=self.get_job_name(job),
- net=self.get_net(),
- image=job.image,
- command=job.command if not job.is_service else None,
- )
- return run_id
-
- def get_status(self, run_id: str) -> JobStatus:
- """
- Given a run_id, it will get the status for that run.
- """
- status = JobStatus(True, None, "", None, None)
- if run_id in self.__status__:
- status = JobStatus(False, 0, "fake logs", None, None)
- return status
-
- def get_execution_order(self):
- return {name: i for i, (name, *log) in enumerate(self.__log__)}
diff --git a/jaypore_ci/jci.py b/jaypore_ci/jci.py
@@ -149,14 +149,11 @@ class Job: # pylint: disable=too-many-instance-attributes
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,
+ error=e,
job_name=self.name,
)
- logs = job_run.stdout.decode()
- self.logs["stdout"] = reporters.clean_logs(logs)
self.status = Status.FAILED
else:
self.logging().info("Trigger called but job already running")
diff --git a/jaypore_ci/remotes/git.py b/jaypore_ci/remotes/git.py
@@ -5,7 +5,7 @@ import time
import subprocess
from jaypore_ci.interfaces import Remote
-from jaypore_ci.repos import Git, Mock
+from jaypore_ci.repos import Git
from jaypore_ci.logging import logger
@@ -26,7 +26,7 @@ class GitRemote(Remote): # pylint: disable=too-many-instance-attributes
"""
Creates a remote instance from the environment.
"""
- assert isinstance(repo, (Git, Mock)), "Git remote can only work in a git repo"
+ assert isinstance(repo, Git), "Git remote can only work in a git repo"
return cls(
repo=repo,
branch=repo.branch,
diff --git a/jaypore_ci/reporters/__init__.py b/jaypore_ci/reporters/__init__.py
@@ -1,4 +1,3 @@
from .common import clean_logs
from .markdown import Markdown
-from .mock import Mock
from .text import Text
diff --git a/jaypore_ci/reporters/mock.py b/jaypore_ci/reporters/mock.py
@@ -1,6 +0,0 @@
-from jaypore_ci.interfaces import Reporter
-
-
-class Mock(Reporter):
- def render(self, pipeline):
- return f"{pipeline}"
diff --git a/jaypore_ci/repos/__init__.py b/jaypore_ci/repos/__init__.py
@@ -1,2 +1 @@
from .git import Git
-from .mock import Mock
diff --git a/jaypore_ci/repos/mock.py b/jaypore_ci/repos/mock.py
@@ -1,20 +0,0 @@
-from typing import List
-
-from jaypore_ci.interfaces import Repo
-
-
-class Mock(Repo):
- def __init__(self, *, files_changed, **kwargs):
- super().__init__(**kwargs)
- self.files_changed = files_changed
-
- def files_changed(self, target: str) -> List[str]:
- "Returns list of files changed between current sha and target"
- return self.files_changed
-
- @classmethod
- def from_env(cls, **kwargs) -> "Mock":
- """
- Save whatever is provided to kwargs
- """
- return cls(**kwargs)
diff --git a/poetry.lock b/poetry.lock
@@ -241,63 +241,63 @@ files = [
[[package]]
name = "coverage"
-version = "7.1.0"
+version = "7.2.0"
description = "Code coverage measurement for Python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "coverage-7.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3b946bbcd5a8231383450b195cfb58cb01cbe7f8949f5758566b881df4b33baf"},
- {file = "coverage-7.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec8e767f13be637d056f7e07e61d089e555f719b387a7070154ad80a0ff31801"},
- {file = "coverage-7.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4a5a5879a939cb84959d86869132b00176197ca561c664fc21478c1eee60d75"},
- {file = "coverage-7.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b643cb30821e7570c0aaf54feaf0bfb630b79059f85741843e9dc23f33aaca2c"},
- {file = "coverage-7.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32df215215f3af2c1617a55dbdfb403b772d463d54d219985ac7cd3bf124cada"},
- {file = "coverage-7.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:33d1ae9d4079e05ac4cc1ef9e20c648f5afabf1a92adfaf2ccf509c50b85717f"},
- {file = "coverage-7.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:29571503c37f2ef2138a306d23e7270687c0efb9cab4bd8038d609b5c2393a3a"},
- {file = "coverage-7.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:63ffd21aa133ff48c4dff7adcc46b7ec8b565491bfc371212122dd999812ea1c"},
- {file = "coverage-7.1.0-cp310-cp310-win32.whl", hash = "sha256:4b14d5e09c656de5038a3f9bfe5228f53439282abcab87317c9f7f1acb280352"},
- {file = "coverage-7.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:8361be1c2c073919500b6601220a6f2f98ea0b6d2fec5014c1d9cfa23dd07038"},
- {file = "coverage-7.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:da9b41d4539eefd408c46725fb76ecba3a50a3367cafb7dea5f250d0653c1040"},
- {file = "coverage-7.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5b15ed7644ae4bee0ecf74fee95808dcc34ba6ace87e8dfbf5cb0dc20eab45a"},
- {file = "coverage-7.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d12d076582507ea460ea2a89a8c85cb558f83406c8a41dd641d7be9a32e1274f"},
- {file = "coverage-7.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2617759031dae1bf183c16cef8fcfb3de7617f394c813fa5e8e46e9b82d4222"},
- {file = "coverage-7.1.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4e4881fa9e9667afcc742f0c244d9364d197490fbc91d12ac3b5de0bf2df146"},
- {file = "coverage-7.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9d58885215094ab4a86a6aef044e42994a2bd76a446dc59b352622655ba6621b"},
- {file = "coverage-7.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ffeeb38ee4a80a30a6877c5c4c359e5498eec095878f1581453202bfacc8fbc2"},
- {file = "coverage-7.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3baf5f126f30781b5e93dbefcc8271cb2491647f8283f20ac54d12161dff080e"},
- {file = "coverage-7.1.0-cp311-cp311-win32.whl", hash = "sha256:ded59300d6330be27bc6cf0b74b89ada58069ced87c48eaf9344e5e84b0072f7"},
- {file = "coverage-7.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:6a43c7823cd7427b4ed763aa7fb63901ca8288591323b58c9cd6ec31ad910f3c"},
- {file = "coverage-7.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7a726d742816cb3a8973c8c9a97539c734b3a309345236cd533c4883dda05b8d"},
- {file = "coverage-7.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc7c85a150501286f8b56bd8ed3aa4093f4b88fb68c0843d21ff9656f0009d6a"},
- {file = "coverage-7.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5b4198d85a3755d27e64c52f8c95d6333119e49fd001ae5798dac872c95e0f8"},
- {file = "coverage-7.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddb726cb861c3117a553f940372a495fe1078249ff5f8a5478c0576c7be12050"},
- {file = "coverage-7.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:51b236e764840a6df0661b67e50697aaa0e7d4124ca95e5058fa3d7cbc240b7c"},
- {file = "coverage-7.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7ee5c9bb51695f80878faaa5598040dd6c9e172ddcf490382e8aedb8ec3fec8d"},
- {file = "coverage-7.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c31b75ae466c053a98bf26843563b3b3517b8f37da4d47b1c582fdc703112bc3"},
- {file = "coverage-7.1.0-cp37-cp37m-win32.whl", hash = "sha256:3b155caf3760408d1cb903b21e6a97ad4e2bdad43cbc265e3ce0afb8e0057e73"},
- {file = "coverage-7.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2a60d6513781e87047c3e630b33b4d1e89f39836dac6e069ffee28c4786715f5"},
- {file = "coverage-7.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f2cba5c6db29ce991029b5e4ac51eb36774458f0a3b8d3137241b32d1bb91f06"},
- {file = "coverage-7.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:beeb129cacea34490ffd4d6153af70509aa3cda20fdda2ea1a2be870dfec8d52"},
- {file = "coverage-7.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c45948f613d5d18c9ec5eaa203ce06a653334cf1bd47c783a12d0dd4fd9c851"},
- {file = "coverage-7.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef382417db92ba23dfb5864a3fc9be27ea4894e86620d342a116b243ade5d35d"},
- {file = "coverage-7.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c7c0d0827e853315c9bbd43c1162c006dd808dbbe297db7ae66cd17b07830f0"},
- {file = "coverage-7.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e5cdbb5cafcedea04924568d990e20ce7f1945a1dd54b560f879ee2d57226912"},
- {file = "coverage-7.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9817733f0d3ea91bea80de0f79ef971ae94f81ca52f9b66500c6a2fea8e4b4f8"},
- {file = "coverage-7.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:218fe982371ac7387304153ecd51205f14e9d731b34fb0568181abaf7b443ba0"},
- {file = "coverage-7.1.0-cp38-cp38-win32.whl", hash = "sha256:04481245ef966fbd24ae9b9e537ce899ae584d521dfbe78f89cad003c38ca2ab"},
- {file = "coverage-7.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:8ae125d1134bf236acba8b83e74c603d1b30e207266121e76484562bc816344c"},
- {file = "coverage-7.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2bf1d5f2084c3932b56b962a683074a3692bce7cabd3aa023c987a2a8e7612f6"},
- {file = "coverage-7.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:98b85dd86514d889a2e3dd22ab3c18c9d0019e696478391d86708b805f4ea0fa"},
- {file = "coverage-7.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38da2db80cc505a611938d8624801158e409928b136c8916cd2e203970dde4dc"},
- {file = "coverage-7.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3164d31078fa9efe406e198aecd2a02d32a62fecbdef74f76dad6a46c7e48311"},
- {file = "coverage-7.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db61a79c07331e88b9a9974815c075fbd812bc9dbc4dc44b366b5368a2936063"},
- {file = "coverage-7.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ccb092c9ede70b2517a57382a601619d20981f56f440eae7e4d7eaafd1d1d09"},
- {file = "coverage-7.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:33ff26d0f6cc3ca8de13d14fde1ff8efe1456b53e3f0273e63cc8b3c84a063d8"},
- {file = "coverage-7.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d47dd659a4ee952e90dc56c97d78132573dc5c7b09d61b416a9deef4ebe01a0c"},
- {file = "coverage-7.1.0-cp39-cp39-win32.whl", hash = "sha256:d248cd4a92065a4d4543b8331660121b31c4148dd00a691bfb7a5cdc7483cfa4"},
- {file = "coverage-7.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:7ed681b0f8e8bcbbffa58ba26fcf5dbc8f79e7997595bf071ed5430d8c08d6f3"},
- {file = "coverage-7.1.0-pp37.pp38.pp39-none-any.whl", hash = "sha256:755e89e32376c850f826c425ece2c35a4fc266c081490eb0a841e7c1cb0d3bda"},
- {file = "coverage-7.1.0.tar.gz", hash = "sha256:10188fe543560ec4874f974b5305cd1a8bdcfa885ee00ea3a03733464c4ca265"},
+ {file = "coverage-7.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90e7a4cbbb7b1916937d380beb1315b12957b8e895d7d9fb032e2038ac367525"},
+ {file = "coverage-7.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:34d7211be69b215ad92298a962b2cd5a4ef4b17c7871d85e15d3d1b6dc8d8c96"},
+ {file = "coverage-7.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971b49dbf713044c3e5f6451b39f65615d4d1c1d9a19948fa0f41b0245a98765"},
+ {file = "coverage-7.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0557289260125a6c453ad5673ba79e5b6841d9a20c9e101f758bfbedf928a77"},
+ {file = "coverage-7.2.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:049806ae2df69468c130f04f0fab4212c46b34ba5590296281423bb1ae379df2"},
+ {file = "coverage-7.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:875b03d92ac939fbfa8ae74a35b2c468fc4f070f613d5b1692f9980099a3a210"},
+ {file = "coverage-7.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c160e34e388277f10c50dc2c7b5e78abe6d07357d9fe7fcb2f3c156713fd647e"},
+ {file = "coverage-7.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:32e6a730fd18b2556716039ab93278ccebbefa1af81e6aa0c8dba888cf659e6e"},
+ {file = "coverage-7.2.0-cp310-cp310-win32.whl", hash = "sha256:f3ff4205aff999164834792a3949f82435bc7c7655c849226d5836c3242d7451"},
+ {file = "coverage-7.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:93db11da6e728587e943dff8ae1b739002311f035831b6ecdb15e308224a4247"},
+ {file = "coverage-7.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cd38140b56538855d3d5722c6d1b752b35237e7ea3f360047ce57f3fade82d98"},
+ {file = "coverage-7.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9dbb21561b0e04acabe62d2c274f02df0d715e8769485353ddf3cf84727e31ce"},
+ {file = "coverage-7.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:171dd3aa71a49274a7e4fc26f5bc167bfae5a4421a668bc074e21a0522a0af4b"},
+ {file = "coverage-7.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4655ecd813f4ba44857af3e9cffd133ab409774e9d2a7d8fdaf4fdfd2941b789"},
+ {file = "coverage-7.2.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1856a8c4aa77eb7ca0d42c996d0ca395ecafae658c1432b9da4528c429f2575c"},
+ {file = "coverage-7.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd67df6b48db18c10790635060858e2ea4109601e84a1e9bfdd92e898dc7dc79"},
+ {file = "coverage-7.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:2d7daf3da9c7e0ed742b3e6b4de6cc464552e787b8a6449d16517b31bbdaddf5"},
+ {file = "coverage-7.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bf9e02bc3dee792b9d145af30db8686f328e781bd212fdef499db5e9e4dd8377"},
+ {file = "coverage-7.2.0-cp311-cp311-win32.whl", hash = "sha256:3713a8ec18781fda408f0e853bf8c85963e2d3327c99a82a22e5c91baffcb934"},
+ {file = "coverage-7.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:88ae5929f0ef668b582fd7cad09b5e7277f50f912183cf969b36e82a1c26e49a"},
+ {file = "coverage-7.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5e29a64e9586194ea271048bc80c83cdd4587830110d1e07b109e6ff435e5dbc"},
+ {file = "coverage-7.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d5302eb84c61e758c9d68b8a2f93a398b272073a046d07da83d77b0edc8d76b"},
+ {file = "coverage-7.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c9fffbc39dc4a6277e1525cab06c161d11ee3995bbc97543dc74fcec33e045b"},
+ {file = "coverage-7.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6ceeab5fca62bca072eba6865a12d881f281c74231d2990f8a398226e1a5d96"},
+ {file = "coverage-7.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:28563a35ef4a82b5bc5160a01853ce62b9fceee00760e583ffc8acf9e3413753"},
+ {file = "coverage-7.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bfa065307667f1c6e1f4c3e13f415b0925e34e56441f5fda2c84110a4a1d8bda"},
+ {file = "coverage-7.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7f992b32286c86c38f07a8b5c3fc88384199e82434040a729ec06b067ee0d52c"},
+ {file = "coverage-7.2.0-cp37-cp37m-win32.whl", hash = "sha256:2c15bd09fd5009f3a79c8b3682b52973df29761030b692043f9834fc780947c4"},
+ {file = "coverage-7.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:f332d61fbff353e2ef0f3130a166f499c3fad3a196e7f7ae72076d41a6bfb259"},
+ {file = "coverage-7.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:577a8bc40c01ad88bb9ab1b3a1814f2f860ff5c5099827da2a3cafc5522dadea"},
+ {file = "coverage-7.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9240a0335365c29c968131bdf624bb25a8a653a9c0d8c5dbfcabf80b59c1973c"},
+ {file = "coverage-7.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:358d3bce1468f298b19a3e35183bdb13c06cdda029643537a0cc37e55e74e8f1"},
+ {file = "coverage-7.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:932048364ff9c39030c6ba360c31bf4500036d4e15c02a2afc5a76e7623140d4"},
+ {file = "coverage-7.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7efa21611ffc91156e6f053997285c6fe88cfef3fb7533692d0692d2cb30c846"},
+ {file = "coverage-7.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:465ea431c3b78a87e32d7d9ea6d081a1003c43a442982375cf2c247a19971961"},
+ {file = "coverage-7.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0f03c229f1453b936916f68a47b3dfb5e84e7ad48e160488168a5e35115320c8"},
+ {file = "coverage-7.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:40785553d68c61e61100262b73f665024fd2bb3c6f0f8e2cd5b13e10e4df027b"},
+ {file = "coverage-7.2.0-cp38-cp38-win32.whl", hash = "sha256:b09dd7bef59448c66e6b490cc3f3c25c14bc85d4e3c193b81a6204be8dd355de"},
+ {file = "coverage-7.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:dc4f9a89c82faf6254d646180b2e3aa4daf5ff75bdb2c296b9f6a6cf547e26a7"},
+ {file = "coverage-7.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c243b25051440386179591a8d5a5caff4484f92c980fb6e061b9559da7cc3f64"},
+ {file = "coverage-7.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4b8fd32f85b256fc096deeb4872aeb8137474da0c0351236f93cbedc359353d6"},
+ {file = "coverage-7.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7f2a7df523791e6a63b40360afa6792a11869651307031160dc10802df9a252"},
+ {file = "coverage-7.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da32526326e8da0effb452dc32a21ffad282c485a85a02aeff2393156f69c1c3"},
+ {file = "coverage-7.2.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c1153a6156715db9d6ae8283480ae67fb67452aa693a56d7dae9ffe8f7a80da"},
+ {file = "coverage-7.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:74cd60fa00f46f28bd40048d6ca26bd58e9bee61d2b0eb4ec18cea13493c003f"},
+ {file = "coverage-7.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:59a427f8a005aa7254074719441acb25ac2c2f60c1f1026d43f846d4254c1c2f"},
+ {file = "coverage-7.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c3c4beddee01c8125a75cde3b71be273995e2e9ec08fbc260dd206b46bb99969"},
+ {file = "coverage-7.2.0-cp39-cp39-win32.whl", hash = "sha256:08e3dd256b8d3e07bb230896c8c96ec6c5dffbe5a133ba21f8be82b275b900e8"},
+ {file = "coverage-7.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad12c74c6ce53a027f5a5ecbac9be20758a41c85425c1bbab7078441794b04ee"},
+ {file = "coverage-7.2.0-pp37.pp38.pp39-none-any.whl", hash = "sha256:ffa637a2d5883298449a5434b699b22ef98dd8e2ef8a1d9e60fa9cfe79813411"},
+ {file = "coverage-7.2.0.tar.gz", hash = "sha256:9cc9c41aa5af16d845b53287051340c363dd03b7ef408e45eec3af52be77810d"},
]
[package.extras]
@@ -319,6 +319,28 @@ files = [
graph = ["objgraph (>=1.7.2)"]
[[package]]
+name = "docker"
+version = "6.0.1"
+description = "A Python library for the Docker Engine API."
+category = "main"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "docker-6.0.1-py3-none-any.whl", hash = "sha256:dbcb3bd2fa80dca0788ed908218bf43972772009b881ed1e20dfc29a65e49782"},
+ {file = "docker-6.0.1.tar.gz", hash = "sha256:896c4282e5c7af5c45e8b683b0b0c33932974fe6e50fc6906a0a83616ab3da97"},
+]
+
+[package.dependencies]
+packaging = ">=14.0"
+pywin32 = {version = ">=304", markers = "sys_platform == \"win32\""}
+requests = ">=2.26.0"
+urllib3 = ">=1.26.0"
+websocket-client = ">=0.32.0"
+
+[package.extras]
+ssh = ["paramiko (>=2.4.3)"]
+
+[[package]]
name = "docutils"
version = "0.19"
description = "Docutils -- Python Documentation Utilities"
@@ -530,24 +552,24 @@ files = [
[[package]]
name = "markdown-it-py"
-version = "2.1.0"
+version = "2.2.0"
description = "Python port of markdown-it. Markdown parsing, done right!"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "markdown-it-py-2.1.0.tar.gz", hash = "sha256:cf7e59fed14b5ae17c0006eff14a2d9a00ed5f3a846148153899a0224e2c07da"},
- {file = "markdown_it_py-2.1.0-py3-none-any.whl", hash = "sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27"},
+ {file = "markdown-it-py-2.2.0.tar.gz", hash = "sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1"},
+ {file = "markdown_it_py-2.2.0-py3-none-any.whl", hash = "sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30"},
]
[package.dependencies]
mdurl = ">=0.1,<1.0"
[package.extras]
-benchmarking = ["psutil", "pytest", "pytest-benchmark (>=3.2,<4.0)"]
-code-style = ["pre-commit (==2.6)"]
-compare = ["commonmark (>=0.9.1,<0.10.0)", "markdown (>=3.3.6,<3.4.0)", "mistletoe (>=0.8.1,<0.9.0)", "mistune (>=2.0.2,<2.1.0)", "panflute (>=2.1.3,<2.2.0)"]
-linkify = ["linkify-it-py (>=1.0,<2.0)"]
+benchmarking = ["psutil", "pytest", "pytest-benchmark"]
+code-style = ["pre-commit (>=3.0,<4.0)"]
+compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"]
+linkify = ["linkify-it-py (>=1,<3)"]
plugins = ["mdit-py-plugins"]
profiling = ["gprof2dot"]
rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
@@ -653,7 +675,7 @@ files = [
name = "packaging"
version = "23.0"
description = "Core utilities for Python packages"
-category = "dev"
+category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -869,6 +891,30 @@ files = [
]
[[package]]
+name = "pywin32"
+version = "305"
+description = "Python for Window Extensions"
+category = "main"
+optional = false
+python-versions = "*"
+files = [
+ {file = "pywin32-305-cp310-cp310-win32.whl", hash = "sha256:421f6cd86e84bbb696d54563c48014b12a23ef95a14e0bdba526be756d89f116"},
+ {file = "pywin32-305-cp310-cp310-win_amd64.whl", hash = "sha256:73e819c6bed89f44ff1d690498c0a811948f73777e5f97c494c152b850fad478"},
+ {file = "pywin32-305-cp310-cp310-win_arm64.whl", hash = "sha256:742eb905ce2187133a29365b428e6c3b9001d79accdc30aa8969afba1d8470f4"},
+ {file = "pywin32-305-cp311-cp311-win32.whl", hash = "sha256:19ca459cd2e66c0e2cc9a09d589f71d827f26d47fe4a9d09175f6aa0256b51c2"},
+ {file = "pywin32-305-cp311-cp311-win_amd64.whl", hash = "sha256:326f42ab4cfff56e77e3e595aeaf6c216712bbdd91e464d167c6434b28d65990"},
+ {file = "pywin32-305-cp311-cp311-win_arm64.whl", hash = "sha256:4ecd404b2c6eceaca52f8b2e3e91b2187850a1ad3f8b746d0796a98b4cea04db"},
+ {file = "pywin32-305-cp36-cp36m-win32.whl", hash = "sha256:48d8b1659284f3c17b68587af047d110d8c44837736b8932c034091683e05863"},
+ {file = "pywin32-305-cp36-cp36m-win_amd64.whl", hash = "sha256:13362cc5aa93c2beaf489c9c9017c793722aeb56d3e5166dadd5ef82da021fe1"},
+ {file = "pywin32-305-cp37-cp37m-win32.whl", hash = "sha256:a55db448124d1c1484df22fa8bbcbc45c64da5e6eae74ab095b9ea62e6d00496"},
+ {file = "pywin32-305-cp37-cp37m-win_amd64.whl", hash = "sha256:109f98980bfb27e78f4df8a51a8198e10b0f347257d1e265bb1a32993d0c973d"},
+ {file = "pywin32-305-cp38-cp38-win32.whl", hash = "sha256:9dd98384da775afa009bc04863426cb30596fd78c6f8e4e2e5bbf4edf8029504"},
+ {file = "pywin32-305-cp38-cp38-win_amd64.whl", hash = "sha256:56d7a9c6e1a6835f521788f53b5af7912090674bb84ef5611663ee1595860fc7"},
+ {file = "pywin32-305-cp39-cp39-win32.whl", hash = "sha256:9d968c677ac4d5cbdaa62fd3014ab241718e619d8e36ef8e11fb930515a1e918"},
+ {file = "pywin32-305-cp39-cp39-win_amd64.whl", hash = "sha256:50768c6b7c3f0b38b7fb14dd4104da93ebced5f1a50dc0e834594bff6fbe1271"},
+]
+
+[[package]]
name = "requests"
version = "2.28.2"
description = "Python HTTP for Humans."
@@ -1149,6 +1195,23 @@ secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "p
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
+name = "websocket-client"
+version = "1.5.1"
+description = "WebSocket client for Python with low level API options"
+category = "main"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "websocket-client-1.5.1.tar.gz", hash = "sha256:3f09e6d8230892547132177f575a4e3e73cfdf06526e20cc02aa1c3b47184d40"},
+ {file = "websocket_client-1.5.1-py3-none-any.whl", hash = "sha256:cdf5877568b7e83aa7cf2244ab56a3213de587bbe0ce9d8b9600fc77b455d89e"},
+]
+
+[package.extras]
+docs = ["Sphinx (>=3.4)", "sphinx-rtd-theme (>=0.5)"]
+optional = ["python-socks", "wsaccel"]
+test = ["websockets"]
+
+[[package]]
name = "wrapt"
version = "1.14.1"
description = "Module for decorators, wrappers and monkey patching."
@@ -1241,4 +1304,4 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools"
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
-content-hash = "9e58aabf16fd54e3083364bca0198366e2130799e0788894b56796eaf8554a39"
+content-hash = "d524bec4d312a1d74020d921a33fd0b03ecdc93c87a161f71c6594c9985a2fc9"
diff --git a/pyproject.toml b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "jaypore_ci"
-version = "0.2.18"
+version = "0.2.19"
description = ""
authors = ["arjoonn sharma <arjoonn.94@gmail.com>"]
homepage = "https://www.jayporeci.in/"
@@ -12,6 +12,7 @@ requests = "^2.28.1"
click = "^8.1.3"
pendulum = "^2.1.2"
structlog = "^22.3.0"
+docker = "^6.0.1"
[tool.poetry.group.dev.dependencies]
pylint = "^2.15.7"
diff --git a/tests/conftest.py b/tests/conftest.py
@@ -4,6 +4,7 @@ import unittest
import pytest
import tests.subprocess_mock # pylint: disable=unused-import
+import tests.docker_mock # pylint: disable=unused-import
from tests.requests_mock import Mock
from jaypore_ci import jci, executors, remotes, reporters, repos
@@ -64,7 +65,7 @@ def idfn(x):
scope="function",
params=list(
jci.Pipeline.env_matrix(
- reporter=[reporters.Text, reporters.Mock, reporters.Markdown],
+ reporter=[reporters.Text, reporters.Markdown],
remote=[
remotes.Mock,
remotes.Email,
@@ -72,8 +73,8 @@ def idfn(x):
remotes.Gitea,
remotes.Github,
],
- repo=[repos.Mock, repos.Git],
- executor=[executors.Mock],
+ repo=[repos.Git],
+ executor=[executors.Docker],
)
),
ids=idfn,
@@ -85,16 +86,7 @@ def pipeline(request):
os.environ["JAYPORE_EMAIL_PASSWORD"] = "fake_email_password"
os.environ["JAYPORE_EMAIL_TO"] = "fake.to@mymailmail.com"
kwargs = {}
- if request.param["repo"] == repos.Mock:
- kwargs["repo"] = repos.Mock.from_env(
- files_changed=[],
- branch="test_branch",
- sha="fake_sha",
- remote="https://fake_remote.com/fake_owner/fake_repo.git",
- commit_message="fake_commit_message",
- )
- else:
- kwargs["repo"] = request.param["repo"].from_env()
+ kwargs["repo"] = request.param["repo"].from_env()
# --- remote
kwargs["remote"] = request.param["remote"].from_env(repo=kwargs["repo"])
if request.param["remote"] == remotes.Gitea and not Mock.gitea_added:
diff --git a/tests/docker_mock.py b/tests/docker_mock.py
@@ -0,0 +1,96 @@
+import random
+from collections import defaultdict
+
+import pendulum
+import docker
+
+
+def cid(short=False):
+ n_chars = 12 if short else 64
+ return "".join(random.sample("0123456789abcdef" * 10, n_chars))
+
+
+class Network:
+ def __init__(self, **kwargs):
+ self.__dict__.update(kwargs)
+
+ def remove(self):
+ pass
+
+
+class Networks:
+ nets = {}
+
+ def list(self, names):
+ return list(filter(None, [self.nets.get(name) for name in names]))
+
+ def create(self, **kwargs):
+ name = kwargs.get("name")
+ self.nets[name] = Network(**kwargs)
+ return name
+
+ def get(self, name):
+ return self.nets[name]
+
+
+class Container:
+ def __init__(self, **kwargs):
+ self.id = cid()
+ self.__dict__.update(kwargs)
+ self.FinishedAt = "0001-01-01T00:00:00Z"
+ self.ExitCode = 0
+
+ def logs(self):
+ return b""
+
+ def stop(self, **_):
+ self.FinishedAt = str(pendulum.now())
+ self.ExitCode = 0
+
+
+class Containers:
+ boxes = {}
+
+ def get(self, container_id):
+ return self.boxes[container_id]
+
+ def run(self, **kwargs):
+ kwargs["StartedAt"] = str(pendulum.now())
+ c = Container(**kwargs)
+ self.boxes[c.id] = c
+ return c
+
+
+class Docker:
+ networks = Networks()
+ containers = Containers()
+
+
+class APIClient:
+ max_running = {}
+ reported_running = defaultdict(int)
+
+ def inspect_container(self, container_id):
+ if container_id not in self.max_running:
+ self.max_running[container_id] = random.choice(range(3, 11))
+ self.reported_running[container_id] += 1
+ is_running = (
+ self.reported_running[container_id] <= self.max_running[container_id]
+ )
+ container = Containers.boxes[container_id]
+ return {
+ "State": {
+ "Running": is_running,
+ "ExitCode": container.ExitCode,
+ "StartedAt": container.StartedAt,
+ "FinishedAt": container.FinishedAt,
+ }
+ }
+
+
+def from_env():
+ return Docker()
+
+
+docker.from_env = from_env
+docker.APIClient = APIClient
diff --git a/tests/subprocess_mock.py b/tests/subprocess_mock.py
@@ -1,5 +1,11 @@
import random
import subprocess
+from typing import NamedTuple
+
+
+class ProcMock(NamedTuple):
+ returncode: int
+ stdout: str
def sha():
@@ -34,4 +40,41 @@ def check_output(cmd, **_):
return text.encode()
+networks = {}
+names = {}
+containers = {}
+
+
+def cid(short=False):
+ n_chars = 12 if short else 64
+ return random.sample("0123456789abcdef" * 10, n_chars)
+
+
+def run(cmd, **_):
+ code, text = 0, ""
+ if "docker network create" in cmd:
+ name = cmd.split()[-1]
+ networks[name] = True
+ elif "docker network ls" in cmd:
+ name = cmd.split("grep")[1]
+ if name in networks:
+ text = f"{cid(short=True)} {name} bridge local"
+ else:
+ code = 1
+ elif "docker network rm" in cmd:
+ name = text = cmd.split(" rm ")[1].split("|")[0].strip()
+ if name not in networks:
+ text = "No such net"
+ elif "docker stop -t 1" in cmd:
+ name = text = cmd.split()[-1]
+ if name not in containers and name not in names:
+ cmd = 1
+ text = f"Error response from daemon: No such container: {name}"
+ elif "docker run -d" in cmd:
+ name = cmd.split("--name")[1].strip().split()[0]
+ containers[name] = text = cid()
+ return ProcMock(returncode=code, stdout=text.encode())
+
+
subprocess.check_output = check_output
+subprocess.run = run