Skip to content

Commit 9833897

Browse files
authored
Merge pull request #745 from sever-sever/T6674
T6674: Add build-scrips for packages without Jenkins
2 parents 013e4d5 + cc7d099 commit 9833897

File tree

121 files changed

+19090
-0
lines changed

Some content is hidden

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

121 files changed

+19090
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
aws-gwlbtun*/
2+
*.tar.gz
3+
*.tar.xz
4+
*.deb
5+
*.dsc
6+
*.buildinfo
7+
*.build
8+
*.changes
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../build.py
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
[[packages]]
2+
name = "aws-gwlbtun"
3+
commit_id = "f78058a"
4+
scm_url = "https://github.com/aws-samples/aws-gateway-load-balancer-tunnel-handler"
5+
6+
7+
## Build cmd start
8+
build_cmd = '''\
9+
mkdir -p debian
10+
echo 'obj-*-linux-gnu/gwlbtun usr/sbin' > debian/install
11+
12+
# changelog
13+
cat <<EOF > debian/changelog
14+
aws-gwlbtun (1.0-1) unstable; urgency=low
15+
16+
* Initial release
17+
18+
-- Your Name <[email protected]> Wed, 29 Aug 2024 09:00:00 +0000
19+
20+
EOF
21+
22+
# control
23+
/bin/bash -c "cat <<EOF > debian/control
24+
Source: aws-gwlbtun
25+
Section: net
26+
Priority: optional
27+
Maintainer: VyOS Package Maintainers <[email protected]>
28+
Build-Depends: debhelper-compat (= 13)
29+
Standards-Version: 4.5.1
30+
Homepage: https://github.com/aws-samples/aws-gateway-load-balancer-tunnel-handler
31+
32+
Package: aws-gwlbtun
33+
Architecture: any
34+
Depends: \${shlibs:Depends}, \${misc:Depends}
35+
Description: AWS Gateway Load Balancer Tunnel Handler
36+
This is a simple package that handles tunneling for the AWS Gateway Load Balancer.
37+
EOF
38+
"
39+
40+
# rules
41+
cat <<EOF > debian/rules
42+
#!/usr/bin/make -f
43+
44+
%: dh $@
45+
46+
build:
47+
dh build
48+
49+
binary:
50+
dh binary
51+
52+
clean:
53+
dh clean
54+
EOF
55+
56+
chmod +x debian/rules
57+
debuild -us -uc -b
58+
'''
59+
## Build cmd end

scripts/package-build/build.py

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Copyright (C) 2024 VyOS maintainers and contributors
4+
#
5+
# This program is free software; you can redistribute it and/or modify
6+
# it under the terms of the GNU General Public License version 2 or later as
7+
# published by the Free Software Foundation.
8+
#
9+
# This program is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
# GNU General Public License for more details.
13+
#
14+
# You should have received a copy of the GNU General Public License
15+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
#
17+
18+
import glob
19+
import shutil
20+
import toml
21+
import os
22+
23+
from argparse import ArgumentParser
24+
from pathlib import Path
25+
from subprocess import run, CalledProcessError
26+
27+
28+
def ensure_dependencies(dependencies: list) -> None:
29+
"""Ensure Debian build dependencies are met"""
30+
if not dependencies:
31+
print("I: No additional dependencies to install")
32+
return
33+
34+
print("I: Ensure Debian build dependencies are met")
35+
run(['sudo', 'apt-get', 'update'], check=True)
36+
run(['sudo', 'apt-get', 'install', '-y'] + dependencies, check=True)
37+
38+
39+
def apply_patches(repo_dir: Path, patch_dir: Path) -> None:
40+
"""Apply patches from the patch directory to the repository"""
41+
if not patch_dir.exists() or not patch_dir.is_dir():
42+
print(f"I: Patch directory {patch_dir} does not exist, skipping patch application")
43+
return
44+
45+
patches = sorted(patch_dir.glob('*'))
46+
if not patches:
47+
print(f"I: No patches found in {patch_dir}")
48+
return
49+
50+
debian_patches_dir = repo_dir / 'debian/patches'
51+
debian_patches_dir.mkdir(parents=True, exist_ok=True)
52+
53+
series_file = debian_patches_dir / 'series'
54+
with series_file.open('a') as series:
55+
for patch in patches:
56+
patch_dest = debian_patches_dir / patch.name
57+
shutil.copy(patch, patch_dest)
58+
series.write(patch.name + '\n')
59+
print(f"I: Applied patch: {patch.name}")
60+
61+
62+
def prepare_package(repo_dir: Path, install_data: str) -> None:
63+
"""Prepare a package"""
64+
if not install_data:
65+
print("I: No install data provided, skipping package preparation")
66+
return
67+
68+
try:
69+
install_file = repo_dir / 'debian/install'
70+
install_file.parent.mkdir(parents=True, exist_ok=True)
71+
install_file.write_text(install_data)
72+
print("I: Prepared package")
73+
except Exception as e:
74+
print(f"Failed to prepare package: {e}")
75+
raise
76+
77+
78+
def build_package(package: list, dependencies: list, patch_dir: Path) -> None:
79+
"""Build a package from the repository
80+
81+
Args:
82+
package (list): List of Packages from toml
83+
dependencies (list): List of additional dependencies
84+
patch_dir (Path): Directory containing patches
85+
"""
86+
repo_name = package['name']
87+
repo_dir = Path(repo_name)
88+
89+
try:
90+
# Clone the repository if it does not exist
91+
if not repo_dir.exists():
92+
run(['git', 'clone', package['scm_url'], str(repo_dir)], check=True)
93+
94+
# Check out the specific commit
95+
run(['git', 'checkout', package['commit_id']], cwd=repo_dir, check=True)
96+
97+
# Ensure dependencies
98+
ensure_dependencies(dependencies)
99+
100+
# Apply patches if any
101+
if (repo_dir / 'patches'):
102+
apply_patches(repo_dir, patch_dir)
103+
104+
# Prepare the package if required
105+
if package.get('prepare_package', False):
106+
prepare_package(repo_dir, package.get('install_data', ''))
107+
108+
# Build dependency package and install it
109+
if (repo_dir / 'debian/control').exists():
110+
try:
111+
run('sudo mk-build-deps --install --tool "apt-get --yes --no-install-recommends"', cwd=repo_dir, check=True, shell=True)
112+
run('sudo dpkg -i *build-deps*.deb', cwd=repo_dir, check=True, shell=True)
113+
except CalledProcessError as e:
114+
print(f"Failed to build package {repo_name}: {e}")
115+
116+
# Build the package, check if we have build_cmd in the package.toml
117+
try:
118+
build_cmd = package.get('build_cmd', 'dpkg-buildpackage -uc -us -tc -F')
119+
run(build_cmd, cwd=repo_dir, check=True, shell=True)
120+
except CalledProcessError as e:
121+
print(e)
122+
print("I: Source packages build failed, ignoring - building binaries only")
123+
build_cmd = package.get('build_cmd', 'dpkg-buildpackage -uc -us -tc -b')
124+
run(build_cmd, cwd=repo_dir, check=True, shell=True)
125+
126+
except CalledProcessError as e:
127+
print(f"Failed to build package {repo_name}: {e}")
128+
finally:
129+
# Clean up repository directory
130+
# shutil.rmtree(repo_dir, ignore_errors=True)
131+
pass
132+
133+
134+
def cleanup_build_deps(repo_dir: Path) -> None:
135+
"""Clean up build dependency packages"""
136+
try:
137+
if repo_dir.exists():
138+
for file in glob.glob(str(repo_dir / '*build-deps*.deb')):
139+
os.remove(file)
140+
print("I: Cleaned up build dependency packages")
141+
except Exception as e:
142+
print(f"Error cleaning up build dependencies: {e}")
143+
144+
145+
def copy_packages(repo_dir: Path) -> None:
146+
"""Copy generated .deb packages to the parent directory"""
147+
try:
148+
deb_files = glob.glob(str(repo_dir / '*.deb'))
149+
for deb_file in deb_files:
150+
shutil.copy(deb_file, repo_dir.parent)
151+
print(f'I: copy generated "{deb_file}" package')
152+
except Exception as e:
153+
print(f"Error copying packages: {e}")
154+
155+
156+
if __name__ == '__main__':
157+
# Prepare argument parser
158+
arg_parser = ArgumentParser()
159+
arg_parser.add_argument('--config',
160+
default='package.toml',
161+
help='Path to the package configuration file')
162+
arg_parser.add_argument('--patch-dir',
163+
default='patches',
164+
help='Path to the directory containing patches')
165+
args = arg_parser.parse_args()
166+
167+
# Load package configuration
168+
with open(args.config, 'r') as file:
169+
config = toml.load(file)
170+
171+
packages = config['packages']
172+
patch_dir = Path(args.patch_dir)
173+
174+
for package in packages:
175+
dependencies = package.get('dependencies', {}).get('packages', [])
176+
177+
# Build the package
178+
build_package(package, dependencies, patch_dir)
179+
180+
# Clean up build dependency packages after build
181+
cleanup_build_deps(Path(package['name']))
182+
183+
# Copy generated .deb packages to parent directory
184+
copy_packages(Path(package['name']))
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
ddclient/
2+
*.buildinfo
3+
*.build
4+
*.changes
5+
*.deb
6+
*.dsc
7+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../build.py
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[[packages]]
2+
name = "ddclient"
3+
commit_id = "debian/3.11.2-1"
4+
scm_url = "https://salsa.debian.org/debian/ddclient"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
dropbear/
2+
*.buildinfo
3+
*.build
4+
*.changes
5+
*.deb
6+
*.dsc
7+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../build.py
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[[packages]]
2+
name = "dropbear"
3+
commit_id = "debian/2022.83-1+deb12u1"
4+
scm_url = "https://salsa.debian.org/debian/dropbear.git"
5+
6+
[packages.dependencies]
7+
packages = ["libpam0g-dev"]

0 commit comments

Comments
 (0)