informed-decision/tests/test_service_image_build.py

53 lines
2.5 KiB
Python
Raw Normal View History

"""Static checks for the owner-CI full service image (.forgejo/workflows/service-image.yaml).
The built image itself is checked in CI (zlib floor, runtime smoke, installed source manifest)
and locally with tools/smoke_container.py; these tests keep the inputs consistent.
"""
import hashlib
import json
from pathlib import Path
import re
import yaml
ROOT = Path(__file__).parents[1]
ZLIB = ROOT / 'deploy' / 'zlib-overlay'
def test_containerfile_installs_the_overlay_zlib_package_and_enforces_the_floor():
text = (ROOT / 'Containerfile').read_text()
pins = json.loads((ZLIB / 'pins.json').read_text())['files']
for name in ('zlib-1.3.2-r1.apk', 'APKINDEX.tar.gz'):
actual = hashlib.sha256((ZLIB / name).read_bytes()).hexdigest()
assert actual == pins[name]
assert f"echo '{actual} /tmp/infd-zlib/x86_64/{name}' | sha256sum -c -" in text
assert '--no-network' in text and "apk info --exists 'zlib>=1.3.2-r1'" in text
# Every stage uses the same pinned base; the wheel is built from source, not a workstation dist/.
bases = re.findall(r'^FROM (\S+)', text, re.M)
assert len(bases) == 3 and len(set(bases)) == 1 and '@sha256:' in bases[0]
assert 'COPY dist/' not in text and 'COPY --from=wheel /dist/' in text
def test_build_context_admits_exactly_the_inputs():
ignore = (ROOT / '.dockerignore').read_text().split()
assert ignore[0] == '**'
for path in ('Containerfile', 'requirements.lock', 'requirements-build.lock', 'pyproject.toml',
'informed_decision/**', 'deploy/zlib-overlay/zlib-1.3.2-r1.apk',
'deploy/zlib-overlay/APKINDEX.tar.gz'):
assert '!' + path in ignore
build_lock = (ROOT / 'requirements-build.lock').read_text()
assert re.search(r'^setuptools==[\d.]+ \\\n\s+--hash=sha256:[0-9a-f]{64}$', build_lock, re.M)
def test_workflow_builds_from_the_pushed_commit_and_reports_the_digest():
flow = yaml.safe_load((ROOT / '.forgejo' / 'workflows' / 'service-image.yaml').read_text())
on = flow.get('on', flow.get(True))
assert on['push']['branches'] == ['main']
steps = flow['jobs']['build-and-push']['steps']
script = steps[0]['run']
assert 'archive/${REF}.tar.gz' in script and ':main-${SHORT}' in script
assert script.index("zlib>=1.3.2-r1") < script.index('docker push')
assert script.index('diff /tmp/source.txt /tmp/installed.txt') < script.index('docker push')
assert steps[1]['name'] == 'Report immutable digest'
assert flow['env']['IMAGE_NAME'] == 'coulomb/informed-decision'