SOURCE_DATE_EPOCH from app's git otherwise fdroiddata metadata file
https://reproducible-builds.org/docs/source-date-epoch
This commit is contained in:
parent
0b6e304922
commit
20b36f1970
@ -479,7 +479,7 @@ def build_local(app, build, vcs, build_dir, output_dir, log_dir, srclib_dir, ext
|
||||
logging.critical("Android NDK '%s' is not a directory!" % ndk_path)
|
||||
raise FDroidException()
|
||||
|
||||
common.set_FDroidPopen_env(build)
|
||||
common.set_FDroidPopen_env(app, build)
|
||||
|
||||
# create ..._toolsversion.log when running in builder vm
|
||||
if onserver:
|
||||
|
@ -1201,6 +1201,25 @@ def get_src_tarball_name(appid, versionCode):
|
||||
return f"{appid}_{versionCode}_src.tar.gz"
|
||||
|
||||
|
||||
def get_source_date_epoch(build_dir):
|
||||
"""Return timestamp suitable for the SOURCE_DATE_EPOCH variable.
|
||||
|
||||
https://reproducible-builds.org/docs/source-date-epoch/
|
||||
|
||||
"""
|
||||
try:
|
||||
return git.repo.Repo(build_dir).git.log(n=1, pretty='%ct')
|
||||
except Exception as e:
|
||||
logging.warning('%s: %s', e.__class__.__name__, build_dir)
|
||||
build_dir = Path(build_dir)
|
||||
appid = build_dir.name
|
||||
data_dir = build_dir.parent.parent
|
||||
metadata_file = f'metadata/{appid}.yml'
|
||||
if (data_dir / '.git').exists() and (data_dir / metadata_file).exists():
|
||||
repo = git.repo.Repo(data_dir)
|
||||
return repo.git.log('-n1', '--pretty=%ct', '--', metadata_file)
|
||||
|
||||
|
||||
def get_build_dir(app):
|
||||
"""Get the dir that this app will be built in."""
|
||||
if app.RepoType == 'srclib':
|
||||
@ -3202,12 +3221,16 @@ def remove_signing_keys(build_dir):
|
||||
logging.info("Cleaned %s of keysigning configs at %s" % (propfile, path))
|
||||
|
||||
|
||||
def set_FDroidPopen_env(build=None):
|
||||
def set_FDroidPopen_env(app=None, build=None):
|
||||
"""Set up the environment variables for the build environment.
|
||||
|
||||
There is only a weak standard, the variables used by gradle, so also set
|
||||
up the most commonly used environment variables for SDK and NDK. Also, if
|
||||
there is no locale set, this will set the locale (e.g. LANG) to en_US.UTF-8.
|
||||
|
||||
If an App instance is provided, then the SOURCE_DATE_EPOCH
|
||||
environment variable will be set based on that app's source repo.
|
||||
|
||||
"""
|
||||
global env, orig_path
|
||||
|
||||
@ -3230,6 +3253,8 @@ def set_FDroidPopen_env(build=None):
|
||||
if missinglocale:
|
||||
env['LANG'] = 'en_US.UTF-8'
|
||||
|
||||
if app:
|
||||
env['SOURCE_DATE_EPOCH'] = get_source_date_epoch(get_build_dir(app))
|
||||
if build is not None:
|
||||
path = build.ndk_path()
|
||||
paths = orig_path.split(os.pathsep)
|
||||
|
@ -205,6 +205,7 @@ class BuildTest(unittest.TestCase):
|
||||
@mock.patch('fdroidserver.build.FDroidPopen')
|
||||
@mock.patch('fdroidserver.common.is_debuggable_or_testOnly', lambda f: False)
|
||||
@mock.patch('fdroidserver.common.get_native_code', lambda f: 'x86')
|
||||
@mock.patch('fdroidserver.common.get_source_date_epoch', lambda f: '1234567890')
|
||||
def test_build_local_maven(self, fake_FDroidPopen, fake_get_apk_id):
|
||||
"""Test build_local() with a maven project"""
|
||||
|
||||
@ -330,6 +331,8 @@ class BuildTest(unittest.TestCase):
|
||||
'fdroidserver.build.FDroidPopen', FakeProcess
|
||||
) as _ignored, mock.patch(
|
||||
'sdkmanager.install', wraps=fake_sdkmanager_install
|
||||
) as _ignored, mock.patch(
|
||||
'fdroidserver.common.get_source_date_epoch', lambda f: '1234567890'
|
||||
) as _ignored:
|
||||
_ignored # silence the linters
|
||||
with self.assertRaises(
|
||||
@ -378,6 +381,7 @@ class BuildTest(unittest.TestCase):
|
||||
@mock.patch('fdroidserver.build.FDroidPopen', FakeProcess)
|
||||
@mock.patch('fdroidserver.common.get_native_code', lambda _ignored: 'x86')
|
||||
@mock.patch('fdroidserver.common.is_debuggable_or_testOnly', lambda _ignored: False)
|
||||
@mock.patch('fdroidserver.common.get_source_date_epoch', lambda f: '1234567890')
|
||||
@mock.patch(
|
||||
'fdroidserver.common.sha256sum',
|
||||
lambda f: 'ad7ce5467e18d40050dc51b8e7affc3e635c85bd8c59be62de32352328ed467e',
|
||||
@ -453,6 +457,7 @@ class BuildTest(unittest.TestCase):
|
||||
self.assertTrue(ndk_dir.exists())
|
||||
self.assertTrue(os.path.exists(config['ndk_paths'][ndk_version]))
|
||||
|
||||
@mock.patch('fdroidserver.common.get_source_date_epoch', lambda f: '1234567890')
|
||||
def test_build_local_clean(self):
|
||||
"""Test if `fdroid build` cleans ant and gradle build products"""
|
||||
os.chdir(self.testdir)
|
||||
|
@ -2468,7 +2468,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase):
|
||||
fdroidserver.common.fill_config_defaults(config)
|
||||
build = fdroidserver.metadata.Build()
|
||||
with self.assertRaises(TypeError):
|
||||
fdroidserver.common.set_FDroidPopen_env(build)
|
||||
fdroidserver.common.set_FDroidPopen_env(build=build)
|
||||
|
||||
@mock.patch.dict(os.environ, clear=True)
|
||||
def test_ndk_paths_in_config_must_be_strings(self):
|
||||
@ -2480,7 +2480,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase):
|
||||
build.ndk = 'r21d'
|
||||
os.environ['PATH'] = '/usr/bin:/usr/sbin'
|
||||
with self.assertRaises(TypeError):
|
||||
fdroidserver.common.set_FDroidPopen_env(build)
|
||||
fdroidserver.common.set_FDroidPopen_env(build=build)
|
||||
|
||||
@mock.patch.dict(os.environ, clear=True)
|
||||
def test_FDroidPopen_envs_paths_can_be_pathlib(self):
|
||||
@ -2567,7 +2567,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase):
|
||||
|
||||
with mock.patch.dict(os.environ, clear=True):
|
||||
os.environ['PATH'] = '/usr/bin:/usr/sbin'
|
||||
fdroidserver.common.set_FDroidPopen_env(build)
|
||||
fdroidserver.common.set_FDroidPopen_env(build=build)
|
||||
self.assertNotIn('', os.getenv('PATH').split(os.pathsep))
|
||||
|
||||
def test_is_repo_file(self):
|
||||
@ -2993,6 +2993,53 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase):
|
||||
for mirror in fdroidserver.common.append_filename_to_mirrors(filename, mirrors):
|
||||
self.assertTrue(mirror['url'].endswith('/' + filename))
|
||||
|
||||
def test_get_source_date_epoch(self):
|
||||
git_repo = git.Repo.init(self.testdir)
|
||||
Path('README').write_text('file to commit')
|
||||
git_repo.git.add(all=True)
|
||||
git_repo.index.commit("README")
|
||||
self.assertEqual(
|
||||
git_repo.git.log(n=1, pretty='%ct'),
|
||||
fdroidserver.common.get_source_date_epoch(self.testdir),
|
||||
)
|
||||
|
||||
def test_get_source_date_epoch_no_scm(self):
|
||||
self.assertIsNone(fdroidserver.common.get_source_date_epoch(self.testdir))
|
||||
|
||||
def test_get_source_date_epoch_not_git(self):
|
||||
"""Test when build_dir is not a git repo, e.g. hg, svn, etc."""
|
||||
appid = 'com.example'
|
||||
build_dir = Path(self.testdir) / 'build' / appid
|
||||
fdroiddata = build_dir.parent.parent
|
||||
(fdroiddata / 'metadata').mkdir()
|
||||
build_dir.mkdir(parents=True)
|
||||
os.chdir(build_dir)
|
||||
git_repo = git.Repo.init(fdroiddata) # fdroiddata is always a git repo
|
||||
with (fdroiddata / f'metadata/{appid}.yml').open('w') as fp:
|
||||
fp.write('AutoName: Example App\n')
|
||||
git_repo.git.add(all=True)
|
||||
git_repo.index.commit("update README")
|
||||
self.assertEqual(
|
||||
git.repo.Repo(fdroiddata).git.log(n=1, pretty='%ct'),
|
||||
fdroidserver.common.get_source_date_epoch(build_dir),
|
||||
)
|
||||
|
||||
@mock.patch.dict(os.environ, {'PATH': os.getenv('PATH')}, clear=True)
|
||||
def test_set_FDroidPopen_env_with_app(self):
|
||||
"""Test SOURCE_DATE_EPOCH in FDroidPopen when build_dir is a git repo."""
|
||||
os.chdir(self.testdir)
|
||||
app = fdroidserver.metadata.App()
|
||||
app.id = 'com.example'
|
||||
build_dir = Path(self.testdir) / 'build' / app.id
|
||||
git_repo = git.Repo.init(build_dir)
|
||||
Path('README').write_text('file to commit')
|
||||
git_repo.git.add(all=True)
|
||||
now = datetime.now(timezone.utc)
|
||||
git_repo.index.commit("README", commit_date=now)
|
||||
fdroidserver.common.set_FDroidPopen_env(app)
|
||||
p = fdroidserver.common.FDroidPopen(['printenv', 'SOURCE_DATE_EPOCH'])
|
||||
self.assertEqual(int(p.output), int(now.timestamp()))
|
||||
|
||||
|
||||
APKS_WITH_JAR_SIGNATURES = (
|
||||
(
|
||||
|
@ -350,6 +350,8 @@ class ScannerTest(unittest.TestCase):
|
||||
with mock.patch(
|
||||
'fdroidserver.common.get_apk_id',
|
||||
return_value=(app.id, build.versionCode, build.versionName),
|
||||
), mock.patch(
|
||||
'fdroidserver.common.get_source_date_epoch', lambda f: '1234567890'
|
||||
):
|
||||
with mock.patch(
|
||||
'fdroidserver.common.is_debuggable_or_testOnly',
|
||||
|
Loading…
x
Reference in New Issue
Block a user