Files
school_compare/scripts/ci/tests/test_release.py
T

65 lines
2.7 KiB
Python
Raw Normal View History

import json
from unittest.mock import Mock
import pytest
from scripts.ci import release
SHA = 'a' * 40
BUILD = 'b' * 32
DIGESTS = ['sha256:' + c * 64 for c in '123']
@pytest.fixture
def docker(monkeypatch):
monkeypatch.setenv('REGISTRY', 'registry.example')
refs = {}
for component, digest in zip(release.COMPONENTS, DIGESTS):
monkeypatch.setenv(component + '_IMAGE_NAME', component.lower())
monkeypatch.setenv(component + '_DIGEST', digest)
refs[f'registry.example/{component.lower()}'] = digest
def run(*args):
if args[0] == 'create': return ''
if args[-1] == '{{json .Manifest}}':
return json.dumps({'digest': refs[args[1].split(':')[0]]})
return json.dumps({'config': {'Labels': {'io.schoolcompare.commit': SHA,
'io.schoolcompare.build-id': BUILD}}})
mock = Mock(side_effect=run)
monkeypatch.setattr(release, 'docker', mock)
return mock
def test_wrong_deployed_build_is_rejected_even_at_same_commit():
assert not release.matches({'frontend': {'sha': SHA, 'build_id': BUILD},
'backend': {'sha': SHA, 'build_id': 'c' * 32}}, SHA, BUILD)
assert release.matches({c: {'sha': SHA, 'build_id': BUILD} for c in ('frontend', 'backend')}, SHA, BUILD)
def test_verification_tags_the_captured_digests(docker):
release.verify(SHA, BUILD)
creates = [c.args for c in docker.call_args_list if c.args[0] == 'create']
assert len(creates) == 3
for call, digest in zip(creates, DIGESTS):
assert call[-1].endswith('@' + digest)
assert call[2].endswith(':verified-' + SHA)
def test_promotion_resolves_all_verified_images_before_mutation(docker):
result = release.promote(SHA)
assert result['build_id'] == BUILD
calls = [c.args for c in docker.call_args_list]
first_write = next(i for i, c in enumerate(calls) if c[0] == 'create')
assert first_write == 6 # each of three candidates needs manifest + config
assert all(c[-1].endswith('@' + d) for c, d in zip(calls[-3:], DIGESTS))
def test_mixed_builds_fail_before_any_tag_is_changed(docker, monkeypatch):
identities = iter([(SHA, BUILD), (SHA, 'c' * 32), (SHA, BUILD)])
monkeypatch.setattr(release, 'image_identity', lambda _: next(identities))
with pytest.raises(ValueError, match='mixed'):
release.promote(SHA)
assert not any(c.args[0] == 'create' for c in docker.call_args_list)
def test_missing_candidate_fails_before_any_tag_is_changed(docker):
docker.side_effect = RuntimeError('missing verified tag')
with pytest.raises(RuntimeError): release.promote(SHA)
assert not any(c.args[0] == 'create' for c in docker.call_args_list)