From 9e9fffc899c41eccd031212ef0af23c78fc7a1c6 Mon Sep 17 00:00:00 2001 From: Jonas Gunz Date: Thu, 26 Jan 2023 19:46:44 +0100 Subject: structure --- Dockerfile | 27 -------- bin/buildpackage.sh | 26 -------- bin/getpackage.py | 159 --------------------------------------------- docker/Dockerfile | 27 ++++++++ docker/bin/buildpackage.sh | 26 ++++++++ docker/bin/getpackage.py | 159 +++++++++++++++++++++++++++++++++++++++++++++ docker/sudoers | 2 + sudoers | 2 - 8 files changed, 214 insertions(+), 214 deletions(-) delete mode 100644 Dockerfile delete mode 100755 bin/buildpackage.sh delete mode 100755 bin/getpackage.py create mode 100644 docker/Dockerfile create mode 100755 docker/bin/buildpackage.sh create mode 100755 docker/bin/getpackage.py create mode 100644 docker/sudoers delete mode 100644 sudoers diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index f7b5e7f..0000000 --- a/Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -FROM archlinux:base-devel - -ENV PACKAGE_NAME="" -ENV PACKAGER="John Doe " -ENV ARCH="x86_64" -ENV FORCE_REBUILD="no" -ENV CHOWN="" - -RUN pacman --noconfirm -Syu -RUN pacman --noconfirm -S git sudo - -RUN groupadd sudo -RUN useradd -G sudo -d /workdir -m aurbuilder -COPY --chown=root:root sudoers /etc/sudoers - - -RUN mkdir /pkgout -VOLUME /pkgout - -RUN pacman --noconfirm -S python python-requests - -RUN mkdir -p /opt/aurbuilder - -COPY --chown=root:root bin/ /opt/aurbuilder -ENV PATH="${PATH}:/opt/aurbuilder" - -CMD buildpackage.sh diff --git a/bin/buildpackage.sh b/bin/buildpackage.sh deleted file mode 100755 index ace52fd..0000000 --- a/bin/buildpackage.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -echo "BUILDING: $PACKAGE_NAME" -echo "PACKAGER: $PACKAGER" - -cd /workdir || exit 1 - -while read -r NAME BASE VER _; do - echo "$NAME $VER for $ARCH" - OUTNAME="$NAME-$VER-$ARCH.pkg" - - # Only build when needed - if [ ! "$FORCE_REBUILD" = "yes" ] && compgen -G "/pkgout/${OUTNAME}*"; then - echo "$NAME $VER ($ARCH) is already built. Skipping." - continue - fi - - sudo -u aurbuilder git clone "https://aur.archlinux.org/$BASE.git" "$BASE" - cd "$BASE" || exit 1 - - sudo -u aurbuilder CARCH="$ARCH" PACKAGER="$PACKAGER" PKGDEST="/pkgout/" \ - makepkg --force --syncdeps --noconfirm --install - - #cp ./*.pkg.tar.zst /pkgout - test -n "$CHOWN" && sudo chown "$CHOWN" "/pkgout/${OUTNAME}"* -done <<< "$(getpackage.py "$PACKAGE_NAME")" diff --git a/bin/getpackage.py b/bin/getpackage.py deleted file mode 100755 index 0091dd6..0000000 --- a/bin/getpackage.py +++ /dev/null @@ -1,159 +0,0 @@ -#!/usr/bin/env python3 -# Create a list of package names required to build supplied AUR package. -# packages present in the official repos will be ignored. - -# relevant docs: -# AUR API: -# https://wiki.archlinux.org/title/Aurweb_RPC_interface -# Package API: -# https://wiki.archlinux.org/title/Official_repositories_web_interface - -import os -import sys -import requests -import json - -#from packaging import version -#version.parse - -def eprint(*args, **kwargs): - print(*args, file=sys.stderr, **kwargs) - - -# TODO we should actually use version limits instead -def sanitize_name(_name): - _name = _name.replace('<','=') - _name = _name.replace('>','=') - - return _name.split('=')[0] - - -# TODO: Don't just take the first one. prioritize maybe Votes, version, git, bin, ... -def aur_search_package(_name): - _name = sanitize_name(_name) - - data = requests.get(f'https://aur.archlinux.org/rpc/?v=5&type=search&by=name&arg={_name}').json() - - for r in data['results']: - p = aur_get_package(r['Name']) - if p is None: - continue - - if 'Provides' in p: - for prov in p['Provides']: - if sanitize_name(prov) == _name: - return p - - return None - - -def aur_get_package(_name): - _name = sanitize_name(_name) - - data = requests.get(f'https://aur.archlinux.org/rpc/?v=5&type=info&arg={_name}').json() - - if len(data['results']) != 1: - return aur_search_package(_name) - - return data['results'][0] - - -def repo_search_package(_name): - _name = sanitize_name(_name) - - data = requests.get(f'https://archlinux.org/packages/search/json/?q={_name}').json() - for r in data['results']: - p = repo_get_package(r['pkgname'], False) - if p is None: - continue - - if 'provides' in p: - for prov in p['provides']: - if sanitize_name(prov) == _name: - return p - - return None - - -def repo_get_package(_name, _search=True): - _name = sanitize_name(_name) - - data = requests.get(f'https://archlinux.org/packages/search/json/?name={_name}').json() - - if len(data['results']) != 1: - if _search: - return repo_search_package(_name) - else: - return None - - return data['results'][0] - - -def build_aur_dependencies(_pkgname): - _pkgname = sanitize_name(_pkgname) - - ret = [] - - maybe_deps = aur_get_package(_pkgname) - if maybe_deps is None: - eprint(f'WARNING: {_pkgname} Was not found in AUR!') - return [] - elif 'Depends' not in maybe_deps: - return [] - - deps = maybe_deps['Depends'] - - for dep in deps: - # if package exists in official repo - if repo_get_package(dep) is not None: - continue - - # detect depency cycles - if dep in ret: - continue - - ret.append(dep) - ret.insert(0,dep) - ret = build_aur_dependencies(dep) + ret - - return ret - -if len(sys.argv) <= 1: - eprint('CRITICAL: No package name provided.') - exit(1) - -PKG=sys.argv[1] - -# name: version -TO_BUILD={} - -maybe_base_pkg_info = aur_get_package(PKG) -if maybe_base_pkg_info is None: - eprint(f'CRITICAL: Package {PKG} not found in AUR') - exit(1) -base_pkg_info = maybe_base_pkg_info - -aur_deps = build_aur_dependencies(PKG) - -# We rely on the rigth order here. -# The dependency must be before the package that depends on it, -# otherwise makepkg will fail -for dep in aur_deps: - pkg = aur_get_package(dep) - - if pkg is None: - eprint(f'WARNING: Dependency {dep} Unmet!') - continue - - TO_BUILD[pkg['Name']] = { - 'version':pkg['Version'], - 'base':pkg['PackageBase'] - } - -TO_BUILD[base_pkg_info['Name']] = { - 'version':base_pkg_info['Version'], - 'base':base_pkg_info['PackageBase'] - } - -for e in TO_BUILD: - print(f'{e}\t{TO_BUILD[e]["base"]}\t{TO_BUILD[e]["version"]}') diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..f7b5e7f --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,27 @@ +FROM archlinux:base-devel + +ENV PACKAGE_NAME="" +ENV PACKAGER="John Doe " +ENV ARCH="x86_64" +ENV FORCE_REBUILD="no" +ENV CHOWN="" + +RUN pacman --noconfirm -Syu +RUN pacman --noconfirm -S git sudo + +RUN groupadd sudo +RUN useradd -G sudo -d /workdir -m aurbuilder +COPY --chown=root:root sudoers /etc/sudoers + + +RUN mkdir /pkgout +VOLUME /pkgout + +RUN pacman --noconfirm -S python python-requests + +RUN mkdir -p /opt/aurbuilder + +COPY --chown=root:root bin/ /opt/aurbuilder +ENV PATH="${PATH}:/opt/aurbuilder" + +CMD buildpackage.sh diff --git a/docker/bin/buildpackage.sh b/docker/bin/buildpackage.sh new file mode 100755 index 0000000..ace52fd --- /dev/null +++ b/docker/bin/buildpackage.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +echo "BUILDING: $PACKAGE_NAME" +echo "PACKAGER: $PACKAGER" + +cd /workdir || exit 1 + +while read -r NAME BASE VER _; do + echo "$NAME $VER for $ARCH" + OUTNAME="$NAME-$VER-$ARCH.pkg" + + # Only build when needed + if [ ! "$FORCE_REBUILD" = "yes" ] && compgen -G "/pkgout/${OUTNAME}*"; then + echo "$NAME $VER ($ARCH) is already built. Skipping." + continue + fi + + sudo -u aurbuilder git clone "https://aur.archlinux.org/$BASE.git" "$BASE" + cd "$BASE" || exit 1 + + sudo -u aurbuilder CARCH="$ARCH" PACKAGER="$PACKAGER" PKGDEST="/pkgout/" \ + makepkg --force --syncdeps --noconfirm --install + + #cp ./*.pkg.tar.zst /pkgout + test -n "$CHOWN" && sudo chown "$CHOWN" "/pkgout/${OUTNAME}"* +done <<< "$(getpackage.py "$PACKAGE_NAME")" diff --git a/docker/bin/getpackage.py b/docker/bin/getpackage.py new file mode 100755 index 0000000..0091dd6 --- /dev/null +++ b/docker/bin/getpackage.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python3 +# Create a list of package names required to build supplied AUR package. +# packages present in the official repos will be ignored. + +# relevant docs: +# AUR API: +# https://wiki.archlinux.org/title/Aurweb_RPC_interface +# Package API: +# https://wiki.archlinux.org/title/Official_repositories_web_interface + +import os +import sys +import requests +import json + +#from packaging import version +#version.parse + +def eprint(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + + +# TODO we should actually use version limits instead +def sanitize_name(_name): + _name = _name.replace('<','=') + _name = _name.replace('>','=') + + return _name.split('=')[0] + + +# TODO: Don't just take the first one. prioritize maybe Votes, version, git, bin, ... +def aur_search_package(_name): + _name = sanitize_name(_name) + + data = requests.get(f'https://aur.archlinux.org/rpc/?v=5&type=search&by=name&arg={_name}').json() + + for r in data['results']: + p = aur_get_package(r['Name']) + if p is None: + continue + + if 'Provides' in p: + for prov in p['Provides']: + if sanitize_name(prov) == _name: + return p + + return None + + +def aur_get_package(_name): + _name = sanitize_name(_name) + + data = requests.get(f'https://aur.archlinux.org/rpc/?v=5&type=info&arg={_name}').json() + + if len(data['results']) != 1: + return aur_search_package(_name) + + return data['results'][0] + + +def repo_search_package(_name): + _name = sanitize_name(_name) + + data = requests.get(f'https://archlinux.org/packages/search/json/?q={_name}').json() + for r in data['results']: + p = repo_get_package(r['pkgname'], False) + if p is None: + continue + + if 'provides' in p: + for prov in p['provides']: + if sanitize_name(prov) == _name: + return p + + return None + + +def repo_get_package(_name, _search=True): + _name = sanitize_name(_name) + + data = requests.get(f'https://archlinux.org/packages/search/json/?name={_name}').json() + + if len(data['results']) != 1: + if _search: + return repo_search_package(_name) + else: + return None + + return data['results'][0] + + +def build_aur_dependencies(_pkgname): + _pkgname = sanitize_name(_pkgname) + + ret = [] + + maybe_deps = aur_get_package(_pkgname) + if maybe_deps is None: + eprint(f'WARNING: {_pkgname} Was not found in AUR!') + return [] + elif 'Depends' not in maybe_deps: + return [] + + deps = maybe_deps['Depends'] + + for dep in deps: + # if package exists in official repo + if repo_get_package(dep) is not None: + continue + + # detect depency cycles + if dep in ret: + continue + + ret.append(dep) + ret.insert(0,dep) + ret = build_aur_dependencies(dep) + ret + + return ret + +if len(sys.argv) <= 1: + eprint('CRITICAL: No package name provided.') + exit(1) + +PKG=sys.argv[1] + +# name: version +TO_BUILD={} + +maybe_base_pkg_info = aur_get_package(PKG) +if maybe_base_pkg_info is None: + eprint(f'CRITICAL: Package {PKG} not found in AUR') + exit(1) +base_pkg_info = maybe_base_pkg_info + +aur_deps = build_aur_dependencies(PKG) + +# We rely on the rigth order here. +# The dependency must be before the package that depends on it, +# otherwise makepkg will fail +for dep in aur_deps: + pkg = aur_get_package(dep) + + if pkg is None: + eprint(f'WARNING: Dependency {dep} Unmet!') + continue + + TO_BUILD[pkg['Name']] = { + 'version':pkg['Version'], + 'base':pkg['PackageBase'] + } + +TO_BUILD[base_pkg_info['Name']] = { + 'version':base_pkg_info['Version'], + 'base':base_pkg_info['PackageBase'] + } + +for e in TO_BUILD: + print(f'{e}\t{TO_BUILD[e]["base"]}\t{TO_BUILD[e]["version"]}') diff --git a/docker/sudoers b/docker/sudoers new file mode 100644 index 0000000..d023346 --- /dev/null +++ b/docker/sudoers @@ -0,0 +1,2 @@ +root ALL=(ALL) ALL +%sudo ALL=(ALL) NOPASSWD: ALL diff --git a/sudoers b/sudoers deleted file mode 100644 index d023346..0000000 --- a/sudoers +++ /dev/null @@ -1,2 +0,0 @@ -root ALL=(ALL) ALL -%sudo ALL=(ALL) NOPASSWD: ALL -- cgit v1.2.3