aboutsummaryrefslogtreecommitdiff
path: root/ci/ciimage
diff options
context:
space:
mode:
authorDaniel Mensinger <daniel@mensinger-ka.de>2020-03-24 16:52:14 +0100
committerDaniel Mensinger <daniel@mensinger-ka.de>2020-04-02 09:47:06 +0200
commit6310f188bec6dd76905f6ee5f8c49ac6ace120c0 (patch)
tree2a3f1d92df6f3bbe7c381aa2350cde429dee57af /ci/ciimage
parent934863ba3b491d5931542c1321576ce582dbaa72 (diff)
downloadmeson-6310f188bec6dd76905f6ee5f8c49ac6ace120c0.zip
meson-6310f188bec6dd76905f6ee5f8c49ac6ace120c0.tar.gz
meson-6310f188bec6dd76905f6ee5f8c49ac6ace120c0.tar.bz2
ci: New CI image builder infrastructure
Diffstat (limited to 'ci/ciimage')
-rw-r--r--ci/ciimage/.gitignore2
-rw-r--r--ci/ciimage/arch/Dockerfile4
-rw-r--r--ci/ciimage/arch/image.json6
-rwxr-xr-xci/ciimage/arch/install.sh2
-rwxr-xr-xci/ciimage/build.py182
-rw-r--r--ci/ciimage/fedora/Dockerfile4
-rw-r--r--ci/ciimage/fedora/image.json8
-rwxr-xr-xci/ciimage/fedora/install.sh2
-rw-r--r--ci/ciimage/opensuse/Dockerfile4
-rw-r--r--ci/ciimage/opensuse/image.json9
-rwxr-xr-xci/ciimage/opensuse/install.sh16
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