jolt 0.9.76__py3-none-any.whl → 0.9.429__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of jolt might be problematic. Click here for more details.
- jolt/__init__.py +88 -7
- jolt/__main__.py +9 -1
- jolt/bin/fstree-darwin-x86_64 +0 -0
- jolt/bin/fstree-linux-x86_64 +0 -0
- jolt/cache.py +839 -367
- jolt/chroot.py +156 -0
- jolt/cli.py +362 -143
- jolt/common_pb2.py +63 -0
- jolt/common_pb2_grpc.py +4 -0
- jolt/config.py +99 -42
- jolt/error.py +19 -4
- jolt/expires.py +2 -2
- jolt/filesystem.py +8 -6
- jolt/graph.py +705 -117
- jolt/hooks.py +63 -1
- jolt/influence.py +129 -6
- jolt/loader.py +369 -121
- jolt/log.py +225 -63
- jolt/manifest.py +28 -38
- jolt/options.py +35 -10
- jolt/pkgs/abseil.py +42 -0
- jolt/pkgs/asio.py +25 -0
- jolt/pkgs/autoconf.py +41 -0
- jolt/pkgs/automake.py +41 -0
- jolt/pkgs/b2.py +31 -0
- jolt/pkgs/boost.py +111 -0
- jolt/pkgs/boringssl.py +32 -0
- jolt/pkgs/busybox.py +39 -0
- jolt/pkgs/bzip2.py +43 -0
- jolt/pkgs/cares.py +29 -0
- jolt/pkgs/catch2.py +36 -0
- jolt/pkgs/cbindgen.py +17 -0
- jolt/pkgs/cista.py +19 -0
- jolt/pkgs/clang.py +44 -0
- jolt/pkgs/cli11.py +23 -0
- jolt/pkgs/cmake.py +48 -0
- jolt/pkgs/cpython.py +196 -0
- jolt/pkgs/crun.py +29 -0
- jolt/pkgs/curl.py +38 -0
- jolt/pkgs/dbus.py +18 -0
- jolt/pkgs/double_conversion.py +24 -0
- jolt/pkgs/fastfloat.py +21 -0
- jolt/pkgs/ffmpeg.py +28 -0
- jolt/pkgs/flatbuffers.py +29 -0
- jolt/pkgs/fmt.py +27 -0
- jolt/pkgs/fstree.py +20 -0
- jolt/pkgs/gflags.py +18 -0
- jolt/pkgs/glib.py +18 -0
- jolt/pkgs/glog.py +25 -0
- jolt/pkgs/glslang.py +21 -0
- jolt/pkgs/golang.py +16 -11
- jolt/pkgs/googlebenchmark.py +18 -0
- jolt/pkgs/googletest.py +46 -0
- jolt/pkgs/gperf.py +15 -0
- jolt/pkgs/grpc.py +73 -0
- jolt/pkgs/hdf5.py +19 -0
- jolt/pkgs/help2man.py +14 -0
- jolt/pkgs/inja.py +28 -0
- jolt/pkgs/jsoncpp.py +31 -0
- jolt/pkgs/libarchive.py +43 -0
- jolt/pkgs/libcap.py +44 -0
- jolt/pkgs/libdrm.py +44 -0
- jolt/pkgs/libedit.py +42 -0
- jolt/pkgs/libevent.py +31 -0
- jolt/pkgs/libexpat.py +27 -0
- jolt/pkgs/libfastjson.py +21 -0
- jolt/pkgs/libffi.py +16 -0
- jolt/pkgs/libglvnd.py +30 -0
- jolt/pkgs/libogg.py +28 -0
- jolt/pkgs/libpciaccess.py +18 -0
- jolt/pkgs/libseccomp.py +21 -0
- jolt/pkgs/libtirpc.py +24 -0
- jolt/pkgs/libtool.py +42 -0
- jolt/pkgs/libunwind.py +35 -0
- jolt/pkgs/libva.py +18 -0
- jolt/pkgs/libvorbis.py +33 -0
- jolt/pkgs/libxml2.py +35 -0
- jolt/pkgs/libxslt.py +17 -0
- jolt/pkgs/libyajl.py +16 -0
- jolt/pkgs/llvm.py +81 -0
- jolt/pkgs/lua.py +54 -0
- jolt/pkgs/lz4.py +26 -0
- jolt/pkgs/m4.py +14 -0
- jolt/pkgs/make.py +17 -0
- jolt/pkgs/mesa.py +81 -0
- jolt/pkgs/meson.py +17 -0
- jolt/pkgs/mstch.py +28 -0
- jolt/pkgs/mysql.py +60 -0
- jolt/pkgs/nasm.py +49 -0
- jolt/pkgs/ncurses.py +30 -0
- jolt/pkgs/ng_log.py +25 -0
- jolt/pkgs/ninja.py +45 -0
- jolt/pkgs/nlohmann_json.py +25 -0
- jolt/pkgs/nodejs.py +19 -11
- jolt/pkgs/opencv.py +24 -0
- jolt/pkgs/openjdk.py +26 -0
- jolt/pkgs/openssl.py +103 -0
- jolt/pkgs/paho.py +76 -0
- jolt/pkgs/patchelf.py +16 -0
- jolt/pkgs/perl.py +42 -0
- jolt/pkgs/pkgconfig.py +64 -0
- jolt/pkgs/poco.py +39 -0
- jolt/pkgs/protobuf.py +77 -0
- jolt/pkgs/pugixml.py +27 -0
- jolt/pkgs/python.py +19 -0
- jolt/pkgs/qt.py +35 -0
- jolt/pkgs/rapidjson.py +26 -0
- jolt/pkgs/rapidyaml.py +28 -0
- jolt/pkgs/re2.py +30 -0
- jolt/pkgs/re2c.py +17 -0
- jolt/pkgs/readline.py +15 -0
- jolt/pkgs/rust.py +41 -0
- jolt/pkgs/sdl.py +28 -0
- jolt/pkgs/simdjson.py +27 -0
- jolt/pkgs/soci.py +46 -0
- jolt/pkgs/spdlog.py +29 -0
- jolt/pkgs/spirv_llvm.py +21 -0
- jolt/pkgs/spirv_tools.py +24 -0
- jolt/pkgs/sqlite.py +83 -0
- jolt/pkgs/ssl.py +12 -0
- jolt/pkgs/texinfo.py +15 -0
- jolt/pkgs/tomlplusplus.py +22 -0
- jolt/pkgs/wayland.py +26 -0
- jolt/pkgs/x11.py +58 -0
- jolt/pkgs/xerces_c.py +20 -0
- jolt/pkgs/xorg.py +360 -0
- jolt/pkgs/xz.py +29 -0
- jolt/pkgs/yamlcpp.py +30 -0
- jolt/pkgs/zeromq.py +47 -0
- jolt/pkgs/zlib.py +69 -0
- jolt/pkgs/zstd.py +33 -0
- jolt/plugins/alias.py +3 -0
- jolt/plugins/allure.py +5 -2
- jolt/plugins/autotools.py +66 -0
- jolt/plugins/cache.py +133 -0
- jolt/plugins/cmake.py +74 -6
- jolt/plugins/conan.py +238 -0
- jolt/plugins/cxx.py +698 -0
- jolt/plugins/cxxinfo.py +7 -0
- jolt/plugins/dashboard.py +1 -1
- jolt/plugins/docker.py +91 -23
- jolt/plugins/email.py +5 -2
- jolt/plugins/email.xslt +144 -101
- jolt/plugins/environ.py +11 -0
- jolt/plugins/fetch.py +141 -0
- jolt/plugins/gdb.py +44 -21
- jolt/plugins/gerrit.py +1 -14
- jolt/plugins/git.py +316 -101
- jolt/plugins/googletest.py +522 -1
- jolt/plugins/http.py +36 -38
- jolt/plugins/libtool.py +63 -0
- jolt/plugins/linux.py +990 -0
- jolt/plugins/logstash.py +4 -4
- jolt/plugins/meson.py +61 -0
- jolt/plugins/ninja-compdb.py +107 -31
- jolt/plugins/ninja.py +929 -134
- jolt/plugins/paths.py +11 -1
- jolt/plugins/pkgconfig.py +219 -0
- jolt/plugins/podman.py +148 -91
- jolt/plugins/python.py +137 -0
- jolt/plugins/remote_execution/__init__.py +0 -0
- jolt/plugins/remote_execution/administration_pb2.py +46 -0
- jolt/plugins/remote_execution/administration_pb2_grpc.py +170 -0
- jolt/plugins/remote_execution/log_pb2.py +32 -0
- jolt/plugins/remote_execution/log_pb2_grpc.py +68 -0
- jolt/plugins/remote_execution/scheduler_pb2.py +41 -0
- jolt/plugins/remote_execution/scheduler_pb2_grpc.py +141 -0
- jolt/plugins/remote_execution/worker_pb2.py +38 -0
- jolt/plugins/remote_execution/worker_pb2_grpc.py +112 -0
- jolt/plugins/report.py +12 -2
- jolt/plugins/rust.py +25 -0
- jolt/plugins/scheduler.py +710 -0
- jolt/plugins/selfdeploy/setup.py +9 -4
- jolt/plugins/selfdeploy.py +138 -88
- jolt/plugins/strings.py +35 -22
- jolt/plugins/symlinks.py +26 -11
- jolt/plugins/telemetry.py +5 -2
- jolt/plugins/timeline.py +13 -3
- jolt/plugins/volume.py +46 -48
- jolt/scheduler.py +591 -191
- jolt/tasks.py +1783 -245
- jolt/templates/export.sh.template +12 -6
- jolt/templates/timeline.html.template +44 -47
- jolt/timer.py +22 -0
- jolt/tools.py +749 -302
- jolt/utils.py +245 -18
- jolt/version.py +1 -1
- jolt/version_utils.py +2 -2
- jolt/xmldom.py +12 -2
- {jolt-0.9.76.dist-info → jolt-0.9.429.dist-info}/METADATA +98 -38
- jolt-0.9.429.dist-info/RECORD +207 -0
- {jolt-0.9.76.dist-info → jolt-0.9.429.dist-info}/WHEEL +1 -1
- jolt/plugins/amqp.py +0 -834
- jolt/plugins/debian.py +0 -338
- jolt/plugins/ftp.py +0 -181
- jolt/plugins/ninja-cache.py +0 -64
- jolt/plugins/ninjacli.py +0 -271
- jolt/plugins/repo.py +0 -253
- jolt-0.9.76.dist-info/RECORD +0 -79
- {jolt-0.9.76.dist-info → jolt-0.9.429.dist-info}/entry_points.txt +0 -0
- {jolt-0.9.76.dist-info → jolt-0.9.429.dist-info}/top_level.txt +0 -0
jolt/plugins/selfdeploy/setup.py
CHANGED
|
@@ -35,6 +35,7 @@ setup(
|
|
|
35
35
|
name=name,
|
|
36
36
|
cmdclass={"build_py": BuildCommand},
|
|
37
37
|
version=__version__,
|
|
38
|
+
python_requires=">=3.8",
|
|
38
39
|
description="A task executor",
|
|
39
40
|
long_description=long_description,
|
|
40
41
|
url="https://github.com/srand/jolt",
|
|
@@ -73,28 +74,32 @@ setup(
|
|
|
73
74
|
"click>=8.1",
|
|
74
75
|
"colorama",
|
|
75
76
|
"fasteners",
|
|
77
|
+
"grpcio>=1.62.2",
|
|
76
78
|
"jinja2",
|
|
77
79
|
"keyring",
|
|
78
80
|
"keyrings.alt",
|
|
81
|
+
"importlib_metadata",
|
|
79
82
|
"lxml",
|
|
80
83
|
"multi_key_dict",
|
|
81
|
-
"ninja
|
|
84
|
+
"ninja",
|
|
85
|
+
"protobuf",
|
|
82
86
|
"psutil",
|
|
83
87
|
"pygit2",
|
|
88
|
+
"py7zr",
|
|
84
89
|
"requests",
|
|
90
|
+
"zstandard",
|
|
85
91
|
"tqdm",
|
|
86
92
|
],
|
|
87
93
|
dependency_links=[],
|
|
88
94
|
extras_require={
|
|
89
95
|
"allure": ["allure-python-commons"],
|
|
90
|
-
"
|
|
91
|
-
"conan": ["conan"],
|
|
96
|
+
"conan": ["conan>=2.0"],
|
|
92
97
|
"dev": ["check-manifest"],
|
|
93
98
|
"doc": ["sphinx-click", "sphinx-rtd-theme"],
|
|
94
99
|
"test": ["coverage"],
|
|
95
100
|
},
|
|
96
101
|
package_data={
|
|
97
|
-
"jolt": ["**/*.sh", "**/*.xslt", "**/*.template"],
|
|
102
|
+
"jolt": ["**/*.sh", "**/*.xslt", "**/*.template", "**/fstree-*-x86_64"],
|
|
98
103
|
},
|
|
99
104
|
entry_points={
|
|
100
105
|
"console_scripts": [
|
jolt/plugins/selfdeploy.py
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
from jolt.error import raise_error_if
|
|
5
|
-
from jolt.manifest import JoltManifest
|
|
6
|
-
from jolt.scheduler import JoltEnvironment
|
|
7
|
-
from jolt.scheduler import LocalExecutor
|
|
8
|
-
from jolt.scheduler import LocalExecutorFactory
|
|
9
|
-
from jolt.scheduler import NetworkExecutorExtension
|
|
10
|
-
from jolt.scheduler import NetworkExecutorExtensionFactory
|
|
11
|
-
from jolt.loader import JoltLoader
|
|
1
|
+
import importlib_metadata
|
|
2
|
+
import os
|
|
3
|
+
|
|
12
4
|
from jolt import config
|
|
13
5
|
from jolt import filesystem as fs
|
|
14
6
|
from jolt import influence
|
|
15
7
|
from jolt import log
|
|
8
|
+
from jolt import common_pb2 as common_pb
|
|
16
9
|
from jolt import utils
|
|
10
|
+
from jolt import version
|
|
11
|
+
from jolt.cache import ArtifactCache
|
|
12
|
+
from jolt.error import raise_error_if
|
|
13
|
+
from jolt.graph import GraphBuilder
|
|
14
|
+
from jolt.loader import JoltLoader
|
|
15
|
+
from jolt.scheduler import JoltEnvironment
|
|
16
|
+
from jolt.scheduler import LocalExecutor
|
|
17
|
+
from jolt.scheduler import LocalExecutorFactory
|
|
18
|
+
from jolt.tasks import Task, TaskRegistry
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
log.verbose("[SelfDeploy] Loaded")
|
|
@@ -27,6 +29,8 @@ _path = fs.path.dirname(_path)
|
|
|
27
29
|
@influence.files(fs.path.join(_path, "**", "*.sh"))
|
|
28
30
|
@influence.files(fs.path.join(_path, "**", "*.xslt"))
|
|
29
31
|
@influence.files(fs.path.join(_path, "**", "*.template"))
|
|
32
|
+
@influence.attribute("dependencies")
|
|
33
|
+
@influence.attribute("extra_dependencies")
|
|
30
34
|
class Jolt(Task):
|
|
31
35
|
name = "jolt"
|
|
32
36
|
|
|
@@ -52,11 +56,7 @@ class Jolt(Task):
|
|
|
52
56
|
|
|
53
57
|
@property
|
|
54
58
|
def extra_dependencies(self):
|
|
55
|
-
|
|
56
|
-
return req.split() if req else []
|
|
57
|
-
|
|
58
|
-
def info(self, fmt, *args, **kwargs):
|
|
59
|
-
log.verbose(fmt, *args, **kwargs)
|
|
59
|
+
return get_extra_dependencies()
|
|
60
60
|
|
|
61
61
|
@property
|
|
62
62
|
def dependencies(self):
|
|
@@ -71,52 +71,14 @@ class Jolt(Task):
|
|
|
71
71
|
no version pinning will be performed. Instead, workers will install
|
|
72
72
|
Jolt with its default loose version requirements.
|
|
73
73
|
"""
|
|
74
|
-
|
|
75
|
-
try:
|
|
76
|
-
from pip._internal.metadata import get_environment
|
|
77
|
-
except ImportError:
|
|
78
|
-
from pip._internal.utils import misc
|
|
79
|
-
return {
|
|
80
|
-
dist.project_name.lower(): dist
|
|
81
|
-
for dist in misc.get_installed_distributions()
|
|
82
|
-
}
|
|
83
|
-
else:
|
|
84
|
-
dists = get_environment(None).iter_installed_distributions()
|
|
85
|
-
return {dist._dist.project_name.lower(): dist._dist for dist in dists}
|
|
86
|
-
|
|
87
|
-
dists = get_installed_distributions()
|
|
88
|
-
reqs = ["jolt"] + [dep.lower() for dep in self.extra_dependencies]
|
|
89
|
-
pkgs = {}
|
|
90
|
-
|
|
91
|
-
while reqs:
|
|
92
|
-
req = reqs.pop()
|
|
93
|
-
|
|
94
|
-
dist = dists.get(req)
|
|
95
|
-
if dist is None:
|
|
96
|
-
self.info("[SelfDeploy] Dependency not found: {}", req)
|
|
97
|
-
req = req.partition("=")[0].partition("<")[0].partition(">")[0]
|
|
98
|
-
pkgs[req] = req
|
|
99
|
-
continue
|
|
100
|
-
|
|
101
|
-
for dep in dist.requires():
|
|
102
|
-
name = dep.project_name.lower()
|
|
103
|
-
if name not in pkgs:
|
|
104
|
-
reqs.append(name)
|
|
105
|
-
|
|
106
|
-
pkgs[req] = f"{dist.project_name}=={dist.version}"
|
|
107
|
-
|
|
108
|
-
del pkgs["jolt"]
|
|
109
|
-
return pkgs.values()
|
|
74
|
+
return get_dependencies(["jolt"] + self.extra_dependencies)
|
|
110
75
|
|
|
111
76
|
def publish(self, artifact, tools):
|
|
112
77
|
with tools.cwd(tools.builddir()):
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
artifact.collect("requirements.txt")
|
|
118
|
-
except Exception:
|
|
119
|
-
log.exception()
|
|
78
|
+
pinned_reqs = self.dependencies
|
|
79
|
+
if pinned_reqs:
|
|
80
|
+
tools.write_file("requirements.txt", "\n".join(pinned_reqs))
|
|
81
|
+
artifact.collect("requirements.txt")
|
|
120
82
|
with tools.cwd(_path):
|
|
121
83
|
artifact.collect('README.rst')
|
|
122
84
|
artifact.collect('setup.py')
|
|
@@ -126,6 +88,7 @@ class Jolt(Task):
|
|
|
126
88
|
artifact.collect('jolt/*/*/*.py')
|
|
127
89
|
artifact.collect('jolt/*/*.xslt')
|
|
128
90
|
artifact.collect('jolt/*/*.template')
|
|
91
|
+
artifact.collect('jolt/bin')
|
|
129
92
|
artifact.collect('jolt/plugins/selfdeploy/README.rst', flatten=True)
|
|
130
93
|
artifact.collect('jolt/plugins/selfdeploy/setup.py', flatten=True)
|
|
131
94
|
for e in self.extra_files:
|
|
@@ -133,32 +96,119 @@ class Jolt(Task):
|
|
|
133
96
|
artifact.collect(fs.path.basename(e))
|
|
134
97
|
|
|
135
98
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
"
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
99
|
+
@utils.cached.method
|
|
100
|
+
def get_dependencies(packages=None):
|
|
101
|
+
reqs = packages or ["jolt"]
|
|
102
|
+
pkgs = {}
|
|
103
|
+
skip = set()
|
|
104
|
+
|
|
105
|
+
while reqs:
|
|
106
|
+
req = reqs.pop()
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
dist = importlib_metadata.distribution(req)
|
|
110
|
+
except (ImportError, importlib_metadata.PackageNotFoundError):
|
|
111
|
+
dist = None
|
|
112
|
+
except Exception:
|
|
113
|
+
dist = None
|
|
114
|
+
if dist is None:
|
|
115
|
+
skip.add(req)
|
|
116
|
+
continue
|
|
117
|
+
|
|
118
|
+
for dep in dist.requires or []:
|
|
119
|
+
dep = dep.split(" ", 1)[0].strip()
|
|
120
|
+
dep = dep.split("[", 1)[0].strip()
|
|
121
|
+
dep = dep.split(";", 1)[0].strip()
|
|
122
|
+
dep = dep.split(">", 1)[0].strip()
|
|
123
|
+
dep = dep.split("=", 1)[0].strip()
|
|
124
|
+
dep = dep.split("<", 1)[0].strip()
|
|
125
|
+
dep = dep.split("!", 1)[0].strip()
|
|
126
|
+
if dep not in pkgs and dep not in skip:
|
|
127
|
+
reqs.append(dep)
|
|
128
|
+
|
|
129
|
+
pkgs[req] = f"{dist.name}=={dist.version}"
|
|
130
|
+
|
|
131
|
+
try:
|
|
132
|
+
del pkgs["jolt"]
|
|
133
|
+
except KeyError:
|
|
134
|
+
pass
|
|
135
|
+
|
|
136
|
+
return list(sorted(pkgs.values()))
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@utils.cached.method
|
|
140
|
+
def get_extra_dependencies():
|
|
141
|
+
req = config.get("selfdeploy", "requires", "")
|
|
142
|
+
return req.split() if req else []
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@utils.cached.method
|
|
146
|
+
def publish_artifact():
|
|
147
|
+
registry = TaskRegistry()
|
|
148
|
+
registry.add_task_class(Jolt)
|
|
149
|
+
acache = ArtifactCache.get()
|
|
150
|
+
env = JoltEnvironment(cache=acache, queue=None)
|
|
151
|
+
gb = GraphBuilder(registry, acache)
|
|
152
|
+
dag = gb.build(["jolt"])
|
|
153
|
+
task = dag.select(lambda graph, task: True)
|
|
154
|
+
assert len(task) == 1, "Too many selfdeploy tasks found"
|
|
155
|
+
task = task[0]
|
|
156
|
+
if not task.is_available_remotely(cache=False):
|
|
157
|
+
factory = LocalExecutorFactory()
|
|
158
|
+
executor = LocalExecutor(factory, task, force_upload=True)
|
|
159
|
+
executor.run(env)
|
|
160
|
+
jolt_url = acache.location(task.artifacts[0])
|
|
161
|
+
raise_error_if(not jolt_url, "Failed to deploy jolt to a remote cache")
|
|
162
|
+
cacheUrl = config.get("http", "uri", config.get("cache", "uri", "") + "/files")
|
|
163
|
+
substituteUrl = config.get("selfdeploy", "baseUri")
|
|
164
|
+
if cacheUrl and substituteUrl:
|
|
165
|
+
return task.identity, jolt_url.replace(cacheUrl, substituteUrl)
|
|
166
|
+
return task.identity, jolt_url
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def get_floating_version():
|
|
170
|
+
identity, url = publish_artifact()
|
|
171
|
+
return common_pb.Client(
|
|
172
|
+
identity=identity,
|
|
173
|
+
url=url,
|
|
174
|
+
version=version.__version__,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def get_pinned_version():
|
|
179
|
+
return common_pb.Client(
|
|
180
|
+
requirements=get_extra_dependencies(),
|
|
181
|
+
version=version.__version__,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def get_nix_version():
|
|
186
|
+
return common_pb.Client(
|
|
187
|
+
requirements=get_extra_dependencies(),
|
|
188
|
+
version=version.__version__,
|
|
189
|
+
nix=True,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def get_client():
|
|
194
|
+
# Floating version is a special case where we want to deploy the Jolt
|
|
195
|
+
# source code to a remote cache and use that URL as the client URL
|
|
196
|
+
# for workers.
|
|
197
|
+
floating = config.getboolean("selfdeploy", "floating", False)
|
|
198
|
+
if floating:
|
|
199
|
+
return get_floating_version()
|
|
200
|
+
|
|
201
|
+
# If Nix has been explicitly disabled, we want to pin versions.
|
|
202
|
+
if not config.getboolean("selfdeploy", "nix", True):
|
|
203
|
+
return get_pinned_version()
|
|
204
|
+
|
|
205
|
+
# If Nix has been explicitly enabled, we want to use the Nix shell.
|
|
206
|
+
if config.getboolean("selfdeploy", "nix", False):
|
|
207
|
+
return get_nix_version()
|
|
208
|
+
|
|
209
|
+
# If we are in a Nix shell, we want to use the Nix shell.
|
|
210
|
+
if os.environ.get("IN_NIX_SHELL"):
|
|
211
|
+
return get_nix_version()
|
|
212
|
+
|
|
213
|
+
# Default to pinned version
|
|
214
|
+
return get_pinned_version()
|
jolt/plugins/strings.py
CHANGED
|
@@ -1,31 +1,50 @@
|
|
|
1
|
-
from jolt.cache import ArtifactAttributeSet
|
|
2
1
|
from jolt.cache import ArtifactAttributeSetProvider
|
|
3
|
-
from jolt.cache import ArtifactStringAttribute
|
|
4
2
|
|
|
5
3
|
|
|
6
|
-
class
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
self._old_value = None
|
|
4
|
+
class StringVariableSet(object):
|
|
5
|
+
"""
|
|
6
|
+
A set of string variables for an artifact.
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
pass
|
|
8
|
+
Example:
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
pass
|
|
10
|
+
.. code-block:: python
|
|
16
11
|
|
|
12
|
+
artifact.strings.foo = "bar"
|
|
13
|
+
print(artifact.strings.foo)
|
|
14
|
+
|
|
15
|
+
"""
|
|
17
16
|
|
|
18
|
-
class StringVariableSet(ArtifactAttributeSet):
|
|
19
17
|
def __init__(self, artifact):
|
|
20
|
-
super(StringVariableSet, self).
|
|
21
|
-
super(
|
|
18
|
+
super(StringVariableSet, self).__setattr__("_attributes", {})
|
|
19
|
+
super(StringVariableSet, self).__setattr__("_artifact", artifact)
|
|
20
|
+
|
|
21
|
+
def _get_attributes(self):
|
|
22
|
+
return self._attributes
|
|
23
|
+
|
|
24
|
+
def __getattr__(self, name):
|
|
25
|
+
attributes = self._get_attributes()
|
|
26
|
+
return attributes.get(name, None)
|
|
27
|
+
|
|
28
|
+
def __setattr__(self, name, value):
|
|
29
|
+
if not isinstance(value, str):
|
|
30
|
+
raise ValueError(f"Value assigned to artifact.strings.{name} must be a string, got {type(value)}")
|
|
31
|
+
attributes = self._get_attributes()
|
|
32
|
+
attributes[name] = self._artifact.tools.expand(value)
|
|
33
|
+
return value
|
|
22
34
|
|
|
23
|
-
def
|
|
24
|
-
return
|
|
35
|
+
def __dict__(self):
|
|
36
|
+
return {key: str(value) for key, value in self.items()}
|
|
37
|
+
|
|
38
|
+
def items(self):
|
|
39
|
+
return self._get_attributes().items()
|
|
25
40
|
|
|
26
41
|
|
|
27
42
|
@ArtifactAttributeSetProvider.Register
|
|
28
43
|
class StringVariableSetProvider(ArtifactAttributeSetProvider):
|
|
44
|
+
"""
|
|
45
|
+
A provider of string variable sets.
|
|
46
|
+
"""
|
|
47
|
+
|
|
29
48
|
def create(self, artifact):
|
|
30
49
|
setattr(artifact, "strings", StringVariableSet(artifact))
|
|
31
50
|
|
|
@@ -34,7 +53,7 @@ class StringVariableSetProvider(ArtifactAttributeSetProvider):
|
|
|
34
53
|
return
|
|
35
54
|
|
|
36
55
|
for key, value in content["strings"].items():
|
|
37
|
-
|
|
56
|
+
setattr(artifact.strings, key, value)
|
|
38
57
|
|
|
39
58
|
def format(self, artifact, content):
|
|
40
59
|
if "strings" not in content:
|
|
@@ -42,9 +61,3 @@ class StringVariableSetProvider(ArtifactAttributeSetProvider):
|
|
|
42
61
|
|
|
43
62
|
for key, value in artifact.strings.items():
|
|
44
63
|
content["strings"][key] = str(value)
|
|
45
|
-
|
|
46
|
-
def apply(self, task, artifact):
|
|
47
|
-
artifact.strings.apply(task, artifact)
|
|
48
|
-
|
|
49
|
-
def unapply(self, task, artifact):
|
|
50
|
-
artifact.strings.unapply(task, artifact)
|
jolt/plugins/symlinks.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
from jolt import cache
|
|
3
2
|
from jolt import config
|
|
4
3
|
from jolt import filesystem as fs
|
|
5
4
|
from jolt import loader
|
|
@@ -19,20 +18,36 @@ class SymlinkTaskHooks(TaskHook):
|
|
|
19
18
|
self._path = config.get("symlinks", "path", "artifacts")
|
|
20
19
|
raise_error_if(not self._path, "symlinks.path not configured")
|
|
21
20
|
|
|
21
|
+
@property
|
|
22
|
+
def rootpath(self):
|
|
23
|
+
return fs.path.normpath(
|
|
24
|
+
fs.path.join(
|
|
25
|
+
fs.path.dirname(loader.JoltLoader.get().build_path),
|
|
26
|
+
self._path
|
|
27
|
+
)
|
|
28
|
+
)
|
|
29
|
+
|
|
22
30
|
def task_finished(self, task):
|
|
23
31
|
if not task.has_artifact():
|
|
24
32
|
return
|
|
25
33
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
for artifact in task.artifacts:
|
|
35
|
+
srcpath = artifact.final_path
|
|
36
|
+
if artifact.name == "main":
|
|
37
|
+
destpath = fs.path.join(
|
|
38
|
+
self.rootpath,
|
|
39
|
+
utils.canonical(task.short_qualified_name),
|
|
40
|
+
)
|
|
41
|
+
else:
|
|
42
|
+
destpath = fs.path.join(
|
|
43
|
+
self.rootpath,
|
|
44
|
+
artifact.name + "@" + utils.canonical(task.short_qualified_name),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
if fs.path.exists(srcpath):
|
|
48
|
+
fs.unlink(destpath, ignore_errors=True)
|
|
49
|
+
fs.makedirs(fs.path.dirname(destpath))
|
|
50
|
+
fs.symlink(srcpath, destpath)
|
|
36
51
|
|
|
37
52
|
def task_pruned(self, task):
|
|
38
53
|
self.task_finished(task)
|
jolt/plugins/telemetry.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from socket import gethostname
|
|
2
1
|
from requests.exceptions import RequestException
|
|
3
2
|
from requests.api import post
|
|
4
3
|
|
|
@@ -38,9 +37,10 @@ class TelemetryHooks(TaskHook):
|
|
|
38
37
|
"name": task.short_qualified_name,
|
|
39
38
|
"identity": task.identity,
|
|
40
39
|
"instance": task.task._instance.value,
|
|
41
|
-
"hostname":
|
|
40
|
+
"hostname": utils.hostname(),
|
|
42
41
|
"role": "client" if client else "worker",
|
|
43
42
|
"event": event,
|
|
43
|
+
"routing_key": getattr(task.task, "routing_key", "default")
|
|
44
44
|
}
|
|
45
45
|
if hasattr(task, "logstash"):
|
|
46
46
|
data["log"] = task.logstash
|
|
@@ -74,6 +74,9 @@ class TelemetryHooks(TaskHook):
|
|
|
74
74
|
if self._network and self._failed:
|
|
75
75
|
self.post(task, "failed", client=True)
|
|
76
76
|
|
|
77
|
+
def task_unstable(self, task):
|
|
78
|
+
self.task_failed(task)
|
|
79
|
+
|
|
77
80
|
def task_finished(self, task):
|
|
78
81
|
if not self._finished:
|
|
79
82
|
return
|
jolt/plugins/timeline.py
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
import os
|
|
3
3
|
|
|
4
|
+
from jolt import log
|
|
5
|
+
from jolt import tools
|
|
4
6
|
from jolt import utils
|
|
5
7
|
from jolt.hooks import TaskHook, TaskHookFactory
|
|
6
|
-
from jolt
|
|
8
|
+
from jolt import config
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
NAME_LOG = "Timeline"
|
|
7
12
|
|
|
8
13
|
|
|
9
14
|
class TimelineHooks(TaskHook):
|
|
10
15
|
def __init__(self):
|
|
16
|
+
self.path = os.path.join(
|
|
17
|
+
config.get_workdir(),
|
|
18
|
+
config.get("timeline", "path", "timeline.html")
|
|
19
|
+
)
|
|
11
20
|
self.tasks = []
|
|
12
21
|
self.task_ids = {}
|
|
22
|
+
self.tools = tools.Tools()
|
|
13
23
|
|
|
14
24
|
def started(self, task):
|
|
15
25
|
task._timeline_started = datetime.now().isoformat()
|
|
@@ -27,8 +37,7 @@ class TimelineHooks(TaskHook):
|
|
|
27
37
|
enumerate=enumerate,
|
|
28
38
|
tasks=self.tasks)
|
|
29
39
|
|
|
30
|
-
|
|
31
|
-
f.write(timeline)
|
|
40
|
+
self.tools.write_file(self.path, timeline, expand=False)
|
|
32
41
|
|
|
33
42
|
def deps(self, task):
|
|
34
43
|
ids = []
|
|
@@ -59,4 +68,5 @@ class TimelineHooks(TaskHook):
|
|
|
59
68
|
@TaskHookFactory.register
|
|
60
69
|
class TimelineFactory(TaskHookFactory):
|
|
61
70
|
def create(self, env):
|
|
71
|
+
log.verbose(NAME_LOG + " Loaded")
|
|
62
72
|
return TimelineHooks()
|
jolt/plugins/volume.py
CHANGED
|
@@ -28,78 +28,76 @@ class DiskVolume(cache.StorageProvider):
|
|
|
28
28
|
self._upload = config.getboolean(NAME, "upload", True)
|
|
29
29
|
self._download = config.getboolean(NAME, "download", True)
|
|
30
30
|
|
|
31
|
-
def _get_path(self,
|
|
32
|
-
return
|
|
31
|
+
def _get_path(self, artifact):
|
|
32
|
+
return artifact.tools.expand(
|
|
33
|
+
"{path}/{name}/{file}",
|
|
33
34
|
path=self._path,
|
|
34
|
-
name=
|
|
35
|
+
name=artifact.task.name,
|
|
35
36
|
file=fs.path.basename(artifact.get_archive_path()))
|
|
36
37
|
|
|
37
|
-
def _get_temp(self,
|
|
38
|
-
return
|
|
38
|
+
def _get_temp(self, artifact):
|
|
39
|
+
return artifact.tools.expand(
|
|
40
|
+
"{path}/{name}/{file}",
|
|
39
41
|
path=self._path,
|
|
40
|
-
name=node.name,
|
|
41
42
|
file=uuid.uuid4())
|
|
42
43
|
|
|
43
44
|
@utils.retried.on_exception(StaleFileHandleError)
|
|
44
|
-
def download(self,
|
|
45
|
+
def download(self, artifact, force=False):
|
|
45
46
|
if not self._download and not force:
|
|
46
47
|
return False
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
else:
|
|
59
|
-
log.exception()
|
|
60
|
-
except Exception:
|
|
49
|
+
path = self._get_path(artifact)
|
|
50
|
+
try:
|
|
51
|
+
log.verbose("[VOLUME] Copying {}", path)
|
|
52
|
+
fs.copy(path, artifact.get_archive_path())
|
|
53
|
+
return True
|
|
54
|
+
except OSError as e:
|
|
55
|
+
if e.errno == errno.ESTALE:
|
|
56
|
+
log.verbose("[VOLUME] got stale file handle, retrying...")
|
|
57
|
+
raise StaleFileHandleError(e)
|
|
58
|
+
else:
|
|
61
59
|
log.exception()
|
|
60
|
+
except Exception:
|
|
61
|
+
log.exception()
|
|
62
62
|
|
|
63
63
|
return False
|
|
64
64
|
|
|
65
65
|
def download_enabled(self):
|
|
66
66
|
return self._download
|
|
67
67
|
|
|
68
|
-
def upload(self,
|
|
68
|
+
def upload(self, artifact, force=False):
|
|
69
69
|
if not self._upload and not force:
|
|
70
70
|
return True
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
71
|
+
path = self._get_path(artifact)
|
|
72
|
+
temp = self._get_temp(artifact)
|
|
73
|
+
try:
|
|
74
|
+
log.verbose("[VOLUME] Copying {}", path)
|
|
75
|
+
fs.copy(artifact.get_archive_path(), temp)
|
|
76
|
+
# To avoid race-condition, make sure that the artifact still is
|
|
77
|
+
# missing before moving it into place.
|
|
78
|
+
if not fs.exists(path):
|
|
79
|
+
fs.rename(temp, path)
|
|
80
|
+
else:
|
|
81
|
+
fs.unlink(temp)
|
|
82
|
+
return True
|
|
83
|
+
except OSError as e:
|
|
84
|
+
if e.errno != errno.EEXIST:
|
|
85
|
+
log.verbose("[VOLUME] Failed to copy artifact, errno={}", os.strerror(e.errno))
|
|
86
|
+
return e.errno == errno.EEXIST
|
|
87
|
+
except Exception:
|
|
88
|
+
log.exception()
|
|
89
|
+
finally:
|
|
90
|
+
fs.unlink(temp, ignore_errors=True)
|
|
91
91
|
return False
|
|
92
92
|
|
|
93
93
|
def upload_enabled(self):
|
|
94
94
|
return self._upload
|
|
95
95
|
|
|
96
|
-
def location(self,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
return avail
|
|
102
|
-
return False
|
|
96
|
+
def location(self, artifact):
|
|
97
|
+
path = self._get_path(artifact)
|
|
98
|
+
avail = fs.path.exists(path)
|
|
99
|
+
log.debug("[VOLUME] {} is{} present", path, "" if avail else " not")
|
|
100
|
+
return avail
|
|
103
101
|
|
|
104
102
|
|
|
105
103
|
@cache.RegisterStorage
|