Commit eebcc99c authored by Carine Dengler's avatar Carine Dengler

Draft: add docker image to build debian package

parent ef77bf95ad6a
......@@ -6,3 +6,4 @@
!get-cube
!docker-cubicweb-helper
!buildpackage
!build-package.py
ARG DIST
FROM debian:$DIST-slim
ARG DIST
ADD "build-package.py" .
RUN apt-get update && \
apt-get -y --no-install-recommends install \
bzip2 \
wget \
gnupg \
ca-certificates \
devscripts \
python \
python-setuptools \
equivs \
&& rm -rf /var/lib/apt/lists/*
#!/usr/bin/env python
import argparse
import contextlib
import glob
import logging
import os
import shutil
import subprocess
import zipfile
LOG = logging.getLogger(__name__)
CLEANUP_PATTERNS = ['*.dsc', '*.changes', '*.buildinfo', '*.gz', '*.bz2',
'*.xz', '*.deb', '*.build', 'lintian.txt', 'lintian.xml']
@contextlib.contextmanager
def chdir(path):
oldcwd = os.getcwd()
os.chdir(path)
try:
yield oldcwd
finally:
os.chdir(oldcwd)
def find_file(pattern):
matches = glob.glob(pattern)
if len(matches) == 0:
raise RuntimeError('No files found for {}'.format(pattern))
elif len(matches) > 1:
raise RuntimeError('Multiple files found for {}: {}'.format(
pattern, matches))
return matches[0]
def run(cmd, **kwargs):
LOG.info('run %s', cmd)
subprocess.check_call(cmd, **kwargs)
def check_output(cmd):
LOG.info('run %s', cmd)
return subprocess.check_output(cmd).strip()
def cleanup_workspace():
for pattern in CLEANUP_PATTERNS:
for filename in glob.glob(pattern):
LOG.info('cleanup: removing {}'.format(filename))
os.unlink(filename)
def unpack_dsc(dsc_file, output):
if dsc_file.startswith('http://') or dsc_file.startswith('https://'):
run(['dget', '--allow-unauthenticated', '--download-only', dsc_file])
dsc_file = find_file('*.dsc')
shutil.rmtree(output, ignore_errors=True)
run(['dpkg-source', '--extract', dsc_file, output])
def _dpkg_build_source_package(addopts=()):
cmd = ['dpkg-buildpackage', '--unsigned-changes',
'--unsigned-source', '--no-pre-clean',
'--no-check-builddeps', '--build=source'] + list(addopts)
run(cmd)
def dch(dist):
local = {
'buster': '+deb10u',
'stretch': '+deb9u',
'buster-backports': '~bpo10+',
'stretch-backports': '~bpo9+',
'jessie-backports': '~bpo8+',
'trusty-backports': '~bpoubuntu14.04+',
'xenial-backports': '~bpoubuntu16.04+',
'artful-backports': '~bpoubuntu17.10+',
'bionic-backports': '~bpoubuntu18.04+',
'focal-backports': '~bpoubuntu20.04+',
}.get(dist, '~{}'.format(dist))
run(['dch', '--distribution', dist, '--local', local,
'Rebuild for {}'.format(dist)])
def build_source_package():
name = check_output(['dpkg-parsechangelog', '--show-field', 'Source'])
version = check_output(['dpkg-parsechangelog', '--show-field',
'Version'])
# assume orig tarball exists and just rebuild the source package
_dpkg_build_source_package(['--source-option=-sp'])
return '{}_{}.dsc'.format(name, version)
def build_binary_package(dsc_file, dist, build_repo=()):
run(['wget', 'https://{}/key.asc'.format(REPO_HOST), '-O', 'key.asc'])
cmd = ['sbuild', '--verbose', '--arch-all', '--dist',
dist, '--no-clean-source', '--extra-repository-key=key.asc']
extra_repo = list(build_repo)
if dist.endswith('-backports'):
codename = dist.split('-', 1)[0]
if codename in ('trusty', 'xenial', 'artful', 'bionic', 'focal'):
distro = 'ubuntu'
else:
distro = 'debian'
if codename != 'jessie':
# jessie doesn't have backports anymore
extra_repo.append(
'deb {}/{} {} main'.format(MIRROR, distro, dist))
if not build_repo:
extra_repo.append('deb http://{} {} main'.format(
REPO_HOST, dist.rsplit('-', 1)[0]))
cmd.append('--build-dep-resolver=aptitude')
if not build_repo:
extra_repo.append('deb http://{} {} main'.format(
REPO_HOST, dist))
for repo in extra_repo:
cmd.extend(['--extra-repository', repo])
cmd.append(dsc_file)
run(cmd)
def upload(repo):
changes = glob.glob('*_amd64.changes')
run(['dcmd', 'scp', '-B'] + changes + [
'{}/{}'.format(APTLY_INCOMING, repo)])
if __name__ == '__main__':
logging.basicConfig(format='%(asctime)-15s %(message)s')
LOG.setLevel(logging.INFO)
parser = argparse.ArgumentParser(description='build debian packages')
parser.add_argument('--source-dir', default='source', help=(
'Source directory where source package with debian packaging is '
'expected'))
parser.add_argument('--from-dsc', help=(
'Generate source directory from an existing dsc file '
'(could be an url)'))
parser.add_argument('--dist', help=(
'sbuild distribution to build package for'))
clean_group = parser.add_mutually_exclusive_group()
clean_group.add_argument('--clean', action='store_true', default=None, help=(
'cleanup workspace before build, remove previous '
'artifacts: {}'.format(', '.join(CLEANUP_PATTERNS))))
clean_group.add_argument('--no-clean', action='store_false', dest='clean')
parser.add_argument('--no-build', action='store_true', help=(
'do not build binary package'))
parser.add_argument('--extra-repository', action='append', help=(
'Extra repository to use during build with sbuild'))
parser.add_argument('--upload-repo', help=(
'upload packages to repository after building'))
parser.add_argument('--no-check', action="store_true", default=None,
help=('add "nocheck" to DEB_BUILD_OPTIONS'))
args = parser.parse_args()
dist = args.dist
repo = args.upload_repo
dsc_file = args.from_dsc
clean = args.clean
no_check = args.no_check
repo = args.upload_repo
source_zip = False
build_repo = []
if 'JOB_NAME' in os.environ:
clean = clean is not False
if dsc_file is None:
dsc_file = os.environ.get('DSC_URL')
if not dsc_file and os.path.exists('source.zip'):
source_zip = True
if dist is None:
dist = os.environ['DIST']
if repo is None and os.environ.get('PUBLISH') == 'true':
repo = os.environ.get('REPO', dist)
if no_check is None:
no_check = os.environ.get('NOCHECK') == 'true'
if os.environ.get('EXTRA_REPO'):
build_repo.extend(os.environ['EXTRA_REPO'].split(','))
if no_check:
os.environ['DEB_BUILD_OPTIONS'] = 'nocheck'
assert dist is not None, 'A target distribution is required'
if clean:
cleanup_workspace()
if source_zip:
LOG.info('extracting source.zip')
with zipfile.ZipFile('source.zip', 'r') as zfile:
zfile.extractall()
dsc_file = find_file('*.dsc')
if dsc_file:
unpack_dsc(dsc_file, args.source_dir)
with chdir(args.source_dir):
if dist not in ('unstable', 'testing'):
dch(dist)
dsc_file = build_source_package()
if not args.no_build:
build_binary_package(dsc_file, dist, build_repo=build_repo)
if 'JOB_NAME' in os.environ:
run('lintian-junit-report --warnings *.dsc *.changes > lintian.xml',
shell=True)
if repo:
upload(repo)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment