mirror of
https://gitlab.com/fdroid/fdroidserver.git
synced 2024-10-05 18:50:09 +02:00
Merge branch 'fdroid-yml-builds' into 'master'
builds straight from source repo using .fdroid.yml The overarching theme of the merge request is allowing _.fdroid.yml_ to be included in an app's source repo, then letting `fdroid build` build the app straight out of the git repo without requiring a setup like _fdroiddata_ (e.g. _config.py_, _metadata/packagename.txt_, etc.). _fdroiddata_ repos can then include source repos with a _.fdroid.yml_ by having _metadata/packagename.txt_ that includes just: ``` Repo Type:git Repo:https://gitlab.com/upstream/app.git ``` Any other metadata fields that are included in _metadata/packagename.txt_ will override what is in _.fdroid.yml_, giving the repo manager the final say about what is included in their repo. This setup provides a number of benefits: * CI systems like jenkins, travis, gitlab-ci can build from _.fdroid.yml_ * very easy to start building apps using `fdroid build`, no separate repo needed * some maintenance can be offloaded to the upstream dev See merge request !184
This commit is contained in:
commit
d7ec321198
8
.gitignore
vendored
8
.gitignore
vendored
@ -16,7 +16,7 @@ docs/html/
|
|||||||
|
|
||||||
# files generated by tests
|
# files generated by tests
|
||||||
tmp/
|
tmp/
|
||||||
tests/repo/icons*
|
/tests/repo/icons*
|
||||||
|
|
||||||
# files used in manual testing
|
# files used in manual testing
|
||||||
/config.py
|
/config.py
|
||||||
@ -24,6 +24,12 @@ tests/repo/icons*
|
|||||||
/logs/
|
/logs/
|
||||||
/metadata/
|
/metadata/
|
||||||
makebuildserver.config.py
|
makebuildserver.config.py
|
||||||
|
/tests/.fdroid.keypass.txt
|
||||||
|
/tests/.fdroid.keystorepass.txt
|
||||||
/tests/config.py
|
/tests/config.py
|
||||||
/tests/fdroid-icon.png
|
/tests/fdroid-icon.png
|
||||||
|
/tests/keystore.jks
|
||||||
|
/tests/OBBMainPatchCurrent.apk
|
||||||
|
/tests/OBBMainTwoVersions.apk
|
||||||
|
/tests/urzip-πÇÇπÇÇ现代汉语通用字-български-عربي1234.apk
|
||||||
/unsigned/
|
/unsigned/
|
||||||
|
@ -952,6 +952,40 @@ def trybuild(app, build, build_dir, output_dir, also_check_dir, srclib_dir, extl
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def get_android_tools_versions(sdk_path, ndk_path=None):
|
||||||
|
'''get a list of the versions of all installed Android SDK/NDK components'''
|
||||||
|
|
||||||
|
if sdk_path[-1] != '/':
|
||||||
|
sdk_path += '/'
|
||||||
|
components = []
|
||||||
|
if ndk_path:
|
||||||
|
ndk_release_txt = os.path.join(ndk_path, 'RELEASE.TXT')
|
||||||
|
if os.path.isfile(ndk_release_txt):
|
||||||
|
with open(ndk_release_txt, 'r') as fp:
|
||||||
|
components.append((os.path.basename(ndk_path), fp.read()[:-1]))
|
||||||
|
|
||||||
|
pattern = re.compile('^Pkg.Revision=(.+)', re.MULTILINE)
|
||||||
|
for root, dirs, files in os.walk(sdk_path):
|
||||||
|
if 'source.properties' in files:
|
||||||
|
source_properties = os.path.join(root, 'source.properties')
|
||||||
|
with open(source_properties, 'r') as fp:
|
||||||
|
m = pattern.search(fp.read())
|
||||||
|
if m:
|
||||||
|
components.append((root[len(sdk_path):], m.group(1)))
|
||||||
|
|
||||||
|
return components
|
||||||
|
|
||||||
|
|
||||||
|
def get_android_tools_version_log(sdk_path, ndk_path):
|
||||||
|
'''get a list of the versions of all installed Android SDK/NDK components'''
|
||||||
|
log = ''
|
||||||
|
components = get_android_tools_versions(sdk_path, ndk_path)
|
||||||
|
for name, version in sorted(components):
|
||||||
|
log += '* ' + name + ' (' + version + ')\n'
|
||||||
|
|
||||||
|
return log
|
||||||
|
|
||||||
|
|
||||||
def parse_commandline():
|
def parse_commandline():
|
||||||
"""Parse the command line. Returns options, parser."""
|
"""Parse the command line. Returns options, parser."""
|
||||||
|
|
||||||
@ -1066,9 +1100,10 @@ def main():
|
|||||||
extlib_dir = os.path.join(build_dir, 'extlib')
|
extlib_dir = os.path.join(build_dir, 'extlib')
|
||||||
|
|
||||||
# Read all app and srclib metadata
|
# Read all app and srclib metadata
|
||||||
allapps = metadata.read_metadata(xref=not options.onserver)
|
pkgs = common.read_pkg_args(options.appid, True)
|
||||||
|
allapps = metadata.read_metadata(not options.onserver, pkgs)
|
||||||
apps = common.read_app_args(options.appid, allapps, True)
|
apps = common.read_app_args(options.appid, allapps, True)
|
||||||
|
|
||||||
for appid, app in list(apps.items()):
|
for appid, app in list(apps.items()):
|
||||||
if (app.Disabled and not options.force) or not app.RepoType or not app.builds:
|
if (app.Disabled and not options.force) or not app.RepoType or not app.builds:
|
||||||
del apps[appid]
|
del apps[appid]
|
||||||
@ -1099,22 +1134,15 @@ def main():
|
|||||||
|
|
||||||
for build in app.builds:
|
for build in app.builds:
|
||||||
wikilog = None
|
wikilog = None
|
||||||
|
tools_version_log = '== Installed Android Tools ==\n\n'
|
||||||
|
tools_version_log += get_android_tools_version_log(config['sdk_path'], build.ndk_path())
|
||||||
try:
|
try:
|
||||||
|
|
||||||
# For the first build of a particular app, we need to set up
|
# For the first build of a particular app, we need to set up
|
||||||
# the source repo. We can reuse it on subsequent builds, if
|
# the source repo. We can reuse it on subsequent builds, if
|
||||||
# there are any.
|
# there are any.
|
||||||
if first:
|
if first:
|
||||||
if app.RepoType == 'srclib':
|
vcs, build_dir = common.setup_vcs(app)
|
||||||
build_dir = os.path.join('build', 'srclib', app.Repo)
|
|
||||||
else:
|
|
||||||
build_dir = os.path.join('build', appid)
|
|
||||||
|
|
||||||
# Set up vcs interface and make sure we have the latest code...
|
|
||||||
logging.debug("Getting {0} vcs interface for {1}"
|
|
||||||
.format(app.RepoType, app.Repo))
|
|
||||||
vcs = common.getvcs(app.RepoType, app.Repo, build_dir)
|
|
||||||
|
|
||||||
first = False
|
first = False
|
||||||
|
|
||||||
logging.debug("Checking " + build.version)
|
logging.debug("Checking " + build.version)
|
||||||
@ -1150,6 +1178,12 @@ def main():
|
|||||||
wikilog = str(vcse)
|
wikilog = str(vcse)
|
||||||
except FDroidException as e:
|
except FDroidException as e:
|
||||||
with open(os.path.join(log_dir, appid + '.log'), 'a+') as f:
|
with open(os.path.join(log_dir, appid + '.log'), 'a+') as f:
|
||||||
|
f.write('\n\n============================================================\n')
|
||||||
|
f.write('versionCode: %s\nversionName: %s\ncommit: %s\n' %
|
||||||
|
(build.vercode, build.version, build.commit))
|
||||||
|
f.write('Build completed at '
|
||||||
|
+ time.strftime("%Y-%m-%d %H:%M:%SZ", time.gmtime()) + '\n')
|
||||||
|
f.write('\n' + tools_version_log + '\n')
|
||||||
f.write(str(e))
|
f.write(str(e))
|
||||||
logging.error("Could not build app %s: %s" % (appid, e))
|
logging.error("Could not build app %s: %s" % (appid, e))
|
||||||
if options.stop:
|
if options.stop:
|
||||||
@ -1164,6 +1198,9 @@ def main():
|
|||||||
failed_apps[appid] = e
|
failed_apps[appid] = e
|
||||||
wikilog = str(e)
|
wikilog = str(e)
|
||||||
|
|
||||||
|
if wikilog:
|
||||||
|
wikilog = tools_version_log + '\n\n' + wikilog
|
||||||
|
|
||||||
if options.wiki and wikilog:
|
if options.wiki and wikilog:
|
||||||
try:
|
try:
|
||||||
# Write a page with the last build log for this version code
|
# Write a page with the last build log for this version code
|
||||||
|
@ -358,9 +358,11 @@ def get_local_metadata_files():
|
|||||||
return glob.glob('.fdroid.[a-jl-z]*[a-rt-z]')
|
return glob.glob('.fdroid.[a-jl-z]*[a-rt-z]')
|
||||||
|
|
||||||
|
|
||||||
# Given the arguments in the form of multiple appid:[vc] strings, this returns
|
|
||||||
# a dictionary with the set of vercodes specified for each package.
|
|
||||||
def read_pkg_args(args, allow_vercodes=False):
|
def read_pkg_args(args, allow_vercodes=False):
|
||||||
|
"""
|
||||||
|
Given the arguments in the form of multiple appid:[vc] strings, this returns
|
||||||
|
a dictionary with the set of vercodes specified for each package.
|
||||||
|
"""
|
||||||
|
|
||||||
vercodes = {}
|
vercodes = {}
|
||||||
if not args:
|
if not args:
|
||||||
@ -380,9 +382,11 @@ def read_pkg_args(args, allow_vercodes=False):
|
|||||||
return vercodes
|
return vercodes
|
||||||
|
|
||||||
|
|
||||||
# On top of what read_pkg_args does, this returns the whole app metadata, but
|
|
||||||
# limiting the builds list to the builds matching the vercodes specified.
|
|
||||||
def read_app_args(args, allapps, allow_vercodes=False):
|
def read_app_args(args, allapps, allow_vercodes=False):
|
||||||
|
"""
|
||||||
|
On top of what read_pkg_args does, this returns the whole app metadata, but
|
||||||
|
limiting the builds list to the builds matching the vercodes specified.
|
||||||
|
"""
|
||||||
|
|
||||||
vercodes = read_pkg_args(args, allow_vercodes)
|
vercodes = read_pkg_args(args, allow_vercodes)
|
||||||
|
|
||||||
@ -482,6 +486,31 @@ def getcvname(app):
|
|||||||
return '%s (%s)' % (app.CurrentVersion, app.CurrentVersionCode)
|
return '%s (%s)' % (app.CurrentVersion, app.CurrentVersionCode)
|
||||||
|
|
||||||
|
|
||||||
|
def get_build_dir(app):
|
||||||
|
'''get the dir that this app will be built in'''
|
||||||
|
|
||||||
|
if app.RepoType == 'srclib':
|
||||||
|
return os.path.join('build', 'srclib', app.Repo)
|
||||||
|
|
||||||
|
return os.path.join('build', app.id)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_vcs(app):
|
||||||
|
'''checkout code from VCS and return instance of vcs and the build dir'''
|
||||||
|
build_dir = get_build_dir(app)
|
||||||
|
|
||||||
|
# Set up vcs interface and make sure we have the latest code...
|
||||||
|
logging.debug("Getting {0} vcs interface for {1}"
|
||||||
|
.format(app.RepoType, app.Repo))
|
||||||
|
if app.RepoType == 'git' and os.path.exists('.fdroid.yml'):
|
||||||
|
remote = os.getcwd()
|
||||||
|
else:
|
||||||
|
remote = app.Repo
|
||||||
|
vcs = getvcs(app.RepoType, remote, build_dir)
|
||||||
|
|
||||||
|
return vcs, build_dir
|
||||||
|
|
||||||
|
|
||||||
def getvcs(vcstype, remote, local):
|
def getvcs(vcstype, remote, local):
|
||||||
if vcstype == 'git':
|
if vcstype == 'git':
|
||||||
return vcs_git(remote, local)
|
return vcs_git(remote, local)
|
||||||
@ -979,8 +1008,8 @@ def retrieve_string_singleline(app_dir, string, xmlfiles=None):
|
|||||||
return retrieve_string(app_dir, string, xmlfiles).replace('\n', ' ').strip()
|
return retrieve_string(app_dir, string, xmlfiles).replace('\n', ' ').strip()
|
||||||
|
|
||||||
|
|
||||||
# Return list of existing files that will be used to find the highest vercode
|
|
||||||
def manifest_paths(app_dir, flavours):
|
def manifest_paths(app_dir, flavours):
|
||||||
|
'''Return list of existing files that will be used to find the highest vercode'''
|
||||||
|
|
||||||
possible_manifests = \
|
possible_manifests = \
|
||||||
[os.path.join(app_dir, 'AndroidManifest.xml'),
|
[os.path.join(app_dir, 'AndroidManifest.xml'),
|
||||||
@ -997,8 +1026,8 @@ def manifest_paths(app_dir, flavours):
|
|||||||
return [path for path in possible_manifests if os.path.isfile(path)]
|
return [path for path in possible_manifests if os.path.isfile(path)]
|
||||||
|
|
||||||
|
|
||||||
# Retrieve the package name. Returns the name, or None if not found.
|
|
||||||
def fetch_real_name(app_dir, flavours):
|
def fetch_real_name(app_dir, flavours):
|
||||||
|
'''Retrieve the package name. Returns the name, or None if not found.'''
|
||||||
for path in manifest_paths(app_dir, flavours):
|
for path in manifest_paths(app_dir, flavours):
|
||||||
if not has_extension(path, 'xml') or not os.path.isfile(path):
|
if not has_extension(path, 'xml') or not os.path.isfile(path):
|
||||||
continue
|
continue
|
||||||
@ -1070,10 +1099,12 @@ def app_matches_packagename(app, package):
|
|||||||
return appid == package
|
return appid == package
|
||||||
|
|
||||||
|
|
||||||
# Extract some information from the AndroidManifest.xml at the given path.
|
|
||||||
# Returns (version, vercode, package), any or all of which might be None.
|
|
||||||
# All values returned are strings.
|
|
||||||
def parse_androidmanifests(paths, app):
|
def parse_androidmanifests(paths, app):
|
||||||
|
"""
|
||||||
|
Extract some information from the AndroidManifest.xml at the given path.
|
||||||
|
Returns (version, vercode, package), any or all of which might be None.
|
||||||
|
All values returned are strings.
|
||||||
|
"""
|
||||||
|
|
||||||
ignoreversions = app.UpdateCheckIgnore
|
ignoreversions = app.UpdateCheckIgnore
|
||||||
ignoresearch = re.compile(ignoreversions).search if ignoreversions else None
|
ignoresearch = re.compile(ignoreversions).search if ignoreversions else None
|
||||||
|
@ -152,24 +152,30 @@ class App():
|
|||||||
self.lastupdated = None
|
self.lastupdated = None
|
||||||
self._modified = set()
|
self._modified = set()
|
||||||
|
|
||||||
# Translates human-readable field names to attribute names, e.g.
|
|
||||||
# 'Auto Name' to 'AutoName'
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def field_to_attr(cls, f):
|
def field_to_attr(cls, f):
|
||||||
|
"""
|
||||||
|
Translates human-readable field names to attribute names, e.g.
|
||||||
|
'Auto Name' to 'AutoName'
|
||||||
|
"""
|
||||||
return f.replace(' ', '')
|
return f.replace(' ', '')
|
||||||
|
|
||||||
# Translates attribute names to human-readable field names, e.g.
|
|
||||||
# 'AutoName' to 'Auto Name'
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def attr_to_field(cls, k):
|
def attr_to_field(cls, k):
|
||||||
|
"""
|
||||||
|
Translates attribute names to human-readable field names, e.g.
|
||||||
|
'AutoName' to 'Auto Name'
|
||||||
|
"""
|
||||||
if k in app_fields:
|
if k in app_fields:
|
||||||
return k
|
return k
|
||||||
f = re.sub(r'([a-z])([A-Z])', r'\1 \2', k)
|
f = re.sub(r'([a-z])([A-Z])', r'\1 \2', k)
|
||||||
return f
|
return f
|
||||||
|
|
||||||
# Constructs an old-fashioned dict with the human-readable field
|
|
||||||
# names. Should only be used for tests.
|
|
||||||
def field_dict(self):
|
def field_dict(self):
|
||||||
|
"""
|
||||||
|
Constructs an old-fashioned dict with the human-readable field
|
||||||
|
names. Should only be used for tests.
|
||||||
|
"""
|
||||||
d = {}
|
d = {}
|
||||||
for k, v in self.__dict__.items():
|
for k, v in self.__dict__.items():
|
||||||
if k == 'builds':
|
if k == 'builds':
|
||||||
@ -182,23 +188,23 @@ class App():
|
|||||||
d[f] = v
|
d[f] = v
|
||||||
return d
|
return d
|
||||||
|
|
||||||
# Gets the value associated to a field name, e.g. 'Auto Name'
|
|
||||||
def get_field(self, f):
|
def get_field(self, f):
|
||||||
|
"""Gets the value associated to a field name, e.g. 'Auto Name'"""
|
||||||
if f not in app_fields:
|
if f not in app_fields:
|
||||||
warn_or_exception('Unrecognised app field: ' + f)
|
warn_or_exception('Unrecognised app field: ' + f)
|
||||||
k = App.field_to_attr(f)
|
k = App.field_to_attr(f)
|
||||||
return getattr(self, k)
|
return getattr(self, k)
|
||||||
|
|
||||||
# Sets the value associated to a field name, e.g. 'Auto Name'
|
|
||||||
def set_field(self, f, v):
|
def set_field(self, f, v):
|
||||||
|
"""Sets the value associated to a field name, e.g. 'Auto Name'"""
|
||||||
if f not in app_fields:
|
if f not in app_fields:
|
||||||
warn_or_exception('Unrecognised app field: ' + f)
|
warn_or_exception('Unrecognised app field: ' + f)
|
||||||
k = App.field_to_attr(f)
|
k = App.field_to_attr(f)
|
||||||
self.__dict__[k] = v
|
self.__dict__[k] = v
|
||||||
self._modified.add(k)
|
self._modified.add(k)
|
||||||
|
|
||||||
# Appends to the value associated to a field name, e.g. 'Auto Name'
|
|
||||||
def append_field(self, f, v):
|
def append_field(self, f, v):
|
||||||
|
"""Appends to the value associated to a field name, e.g. 'Auto Name'"""
|
||||||
if f not in app_fields:
|
if f not in app_fields:
|
||||||
warn_or_exception('Unrecognised app field: ' + f)
|
warn_or_exception('Unrecognised app field: ' + f)
|
||||||
k = App.field_to_attr(f)
|
k = App.field_to_attr(f)
|
||||||
@ -207,8 +213,8 @@ class App():
|
|||||||
else:
|
else:
|
||||||
self.__dict__[k].append(v)
|
self.__dict__[k].append(v)
|
||||||
|
|
||||||
# Like dict.update(), but using human-readable field names
|
|
||||||
def update_fields(self, d):
|
def update_fields(self, d):
|
||||||
|
'''Like dict.update(), but using human-readable field names'''
|
||||||
for f, v in d.items():
|
for f, v in d.items():
|
||||||
if f == 'builds':
|
if f == 'builds':
|
||||||
for b in v:
|
for b in v:
|
||||||
@ -218,6 +224,21 @@ class App():
|
|||||||
else:
|
else:
|
||||||
self.set_field(f, v)
|
self.set_field(f, v)
|
||||||
|
|
||||||
|
def update(self, d):
|
||||||
|
'''Like dict.update()'''
|
||||||
|
for k, v in d.__dict__.items():
|
||||||
|
if k == '_modified':
|
||||||
|
continue
|
||||||
|
elif k == 'builds':
|
||||||
|
for b in v:
|
||||||
|
build = Build()
|
||||||
|
del(b.__dict__['_modified'])
|
||||||
|
build.update_flags(b.__dict__)
|
||||||
|
self.builds.append(build)
|
||||||
|
elif v:
|
||||||
|
self.__dict__[k] = v
|
||||||
|
self._modified.add(k)
|
||||||
|
|
||||||
|
|
||||||
TYPE_UNKNOWN = 0
|
TYPE_UNKNOWN = 0
|
||||||
TYPE_OBSOLETE = 1
|
TYPE_OBSOLETE = 1
|
||||||
@ -772,9 +793,13 @@ def read_srclibs():
|
|||||||
srclibs[srclibname] = parse_srclib(metadatapath)
|
srclibs[srclibname] = parse_srclib(metadatapath)
|
||||||
|
|
||||||
|
|
||||||
# Read all metadata. Returns a list of 'app' objects (which are dictionaries as
|
def read_metadata(xref=True, check_vcs=[]):
|
||||||
# returned by the parse_txt_metadata function.
|
"""
|
||||||
def read_metadata(xref=True):
|
Read all metadata. Returns a list of 'app' objects (which are dictionaries as
|
||||||
|
returned by the parse_txt_metadata function.
|
||||||
|
|
||||||
|
check_vcs is the list of packageNames to check for .fdroid.yml in source
|
||||||
|
"""
|
||||||
|
|
||||||
# Always read the srclibs before the apps, since they can use a srlib as
|
# Always read the srclibs before the apps, since they can use a srlib as
|
||||||
# their source repository.
|
# their source repository.
|
||||||
@ -801,7 +826,7 @@ def read_metadata(xref=True):
|
|||||||
packageName, _ = fdroidserver.common.get_extension(os.path.basename(metadatapath))
|
packageName, _ = fdroidserver.common.get_extension(os.path.basename(metadatapath))
|
||||||
if packageName in apps:
|
if packageName in apps:
|
||||||
warn_or_exception("Found multiple metadata files for " + packageName)
|
warn_or_exception("Found multiple metadata files for " + packageName)
|
||||||
app = parse_metadata(metadatapath)
|
app = parse_metadata(metadatapath, packageName in check_vcs)
|
||||||
check_metadata(app)
|
check_metadata(app)
|
||||||
apps[app.id] = app
|
apps[app.id] = app
|
||||||
|
|
||||||
@ -904,6 +929,11 @@ def post_metadata_parse(app):
|
|||||||
elif ftype == TYPE_STRING:
|
elif ftype == TYPE_STRING:
|
||||||
if isinstance(v, bool) and v:
|
if isinstance(v, bool) and v:
|
||||||
build.__dict__[k] = 'yes'
|
build.__dict__[k] = 'yes'
|
||||||
|
elif ftype == TYPE_LIST:
|
||||||
|
if isinstance(v, bool) and v:
|
||||||
|
build.__dict__[k] = ['yes']
|
||||||
|
elif isinstance(v, str):
|
||||||
|
build.__dict__[k] = [v]
|
||||||
|
|
||||||
if not app.Description:
|
if not app.Description:
|
||||||
app.Description = 'No description available'
|
app.Description = 'No description available'
|
||||||
@ -949,7 +979,9 @@ def _decode_bool(s):
|
|||||||
warn_or_exception("Invalid bool '%s'" % s)
|
warn_or_exception("Invalid bool '%s'" % s)
|
||||||
|
|
||||||
|
|
||||||
def parse_metadata(metadatapath):
|
def parse_metadata(metadatapath, check_vcs=False):
|
||||||
|
'''parse metadata file, optionally checking the git repo for metadata first'''
|
||||||
|
|
||||||
_, ext = fdroidserver.common.get_extension(metadatapath)
|
_, ext = fdroidserver.common.get_extension(metadatapath)
|
||||||
accepted = fdroidserver.common.config['accepted_formats']
|
accepted = fdroidserver.common.config['accepted_formats']
|
||||||
if ext not in accepted:
|
if ext not in accepted:
|
||||||
@ -958,7 +990,11 @@ def parse_metadata(metadatapath):
|
|||||||
|
|
||||||
app = App()
|
app = App()
|
||||||
app.metadatapath = metadatapath
|
app.metadatapath = metadatapath
|
||||||
app.id, _ = fdroidserver.common.get_extension(os.path.basename(metadatapath))
|
name, _ = fdroidserver.common.get_extension(os.path.basename(metadatapath))
|
||||||
|
if name == '.fdroid':
|
||||||
|
check_vcs = False
|
||||||
|
else:
|
||||||
|
app.id = name
|
||||||
|
|
||||||
with open(metadatapath, 'r', encoding='utf-8') as mf:
|
with open(metadatapath, 'r', encoding='utf-8') as mf:
|
||||||
if ext == 'txt':
|
if ext == 'txt':
|
||||||
@ -972,7 +1008,28 @@ def parse_metadata(metadatapath):
|
|||||||
else:
|
else:
|
||||||
warn_or_exception('Unknown metadata format: %s' % metadatapath)
|
warn_or_exception('Unknown metadata format: %s' % metadatapath)
|
||||||
|
|
||||||
|
if check_vcs and app.Repo:
|
||||||
|
build_dir = fdroidserver.common.get_build_dir(app)
|
||||||
|
metadata_in_repo = os.path.join(build_dir, '.fdroid.yml')
|
||||||
|
if not os.path.isfile(metadata_in_repo):
|
||||||
|
vcs, build_dir = fdroidserver.common.setup_vcs(app)
|
||||||
|
vcs.gotorevision('HEAD') # HEAD since we can't know where else to go
|
||||||
|
if os.path.isfile(metadata_in_repo):
|
||||||
|
logging.debug('Including metadata from ' + metadata_in_repo)
|
||||||
|
app.update(parse_metadata(metadata_in_repo))
|
||||||
|
|
||||||
post_metadata_parse(app)
|
post_metadata_parse(app)
|
||||||
|
|
||||||
|
if not app.id:
|
||||||
|
if app.builds:
|
||||||
|
build = app.builds[-1]
|
||||||
|
if build.subdir:
|
||||||
|
root_dir = build.subdir
|
||||||
|
else:
|
||||||
|
root_dir = '.'
|
||||||
|
paths = fdroidserver.common.manifest_paths(root_dir, build.gradle)
|
||||||
|
_, _, app.id = fdroidserver.common.parse_androidmanifests(paths, app)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,12 +25,13 @@ class ImportTest(unittest.TestCase):
|
|||||||
'''fdroid import'''
|
'''fdroid import'''
|
||||||
|
|
||||||
def test_import_gitlab(self):
|
def test_import_gitlab(self):
|
||||||
|
os.chdir(os.path.dirname(__file__))
|
||||||
# FDroidPopen needs some config to work
|
# FDroidPopen needs some config to work
|
||||||
config = dict()
|
config = dict()
|
||||||
fdroidserver.common.fill_config_defaults(config)
|
fdroidserver.common.fill_config_defaults(config)
|
||||||
fdroidserver.common.config = config
|
fdroidserver.common.config = config
|
||||||
|
|
||||||
url = 'https://gitlab.com/fdroid/fdroidclient'
|
url = 'https://gitlab.com/eighthave/ci-test-app'
|
||||||
r = requests.head(url)
|
r = requests.head(url)
|
||||||
if r.status_code != 200:
|
if r.status_code != 200:
|
||||||
print("ERROR", url, 'unreachable (', r.status_code, ')')
|
print("ERROR", url, 'unreachable (', r.status_code, ')')
|
||||||
@ -41,8 +42,8 @@ class ImportTest(unittest.TestCase):
|
|||||||
app.UpdateCheckMode = "Tags"
|
app.UpdateCheckMode = "Tags"
|
||||||
root_dir, src_dir = import_proxy.get_metadata_from_url(app, url)
|
root_dir, src_dir = import_proxy.get_metadata_from_url(app, url)
|
||||||
self.assertEqual(app.RepoType, 'git')
|
self.assertEqual(app.RepoType, 'git')
|
||||||
self.assertEqual(app.WebSite, 'https://gitlab.com/fdroid/fdroidclient')
|
self.assertEqual(app.WebSite, 'https://gitlab.com/eighthave/ci-test-app')
|
||||||
self.assertEqual(app.Repo, 'https://gitlab.com/fdroid/fdroidclient.git')
|
self.assertEqual(app.Repo, 'https://gitlab.com/eighthave/ci-test-app.git')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
21
tests/metadata/info.guardianproject.checkey.txt
Normal file
21
tests/metadata/info.guardianproject.checkey.txt
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
Categories:Development,GuardianProject
|
||||||
|
License:GPLv3
|
||||||
|
Web Site:https://dev.guardianproject.info/projects/checkey
|
||||||
|
Source Code:https://github.com/guardianproject/checkey
|
||||||
|
Issue Tracker:https://dev.guardianproject.info/projects/checkey/issues
|
||||||
|
Bitcoin:1Fi5xUHiAPRKxHvyUGVFGt9extBe8Srdbk
|
||||||
|
|
||||||
|
Auto Name:Checkey
|
||||||
|
Summary:Info on local apps
|
||||||
|
Description:
|
||||||
|
Checkey is a utility for getting information about the APKs that are installed
|
||||||
|
on your device. Starting with a list of all of the apps that you have
|
||||||
|
installed on your device, it will show you the APK signature with a single
|
||||||
|
touch, and provides links to virustotal.com and androidobservatory.org to
|
||||||
|
easily access the profiles of that APK. It will also let you export the
|
||||||
|
signing certificate and generate ApkSignaturePin pin files for use with the
|
||||||
|
TrustedIntents library.
|
||||||
|
.
|
||||||
|
|
||||||
|
|
||||||
|
Current Version Code:9999999
|
Binary file not shown.
Binary file not shown.
2
tests/metadata/org.fdroid.ci.test.app.txt
Normal file
2
tests/metadata/org.fdroid.ci.test.app.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Repo Type:git
|
||||||
|
Repo:https://gitlab.com/eighthave/ci-test-app
|
Binary file not shown.
9
tests/metadata/raw.template.txt
Normal file
9
tests/metadata/raw.template.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
License:Unknown
|
||||||
|
Web Site:
|
||||||
|
Source Code:
|
||||||
|
Issue Tracker:
|
||||||
|
Changelog:
|
||||||
|
Summary:Template
|
||||||
|
Description:
|
||||||
|
Template
|
||||||
|
.
|
@ -100,6 +100,8 @@ echo_header "test python getsig replacement"
|
|||||||
|
|
||||||
cd $WORKSPACE/tests/getsig
|
cd $WORKSPACE/tests/getsig
|
||||||
./make.sh
|
./make.sh
|
||||||
|
|
||||||
|
cd $WORKSPACE/tests
|
||||||
for testcase in $WORKSPACE/tests/*.TestCase; do
|
for testcase in $WORKSPACE/tests/*.TestCase; do
|
||||||
$testcase
|
$testcase
|
||||||
done
|
done
|
||||||
@ -138,6 +140,19 @@ $fdroid readmeta
|
|||||||
$fdroid update
|
$fdroid update
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------#
|
||||||
|
echo_header 'run `fdroid build` in fresh git checkout from import.TestCase'
|
||||||
|
|
||||||
|
cd $WORKSPACE/tests/tmp/importer
|
||||||
|
if [ -d $ANDROID_HOME/platforms/android-23 ]; then
|
||||||
|
echo "build_tools = '`ls -1 $ANDROID_HOME/build-tools/ | sort -n | tail -1`'" > config.py
|
||||||
|
echo "force_build_tools = True" >> config.py
|
||||||
|
$fdroid build --verbose org.fdroid.ci.test.app:300
|
||||||
|
else
|
||||||
|
echo 'WARNING: Skipping `fdroid build` test since android-23 is missing!'
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------#
|
#------------------------------------------------------------------------------#
|
||||||
echo_header "copy tests/repo, generate java/gpg keys, update, and gpgsign"
|
echo_header "copy tests/repo, generate java/gpg keys, update, and gpgsign"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user