Build local product stack with Vault-managed secrets (#42)

This commit is contained in:
Stephan D committed 2026-09-12 21:04:42 +02:00
1 parent 8e2ef7aa88
commit 184a3be413
32 files changed
+1191 -10

No files matched your search

+72
View File
@@ -0,0 +1,72 @@
#!/usr/bin/env python3
"""Resolve stable upstream releases on every build; pin their registry digests."""
import concurrent.futures
import json
import os
from pathlib import Path
import re
import subprocess
import urllib.request
ROOT = Path(__file__).resolve().parents[1]
STATE = ROOT / '.local' / 'dev'
def get(url):
with urllib.request.urlopen(url, timeout=45) as response:
return json.load(response)
def image(repo, alias):
url = f'https://hub.docker.com/v2/repositories/{repo}/tags'
selected = get(f'{url}/{alias}')
digest = selected['digest']
if not re.fullmatch(r'sha256:[a-f0-9]{64}', digest):
raise ValueError('Registry returned an invalid digest')
# Find the exact numeric tag represented by the maintained stable alias.
candidates = get(f'{url}?page_size=100')['results']
names = [x['name'] for x in candidates if x.get('digest') == digest
and re.fullmatch(r'\d+\.\d+(?:\.\d+)?(?:-alpine)?', x['name'])]
if not names:
raise ValueError(f'No stable version tag for {repo}:{alias}')
tag = max(names, key=lambda x: tuple(map(int, x.split('-')[0].split('.'))))
return f'{repo}:{tag}@{digest}'
def flutter():
commit = get('https://api.github.com/repos/flutter/flutter/commits/stable')['sha']
tags = subprocess.check_output(['git', 'ls-remote', '--tags',
'https://github.com/flutter/flutter.git'], text=True)
names = [line.split('refs/tags/')[1] for line in tags.splitlines()
if line.startswith(commit + '\trefs/tags/')
and re.fullmatch(r'\d+\.\d+\.\d+', line.split('refs/tags/')[1])]
if not names:
raise ValueError('Flutter stable does not point at a stable release tag')
return max(names, key=lambda x: tuple(map(int, x.split('.')))), commit
def main():
go = get('https://go.dev/dl/?mode=json')[0]
if not go['stable'] or not re.fullmatch(r'go\d+\.\d+\.\d+', go['version']):
raise ValueError('Go release is not stable')
specs = {'VAULT_IMAGE': ('hashicorp/vault', 'latest'),
'MONGO_IMAGE': ('library/mongo', 'latest'),
'NATS_IMAGE': ('library/nats', 'latest'),
'NGINX_IMAGE': ('library/nginx', 'stable-alpine'),
'GO_IMAGE': ('library/golang', go['version'][2:] + '-alpine'),
'UBUNTU_IMAGE': ('library/ubuntu', 'latest')}
with concurrent.futures.ThreadPoolExecutor() as pool:
futures = {key: pool.submit(image, *spec) for key, spec in specs.items()}
refs = {key: future.result() for key, future in futures.items()}
refs['FLUTTER_VERSION'], refs['FLUTTER_COMMIT'] = flutter()
STATE.mkdir(parents=True, exist_ok=True, mode=0o700)
target = STATE / 'images.env'
temporary = target.with_suffix('.tmp')
temporary.write_text(''.join(f'{key}={value}\n' for key, value in refs.items()))
os.replace(temporary, target)
for key, value in refs.items():
print(f'{key}={value}')
if __name__ == '__main__':
main()