pipeforge 1.0.0__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.
- pipeforge/__init__.py +1201 -0
- pipeforge/__main__.py +208 -0
- pipeforge/_internal/__init__.py +0 -0
- pipeforge/_internal/core_loop.py +700 -0
- pipeforge/_internal/database.py +515 -0
- pipeforge/_internal/drawing.py +544 -0
- pipeforge/_internal/file_loader.py +654 -0
- pipeforge/_internal/inspector.py +555 -0
- pipeforge/_internal/params.py +148 -0
- pipeforge/_internal/pipeline.py +212 -0
- pipeforge/_internal/script.py +1004 -0
- pipeforge/_internal/utils.py +122 -0
- pipeforge/examples/hello_jenkins.toml +16 -0
- pipeforge/examples/hello_world.toml +67 -0
- pipeforge/examples/merge_pull_request.toml +240 -0
- pipeforge/examples/multi_pipeline.toml +93 -0
- pipeforge/examples/multi_pipeline_2.toml +54 -0
- pipeforge/examples/nightly.toml +19 -0
- pipeforge/examples/retries.toml +43 -0
- pipeforge/examples/scripts/hello_world__get_purpose_in_life.py +34 -0
- pipeforge/examples/scripts/hello_world__print_summary.py +27 -0
- pipeforge/examples/scripts/hello_world__repeat_purpose.py +33 -0
- pipeforge/examples/scripts/retry.py +25 -0
- pipeforge/examples/scripts/timeout.py +25 -0
- pipeforge/examples/timeout.toml +37 -0
- pipeforge-1.0.0.dist-info/METADATA +198 -0
- pipeforge-1.0.0.dist-info/RECORD +29 -0
- pipeforge-1.0.0.dist-info/WHEEL +4 -0
- pipeforge-1.0.0.dist-info/entry_points.txt +2 -0
pipeforge/__main__.py
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
#!/bin/env python
|
|
2
|
+
# vim: colorcolumn=101 textwidth=100
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
import mongoengine
|
|
7
|
+
import curses
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from ._internal import file_loader # Local module
|
|
11
|
+
from ._internal import inspector # Local module
|
|
12
|
+
from ._internal import pipeline # Local module
|
|
13
|
+
from ._internal import script # Local module
|
|
14
|
+
from ._internal import utils # Local module
|
|
15
|
+
|
|
16
|
+
except Exception:
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
from _internal import file_loader # Local module
|
|
20
|
+
from _internal import inspector # Local module
|
|
21
|
+
from _internal import pipeline # Local module
|
|
22
|
+
from _internal import script # Local module
|
|
23
|
+
from _internal import utils # Local module
|
|
24
|
+
|
|
25
|
+
except Exception:
|
|
26
|
+
from pipeforge._internal import file_loader # Local module
|
|
27
|
+
from pipeforge._internal import inspector # Local module
|
|
28
|
+
from pipeforge._internal import pipeline # Local module
|
|
29
|
+
from pipeforge._internal import script # Local module
|
|
30
|
+
from pipeforge._internal import utils # Local module
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
####################################################################################################
|
|
35
|
+
# Auxiliary functions
|
|
36
|
+
####################################################################################################
|
|
37
|
+
|
|
38
|
+
def print_help():
|
|
39
|
+
print("")
|
|
40
|
+
print("Usage:")
|
|
41
|
+
print("")
|
|
42
|
+
print("> Use case #1: Running a pipeline from a *.{json,toml} file")
|
|
43
|
+
print("")
|
|
44
|
+
print(f" {sys.argv[0]} run <database_url> <path_to_file> [<ScriptManagerClass>]")
|
|
45
|
+
print("")
|
|
46
|
+
print(" ...where:")
|
|
47
|
+
print("")
|
|
48
|
+
print(" * <database_url> is the URL of the supporting database that we will use to save/")
|
|
49
|
+
print(" query pipeline data. Example: mongodb://localhost:27017/pipelines")
|
|
50
|
+
print("")
|
|
51
|
+
print(" * <path_to_file> is a path to a JSON/TOML file defining the jobs that make")
|
|
52
|
+
print(" the pipeline.")
|
|
53
|
+
print("")
|
|
54
|
+
print(" * <ScriptManagerClass> is an optional parameter that specifies which backend")
|
|
55
|
+
print(" to use to run the scripts. If none is specified, 'DummyScriptManager' is used.")
|
|
56
|
+
print(" Other possible values are 'TestScriptManager', 'LocalScriptManager' and")
|
|
57
|
+
print(" 'JenkinsScriptManager'. For details about each of them, run this from a python")
|
|
58
|
+
print(" interpreter:")
|
|
59
|
+
print("")
|
|
60
|
+
print(" import pipeforge")
|
|
61
|
+
print(" help(pipeforge._internal.script)")
|
|
62
|
+
print("")
|
|
63
|
+
print(" There are a series of environment variables that affect this mode's behavior:")
|
|
64
|
+
print("")
|
|
65
|
+
print(" * PIPEFORGERUNNER_LOG_LEVEL : Can be 'NORMAL', 'DEBUG' or 'SHY'")
|
|
66
|
+
print(" * PIPEFORGERUNNER_HEARTBEAT_SECONDS : Time between each core loop iteration")
|
|
67
|
+
print("")
|
|
68
|
+
print("")
|
|
69
|
+
print("> Use case #2: Print an example of a *.{json,toml} file")
|
|
70
|
+
print("")
|
|
71
|
+
print(f" {sys.argv[0]} example")
|
|
72
|
+
print("")
|
|
73
|
+
print("")
|
|
74
|
+
print("> Use case #3: Check a *.{json,toml} file (make sure it contains no errors)")
|
|
75
|
+
print("")
|
|
76
|
+
print(f" {sys.argv[0]} check <path_to_file>")
|
|
77
|
+
print("")
|
|
78
|
+
print(" ...where:")
|
|
79
|
+
print("")
|
|
80
|
+
print(" * <path_to_file> is a path to the JSON/TOML file you want to check.")
|
|
81
|
+
print("")
|
|
82
|
+
print("")
|
|
83
|
+
print("> Use case #4: Interactive tool to inspect all pipelines in a database")
|
|
84
|
+
print("")
|
|
85
|
+
print(f" {sys.argv[0]} inspector <database_url>")
|
|
86
|
+
print("")
|
|
87
|
+
print(" ...where:")
|
|
88
|
+
print("")
|
|
89
|
+
print(" * <database_url> is the URL of the supporting database that we will use to save/")
|
|
90
|
+
print(" query pipeline data. Example: mongodb://localhost:27017/pipelines")
|
|
91
|
+
print("")
|
|
92
|
+
print("")
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
####################################################################################################
|
|
97
|
+
# main() Execution starts here.
|
|
98
|
+
####################################################################################################
|
|
99
|
+
|
|
100
|
+
if len(sys.argv) == 1 or sys.argv[1] not in ["run", "example", "check", "inspector"]:
|
|
101
|
+
print_help()
|
|
102
|
+
sys.exit(-1)
|
|
103
|
+
|
|
104
|
+
subcommand = sys.argv[1]
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
#~ RUN ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
108
|
+
|
|
109
|
+
if subcommand == "run":
|
|
110
|
+
|
|
111
|
+
if len(sys.argv) != 4 and len(sys.argv) != 5:
|
|
112
|
+
print_help()
|
|
113
|
+
sys.exit(-1)
|
|
114
|
+
|
|
115
|
+
database_url = sys.argv[2]
|
|
116
|
+
input_file = sys.argv[3]
|
|
117
|
+
|
|
118
|
+
if len(sys.argv) == 5:
|
|
119
|
+
script_manager = eval("script." + sys.argv[4])
|
|
120
|
+
else:
|
|
121
|
+
script_manager = script.DummyScriptManager # default class
|
|
122
|
+
|
|
123
|
+
if not os.path.exists(input_file):
|
|
124
|
+
print(f"File not found: {input_file}")
|
|
125
|
+
sys.exit(-1)
|
|
126
|
+
|
|
127
|
+
utils.log_configure(os.getenv("PIPEFORGERUNNER_LOG_LEVEL", "NORMAL"))
|
|
128
|
+
|
|
129
|
+
p = pipeline.Pipeline(database_url, input_file)
|
|
130
|
+
|
|
131
|
+
utils.log("DEBUG", "")
|
|
132
|
+
utils.log("DEBUG+NORMAL", f"Running pipeline with URI = {p.uri} using {script_manager.__name__}")
|
|
133
|
+
|
|
134
|
+
execution_results = p.run(
|
|
135
|
+
script_manager = script_manager(),
|
|
136
|
+
polling_period = int(os.getenv("PIPEFORGERUNNER_HEARTBEAT_SECONDS", "30")))
|
|
137
|
+
|
|
138
|
+
for i, (ret, db_pipeline_id) in enumerate(execution_results):
|
|
139
|
+
|
|
140
|
+
print("")
|
|
141
|
+
print("")
|
|
142
|
+
print(f"Pipeline #{i} result = {ret}")
|
|
143
|
+
print(f"(DB,pipeline) ID = {db_pipeline_id}")
|
|
144
|
+
print("")
|
|
145
|
+
|
|
146
|
+
#p.draw_timeline(mode="ascii:150:stdout:auto")
|
|
147
|
+
pipeline.Pipeline(db_pipeline_id).draw_timeline(mode="ascii:150:stdout:auto")
|
|
148
|
+
|
|
149
|
+
if ret == "SUCCESS": sys.exit(0)
|
|
150
|
+
else : sys.exit(-1)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
#~ EXAMPLE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
154
|
+
|
|
155
|
+
elif subcommand == "example":
|
|
156
|
+
example = os.path.join(os.path.dirname(os.path.realpath(__file__)),
|
|
157
|
+
"examples",
|
|
158
|
+
"merge_pull_request.toml")
|
|
159
|
+
|
|
160
|
+
print(open(example).read())
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
#~ CHECK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
164
|
+
|
|
165
|
+
elif subcommand == "check":
|
|
166
|
+
|
|
167
|
+
if len(sys.argv) != 3:
|
|
168
|
+
print_help()
|
|
169
|
+
sys.exit(-1)
|
|
170
|
+
|
|
171
|
+
utils.log_configure("NORMAL", include_timestamp=False)
|
|
172
|
+
|
|
173
|
+
try:
|
|
174
|
+
file_loader.FileLoader(sys.argv[2], validation_mode=True)
|
|
175
|
+
except Exception:
|
|
176
|
+
print("")
|
|
177
|
+
print("File contains errors")
|
|
178
|
+
|
|
179
|
+
#raise(e) # Uncomment this line for debugging purposes
|
|
180
|
+
sys.exit(-1)
|
|
181
|
+
|
|
182
|
+
print("")
|
|
183
|
+
print("File is OK")
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
#~ INSPECTOR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
187
|
+
|
|
188
|
+
elif subcommand == "inspector":
|
|
189
|
+
|
|
190
|
+
if len(sys.argv) != 3:
|
|
191
|
+
print_help()
|
|
192
|
+
sys.exit(-1)
|
|
193
|
+
|
|
194
|
+
database_url = sys.argv[2]
|
|
195
|
+
|
|
196
|
+
print("")
|
|
197
|
+
print("Connecting to database, please wait...")
|
|
198
|
+
|
|
199
|
+
mongoengine.connect(host=database_url)
|
|
200
|
+
|
|
201
|
+
try:
|
|
202
|
+
g = inspector.TUI(database_url)
|
|
203
|
+
curses.wrapper(g.loop)
|
|
204
|
+
|
|
205
|
+
except Exception as e:
|
|
206
|
+
if str(e) != "Quit":
|
|
207
|
+
raise e
|
|
208
|
+
|
|
File without changes
|