forked from pyupio/safety
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbinaries.py
123 lines (99 loc) · 3.69 KB
/
binaries.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
"""Github Action Build
This file is used to build and distribute the safety binary on Github actions.
Take a look at the corresponding main.yml as well.
"""
import os
import subprocess
import sys
from collections import OrderedDict
class environment:
WIN = "win"
LINUX = "linux"
MACOS = "macos"
def __init__(self):
os_mapping = {
"windows-latest": self.WIN,
"ubuntu-20.04": self.LINUX,
"macos-latest": self.MACOS
}
self.os = os_mapping[os.getenv("BINARY_OS")]
@property
def python(self):
for arch, python in self.PYTHON_BINARIES[self.os].items():
yield arch, python
WIN_BASE_PATH = "C:\\hostedtoolcache\\windows\\Python\\3.10.11"
PYTHON_BINARIES = {
WIN: {
64: f"{WIN_BASE_PATH}\\x64\\python.exe", # setup-python default
32: f"{WIN_BASE_PATH}\\x86\\python.exe"
},
# Order is important. If the 32 bit release gets built first,
# you'll run into permission problems due to docker clobbering
# up the current working directory.
LINUX: OrderedDict([
(64, "python3"),
]),
MACOS: {
64: "python3",
}
}
def run(self, command):
"""Runs the given command via subprocess.check_output.
Exits with -1 if the command wasn't successfull.
"""
try:
print(f"RUNNING: {command}")
print("-" * 80)
result = subprocess.run(command, shell=True, check=True,
stdout=subprocess.PIPE)
if result:
print(result.stdout.decode('utf-8').strip())
except subprocess.CalledProcessError as e:
print(f"ERROR calling '{command}'")
print("-" * 20)
print(e.output and e.output.decode('utf-8'))
sys.exit(-1)
def install(self):
"""
Install required dependencies
"""
for arch, python in self.python:
self.run(f"{python} -m pip install pyinstaller")
self.run(f"{python} -m pip install -r test_requirements.txt")
def dist(self):
"""Runs Pyinstaller producing a binary for every platform arch."""
for arch, python in self.python:
# Build the binary
build_path = os.path.join("dist", f"safety-{arch}")
self.run(f"{python} -m PyInstaller safety.spec"
f" --distpath {build_path}")
# There seems to be no way to tell pyinstaller the binary name.
# This leads to problems with artifact collector because
# every binary is named the same.
#
# Move them around so they can be picked up correctly
#
artifact_path = os.path.join(
os.getcwd(),
"dist",
f"safety-{self.os}-{'i686' if arch == 32 else 'x86_64'}"
)
binary_path = os.path.join(os.getcwd(), build_path, "safety")
if self.os == self.WIN:
self.run(f"move {binary_path}.exe {artifact_path}.exe")
else:
self.run(f"cp {binary_path} {artifact_path}")
def test(self):
"""
Runs tests for every available arch on the current platform.
"""
for arch, python in self.python:
self.run(f"{python} -m pytest --log-level=DEBUG")
if __name__ == "__main__":
if len(sys.argv) <= 1 or sys.argv[1] not in ['install', 'test', 'dist']:
print("usage: binaries.py [install|test|dist]")
sys.exit(-1)
env = environment()
# Runs the command in sys.argv[1] (install|test|dist)
getattr(env, sys.argv[1])()
sys.exit(0)