Add dual HTTPS repository sources and dependency fallback
This commit is contained in:
1 parent
1e535c83eb
commit
06a3d8506b
5 files changed
+30
-42
No files matched your search
+1
-1
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# Prepare configured external dependencies, then build and start Docker Compose.
|
||||
# Initialize dependencies via GitHub HTTPS with self-hosted HTTPS fallback, then build Docker Compose.
|
||||
set -eu
|
||||
PROJECT_ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
|
||||
python3 "$PROJECT_ROOT/scripts/init-deps.py"
|
||||
|
||||
+5
-10
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Initialize pinned dependencies over GitHub HTTPS; optionally prefer authorized SSH."""
|
||||
"""Initialize pinned dependencies over GitHub HTTPS with a self-hosted HTTPS fallback."""
|
||||
import argparse
|
||||
import os
|
||||
from pathlib import Path
|
||||
@@ -14,7 +14,7 @@ def git(*args, **kwargs):
|
||||
return subprocess.run(['git', *args], cwd=ROOT, **kwargs)
|
||||
|
||||
|
||||
def initialize(name, override, prefer_ssh=False):
|
||||
def initialize(name, override):
|
||||
path = f'external/{name}'
|
||||
checkout = ROOT / path
|
||||
pin = git('ls-files', '--stage', '--', path, text=True, capture_output=True, check=True).stdout.split()
|
||||
@@ -34,13 +34,9 @@ def initialize(name, override, prefer_ssh=False):
|
||||
raise RuntimeError(f'Local repository does not exist: {source}')
|
||||
sources = [source.as_uri()]
|
||||
else:
|
||||
sources = [f'https://github.com/TheBadRoger/{name}.git']
|
||||
if prefer_ssh:
|
||||
sources.insert(0, f'ChuGit:/srv/git/{name}.git')
|
||||
sources = [f'https://github.com/TheBadRoger/{name}.git',
|
||||
f'https://repo.chunana.cn/ChuNa7a/{name}.git']
|
||||
transport_env = {**os.environ, 'GIT_TERMINAL_PROMPT': '0'}
|
||||
configured_ssh = git('config', '--get', 'core.sshCommand', capture_output=True, check=False)
|
||||
if configured_ssh.returncode != 0 and not any(name in transport_env for name in ['GIT_SSH', 'GIT_SSH_COMMAND']):
|
||||
transport_env['GIT_SSH_COMMAND'] = 'ssh -o BatchMode=yes -o ConnectTimeout=10 -o ConnectionAttempts=1'
|
||||
for url in sources:
|
||||
print(f'{name}: trying {url}', flush=True)
|
||||
git('config', '--local', f'submodule.{path}.url', url, check=True)
|
||||
@@ -63,10 +59,9 @@ def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--database-repo', type=Path, help='explicit local development source for ChuSQL')
|
||||
parser.add_argument('--driver-repo', type=Path, help='explicit local development source for the driver')
|
||||
parser.add_argument('--prefer-ssh', action='store_true', help='authorized devices: try ChuGit SSH first, then GitHub HTTPS')
|
||||
args = parser.parse_args()
|
||||
for name, override in zip(PROJECTS, [args.database_repo, args.driver_repo]):
|
||||
initialize(name, override, args.prefer_ssh)
|
||||
initialize(name, override)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
+12
-18
@@ -11,7 +11,7 @@ SCRIPT = Path(__file__).with_name('init-deps.py')
|
||||
|
||||
|
||||
class InitializeDependencies(unittest.TestCase):
|
||||
def test_https_default_and_authorized_ssh_fallback_preserve_pins(self):
|
||||
def test_https_default_and_self_hosted_fallback_preserve_pins(self):
|
||||
with tempfile.TemporaryDirectory(prefix='chublog deps ') as temporary:
|
||||
root = Path(temporary)
|
||||
project = root / 'blog'
|
||||
@@ -37,7 +37,7 @@ class InitializeDependencies(unittest.TestCase):
|
||||
# Dirty source must never leak into the blog or fetched dependency.
|
||||
(source / 'source.txt').write_text('uncommitted changes')
|
||||
path = f'external/{name}'
|
||||
modules.append(f'[submodule "{path}"]\n path = {path}\n url = ChuGit:/srv/git/{name}.git\n')
|
||||
modules.append(f'[submodule "{path}"]\n path = {path}\n url = https://github.com/TheBadRoger/{name}.git\n')
|
||||
git(project, 'update-index', '--add', '--cacheinfo', f'160000,{oid},{path}')
|
||||
sources.append(str(source))
|
||||
(project / '.gitmodules').write_text(''.join(modules))
|
||||
@@ -61,31 +61,25 @@ class InitializeDependencies(unittest.TestCase):
|
||||
for name in ['ChuSQL', 'ChuSQL-RustDriver']:
|
||||
self.assertEqual((fresh / f'external/{name}/source.txt').read_text(), f'{name} committed source')
|
||||
self.assertEqual(git(fresh / f'external/{name}', 'config', '--get', 'remote.origin.url'), f'https://github.com/TheBadRoger/{name}.git')
|
||||
unavailable = root / 'unavailable'
|
||||
git(root, 'clone', '--no-local', str(project), str(unavailable))
|
||||
(unavailable / 'scripts').mkdir()
|
||||
shutil.copy2(SCRIPT, unavailable / 'scripts/init-deps.py')
|
||||
subprocess.run(['python3', 'scripts/init-deps.py', '--prefer-ssh'], cwd=unavailable, env=fallback_env, check=True, capture_output=True)
|
||||
for name in ['ChuSQL', 'ChuSQL-RustDriver']:
|
||||
self.assertEqual((unavailable / f'external/{name}/source.txt').read_text(), f'{name} committed source')
|
||||
# Also cover an accessible but empty authorized SSH bare repository: the initial
|
||||
# submodule clone succeeds, fetching the pinned commit fails, then GitHub recovers.
|
||||
empty = root / 'empty.git'
|
||||
git(root, 'init', '--bare', str(empty))
|
||||
# An empty GitHub source clones successfully but lacks the pin; the
|
||||
# self-hosted HTTPS fallback must recover the partial checkout.
|
||||
partial = root / 'partial'
|
||||
git(root, 'clone', '--no-local', str(project), str(partial))
|
||||
(partial / 'scripts').mkdir()
|
||||
shutil.copy2(SCRIPT, partial / 'scripts/init-deps.py')
|
||||
partial_env = {**fallback_env, 'GIT_CONFIG_COUNT': '4'}
|
||||
for i, name in enumerate(['ChuSQL', 'ChuSQL-RustDriver'], start=2):
|
||||
partial_env = {**env, 'GIT_ALLOW_PROTOCOL': 'file', 'GIT_CONFIG_COUNT': '4'}
|
||||
for i, (name, source) in enumerate(zip(['ChuSQL', 'ChuSQL-RustDriver'], sources)):
|
||||
empty_source = root / f'empty-{name}.git'
|
||||
git(root, 'clone', '--bare', str(empty), str(empty_source))
|
||||
git(root, 'init', '--bare', str(empty_source))
|
||||
partial_env[f'GIT_CONFIG_KEY_{i}'] = f'url.{empty_source.as_uri()}.insteadOf'
|
||||
partial_env[f'GIT_CONFIG_VALUE_{i}'] = f'ChuGit:/srv/git/{name}.git'
|
||||
result = subprocess.run(['python3', 'scripts/init-deps.py', '--prefer-ssh'], cwd=partial, env=partial_env, text=True, capture_output=True)
|
||||
partial_env[f'GIT_CONFIG_VALUE_{i}'] = f'https://github.com/TheBadRoger/{name}.git'
|
||||
partial_env[f'GIT_CONFIG_KEY_{i + 2}'] = f'url.{Path(source).as_uri()}.insteadOf'
|
||||
partial_env[f'GIT_CONFIG_VALUE_{i + 2}'] = f'https://repo.chunana.cn/ChuNa7a/{name}.git'
|
||||
result = subprocess.run(['python3', 'scripts/init-deps.py'], cwd=partial, env=partial_env, text=True, capture_output=True)
|
||||
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
||||
for name in ['ChuSQL', 'ChuSQL-RustDriver']:
|
||||
self.assertEqual((partial / f'external/{name}/source.txt').read_text(), f'{name} committed source')
|
||||
self.assertEqual(git(partial / f'external/{name}', 'config', '--get', 'remote.origin.url'), f'https://repo.chunana.cn/ChuNa7a/{name}.git')
|
||||
# Running the initialization a second time must preserve the same pins.
|
||||
subprocess.run(['python3', 'scripts/init-deps.py', '--database-repo', sources[0], '--driver-repo', sources[1]], cwd=project, env=env, check=True, capture_output=True)
|
||||
|
||||
|
||||
Reference in new issue
Block a user