mirror of
https://gitlab.com/fdroid/fdroidserver.git
synced 2024-09-21 04:10:37 +02:00
wip
This commit is contained in:
parent
ffa9e74d3f
commit
2f2a09fe14
@ -19,58 +19,13 @@
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
import logging
|
||||
# import logging
|
||||
import argparse
|
||||
|
||||
from fdroidserver import _
|
||||
import fdroidserver.common
|
||||
|
||||
|
||||
def sudo_run(app, build):
|
||||
# before doing anything, run the sudo commands to setup the VM
|
||||
if build.sudo:
|
||||
logging.info("Running 'sudo' commands in %s" % os.getcwd())
|
||||
|
||||
p = fdroidserver.common.FDroidPopen(
|
||||
[
|
||||
'sudo',
|
||||
'DEBIAN_FRONTEND=noninteractive',
|
||||
'bash',
|
||||
'-e',
|
||||
'-u',
|
||||
'-o',
|
||||
'pipefail',
|
||||
'-x',
|
||||
'-c',
|
||||
'; '.join(build.sudo),
|
||||
]
|
||||
)
|
||||
if p.returncode != 0:
|
||||
raise BuildException(
|
||||
"Error running sudo command for %s:%s" % (app.id, build.versionName),
|
||||
p.output,
|
||||
)
|
||||
|
||||
|
||||
def sudo_lock_root(app, build):
|
||||
p = fdroidserver.common.FDroidPopen(['sudo', 'passwd', '--lock', 'root'])
|
||||
if p.returncode != 0:
|
||||
raise BuildException(
|
||||
"Error locking root account for %s:%s" % (app.id, build.versionName),
|
||||
p.output,
|
||||
)
|
||||
|
||||
|
||||
def sudo_uninstall(app, build):
|
||||
p = fdroidserver.common.FDroidPopen(
|
||||
['sudo', 'SUDO_FORCE_REMOVE=yes', 'dpkg', '--purge', 'sudo']
|
||||
)
|
||||
if p.returncode != 0:
|
||||
raise BuildException(
|
||||
"Error removing sudo for %s:%s" % (app.id, build.versionName), p.output
|
||||
)
|
||||
|
||||
|
||||
def log_tools_version(app, build, log_dir):
|
||||
log_path = os.path.join(
|
||||
log_dir, fdroidserver.common.get_toolsversion_logname(app, build)
|
||||
@ -86,24 +41,6 @@ def main():
|
||||
"for one specific build"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sudo-run",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help=_("run commands listed in sudo-metadata"),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sudo-uninstall",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help=_("uninstall sudo executing sudo-metadata"),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sudo-lock-root",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help=_("lock root user account"),
|
||||
)
|
||||
parser.add_argument(
|
||||
"APP_VERSION",
|
||||
help=_("app id and version code tuple 'APPID:VERCODE'"),
|
||||
@ -114,6 +51,8 @@ def main():
|
||||
options = fdroidserver.common.parse_args(parser)
|
||||
config = fdroidserver.common.get_config()
|
||||
|
||||
config # silence pyflakes
|
||||
|
||||
package_name, version_code = fdroidserver.common.split_pkg_arg(options.APP_VERSION)
|
||||
app, build = fdroidserver.metadata.read_build_metadata(package_name, version_code)
|
||||
|
||||
@ -126,17 +65,8 @@ def main():
|
||||
for d in (srclib_dir, extlib_dir, log_dir, output_dir):
|
||||
d.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
# run sudo stuff
|
||||
fdroidserver.common.set_FDroidPopen_env(build)
|
||||
if options.sudo_run:
|
||||
sudo_run(app, build)
|
||||
if options.sudo_lock_root:
|
||||
sudo_lock_root(app, build)
|
||||
if options.sudo_uninstall:
|
||||
sudo_uninstall(app, build)
|
||||
|
||||
# TODO: in the past this was only logged when running as 'fdroid build
|
||||
# --onserver' is this this output still valuable or can we remove it?
|
||||
# --onserver', is this output still valuable or can we remove it?
|
||||
log_tools_version(app, build, log_dir)
|
||||
|
||||
# do git/vcs checkout
|
||||
|
@ -1,8 +1,8 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import glob
|
||||
import shutil
|
||||
import gettext
|
||||
import logging
|
||||
import pathlib
|
||||
import tarfile
|
||||
@ -16,8 +16,17 @@ import fdroidserver.exception
|
||||
from fdroidserver import _
|
||||
|
||||
|
||||
def rlimit_check(apps_count):
|
||||
"""make sure enough open files are allowed to process everything"""
|
||||
def rlimit_check(apps_count=1):
|
||||
"""Make sure linux is confgured to allow for enough simultaneously oepn files.
|
||||
|
||||
TODO: check if this is obsolete
|
||||
|
||||
Parameters
|
||||
----------
|
||||
apps_count
|
||||
In the past this used to be `len(apps)` In this context we're
|
||||
always buidling just one app so this is always 1
|
||||
"""
|
||||
try:
|
||||
import resource # not available on Windows
|
||||
|
||||
@ -37,7 +46,18 @@ def rlimit_check(apps_count):
|
||||
pass
|
||||
|
||||
|
||||
def get_ndk_path(build):
|
||||
def install_ndk(build, config):
|
||||
"""Make sure the requested NDK version is or gets installed
|
||||
|
||||
TODO: check if this should be moved to a script that runs before starting
|
||||
the build. e.g. `build_local_prepare` or `build_local_sudo`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
build
|
||||
Metadata build entry that's about the build and may contain the
|
||||
requested NDK version
|
||||
"""
|
||||
ndk_path = build.ndk_path()
|
||||
if build.ndk or (build.buildjni and build.buildjni != ['no']):
|
||||
if not ndk_path:
|
||||
@ -47,13 +67,11 @@ def get_ndk_path(build):
|
||||
if k.endswith("_orig"):
|
||||
continue
|
||||
logging.warning(" %s: %s" % (k, v))
|
||||
if onserver:
|
||||
fdroidserver.common.auto_install_ndk(build)
|
||||
else:
|
||||
raise fdroidserver.exception.FDroidException()
|
||||
fdroidserver.common.auto_install_ndk(build)
|
||||
elif not os.path.isdir(ndk_path):
|
||||
logging.critical("Android NDK '%s' is not a directory!" % ndk_path)
|
||||
raise fdroidserver.exception.FDroidException()
|
||||
return ndk_path
|
||||
|
||||
|
||||
def get_build_root_dir(app, build):
|
||||
@ -71,7 +89,7 @@ def transform_first_char(string, method):
|
||||
return method(string[0]) + string[1:]
|
||||
|
||||
|
||||
def init_build_subprocess(app, build, config):
|
||||
def init_build(app, build, config):
|
||||
# We need to clean via the build tool in case the binary dirs are
|
||||
# different from the default ones
|
||||
root_dir = get_build_root_dir(app, build)
|
||||
@ -133,10 +151,21 @@ def init_build_subprocess(app, build, config):
|
||||
"Error cleaning %s:%s" % (app.id, build.versionName), p.output
|
||||
)
|
||||
|
||||
return p, gradletasks, flavours_cmd
|
||||
return gradletasks, flavours_cmd
|
||||
|
||||
|
||||
def sanitize_build_dir(app):
|
||||
"""delete build output directories
|
||||
|
||||
This function deletes the default build/binary/target/... output
|
||||
directories for follwoing build tools: gradle, maven, ant, jni. It also
|
||||
deletes gradle-wrapper if present.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
app
|
||||
The metadata of the app to sanitize
|
||||
"""
|
||||
build_dir = fdroidserver.common.get_build_dir(app)
|
||||
for root, dirs, files in os.walk(build_dir):
|
||||
|
||||
@ -206,9 +235,8 @@ def make_tarball(app, build, tmp_dir):
|
||||
tarball.close()
|
||||
|
||||
|
||||
def execute_build_commands(app, build):
|
||||
build_dir = fdroidserver.common.get_build_dir(app)
|
||||
srclibpaths = get_srclibpaths(build, build_dir)
|
||||
def execute_build_commands(app, build, srclibpaths):
|
||||
root_dir = get_build_root_dir(app, build)
|
||||
if build.build:
|
||||
logging.info("Running 'build' commands in %s" % root_dir)
|
||||
cmd = fdroidserver.common.replace_config_vars("; ".join(build.build), build)
|
||||
@ -228,22 +256,23 @@ def execute_build_commands(app, build):
|
||||
)
|
||||
|
||||
|
||||
def get_srclibpaths(build, srclib_dir):
|
||||
def checkout_srclibs(app, build):
|
||||
""""""
|
||||
build_dir = fdroidserver.common.get_build_dir(app)
|
||||
srclibpaths = []
|
||||
if build.srclibs:
|
||||
logging.info("Collecting source libraries")
|
||||
for lib in build.srclibs:
|
||||
srclibpaths.append(
|
||||
fdroidserver.common.getsrclib(
|
||||
lib, srclib_dir, preponly=onserver, refresh=refresh, build=build
|
||||
lib, build_dir, prepare=False, refresh=False, build=build
|
||||
)
|
||||
)
|
||||
return srclibpaths
|
||||
|
||||
|
||||
def execute_buildjni_commands(app, build):
|
||||
def execute_buildjni_commands(app, build, ndk_path):
|
||||
root_dir = get_build_root_dir(app, build)
|
||||
ndk_path = get_ndk_path(build)
|
||||
if build.buildjni and build.buildjni != ['no']:
|
||||
logging.info("Building the native code")
|
||||
jni_components = build.buildjni
|
||||
@ -274,11 +303,12 @@ def execute_buildjni_commands(app, build):
|
||||
)
|
||||
|
||||
|
||||
def execute_build___(app, build, config, gradletasks):
|
||||
def execute_build(app, build, config, gradletasks):
|
||||
build_dir = fdroidserver.common.get_build_dir(app)
|
||||
root_dir = get_build_root_dir(app, build)
|
||||
|
||||
p = None
|
||||
bindir = None
|
||||
bmethod = build.build_method()
|
||||
if bmethod == 'maven':
|
||||
logging.info("Building Maven project...")
|
||||
@ -344,221 +374,10 @@ def execute_build___(app, build, config, gradletasks):
|
||||
|
||||
bindir = os.path.join(root_dir, 'bin')
|
||||
|
||||
if os.path.isdir(os.path.join(build_dir, '.git')):
|
||||
import git
|
||||
|
||||
commit_id = fdroidserver.common.get_head_commit_id(git.repo.Repo(build_dir))
|
||||
else:
|
||||
commit_id = build.commit
|
||||
|
||||
if p is not None and p.returncode != 0:
|
||||
raise fdroidserver.exception.BuildException(
|
||||
"Build failed for %s:%s@%s" % (app.id, build.versionName, commit_id),
|
||||
p.output,
|
||||
)
|
||||
logging.info(
|
||||
"Successfully built version {versionName} of {appid} from {commit_id}".format(
|
||||
versionName=build.versionName, appid=app.id, commit_id=commit_id
|
||||
)
|
||||
)
|
||||
|
||||
return p
|
||||
return p, bindir
|
||||
|
||||
|
||||
def collect_build_output(app, build, p, flavours_cmd):
|
||||
root_dir = get_build_root_dir(app, build)
|
||||
|
||||
omethod = build.output_method()
|
||||
if omethod == 'maven':
|
||||
stdout_apk = '\n'.join(
|
||||
[
|
||||
line
|
||||
for line in p.output.splitlines()
|
||||
if any(a in line for a in ('.apk', '.ap_', '.jar'))
|
||||
]
|
||||
)
|
||||
m = re.match(
|
||||
r".*^\[INFO\] .*apkbuilder.*/([^/]*)\.apk", stdout_apk, re.S | re.M
|
||||
)
|
||||
if not m:
|
||||
m = re.match(
|
||||
r".*^\[INFO\] Creating additional unsigned apk file .*/([^/]+)\.apk[^l]",
|
||||
stdout_apk,
|
||||
re.S | re.M,
|
||||
)
|
||||
if not m:
|
||||
m = re.match(
|
||||
r'.*^\[INFO\] [^$]*aapt \[package,[^$]*'
|
||||
+ bindir
|
||||
+ r'/([^/]+)\.ap[_k][,\]]',
|
||||
stdout_apk,
|
||||
re.S | re.M,
|
||||
)
|
||||
|
||||
if not m:
|
||||
m = re.match(
|
||||
r".*^\[INFO\] Building jar: .*/" + bindir + r"/(.+)\.jar",
|
||||
stdout_apk,
|
||||
re.S | re.M,
|
||||
)
|
||||
if not m:
|
||||
raise fdroidserver.exception.BuildException('Failed to find output')
|
||||
src = m.group(1)
|
||||
src = os.path.join(bindir, src) + '.apk'
|
||||
|
||||
elif omethod == 'gradle':
|
||||
src = None
|
||||
apk_dirs = [
|
||||
# gradle plugin >= 3.0
|
||||
os.path.join(root_dir, 'build', 'outputs', 'apk', 'release'),
|
||||
# gradle plugin < 3.0 and >= 0.11
|
||||
os.path.join(root_dir, 'build', 'outputs', 'apk'),
|
||||
# really old path
|
||||
os.path.join(root_dir, 'build', 'apk'),
|
||||
]
|
||||
# If we build with gradle flavours with gradle plugin >= 3.0 the APK will be in
|
||||
# a subdirectory corresponding to the flavour command used, but with different
|
||||
# capitalization.
|
||||
if flavours_cmd:
|
||||
apk_dirs.append(
|
||||
os.path.join(
|
||||
root_dir,
|
||||
'build',
|
||||
'outputs',
|
||||
'apk',
|
||||
transform_first_char(flavours_cmd, str.lower),
|
||||
'release',
|
||||
)
|
||||
)
|
||||
for apks_dir in apk_dirs:
|
||||
for apkglob in ['*-release-unsigned.apk', '*-unsigned.apk', '*.apk']:
|
||||
apks = glob.glob(os.path.join(apks_dir, apkglob))
|
||||
|
||||
if len(apks) > 1:
|
||||
raise fdroidserver.exception.BuildException(
|
||||
'More than one resulting apks found in %s' % apks_dir,
|
||||
'\n'.join(apks),
|
||||
)
|
||||
if len(apks) == 1:
|
||||
src = apks[0]
|
||||
break
|
||||
if src is not None:
|
||||
break
|
||||
|
||||
if src is None:
|
||||
raise fdroidserver.exception.BuildException('Failed to find any output apks')
|
||||
|
||||
elif omethod == 'ant':
|
||||
stdout_apk = '\n'.join(
|
||||
[line for line in p.output.splitlines() if '.apk' in line]
|
||||
)
|
||||
src = re.match(
|
||||
r".*^.*Creating (.+) for release.*$.*", stdout_apk, re.S | re.M
|
||||
).group(1)
|
||||
src = os.path.join(bindir, src)
|
||||
elif omethod == 'raw':
|
||||
output_path = fdroidserver.common.replace_build_vars(build.output, build)
|
||||
globpath = os.path.join(root_dir, output_path)
|
||||
apks = glob.glob(globpath)
|
||||
if len(apks) > 1:
|
||||
raise fdroidserver.exception.BuildException('Multiple apks match %s' % globpath, '\n'.join(apks))
|
||||
if len(apks) < 1:
|
||||
raise fdroidserver.exception.BuildException('No apks match %s' % globpath)
|
||||
src = os.path.normpath(apks[0])
|
||||
|
||||
|
||||
def buildbuildbuild___(app, build, config, gradletasks):
|
||||
root_dir = get_build_root_dir(app, build)
|
||||
|
||||
bmethod = build.build_method()
|
||||
if bmethod == 'maven':
|
||||
logging.info("Building Maven project...")
|
||||
|
||||
if '@' in build.maven:
|
||||
maven_dir = os.path.join(root_dir, build.maven.split('@', 1)[1])
|
||||
else:
|
||||
maven_dir = root_dir
|
||||
|
||||
mvncmd = [
|
||||
config['mvn3'],
|
||||
'-Dandroid.sdk.path=' + config['sdk_path'],
|
||||
'-Dmaven.jar.sign.skip=true',
|
||||
'-Dmaven.test.skip=true',
|
||||
'-Dandroid.sign.debug=false',
|
||||
'-Dandroid.release=true',
|
||||
'package',
|
||||
]
|
||||
if build.target:
|
||||
target = build.target.split('-')[1]
|
||||
fdroidserver.common.regsub_file(
|
||||
r'<platform>[0-9]*</platform>',
|
||||
r'<platform>%s</platform>' % target,
|
||||
os.path.join(root_dir, 'pom.xml'),
|
||||
)
|
||||
if '@' in build.maven:
|
||||
fdroidserver.common.regsub_file(
|
||||
r'<platform>[0-9]*</platform>',
|
||||
r'<platform>%s</platform>' % target,
|
||||
os.path.join(maven_dir, 'pom.xml'),
|
||||
)
|
||||
|
||||
p = fdroidserver.common.FDroidPopen(mvncmd, cwd=maven_dir)
|
||||
|
||||
bindir = os.path.join(root_dir, 'target')
|
||||
|
||||
elif bmethod == 'gradle':
|
||||
logging.info("Building Gradle project...")
|
||||
|
||||
cmd = [config['gradle']]
|
||||
if build.gradleprops:
|
||||
cmd += ['-P' + kv for kv in build.gradleprops]
|
||||
|
||||
cmd += gradletasks
|
||||
|
||||
p = fdroidserver.common.FDroidPopen(
|
||||
cmd,
|
||||
cwd=root_dir,
|
||||
envs={
|
||||
"GRADLE_VERSION_DIR": config['gradle_version_dir'],
|
||||
"CACHEDIR": config['cachedir'],
|
||||
},
|
||||
)
|
||||
|
||||
elif bmethod == 'ant':
|
||||
logging.info("Building Ant project...")
|
||||
cmd = ['ant']
|
||||
if build.antcommands:
|
||||
cmd += build.antcommands
|
||||
else:
|
||||
cmd += ['release']
|
||||
p = fdroidserver.common.FDroidPopen(cmd, cwd=root_dir)
|
||||
|
||||
bindir = os.path.join(root_dir, 'bin')
|
||||
|
||||
|
||||
def check_build_success(app, build, p):
|
||||
build_dir = fdroidserver.common.get_build_dir(app)
|
||||
|
||||
if os.path.isdir(os.path.join(build_dir, '.git')):
|
||||
import git
|
||||
|
||||
commit_id = fdroidserver.common.get_head_commit_id(git.repo.Repo(build_dir))
|
||||
else:
|
||||
commit_id = build.commit
|
||||
|
||||
if p is not None and p.returncode != 0:
|
||||
raise fdroidserver.exception.BuildException(
|
||||
"Build failed for %s:%s@%s" % (app.id, build.versionName, commit_id),
|
||||
p.output,
|
||||
)
|
||||
logging.info(
|
||||
"Successfully built version {versionName} of {appid} from {commit_id}".format(
|
||||
versionName=build.versionName, appid=app.id, commit_id=commit_id
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def collect_output_again(app, build, p, flavours_cmd):
|
||||
def collect_build_output(app, build, p, flavours_cmd, bindir):
|
||||
root_dir = get_build_root_dir(app, build)
|
||||
|
||||
omethod = build.output_method()
|
||||
@ -640,7 +459,9 @@ def collect_output_again(app, build, p, flavours_cmd):
|
||||
break
|
||||
|
||||
if src is None:
|
||||
raise fdroidserver.exception.BuildException('Failed to find any output apks')
|
||||
raise fdroidserver.exception.BuildException(
|
||||
'Failed to find any output apks'
|
||||
)
|
||||
|
||||
elif omethod == 'ant':
|
||||
stdout_apk = '\n'.join(
|
||||
@ -655,17 +476,39 @@ def collect_output_again(app, build, p, flavours_cmd):
|
||||
globpath = os.path.join(root_dir, output_path)
|
||||
apks = glob.glob(globpath)
|
||||
if len(apks) > 1:
|
||||
raise fdroidserver.exception.BuildException('Multiple apks match %s' % globpath, '\n'.join(apks))
|
||||
raise fdroidserver.exception.BuildException(
|
||||
'Multiple apks match %s' % globpath, '\n'.join(apks)
|
||||
)
|
||||
if len(apks) < 1:
|
||||
raise fdroidserver.exception.BuildException('No apks match %s' % globpath)
|
||||
src = os.path.normpath(apks[0])
|
||||
return src
|
||||
|
||||
|
||||
def execute_postbuild(app, build, src):
|
||||
def check_build_success(app, build, p):
|
||||
build_dir = fdroidserver.common.get_build_dir(app)
|
||||
|
||||
if os.path.isdir(os.path.join(build_dir, '.git')):
|
||||
import git
|
||||
|
||||
commit_id = fdroidserver.common.get_head_commit_id(git.repo.Repo(build_dir))
|
||||
else:
|
||||
commit_id = build.commit
|
||||
|
||||
if p is not None and p.returncode != 0:
|
||||
raise fdroidserver.exception.BuildException(
|
||||
"Build failed for %s:%s@%s" % (app.id, build.versionName, commit_id),
|
||||
p.output,
|
||||
)
|
||||
logging.info(
|
||||
"Successfully built version {versionName} of {appid} from {commit_id}".format(
|
||||
versionName=build.versionName, appid=app.id, commit_id=commit_id
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def execute_postbuild(app, build, src, srclibpaths):
|
||||
root_dir = get_build_root_dir(app, build)
|
||||
srclibpaths = get_srclibpaths(build, build_dir)
|
||||
|
||||
if build.postbuild:
|
||||
logging.info(f"Running 'postbuild' commands in {root_dir}")
|
||||
@ -673,9 +516,9 @@ def execute_postbuild(app, build, src):
|
||||
|
||||
# Substitute source library paths into commands...
|
||||
for name, number, libpath in srclibpaths:
|
||||
cmd = cmd.replace(f"$${name}$$", str(Path.cwd() / libpath))
|
||||
cmd = cmd.replace(f"$${name}$$", str(pathlib.Path.cwd() / libpath))
|
||||
|
||||
cmd = cmd.replace('$$OUT$$', str(Path(src).resolve()))
|
||||
cmd = cmd.replace('$$OUT$$', str(pathlib.Path(src).resolve()))
|
||||
|
||||
p = fdroidserver.common.FDroidPopen(
|
||||
['bash', '-e', '-u', '-o', 'pipefail', '-x', '-c', cmd], cwd=root_dir
|
||||
@ -722,14 +565,20 @@ def get_metadata_from_apk(app, build, apkfile):
|
||||
native_code = fdroidserver.common.get_native_code(apkfile)
|
||||
|
||||
if build.buildjni and build.buildjni != ['no'] and not native_code:
|
||||
raise fdroidserver.exception.BuildException("Native code should have been built but none was packaged")
|
||||
raise fdroidserver.exception.BuildException(
|
||||
"Native code should have been built but none was packaged"
|
||||
)
|
||||
if build.novcheck:
|
||||
versionCode = build.versionCode
|
||||
versionName = build.versionName
|
||||
if not versionCode or versionName is None:
|
||||
raise fdroidserver.exception.BuildException("Could not find version information in build in output")
|
||||
raise fdroidserver.exception.BuildException(
|
||||
"Could not find version information in build in output"
|
||||
)
|
||||
if not appid:
|
||||
raise fdroidserver.exception.BuildException("Could not find package ID in output")
|
||||
raise fdroidserver.exception.BuildException(
|
||||
"Could not find package ID in output"
|
||||
)
|
||||
if appid != app.id:
|
||||
raise fdroidserver.exception.BuildException(
|
||||
"Wrong package ID - build " + appid + " but expected " + app.id
|
||||
@ -749,7 +598,9 @@ def validate_build_artifacts(app, build, src):
|
||||
# code in our new APK match what we expect...
|
||||
logging.debug("Checking " + src)
|
||||
if not os.path.exists(src):
|
||||
raise fdroidserver.exception.BuildException("Unsigned APK is not at expected location of " + src)
|
||||
raise fdroidserver.exception.BuildException(
|
||||
"Unsigned APK is not at expected location of " + src
|
||||
)
|
||||
|
||||
if fdroidserver.common.get_file_extension(src) == 'apk':
|
||||
vercode, version = get_metadata_from_apk(app, build, src)
|
||||
@ -792,7 +643,7 @@ def run_this_build(config, options, package_name, version_code):
|
||||
|
||||
# not sure if this makes any sense to change open file limits since we know
|
||||
# that this script will only ever build one app
|
||||
rlimit_check(1)
|
||||
rlimit_check()
|
||||
|
||||
logging.info(
|
||||
"Building version %s (%s) of %s"
|
||||
@ -801,7 +652,7 @@ def run_this_build(config, options, package_name, version_code):
|
||||
|
||||
# init fdroid Popen wrapper
|
||||
fdroidserver.common.set_FDroidPopen_env(build)
|
||||
p, gradletasks, flavours_cmd = init_build_subprocess(app, build, config)
|
||||
gradletasks, flavours_cmd = init_build(app, build, config)
|
||||
|
||||
sanitize_build_dir(app)
|
||||
|
||||
@ -814,20 +665,20 @@ def run_this_build(config, options, package_name, version_code):
|
||||
make_tarball(app, build, tmp_dir)
|
||||
|
||||
# Run a build command if one is required...
|
||||
execute_build_commands(app, build)
|
||||
srclibpaths = checkout_srclibs(app, build)
|
||||
execute_build_commands(app, build, srclibpaths)
|
||||
|
||||
# Build native stuff if required...
|
||||
execute_buildjni_commands(app, build)
|
||||
ndk_path = install_ndk(build, config) # TODO: move to prepare step?
|
||||
execute_buildjni_commands(app, build, ndk_path)
|
||||
|
||||
# Build the release...
|
||||
p = execute_build___(app, build, config, gradletasks)
|
||||
collect_build_output(app, build, p, flavours_cmd)
|
||||
buildbuildbuild___(app, build, config, gradletasks)
|
||||
p, bindir = execute_build(app, build, config, gradletasks)
|
||||
check_build_success(app, build, p)
|
||||
src = collect_output_again(app, build, p, flavours_cmd)
|
||||
src = collect_build_output(app, build, p, flavours_cmd, bindir)
|
||||
|
||||
# Run a postbuild command if one is required...
|
||||
execute_postbuild(app, build, src)
|
||||
execute_postbuild(app, build, src, srclibpaths)
|
||||
|
||||
validate_build_artifacts(app, build, src)
|
||||
|
||||
@ -835,6 +686,7 @@ def run_this_build(config, options, package_name, version_code):
|
||||
|
||||
move_build_output(app, build, src, tmp_dir)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description=_(
|
||||
@ -844,7 +696,8 @@ def main():
|
||||
)
|
||||
)
|
||||
parser.add_argument(
|
||||
"APP_VERSION", help=_("app id and version code tuple (e.g. org.fdroid.fdroid:1019051)")
|
||||
"APP_VERSION",
|
||||
help=_("app id and version code tuple (e.g. org.fdroid.fdroid:1019051)"),
|
||||
)
|
||||
|
||||
# fdroid args/opts boilerplate
|
||||
|
104
fdroidserver/build_local_sudo.py
Normal file
104
fdroidserver/build_local_sudo.py
Normal file
@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# build.py - part of the FDroid server tools
|
||||
# Copyright (C) 2024, Michael Pöhn <michael@poehn.at>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import os
|
||||
import logging
|
||||
import argparse
|
||||
|
||||
from fdroidserver import _
|
||||
import fdroidserver.common
|
||||
|
||||
|
||||
def sudo_run(app, build):
|
||||
# before doing anything, run the sudo commands to setup the VM
|
||||
if build.sudo:
|
||||
logging.info("Running 'sudo' commands in %s" % os.getcwd())
|
||||
|
||||
p = fdroidserver.common.FDroidPopen(
|
||||
[
|
||||
'sudo',
|
||||
'DEBIAN_FRONTEND=noninteractive',
|
||||
'bash',
|
||||
'-e',
|
||||
'-u',
|
||||
'-o',
|
||||
'pipefail',
|
||||
'-x',
|
||||
'-c',
|
||||
'; '.join(build.sudo),
|
||||
]
|
||||
)
|
||||
if p.returncode != 0:
|
||||
raise fdroidserver.exception.BuildException(
|
||||
"Error running sudo command for %s:%s" % (app.id, build.versionName),
|
||||
p.output,
|
||||
)
|
||||
|
||||
|
||||
def sudo_lock_root(app, build):
|
||||
p = fdroidserver.common.FDroidPopen(['sudo', 'passwd', '--lock', 'root'])
|
||||
if p.returncode != 0:
|
||||
raise fdroidserver.exception.BuildException(
|
||||
"Error locking root account for %s:%s" % (app.id, build.versionName),
|
||||
p.output,
|
||||
)
|
||||
|
||||
|
||||
def sudo_uninstall(app, build):
|
||||
p = fdroidserver.common.FDroidPopen(
|
||||
['sudo', 'SUDO_FORCE_REMOVE=yes', 'dpkg', '--purge', 'sudo']
|
||||
)
|
||||
if p.returncode != 0:
|
||||
raise fdroidserver.exception.BuildException(
|
||||
"Error removing sudo for %s:%s" % (app.id, build.versionName), p.output
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description=_(
|
||||
"""Run sudo commands """
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"APP_VERSION",
|
||||
help=_("app id and version code tuple 'APPID:VERCODE'"),
|
||||
)
|
||||
|
||||
# fdroid args/opts boilerplate
|
||||
fdroidserver.common.setup_global_opts(parser)
|
||||
options = fdroidserver.common.parse_args(parser)
|
||||
config = fdroidserver.common.get_config()
|
||||
config # silcense pyflakes
|
||||
|
||||
package_name, version_code = fdroidserver.common.split_pkg_arg(options.APP_VERSION)
|
||||
app, build = fdroidserver.metadata.read_build_metadata(package_name, version_code)
|
||||
|
||||
|
||||
# intialize FDroidPopen
|
||||
# TODO: remove once FDroidPopen is replaced with vm/container exec
|
||||
fdroidserver.common.set_FDroidPopen_env(build)
|
||||
|
||||
# run sudo stuff
|
||||
sudo_run(app, build)
|
||||
sudo_lock_root(app, build)
|
||||
sudo_uninstall(app, build)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
69
tests/build_local_run.TestCase
Executable file
69
tests/build_local_run.TestCase
Executable file
@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
# import json
|
||||
# import shutil
|
||||
# import logging
|
||||
import inspect
|
||||
# import tempfile
|
||||
import unittest
|
||||
import unittest.mock
|
||||
|
||||
localmodule = os.path.realpath(
|
||||
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
|
||||
)
|
||||
print('localmodule: ' + localmodule)
|
||||
if localmodule not in sys.path:
|
||||
sys.path.insert(0, localmodule)
|
||||
|
||||
import fdroidserver.build_local_run
|
||||
import fdroidserver.metadata
|
||||
|
||||
|
||||
class GetBuildRootDirTest(unittest.TestCase):
|
||||
def test_no_subdir(self):
|
||||
app = unittest.mock.MagicMock()
|
||||
app.id = "fake.app"
|
||||
build = unittest.mock.MagicMock()
|
||||
build.subdir = None
|
||||
|
||||
gbdmock = unittest.mock.Mock(return_value="ok")
|
||||
with unittest.mock.patch("fdroidserver.common.get_build_dir", gbdmock):
|
||||
r = fdroidserver.build_local_run.get_build_root_dir(app, build)
|
||||
|
||||
gbdmock.assert_called_once_with(app)
|
||||
self.assertEqual(r, "ok")
|
||||
|
||||
def test_subdir(self):
|
||||
app = unittest.mock.MagicMock()
|
||||
app.id = "fake.app"
|
||||
build = unittest.mock.MagicMock()
|
||||
build.subdir = "abc/def"
|
||||
|
||||
gbdmock = unittest.mock.Mock(return_value="ok")
|
||||
with unittest.mock.patch("fdroidserver.common.get_build_dir", gbdmock):
|
||||
r = fdroidserver.build_local_run.get_build_root_dir(app, build)
|
||||
|
||||
gbdmock.assert_called_once_with(app)
|
||||
self.assertEqual(r, "ok/abc/def")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.chdir(os.path.dirname(__file__))
|
||||
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"-v",
|
||||
"--verbose",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Spew out even more information than normal",
|
||||
)
|
||||
fdroidserver.common.options = fdroidserver.common.parse_args(parser)
|
||||
|
||||
newSuite = unittest.TestSuite()
|
||||
newSuite.addTest(unittest.makeSuite(GetBuildRootDirTest))
|
||||
unittest.main(failfast=False)
|
Loading…
Reference in New Issue
Block a user