Skip to content

Commit

Permalink
Merge pull request #105 from nathanchance/move-images-to-releases
Browse files Browse the repository at this point in the history
Move images to GitHub releases
  • Loading branch information
nathanchance authored Jun 9, 2023
2 parents 012c3ac + 98f47f1 commit e6bb228
Show file tree
Hide file tree
Showing 23 changed files with 322 additions and 137 deletions.
6 changes: 1 addition & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Run shellcheck and shfmt on all shell files and several Python linters on all Python files in this repository
# Run several Python linters on all Python files in this repository
name: Lint checks
on: [push, pull_request]
jobs:
Expand All @@ -10,7 +10,3 @@ jobs:
uses: ClangBuiltLinux/actions-workflows/.github/workflows/python_lint.yml@main
with:
python_version: ${{ matrix.version }}
shellcheck:
uses: ClangBuiltLinux/actions-workflows/.github/workflows/shellcheck.yml@main
shfmt:
uses: ClangBuiltLinux/actions-workflows/.github/workflows/shfmt.yml@main
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
images/
qemu-binaries/
*.pyc
28 changes: 14 additions & 14 deletions boot-qemu.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

import utils

BOOT_UTILS = Path(__file__).resolve().parent
SUPPORTED_ARCHES = [
'arm',
'arm32_v5',
Expand Down Expand Up @@ -45,6 +44,7 @@ def __init__(self):
self.efi = False
self.gdb = False
self.gdb_bin = ''
self.gh_json_file = None
self.interactive = False
self.kernel = None
self.kernel_dir = None
Expand Down Expand Up @@ -163,16 +163,8 @@ def _have_dev_kvm_access(self):
def _prepare_initrd(self):
if not self._initrd_arch:
raise RuntimeError('No initrd architecture specified?')
if not (src := Path(BOOT_UTILS, 'images', self._initrd_arch,
'rootfs.cpio.zst')):
raise FileNotFoundError(f"initrd ('{src}') does not exist?")

(dst := src.with_suffix('')).unlink(missing_ok=True)

utils.check_cmd('zstd')
subprocess.run(['zstd', '-d', src, '-o', dst, '-q'], check=True)

return dst
return utils.prepare_initrd(self._initrd_arch,
gh_json_file=self.gh_json_file)

def _run_fg(self):
# Pretty print and run QEMU command
Expand Down Expand Up @@ -370,7 +362,7 @@ def _can_use_kvm(self):
# 32-bit EL1 is not supported on all cores so support for it must be
# explicitly queried via the KVM_CHECK_EXTENSION ioctl().
try:
subprocess.run(Path(BOOT_UTILS, 'utils',
subprocess.run(Path(utils.BOOT_UTILS, 'utils',
'aarch64_32_bit_el1_supported'),
check=True)
except subprocess.CalledProcessError:
Expand Down Expand Up @@ -437,7 +429,7 @@ def _setup_efi(self):
]
aavmf = utils.find_first_file(usr_share, aavmf_locations)

self._efi_img = Path(BOOT_UTILS, 'images', self._initrd_arch,
self._efi_img = Path(utils.BOOT_UTILS, 'images', self._initrd_arch,
'efi.img')
# This file is in /usr/share, so it must be copied in order to be
# modified.
Expand Down Expand Up @@ -652,7 +644,7 @@ def run(self):
Path('OVMF/OVMF_VARS.fd'), # Debian and Ubuntu
]
ovmf_vars = utils.find_first_file(usr_share, ovmf_vars_locations)
self._efi_vars = Path(BOOT_UTILS, 'images', self.initrd_arch,
self._efi_vars = Path(utils.BOOT_UTILS, 'images', self.initrd_arch,
ovmf_vars.name)
# This file is in /usr/share, so it must be copied in order to be
# modified.
Expand Down Expand Up @@ -750,6 +742,11 @@ def parse_arguments():
'--gdb-bin',
default='gdb-multiarch',
help='gdb binary to use for debugging (default: gdb-multiarch)')
parser.add_argument(
'--gh-json-file',
help=
'Use file for downloading rootfs images, instead of querying GitHub API directly'
)
parser.add_argument(
'-k',
'--kernel-location',
Expand Down Expand Up @@ -837,6 +834,9 @@ def parse_arguments():
runner.gdb = True
runner.gdb_bin = args.gdb_bin

if args.gh_json_file:
runner.gh_json_file = Path(args.gh_json_file).resolve()

if args.no_kvm:
runner.use_kvm = False

Expand Down
36 changes: 13 additions & 23 deletions boot-uml.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

import utils

base_folder = Path(__file__).resolve().parent


def parse_arguments():
"""
Expand All @@ -19,6 +17,12 @@ def parse_arguments():
"""
parser = argparse.ArgumentParser()

parser.add_argument(
'-g',
'--gh-json-file',
help=
'Use file for downloading rootfs images, instead of querying GitHub API directly'
)
parser.add_argument(
"-i",
"--interactive",
Expand All @@ -38,26 +42,6 @@ def parse_arguments():
return parser.parse_args()


def decomp_rootfs():
"""
Decompress and get the full path of the initial ramdisk for use with UML.
Returns:
rootfs (Path): rootfs Path object containing full path to rootfs.
"""
rootfs = base_folder.joinpath("images", "x86_64", "rootfs.ext4")

# This could be 'rootfs.unlink(missing_ok=True)' but that was only added in Python 3.8.
if rootfs.exists():
rootfs.unlink()

utils.check_cmd("zstd")
subprocess.run(["zstd", "-q", "-d", f"{rootfs}.zst", "-o", rootfs],
check=True)

return rootfs


def run_kernel(kernel_image, rootfs, interactive):
"""
Run UML command with path to rootfs and additional arguments based on user
Expand All @@ -77,6 +61,12 @@ def run_kernel(kernel_image, rootfs, interactive):

if __name__ == '__main__':
args = parse_arguments()

kernel = utils.get_full_kernel_path(args.kernel_location, "linux")

run_kernel(kernel, decomp_rootfs(), args.interactive)
initrd_args = {'rootfs_format': 'ext4'}
if args.gh_json_file:
initrd_args['gh_json_file'] = Path(args.gh_json_file).resolve()
initrd = utils.prepare_initrd('x86_64', **initrd_args)

run_kernel(kernel, initrd, args.interactive)
1 change: 1 addition & 0 deletions buildroot/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
src/
out/
169 changes: 169 additions & 0 deletions buildroot/rebuild.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#!/usr/bin/env python3

from argparse import ArgumentParser
import datetime
import os
from pathlib import Path
import shutil
import subprocess

BUILDROOT_VERSION = '2022.02'
SUPPORTED_ARCHES = [
'arm64',
'arm64be',
'arm',
'm68k',
'mips',
'mipsel',
'ppc32',
'ppc64',
'ppc64le',
'riscv',
's390',
'x86',
'x86_64',
]
RELEASE_TAG = datetime.datetime.now(
tz=datetime.timezone.utc).strftime('%Y%m%d-%H%M%S')
ROOT_FOLDER = Path(__file__).resolve().parent
OUT_FOLDER = Path(ROOT_FOLDER, 'out')
SRC_FOLDER = Path(ROOT_FOLDER, 'src')


def buildroot_make(make_arg=None, **kwargs):
make_cmd = ['make', f"-j{os.cpu_count()}"]
if make_arg:
make_cmd.append(make_arg)
subprocess.run(make_cmd, **kwargs, check=True, cwd=SRC_FOLDER)


def build_image(architecture, edit_config):
buildroot_make('clean')

config = Path(ROOT_FOLDER, f"{architecture}.config")
# Python documentation notes that when subprocess.Popen()'s env parameter
# is not None, the current process's envirionment is not inherited, which
# causes issues because PATH is not inherited. Add BR2_DEFCONFIG to the
# environment, rather than replacing it (we support Python 3.8, so we
# cannot use 'os.environ | {...}').
buildroot_make('defconfig', env={**os.environ, 'BR2_DEFCONFIG': config})
if edit_config:
buildroot_make('menuconfig')
buildroot_make('savedefconfig')

buildroot_make()

OUT_FOLDER.mkdir(exist_ok=True, parents=True)

images = [Path(SRC_FOLDER, 'output/images/rootfs.cpio')]
# For x86_64, we also build an ext4 image for UML
if architecture == 'x86_64':
images.append(images[0].with_suffix('.ext4'))

for image in images:
if not image.exists():
raise FileNotFoundError(
f"{image} could not be found! Did the build error?")
zstd_cmd = [
'zstd', '-f', '-19', '-o',
Path(OUT_FOLDER, f"{architecture}-{image.name}.zst"), image
]
subprocess.run(zstd_cmd, check=True)


def download_and_extract_buildroot():
SRC_FOLDER.mkdir(parents=True)

tarball = Path(ROOT_FOLDER, f"buildroot-{BUILDROOT_VERSION}.tar.gz")
tarball.unlink(missing_ok=True)

curl_cmd = [
'curl', '-LSs', '-o', tarball,
f"https://buildroot.org/downloads/{tarball.name}"
]
subprocess.run(curl_cmd, check=True)

sha256_cmd = ['sha256sum', '--quiet', '-c', f"{tarball.name}.sha256"]
subprocess.run(sha256_cmd, check=True, cwd=ROOT_FOLDER)

tar_cmd = [
'tar', '-C', SRC_FOLDER, '--strip-components=1', '-axf', tarball
]
subprocess.run(tar_cmd, check=True)

tarball.unlink(missing_ok=True)


def download_buildroot_if_necessary():
if SRC_FOLDER.exists():
# Make support/scripts/setlocalversion do nothing because we are in a
# git repository so it will return information about this repo, not
# Buildroot
setlocalversion = Path(SRC_FOLDER, 'support/scripts/setlocalversion')
setlocalversion.write_text('', encoding='utf-8')

installed_version = subprocess.run(['make', 'print-version'],
capture_output=True,
check=True,
cwd=SRC_FOLDER,
text=True).stdout.strip()
if installed_version != BUILDROOT_VERSION:
shutil.rmtree(SRC_FOLDER)
download_and_extract_buildroot()
else:
download_and_extract_buildroot()


def release_images():
if not shutil.which('gh'):
raise RuntimeError(
"Could not find GitHub CLI ('gh') on your system, please install it to do releases!"
)

gh_cmd = [
'gh', '-R', 'ClangBuiltLinux/boot-utils', 'release', 'create',
'--generate-notes', RELEASE_TAG, *list(OUT_FOLDER.iterdir())
]
subprocess.run(gh_cmd, check=True)


def parse_arguments():
parser = ArgumentParser()

parser.add_argument(
'-a',
'--architectures',
choices=[*SUPPORTED_ARCHES, 'all'],
default=SUPPORTED_ARCHES,
help=
'The architectures to build images for. Defaults to all supported architectures.',
nargs='+')
parser.add_argument(
'-e',
'--edit-config',
action='store_true',
help='Edit configuration file and run savedefconfig on result')
parser.add_argument(
'-r',
'--release',
action='store_true',
help=f"Create a release on GitHub (tag: {RELEASE_TAG})")

return parser.parse_args()


if __name__ == '__main__':
args = parse_arguments()

if not shutil.which('zstd'):
raise RuntimeError(
'zstd could not be found on your system, please install it!')

architectures = SUPPORTED_ARCHES if 'all' in args.architectures else args.architectures

download_buildroot_if_necessary()
for arch in architectures:
build_image(arch, args.edit_config)

if args.release:
release_images()
Loading

0 comments on commit e6bb228

Please sign in to comment.