Skip to content

Commit 4caf0b9

Browse files
Enhanced make_package.py to automate the process more
1 parent bb87d2f commit 4caf0b9

405 files changed

Lines changed: 121555 additions & 43 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

tools/make_package.py

Lines changed: 171 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,49 +14,179 @@
1414
# limitations under the License.
1515

1616
import os
17+
import sys
1718
import pathlib
1819
import jinja2
1920
import platform
2021
import subprocess
22+
import getpass
23+
import argparse
2124

22-
# Functions
23-
# Custom filter for Jinja2 to determine the directory of a given file path
24-
def dirname(path):
25-
return os.path.dirname(path)
26-
27-
# Set filepath and file variables
28-
root_dir = pathlib.Path(__file__).absolute().parent.parent
29-
pkg_dir = root_dir.joinpath("pfSense-pkg-API")
30-
template_dir = root_dir.joinpath("tools").joinpath("templates")
31-
files_dir = pkg_dir.joinpath("files")
32-
file_paths = {"dir": [], "file": []}
33-
excluded_files = ["pkg-deinstall.in", "pkg-install.in", "etc", "usr"]
34-
35-
# Set Jijna2 environment and variables
36-
j2_env = jinja2.Environment(loader=jinja2.FileSystemLoader(searchpath=str(template_dir)))
37-
j2_env.filters["dirname"] = dirname
38-
plist_template = j2_env.get_template("pkg-plist.j2")
39-
makefile_template = j2_env.get_template("Makefile.j2")
40-
41-
# Loop through each of our files and directories and store them for Jinja2 to render
42-
for root, dirs, files in os.walk(files_dir, topdown=True):
43-
root = pathlib.Path(str(root).replace(str(files_dir), ""))
44-
for dir in dirs:
45-
if dir not in excluded_files:
46-
file_paths["dir"].append(str(root.joinpath(dir)))
47-
for file in files:
48-
if file not in excluded_files:
49-
file_paths["file"].append(str(root.joinpath(file)))
50-
51-
# Generate pkg-plist file
52-
with open(pkg_dir.joinpath("pkg-plist"), "w") as pw:
53-
pw.write(plist_template.render(files=file_paths))
54-
# Generate Makefile file
55-
with open(pkg_dir.joinpath("Makefile"), "w") as mw:
56-
mw.write(makefile_template.render(files=file_paths).replace(" ", "\t"))
57-
58-
# If we are running on FreeBSD, make package. Otherwise display warning that package was not compiled
59-
if platform.system() == "FreeBSD":
60-
s = subprocess.call(["/usr/bin/make", "package", "-C", pkg_dir, "DISABLE_VULNERABILITIES=yes"])
61-
else:
62-
print("WARNING: System is not FreeBSD. Generated Makefile and pkg-plist but did not attempt to make package.")
25+
class MakePackage:
26+
def __init__(self):
27+
self.__start_argparse__()
28+
self.port_version = self.args.tag.split(".")[2]
29+
self.port_revision = ".".join(self.args.tag.split(".")[0:2])
30+
31+
# Run tasks for build mode
32+
if self.args.build:
33+
self.build_on_remote_host()
34+
else:
35+
self.generate_makefile()
36+
37+
# Custom filter for Jinja2 to determine the directory of a given file path
38+
def dirname(self, path):
39+
return os.path.dirname(path)
40+
41+
def generate_makefile(self):
42+
# Set filepath and file variables
43+
root_dir = pathlib.Path(__file__).absolute().parent.parent
44+
pkg_dir = root_dir.joinpath("pfSense-pkg-API")
45+
template_dir = root_dir.joinpath("tools").joinpath("templates")
46+
files_dir = pkg_dir.joinpath("files")
47+
file_paths = {"dir": [], "file": [], "port_version": self.port_version, "port_revision": self.port_revision}
48+
excluded_files = ["pkg-deinstall.in", "pkg-install.in", "etc", "usr"]
49+
50+
# Set Jijna2 environment and variables
51+
j2_env = jinja2.Environment(loader=jinja2.FileSystemLoader(searchpath=str(template_dir)))
52+
j2_env.filters["dirname"] = self.dirname
53+
plist_template = j2_env.get_template("pkg-plist.j2")
54+
makefile_template = j2_env.get_template("Makefile.j2")
55+
56+
# Loop through each of our files and directories and store them for Jinja2 to render
57+
for root, dirs, files in os.walk(files_dir, topdown=True):
58+
root = pathlib.Path(str(root).replace(str(files_dir), ""))
59+
for dir in dirs:
60+
if dir not in excluded_files:
61+
file_paths["dir"].append(str(root.joinpath(dir)))
62+
for file in files:
63+
if file not in excluded_files:
64+
file_paths["file"].append(str(root.joinpath(file)))
65+
66+
# Generate pkg-plist file
67+
with open(pkg_dir.joinpath("pkg-plist"), "w") as pw:
68+
pw.write(plist_template.render(files=file_paths))
69+
# Generate Makefile file
70+
with open(pkg_dir.joinpath("Makefile"), "w") as mw:
71+
mw.write(makefile_template.render(files=file_paths).replace(" ", "\t"))
72+
73+
self.build_package(pkg_dir)
74+
75+
def run_ssh_cmd(self, cmd):
76+
ssh_cmd = "ssh {u}@{h} '{c}'".format(u=self.args.username, h=self.args.host, c=cmd)
77+
return subprocess.call(ssh_cmd, shell=True)
78+
79+
def run_scp_cmd(self, src, dst, recurse=False):
80+
scp_cmd = "scp {r} {s} {d}".format(r="-r" if recurse else "", s=src, d=dst)
81+
return subprocess.call(scp_cmd, shell=True)
82+
83+
def build_package(self, pkg_dir):
84+
# If we are running on FreeBSD, make package. Otherwise display warning that package was not compiled
85+
if platform.system() == "FreeBSD":
86+
s = subprocess.call(["/usr/bin/make", "package", "-C", pkg_dir, "DISABLE_VULNERABILITIES=yes"])
87+
else:
88+
print("WARNING: System is not FreeBSD. Generated Makefile and pkg-plist but did not attempt to build pkg.")
89+
90+
def build_on_remote_host(self):
91+
# Automate the process to pull, build and retrieve the package on a remote host
92+
build_cmds = [
93+
"mkdir -p ~/build/",
94+
"rm -rf ~/build/pfsense-api",
95+
"git clone https://github.com/jaredhendrickson13/pfsense-api.git ~/build/pfsense-api/",
96+
"git -C ~/build/pfsense-api checkout " + self.args.branch,
97+
"python3 ~/build/pfsense-api/tools/make_package.py --tag {t}".format(t=self.args.tag)
98+
]
99+
100+
# Join our build commands into a single command to run via SSH
101+
self.run_ssh_cmd(" && ".join(build_cmds))
102+
103+
# Retrieve the built package
104+
if self.args.freebsd == 11:
105+
src = "{u}@{h}:~/build/pfsense-api/pfSense-pkg-API/pfSense-pkg-API/pfSense-pkg-API-{v}{r}.txz"
106+
src = cmd.format(
107+
u=self.args.username,
108+
h=self.args.host,
109+
v=self.port_version,
110+
r="_" + self.port_revision if self.port_revision != "0" else ""
111+
)
112+
self.run_scp_cmd(src, ".")
113+
else:
114+
src = "{u}@{h}:~/build/pfsense-api/pfSense-pkg-API/pfSense-pkg-API/work/pkg/pfSense-pkg-API-{v}{r}.txz"
115+
src = src.format(
116+
u=self.args.username,
117+
h=self.args.host,
118+
v=self.port_version,
119+
r="_" + self.port_revision if self.port_revision != "0" else ""
120+
)
121+
self.run_scp_cmd(src, ".")
122+
123+
def __start_argparse__(self):
124+
# Custom port type for argparse
125+
def tag(value_string):
126+
value = str(value_string).split(".")
127+
valid = True
128+
129+
# Require 3 items (M.m.p)
130+
if len(value) == 3:
131+
for i in value:
132+
# Value cannot be blank
133+
if i == "":
134+
valid = False
135+
else:
136+
valid = False
137+
138+
# Return value if valid, otherwise throw error
139+
if valid:
140+
return value_string
141+
else:
142+
raise argparse.ArgumentTypeError("%s is not a semantic version tag" % value_string)
143+
144+
parser = argparse.ArgumentParser(
145+
description="Build the pfSense API on FreeBSD"
146+
)
147+
parser.add_argument(
148+
'--host', '-i',
149+
dest="host",
150+
type=str,
151+
required=True if "--remote" in sys.argv or "-r" in sys.argv else False,
152+
help="The host to connect to when using --build mode"
153+
)
154+
parser.add_argument(
155+
'--freebsd', '-f',
156+
dest="freebsd",
157+
type=int,
158+
default=12,
159+
help="The version of FreeBSD running on the remote host"
160+
)
161+
parser.add_argument(
162+
'--branch', '-b',
163+
dest="branch",
164+
type=str,
165+
default="master",
166+
help="The branch to build"
167+
)
168+
parser.add_argument(
169+
'--username', '-u',
170+
dest="username",
171+
type=str,
172+
default=getpass.getuser(),
173+
help="The username to use with SSH."
174+
)
175+
parser.add_argument(
176+
'--tag', '-t',
177+
dest="tag",
178+
type=tag,
179+
required=True,
180+
help="The version tag to use when building."
181+
)
182+
parser.add_argument(
183+
'--remote', '-r',
184+
dest="build",
185+
action="store_true",
186+
required=False,
187+
help='Enable remote build mode'
188+
)
189+
self.args = parser.parse_args()
190+
191+
192+
MakePackage()

tools/templates/Makefile.j2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# $FreeBSD$
22

33
PORTNAME=pfSense-pkg-API
4-
PORTVERSION=1.2
5-
PORTREVISION=0
4+
PORTVERSION={{ port_version }}
5+
PORTREVISION={{ port_revision }}
66
CATEGORIES=sysutils
77
MASTER_SITES=# empty
88
DISTFILES=# empty

0 commit comments

Comments
 (0)