def localbuild(arch, repo, context, file, tag, branch_tag, setup, pull, push): """Build docker containers""" arch = list(arch or ['amd']) tags = list(tag) if branch_tag: tags.append( getenv('TRAVIS_BRANCH') # Travis or getenv('Build.SourceBranchName') # Azure Pipelines or check_output( 'git rev-parse --abbrev-ref HEAD'.split()).decode().rstrip()) tags = [re.sub('[/_:]', '-', t) for t in tags] if setup: for f in glob('dist/*'): remove(f) utils.run('python setup.py sdist') utils.run(f'pipenv lock --requirements > {context}/requirements.txt') utils.distcopy('dist/', [f'{context}/dist/']) # single command utils.run(f'cd {context}' ' && if [ -f ./localbuild.sh ]; then bash ./localbuild.sh; fi') for a in arch: prefix = '' commands = [] build_args = [] build_tags = ['local', *tags] if a == 'arm': prefix = 'rpi-' commands += [ 'docker run --rm --privileged multiarch/qemu-user-static:register --reset', ] if pull: build_args.append('--pull') build_args += [ '--build-arg service_info="$(git describe) @ $(date)"', '--no-cache', ' '.join([f'--tag {repo}:{prefix}{t}' for t in build_tags]), f'--file {context}/{a}/{file}', context, ] commands.append(f'docker build {" ".join(build_args)}') utils.run(' && '.join(commands)) if push: # We're skipping the local tag [utils.run(f'docker push {repo}:{prefix}{t}') for t in tags]
def enable_experimental(): cfg = '/etc/docker/daemon.json' try: with open(cfg, 'r') as f: content = f.read() config = json.loads(content or '{}') except FileNotFoundError: # pragma: no cover config = {} if config.get('experimental'): return h, temp = tempfile.mkstemp() with open(temp, 'w') as f: config['experimental'] = True json.dump(config, f, indent=4) utils.run(f'sudo mv -f {temp} {cfg}') utils.run('sudo systemctl restart docker')
def build_python_images(): for tag in PYTHON_TAGS: with open(f'{WORKDIR}/Dockerfile', 'w') as f: f.write('\n'.join([ f'FROM arm32v7/python:{tag}', 'COPY ./qemu-arm-static /usr/bin/qemu-arm-static', ])) utils.run(f'docker pull --platform=linux/arm arm32v7/python:{tag}') utils.run( f'docker build --platform=linux/arm --no-cache -t brewblox/rpi-python:{tag} {WORKDIR}' ) utils.run(f'docker push brewblox/rpi-python:{tag}')
def build_node_images(): for tag in NODE_TAGS: with open(f'{WORKDIR}/Dockerfile', 'w') as f: f.write('\n'.join([ f'FROM arm32v7/node:{tag}', 'COPY ./qemu-arm-static /usr/bin/qemu-arm-static', ])) utils.run(f'docker pull --platform=linux/arm arm32v7/node:{tag}') utils.run( f'docker build --platform=linux/arm --no-cache -t brewblox/rpi-node:{tag} {WORKDIR}' ) utils.run(f'docker push brewblox/rpi-node:{tag}') # Alpine is an exception, as it runs on armv6, and must install packages with open(f'{WORKDIR}/Dockerfile', 'w') as f: f.write('\n'.join([ 'FROM arm32v6/alpine', 'COPY ./qemu-arm-static /usr/bin/qemu-arm-static', 'RUN apk add --no-cache nodejs npm', ])) utils.run('docker pull --platform=linux/arm arm32v6/alpine') utils.run( f'docker build --platform=linux/arm --no-cache -t brewblox/rpi-node:10-alpine {WORKDIR}' ) utils.run('docker push brewblox/rpi-node:10-alpine')
def install_qemu(): utils.run('sudo apt update') utils.run( 'sudo apt install -y qemu qemu-user-static qemu-user binfmt-support') utils.run(f'cp $(which qemu-arm-static) {WORKDIR}/')
def release_stable(): """Push newest-tag -> stable for all managed repositories""" for repo in AMD_ARM_REPOS + AMD_REPOS: utils.run(f'docker pull {repo}:newest-tag') for repo in AMD_ARM_REPOS: utils.run(f'docker pull {repo}:rpi-newest-tag') # start pushing after all pulls are ok for repo in AMD_ARM_REPOS + AMD_REPOS: utils.run(f'docker tag {repo}:newest-tag {repo}:stable') utils.run(f'docker push {repo}:stable') for repo in AMD_ARM_REPOS: utils.run(f'docker tag {repo}:rpi-newest-tag {repo}:rpi-stable') utils.run(f'docker push {repo}:rpi-stable')
def test_run(mocked_ext): utils.run('cmd') mocked_ext['check_call'].assert_called_once_with('cmd', shell=True, stderr=utils.STDOUT)