tools(ci): support running with podman
Also turns of sudo if user in the `docker` group
Change-Id: Ife5a74f36d2b061b67d218a3c376f6415dd6ad30
diff --git a/tools/run_test_like_ci b/tools/run_test_like_ci
index e569b98..98b788e 100755
--- a/tools/run_test_like_ci
+++ b/tools/run_test_like_ci
@@ -15,31 +15,92 @@
from __future__ import print_function
import argparse
+import distutils
+import grp
+import os
+import readline
import sys
import shutil
import subprocess
-import os
+from pipes import quote
+
+try:
+ from shutil import which as find_executable
+except AttributeError:
+ from distutils.spawn import find_executable
REPO_ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(os.path.join(REPO_ROOT, 'infra', 'ci'))
from config import JOB_CONFIGS, SANDBOX_IMG
+try:
+ input = raw_input
+except NameError:
+ pass
+
+
+def user_in_docker_group():
+ try:
+ group = grp.getgrnam('docker')
+ except KeyError:
+ return False
+ else:
+ return group.gr_gid in os.getgroups()
+
+
+def decision(question='Would you like to continue', confirm=True, default='n'):
+ default = default.lower().strip()
+ yes = default in {'y', 'yes'}
+ no = default in {'n', 'no'}
+ default = 'y' if yes else 'n'
+ prompt = '%s? [%s/%s]: ' % (question, 'Y' if yes else 'y', 'N' if no else 'n')
+ if not confirm:
+ print('%sy' % prompt)
+ return
+ while True:
+ choice = input(prompt).lower().strip()
+ if not choice:
+ choice = default
+ if choice in {'y', 'yes'}:
+ return
+ elif choice in {'n', 'no'}:
+ sys.exit(3)
+
def main():
- parser = argparse.ArgumentParser()
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('config', choices=JOB_CONFIGS.keys())
+ parser.add_argument(
+ '--runner',
+ help='The container runner executable to use',
+ choices=('podman', 'docker'),
+ default='podman' if find_executable('podman') else 'docker')
+ parser.add_argument(
+ '--image', default=SANDBOX_IMG, help='The image to use to run the tests')
+ group = parser.add_mutually_exclusive_group()
+ group.add_argument(
+ '--confirm',
+ action='store_true',
+ default=True,
+ help='User confirmation of decision prompts')
+ group.add_argument(
+ '--no-confirm',
+ dest='confirm',
+ action='store_false',
+ help='Forces confirmation of decision prompts')
args = parser.parse_args()
# Check that the directory is clean.
git_cmd = ['git', '-C', REPO_ROOT, 'status', '--porcelain']
- modified_files = subprocess.check_output(git_cmd)
+ modified_files = subprocess.check_output(git_cmd).decode()
if modified_files:
print('The current Git repo has modified/untracked files.')
print('The sandboxed VM will fetch the HEAD of your current git repo.')
print('This is probably not the state you want to be in.')
- print('I suggest you press CTRL+C, commit and then re-run this script')
+ print('I suggest you stop, commit and then re-run this script')
print('Modified files:\n' + modified_files)
- raw_input('If you think you know what you are doing, press Enter instead')
+ decision('Do you know what you are doing', confirm=args.confirm)
env = {
'PERFETTO_TEST_GIT_REF': 'file:///ci/source',
@@ -47,31 +108,37 @@
env.update(JOB_CONFIGS[args.config])
workdir = os.path.join(REPO_ROOT, 'out', 'tmp.ci')
- cmd = [
- 'sudo', '--', 'docker', 'run', '-it', '--name', 'perfetto_ci',
- '--cap-add', 'SYS_PTRACE', '--rm', '--volume',
+ cmd = []
+ if args.runner == 'docker' and not user_in_docker_group():
+ cmd += ['sudo', '--']
+ cmd += [
+ args.runner, 'run', '-it', '--name', 'perfetto_ci', '--cap-add',
+ 'SYS_PTRACE', '--rm', '--volume',
'%s:/ci/ramdisk' % workdir, '--tmpfs', '/tmp:exec',
'--volume=%s:/ci/source:ro' % REPO_ROOT
]
for kv in env.items():
cmd += ['--env', '%s=%s' % kv]
- cmd += [SANDBOX_IMG]
+ cmd += [args.image]
cmd += [
'bash', '-c',
'cd /ci/ramdisk; bash /ci/init.sh || sudo -u perfetto -EH bash -i'
]
- print('About to run\n', ' '.join(cmd))
+ print(
+ 'About to run\n',
+ ' '.join('\n ' + c if c.startswith('--') or c == 'bash' else quote(c)
+ for c in cmd))
print('')
print('The VM will have read-only acess to: %s, mounted as /ci/source' %
REPO_ROOT)
print('The VM workdir /ci/ramdisk will be mounted into: %s' % workdir)
print('The contents of %s will be deleted before starting the VM' % workdir)
- raw_input('Press a key to continue')
+ decision(confirm=args.confirm)
shutil.rmtree(workdir, ignore_errors=True)
os.makedirs(workdir)
- os.execvp(cmd[0], cmd[1:])
+ os.execvp(cmd[0], cmd)
if __name__ == '__main__':