Merge remote-tracking branch 'upstream/master' into spark/aarch64-settings-boot-dropins

This commit is contained in:
Marcelo Alcantara committed 2026-09-28 07:42:17 +10:00
commit 919b084b93
80 files changed
+1377 -455

No files matched your search

+49
View File
@@ -0,0 +1,49 @@
#!/bin/bash
# Every git source in the repository names an immutable commit or a tag.
#
# A source that follows a branch ("#branch=quattro", or no fragment at all)
# produces a package whose contents depend on when it was built, and nothing
# in this repository changes when that branch moves, so the CI publish path,
# which builds what a merge touched, never rebuilds it. Packages that need to
# follow a branch declare a git_branch upstream watch instead, and the tracker
# turns each new tip into a commit pin here (docs/upstream-sources.md).
set -euo pipefail
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
PKGBUILDS_DIR=${PKGBUILDS_DIR:-$BUILD_ROOT/pkgbuilds}
failures=0
checked=0
for pkgdir in "$PKGBUILDS_DIR"/*/; do
[[ -f "$pkgdir/PKGBUILD" ]] || continue
package=$(basename "$pkgdir")
for arch in x86_64 aarch64; do
# Sourced the way the build tooling reads recipes: CARCH set, the local
# source override unset, so conditional and arch-suffixed arrays count.
sources=$(cd "$pkgdir" && env -u OMARCHY_SRC CARCH="$arch" bash -c '
source PKGBUILD >/dev/null 2>&1
printf "%s\n" "${source[@]}" "${source_x86_64[@]}" "${source_aarch64[@]}"' 2>/dev/null) || {
echo "FAIL: $package: PKGBUILD could not be sourced for $arch"
failures=$((failures + 1))
continue
}
while IFS= read -r entry; do
[[ -n "$entry" ]] || continue
url="${entry#*::}"
[[ "$url" == git+* ]] || continue
checked=$((checked + 1))
case "$url" in
*'#commit='*|*'#tag='*) ;;
*)
echo "FAIL: $package ($arch): git source is not pinned to a commit or tag: $url"
failures=$((failures + 1))
;;
esac
done <<<"$sources"
done
done
if ((failures)); then
echo "$failures unpinned git source(s). Pin with #commit= (and a git_branch upstream watch to move the pin), or #tag= with a checksum."
exit 1
fi
echo "PASS: $checked git source(s) across pkgbuilds/ are pinned to a commit or tag"
+154
View File
@@ -178,6 +178,160 @@ b2sums=('old' 'local-b2')
expected = subprocess.check_output(['git', '-c', 'core.abbrev=no', '-C', str(repo), 'archive', '--format', 'tar', 'v1.0'])
self.assertEqual(archive.read_bytes(), expected)
def branch_fixture(self, fresh_tip=False):
"""An upstream with two release tags and commits past the newest one,
all committed years ago; with fresh_tip, one more commit dated now."""
repo = self.root / 'branch-upstream'
repo.mkdir()
git = ['git', '-C', str(repo), '-c', 'user.name=Test', '-c', 'user.email=test@example.test']
old = {**os.environ, 'GIT_COMMITTER_DATE': '2020-01-01T00:00:00+00:00', 'GIT_AUTHOR_DATE': '2020-01-01T00:00:00+00:00'}
subprocess.run(['git', 'init', '-q', '-b', 'main', str(repo)], check=True)
shas = []
def commit(index, env):
(repo / 'source').write_text(f'revision {index}')
subprocess.run([*git, 'add', '.'], check=True)
subprocess.run([*git, 'commit', '-qm', f'commit {index}'], env=env, check=True)
shas.append(subprocess.check_output([*git, 'rev-parse', 'HEAD'], text=True).strip())
for index, tag in enumerate([None, 'v1.0.0', 'v1.1.0', None, None]):
commit(index, old)
if tag:
subprocess.run([*git, 'tag', tag], check=True)
# A newer release tagged on another branch is not something main is "past".
subprocess.run([*git, 'checkout', '-q', '-b', 'hotfix', shas[1]], check=True)
(repo / 'hotfix').write_text('x')
subprocess.run([*git, 'add', '.'], check=True)
subprocess.run([*git, 'commit', '-qm', 'hotfix'], env=old, check=True)
subprocess.run([*git, 'tag', 'v9.9.9'], check=True)
subprocess.run([*git, 'checkout', '-q', 'main'], check=True)
if fresh_tip:
commit(len(shas), os.environ)
return repo, shas
def redirect_clone(self, repo):
command = w.subprocess.run
def redirect(args, **kwargs):
if 'clone' in args:
args = [f'file://{repo}' if arg == 'https://example.test/tool.git' else arg for arg in args]
return command(args, **kwargs)
return patch.object(w.subprocess, 'run', side_effect=redirect)
def test_git_branch_versions_from_reachable_tag_and_shares_one_clone(self):
repo, shas = self.branch_fixture()
with self.redirect_clone(repo):
tip = w.git_branch_tip('https://example.test/tool.git', 'main', r'v(?P<version>[0-9.]+)', self.fetch.cache)
again = w.git_branch_tip('https://example.test/tool.git', 'main', None, self.fetch.cache)
self.assertEqual((tip['commit'], tip['tag'], tip['version'], tip['distance'], tip['count']), (shas[-1], 'v1.1.0', '1.1.0', '2', '5'))
self.assertEqual(again['commit'], shas[-1])
self.assertEqual(len(list(self.fetch.cache.glob('*.branch.git'))), 1, 'one clone per branch per run')
watch = {'git_branch': 'https://example.test/tool.git', 'branch': 'main', 'tag_pattern': r'v(?P<version>[0-9.]+)',
'version': '{version}.r{distance}.g{commit:.7}', 'variables': {'_commit': '{commit}'}}
pkgver = w.candidate(watch, tip)['pkgver']
self.assertEqual(pkgver, f'1.1.0.r2.g{shas[-1][:7]}')
self.assertEqual(w.vercmp(pkgver, '1.1.0'), 1)
self.assertEqual(w.vercmp(pkgver, '1.1.1'), -1)
with self.redirect_clone(repo), self.assertRaisesRegex(ValueError, 'no tag'):
w.git_branch_tip('https://example.test/tool.git', 'main', r'release-(?P<version>[0-9.]+)', self.root / 'other-cache')
def test_git_branch_min_age_holds_the_tip_instead_of_selecting_history(self):
repo, shas = self.branch_fixture(fresh_tip=True)
watch = {'git_branch': 'https://example.test/tool.git', 'branch': 'main'}
with self.redirect_clone(repo):
releases = w.discover(watch, self.fetch)
self.assertEqual(w.select_release(releases)['values']['commit'], shas[-1])
self.assertIsNone(w.select_release(releases, min_age=3600))
self.assertEqual(w.select_release(releases, min_age=3600, bypass=True)['values']['commit'], shas[-1])
def branch_sync_fixture(self):
repo, shas = self.branch_fixture()
for directory in ['bin', 'helpers']:
shutil.copytree(ROOT / directory, self.root / directory)
for name in ['dev', 'settings-dev']:
package = self.root / 'pkgbuilds' / name
(package / '.omarchy').mkdir(parents=True)
(package / '.omarchy/package.json').write_text(json.dumps({
'source': 'local', 'auto_merge': True, 'upstream': {'watch': {
'git_branch': 'https://example.test/tool.git', 'branch': 'main',
'tag_pattern': r'v(?P<version>[0-9.]+)',
'version': '{version}.r{count}.g{commit:.7}',
'variables': {'_commit': '{commit}'}}}}))
(package / 'PKGBUILD').write_text(f'''pkgname={name}
pkgver=1.0.0
pkgrel=1
_commit={shas[1]}
arch=('any')
source=("tool::git+https://example.test/tool.git#commit=${{_commit}}")
sha256sums=('old')
''')
stub = self.root / 'stub'
stub.mkdir()
git = stub / 'git'
git.write_text('''#!/usr/bin/env python3
import os, sys
args = [os.environ['BRANCH_FIXTURE'] if arg == 'https://example.test/tool.git' else arg for arg in sys.argv[1:]]
os.execv(os.environ['REAL_GIT'], ['git', *args])
''')
git.chmod(0o755)
env = {**os.environ, 'PATH': str(stub) + os.pathsep + os.environ['PATH'],
'BRANCH_FIXTURE': f'file://{repo}', 'REAL_GIT': shutil.which('git')}
def sync(*args):
return subprocess.run([str(self.root / 'bin/sync-upstream'), *args],
env=env, text=True, capture_output=True)
return self.root / 'pkgbuilds', shas[-1], sync
def test_targeted_branch_sync_updates_siblings_and_then_noops(self):
packages, tip, sync = self.branch_sync_fixture()
result = sync('--lane', 'auto-merge', 'dev')
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
for package in packages.iterdir():
recipe = w.read_recipe(package / 'PKGBUILD')
self.assertEqual(w.scalar(recipe, '_commit'), tip)
self.assertEqual(w.scalar(recipe, 'pkgver'), f'1.1.0.r5.g{tip[:7]}')
self.assertRegex(recipe['sha256sums'][0], r'^[0-9a-f]{64}$')
self.assertIn('Updated: 2', result.stdout)
result = sync('--lane', 'auto-merge', 'dev')
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
self.assertIn('Updated: 0', result.stdout)
def test_branch_sync_rolls_back_when_a_sibling_fails(self):
packages, tip, sync = self.branch_sync_fixture()
broken = packages / 'settings-dev/PKGBUILD'
broken.write_text(broken.read_text().replace("sha256sums=('old')", 'sha256sums=()'))
before = {p: p.read_bytes() for p in packages.glob('*/PKGBUILD')}
result = sync('--lane', 'auto-merge', 'dev')
self.assertEqual(result.returncode, 1, result.stdout + result.stderr)
self.assertIn('Lockstep violation', result.stdout + result.stderr)
self.assertIn('Updated: 0', result.stdout)
self.assertEqual(before, {p: p.read_bytes() for p in before})
def test_reviewed_lane_leaves_auto_merge_packages_untouched(self):
packages, tip, sync = self.branch_sync_fixture()
before = {p: p.read_bytes() for p in packages.glob('*/PKGBUILD')}
result = sync('--lane', 'reviewed')
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
self.assertIn('Updated: 0', result.stdout)
self.assertEqual(before, {p: p.read_bytes() for p in before})
def test_different_lanes_cannot_split_a_branch_pair(self):
packages, tip, sync = self.branch_sync_fixture()
metadata = packages / 'settings-dev/.omarchy/package.json'
metadata.write_text(metadata.read_text().replace('"auto_merge": true', '"auto_merge": false'))
before = {p: p.read_bytes() for p in packages.glob('*/PKGBUILD')}
result = sync('--lane', 'auto-merge', 'dev')
self.assertEqual(result.returncode, 1, result.stdout + result.stderr)
self.assertIn('Lockstep violation', result.stdout + result.stderr)
self.assertEqual(before, {p: p.read_bytes() for p in before})
def test_git_branch_tag_template_requires_tag_pattern(self):
base = {'git_branch': 'https://example.test/tool.git', 'branch': 'main'}
w.validate({**base, 'version': '{date}.r{count}'})
w.validate({**base, 'tag_pattern': r'v(?P<version>[0-9.]+)', 'version': '{version}.r{distance}.g{commit:.7}'})
for extra in [{'version': '{version}.r{distance}'}, {'version': '{tag}'}, {'tag_pattern': 'v[0-9.]+'},
{'tag_pattern': 7}, {'tag_pattern': ''}]:
with self.subTest(extra=extra), self.assertRaises(ValueError):
w.validate({**base, **extra})
with self.assertRaisesRegex(ValueError, 'only applies'):
w.validate({'github': 'owner/tool', 'pattern': r'v(?P<version>[0-9.]+)', 'tag_pattern': r'v(?P<version>[0-9.]+)'})
def test_invalid_optional_metadata_fails_validation(self):
valid = {'github': 'owner/tool', 'pattern': r'v(?P<version>[0-9.]+)'}
for extra in [{'variables': []}, {'fields': {'commit': 3}}, {'submodules': {'pkgver': 'libs/common'}},