diff options
author | Daniel Mensinger <daniel@mensinger-ka.de> | 2020-03-24 16:52:14 +0100 |
---|---|---|
committer | Daniel Mensinger <daniel@mensinger-ka.de> | 2020-04-02 09:47:06 +0200 |
commit | 6310f188bec6dd76905f6ee5f8c49ac6ace120c0 (patch) | |
tree | 2a3f1d92df6f3bbe7c381aa2350cde429dee57af /ci | |
parent | 934863ba3b491d5931542c1321576ce582dbaa72 (diff) | |
download | meson-6310f188bec6dd76905f6ee5f8c49ac6ace120c0.zip meson-6310f188bec6dd76905f6ee5f8c49ac6ace120c0.tar.gz meson-6310f188bec6dd76905f6ee5f8c49ac6ace120c0.tar.bz2 |
ci: New CI image builder infrastructure
Diffstat (limited to 'ci')
-rw-r--r-- | ci/ciimage/.gitignore | 2 | ||||
-rw-r--r-- | ci/ciimage/arch/Dockerfile | 4 | ||||
-rw-r--r-- | ci/ciimage/arch/image.json | 6 | ||||
-rwxr-xr-x | ci/ciimage/arch/install.sh | 2 | ||||
-rwxr-xr-x | ci/ciimage/build.py | 182 | ||||
-rw-r--r-- | ci/ciimage/fedora/Dockerfile | 4 | ||||
-rw-r--r-- | ci/ciimage/fedora/image.json | 8 | ||||
-rwxr-xr-x | ci/ciimage/fedora/install.sh | 2 | ||||
-rw-r--r-- | ci/ciimage/opensuse/Dockerfile | 4 | ||||
-rw-r--r-- | ci/ciimage/opensuse/image.json | 9 | ||||
-rwxr-xr-x | ci/ciimage/opensuse/install.sh | 16 |
11 files changed, 220 insertions, 19 deletions
diff --git a/ci/ciimage/.gitignore b/ci/ciimage/.gitignore new file mode 100644 index 0000000..02a0319 --- /dev/null +++ b/ci/ciimage/.gitignore @@ -0,0 +1,2 @@ +/build_* +/test_* diff --git a/ci/ciimage/arch/Dockerfile b/ci/ciimage/arch/Dockerfile deleted file mode 100644 index b8a36cd..0000000 --- a/ci/ciimage/arch/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM archlinux:latest - -ADD install.sh /usr/sbin/docker-arch-install -RUN docker-arch-install diff --git a/ci/ciimage/arch/image.json b/ci/ciimage/arch/image.json new file mode 100644 index 0000000..5254073 --- /dev/null +++ b/ci/ciimage/arch/image.json @@ -0,0 +1,6 @@ +{ + "base_image": "archlinux:latest", + "env": { + "CI": "1" + } +} diff --git a/ci/ciimage/arch/install.sh b/ci/ciimage/arch/install.sh index 1aeb85c..7b6eda9 100755 --- a/ci/ciimage/arch/install.sh +++ b/ci/ciimage/arch/install.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -e + # Inspired by https://github.com/greyltc/docker-archlinux-aur/blob/master/add-aur.sh pkgs=( diff --git a/ci/ciimage/build.py b/ci/ciimage/build.py new file mode 100755 index 0000000..bc4ec1c --- /dev/null +++ b/ci/ciimage/build.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python3 + +import json +import argparse +import stat +import textwrap +import shutil +import subprocess +from tempfile import TemporaryDirectory +from pathlib import Path +import typing as T + +image_namespace = 'mesonbuild' + +image_def_file = 'image.json' +install_script = 'install.sh' + +class ImageDef: + def __init__(self, image_dir: Path) -> None: + path = image_dir / image_def_file + data = json.loads(path.read_text()) + + assert isinstance(data, dict) + assert all([x in data for x in ['base_image', 'env']]) + assert isinstance(data['base_image'], str) + assert isinstance(data['env'], dict) + + self.base_image: str = data['base_image'] + self.env: T.Dict[str, str] = data['env'] + +class BuilderBase(): + def __init__(self, data_dir: Path, temp_dir: Path) -> None: + self.data_dir = data_dir + self.temp_dir = temp_dir + + self.validate_data_dir() + + self.image_def = ImageDef(self.data_dir) + + self.docker = shutil.which('docker') + self.git = shutil.which('git') + if self.docker is None: + raise RuntimeError('Unable to find docker') + if self.git is None: + raise RuntimeError('Unable to find git') + + def validate_data_dir(self) -> None: + files = [ + self.data_dir / image_def_file, + self.data_dir / install_script, + ] + if not self.data_dir.exists(): + raise RuntimeError(f'{self.data_dir.as_posix()} does not exist') + for i in files: + if not i.exists(): + raise RuntimeError(f'{i.as_posix()} does not exist') + if not i.is_file(): + raise RuntimeError(f'{i.as_posix()} is not a regular file') + +class Builder(BuilderBase): + def gen_bashrc(self) -> None: + out_file = self.temp_dir / 'env_vars.sh' + out_data = '' + + for key, val in self.image_def.env.items(): + out_data += f'export {key}="{val}"\n' + + out_file.write_text(out_data) + + # make it executable + mode = out_file.stat().st_mode + out_file.chmod(mode | stat.S_IEXEC) + + def gen_dockerfile(self) -> None: + out_file = self.temp_dir / 'Dockerfile' + out_data = textwrap.dedent(f'''\ + FROM {self.image_def.base_image} + + ADD install.sh /usr/sbin/docker-do-install + ADD env_vars.sh /env_vars.sh + RUN docker-do-install + ''') + + out_file.write_text(out_data) + + def do_build(self) -> None: + # copy files + for i in self.data_dir.iterdir(): + shutil.copy(str(i), str(self.temp_dir)) + + self.gen_bashrc() + self.gen_dockerfile() + + cmd_git = [self.git, 'rev-parse', '--short', 'HEAD'] + res = subprocess.run(cmd_git, cwd=self.data_dir, stdout=subprocess.PIPE) + if res.returncode != 0: + raise RuntimeError('Failed to get the current commit hash') + commit_hash = res.stdout.decode().strip() + + cmd = [ + self.docker, 'build', + '-t', f'{image_namespace}/{self.data_dir.name}:latest', + '-t', f'{image_namespace}/{self.data_dir.name}:{commit_hash}', + '--pull', + self.temp_dir.as_posix(), + ] + if subprocess.run(cmd).returncode != 0: + raise RuntimeError('Failde to build the docker image') + +class ImageTester(BuilderBase): + def __init__(self, data_dir: Path, temp_dir: Path, ci_root: Path) -> None: + super().__init__(data_dir, temp_dir) + self.meson_root = ci_root.parent.parent.resolve() + + def gen_dockerfile(self) -> None: + out_file = self.temp_dir / 'Dockerfile' + out_data = textwrap.dedent(f'''\ + FROM {image_namespace}/{self.data_dir.name} + + ADD meson /meson + ''') + + out_file.write_text(out_data) + + def copy_meson(self) -> None: + shutil.copytree( + self.meson_root, + self.temp_dir / 'meson', + ignore=shutil.ignore_patterns( + '.git', + '*_cache', + 'work area', + self.temp_dir.name, + ) + ) + + def do_test(self): + self.copy_meson() + self.gen_dockerfile() + + try: + build_cmd = [ + self.docker, 'build', + '-t', 'meson_test_image', + self.temp_dir.as_posix(), + ] + if subprocess.run(build_cmd).returncode != 0: + raise RuntimeError('Failde to build the test docker image') + + test_cmd = [ + self.docker, 'run', '--rm', '-t', 'meson_test_image', + '/usr/bin/bash', '-c', 'source /env_vars.sh; cd meson; ./run_tests.py' + ] + if subprocess.run(test_cmd).returncode != 0: + raise RuntimeError('Running tests failed') + finally: + cleanup_cmd = [self.docker, 'rmi', '-f', 'meson_test_image'] + subprocess.run(cleanup_cmd).returncode + +def main() -> None: + parser = argparse.ArgumentParser(description='Meson CI image builder') + parser.add_argument('what', type=str, help='Which image to build / test') + parser.add_argument('-t', '--type', choices=['build', 'test'], help='What to do', required=True) + + args = parser.parse_args() + + ci_root = Path(__file__).parent + ci_data = ci_root / args.what + + with TemporaryDirectory(prefix=f'{args.type}_{args.what}_', dir=ci_root) as td: + ci_build = Path(td) + print(f'Build dir: {ci_build}') + + if args.type == 'build': + builder = Builder(ci_data, ci_build) + builder.do_build() + elif args.type == 'test': + tester = ImageTester(ci_data, ci_build, ci_root) + tester.do_test() + +if __name__ == '__main__': + main() diff --git a/ci/ciimage/fedora/Dockerfile b/ci/ciimage/fedora/Dockerfile deleted file mode 100644 index fa552e4..0000000 --- a/ci/ciimage/fedora/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM fedora:latest - -ADD install.sh /usr/sbin/docker-fedora-install -RUN docker-fedora-install diff --git a/ci/ciimage/fedora/image.json b/ci/ciimage/fedora/image.json new file mode 100644 index 0000000..ae9ff4f --- /dev/null +++ b/ci/ciimage/fedora/image.json @@ -0,0 +1,8 @@ +{ + "base_image": "fedora:latest", + "env": { + "CI": "1", + "SKIP_SCIENTIFIC": "1", + "SKIP_STATIC_BOOST": "1" + } +} diff --git a/ci/ciimage/fedora/install.sh b/ci/ciimage/fedora/install.sh index e1544fa..242d677 100755 --- a/ci/ciimage/fedora/install.sh +++ b/ci/ciimage/fedora/install.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -e + pkgs=( python python-setuptools python-wheel python-pip python-pytest-xdist pygobject3 python3-devel python2-devel ninja-build make git autoconf automake patch python3-Cython python2-Cython python3-jsonschema diff --git a/ci/ciimage/opensuse/Dockerfile b/ci/ciimage/opensuse/Dockerfile deleted file mode 100644 index 3d97bac..0000000 --- a/ci/ciimage/opensuse/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM opensuse/tumbleweed:latest - -ADD install.sh /usr/sbin/docker-opensuse-install -RUN docker-opensuse-install diff --git a/ci/ciimage/opensuse/image.json b/ci/ciimage/opensuse/image.json new file mode 100644 index 0000000..74acbe5 --- /dev/null +++ b/ci/ciimage/opensuse/image.json @@ -0,0 +1,9 @@ +{ + "base_image": "opensuse/tumbleweed:latest", + "env": { + "CI": "1", + "SKIP_SCIENTIFIC": "1", + "SKIP_STATIC_BOOST": "1", + "SINGLE_DUB_COMPILER": "1" + } +} diff --git a/ci/ciimage/opensuse/install.sh b/ci/ciimage/opensuse/install.sh index 5cb61ec..a158e0b 100755 --- a/ci/ciimage/opensuse/install.sh +++ b/ci/ciimage/opensuse/install.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -e + pkgs=( python3-setuptools python3-wheel python3-pip python3-pytest-xdist python3 python2 ninja make git autoconf automake patch python3-Cython python2-Cython python3-jsonschema @@ -17,22 +19,22 @@ pkgs=( ) # Sys update -zypper patch --with-update --with-optional -zypper update +zypper --non-interactive patch --with-update --with-optional +zypper --non-interactive update # Install deps zypper install -y "${pkgs[@]}" python3 -m pip install hotdoc gobject PyGObject -echo 'export PKG_CONFIG_PATH="/usr/lib64/mpi/gcc/openmpi3/lib64/pkgconfig:$PKG_CONFIG_PATH"' >> ~/.bashrc +echo 'export PKG_CONFIG_PATH="/usr/lib64/mpi/gcc/openmpi3/lib64/pkgconfig:$PKG_CONFIG_PATH"' >> /env_vars.sh # dmd is very special on OpenSUSE (as in the packages do not work) # see https://bugzilla.opensuse.org/show_bug.cgi?id=1162408 curl -fsS https://dlang.org/install.sh | bash -s dmd | tee dmd_out.txt -cat dmd_out.txt | grep source | sed 's/^[^`]*`//g' | sed 's/`.*//g' >> ~/.bashrc -chmod +x ~/.bashrc +cat dmd_out.txt | grep source | sed 's/^[^`]*`//g' | sed 's/`.*//g' >> /env_vars.sh +chmod +x /env_vars.sh -source ~/.bashrc +source /env_vars.sh dub fetch urld dub build urld --compiler=dmd @@ -41,4 +43,4 @@ dub build dubtestproject:test1 --compiler=dmd dub build dubtestproject:test2 --compiler=dmd # Cleanup -zypper clean --all +zypper --non-interactive clean --all |