All checks were successful
Build and Publish Service Image / build-and-push (push) Successful in 2m38s
.forgejo/workflows/service-image.yaml builds Containerfile from the pushed commit's tarball and pushes forgejo.coulomb.social/coulomb/informed-decision :main-<short sha>, then reports the immutable digest. Before pushing it checks the zlib floor, the runtime smoke (tools/zlib_overlay/check_runtime.py) and that the installed modules equal the commit's source. Containerfile builds the wheel in-image (hash-pinned setuptools in requirements-build.lock) and installs the zlib overlay's hash-pinned, Alpine-signed zlib-1.3.2-r1 package offline, failing below 1.3.2-r1, so the live image's zlib fix cannot regress. Overlay workflows are unchanged. Local build: 13/13 container checks, zlib 1.3.2-r1, source manifest match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 5502@bnt-lap001 Assistant-Session: 68b3b02f-5d0f-4e71-8421-796f62e50196
52 lines
2.5 KiB
Python
52 lines
2.5 KiB
Python
"""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'
|