Install repo-manager e77f8b4 from its own uv.lock into an isolated venv in the builder stage (commit identity asserted via git), copy it into the runtime image and set ACTIVITY_CORE_RMGR_BIN. Add a pin test and the founder-executed rollout package (Argo CD manifest diff, PVC, token route blocker, trial runbooks). Nothing deployed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 692292@bnt-lap001 Assistant-Session: 89c7d8e8-e1b3-47eb-9411-a0ab227fca2f
98 lines
5.2 KiB
Python
98 lines
5.2 KiB
Python
"""Adoption and routine-promotion boundaries are checked without cluster access."""
|
|
import importlib.util
|
|
from pathlib import Path
|
|
import copy
|
|
import pytest
|
|
import yaml
|
|
ROOT=Path(__file__).resolve().parents[1]
|
|
def load(name):
|
|
spec=importlib.util.spec_from_file_location(name,ROOT/'scripts'/f'{name}.py')
|
|
mod=importlib.util.module_from_spec(spec);spec.loader.exec_module(mod);return mod
|
|
|
|
def test_render_exact_reviewed_set_and_no_jobs_or_secrets():
|
|
render=load('render_gitops')
|
|
assert render.render()==(ROOT/'k8s/gitops/runtime.yaml').read_text()
|
|
docs=list(yaml.safe_load_all(render.render()))
|
|
assert len(docs)==9
|
|
assert {d['kind'] for d in docs}=={'Deployment','ConfigMap','Service'}
|
|
assert all(d['metadata']['namespace']=='activity-core' for d in docs)
|
|
worker=next(d for d in docs if d['metadata']['name']=='actcore-worker')
|
|
mounts=worker['spec']['template']['spec']['containers'][0]['volumeMounts']
|
|
assert any(m.get('subPath')=='entrypoint' and m['name']=='backup-verified' for m in mounts)
|
|
|
|
|
|
def test_image_workflow_publishes_commit_tag_and_digest():
|
|
text=(ROOT/'.forgejo/workflows/image.yaml').read_text()
|
|
assert ':latest' not in text and ':git-${REF}' in text
|
|
assert '${REF}.tar.gz' in text and '--target test' in text
|
|
assert 'RepoDigests' in text
|
|
|
|
|
|
def test_build_inputs_are_pinned():
|
|
text=(ROOT/'Dockerfile').read_text()
|
|
assert text.count('python:3.12-slim@sha256:')==2
|
|
assert 'uv==0.5.9' in text and '--frozen' in text
|
|
|
|
|
|
def promotion():
|
|
from datetime import datetime,timezone
|
|
before=list(yaml.safe_load_all((ROOT/'k8s/gitops/runtime.yaml').read_text()))
|
|
after=copy.deepcopy(before)
|
|
worker=next(d for d in after if d['metadata']['name']=='actcore-worker')
|
|
container=worker['spec']['template']['spec']['containers'][0]
|
|
container.update(image='forgejo.coulomb.social/coulomb/activity-core@sha256:'+'a'*64,imagePullPolicy='IfNotPresent')
|
|
evidence=dict(schema_version=1,identity_admitted=True,authority='ACTIVITY-WP-0041-image-only-v1',checks='pass',review_result='pass',reviewer='independent-ci',producer='build-ci',candidate_commit='a'*40,rollback_commit='b'*40,healthy_since='2026-09-26T00:00:00Z',observed_at='2026-09-27T01:00:00Z',argo_synced=True,argo_healthy=True)
|
|
return before,after,evidence,datetime(2026,9,27,1,tzinfo=timezone.utc)
|
|
|
|
def test_admits_only_digest_release_after_soak():
|
|
assert load('check_gitops_promotion').validate(*promotion())['deployments']==['actcore-worker']
|
|
|
|
@pytest.mark.parametrize('key,value',[('identity_admitted',False),('checks','fail'),('reviewer','build-ci'),('healthy_since','2026-09-27T00:00:00Z'),('observed_at','2026-09-26T01:00:00Z'),('argo_healthy',False),('rollback_commit','not-a-sha')])
|
|
def test_refuses_missing_release_guards(key,value):
|
|
before,after,evidence,now=promotion();evidence[key]=value
|
|
with pytest.raises(ValueError):load('check_gitops_promotion').validate(before,after,evidence,now)
|
|
|
|
@pytest.mark.parametrize('change',['command','resources','tag','inventory'])
|
|
def test_refuses_authority_expansion(change):
|
|
before,after,evidence,now=promotion()
|
|
worker=next(d for d in after if d['metadata']['name']=='actcore-worker')
|
|
c=worker['spec']['template']['spec']['containers'][0]
|
|
if change=='command':c['command']=['sh']
|
|
elif change=='resources':c['resources']={'requests':{'cpu':'2'}}
|
|
elif change=='tag':c['image']='forgejo.coulomb.social/coulomb/activity-core:latest'
|
|
else:after.pop()
|
|
with pytest.raises(ValueError):load('check_gitops_promotion').validate(before,after,evidence,now)
|
|
|
|
|
|
def test_frontend_projection_checks_content_and_pin(tmp_path):
|
|
renderer=load('render_gitops')
|
|
cm=next(d for d in yaml.safe_load_all(renderer.render()) if d['metadata']['name']=='actcore-external-activity-definitions')
|
|
for name,body in cm['data'].items():
|
|
if name.startswith('frontend-patterns-'): (tmp_path/name).write_text(body)
|
|
renderer.verify_frontend(tmp_path)
|
|
(tmp_path/'frontend-patterns-daily.md').write_text('tampered')
|
|
with pytest.raises(ValueError): renderer.verify_frontend(tmp_path)
|
|
|
|
|
|
def test_retention_projection_is_pinned_and_mounted(tmp_path):
|
|
renderer=load('render_gitops')
|
|
docs=list(yaml.safe_load_all(renderer.render()))
|
|
cm=next(d for d in docs if d['metadata']['name']=='actcore-ops-service-inventory')
|
|
source=tmp_path/'prune.py';source.write_text(cm['data']['forgejo_package_prune.py'])
|
|
renderer.verify_platform(source)
|
|
worker=next(d for d in docs if d['metadata']['name']=='actcore-worker')
|
|
mounts=worker['spec']['template']['spec']['containers'][0]['volumeMounts']
|
|
assert any(m.get('subPath')=='forgejo_package_prune.py' and m['readOnly'] is True for m in mounts)
|
|
source.write_text('tampered')
|
|
with pytest.raises(ValueError):renderer.verify_platform(source)
|
|
|
|
|
|
def test_repo_manager_cli_is_pinned_and_isolated():
|
|
# RMGR-WP-0020-T04: rmgr enters the worker from repo-manager's own lock at the
|
|
# founder-reviewed commit, in its own venv, and is the code-fixed executable.
|
|
text=(ROOT/'Dockerfile').read_text()
|
|
assert 'ARG REPO_MANAGER_COMMIT=e77f8b457647ff23697e45a74615edde5f42d39d' in text
|
|
assert 'rev-parse HEAD)" = "${REPO_MANAGER_COMMIT}"' in text
|
|
assert 'uv sync --no-dev --frozen --no-editable' in text
|
|
assert 'COPY --from=builder /opt/repo-manager/.venv /opt/repo-manager/.venv' in text
|
|
assert 'ENV ACTIVITY_CORE_RMGR_BIN="/opt/repo-manager/.venv/bin/rmgr"' in text
|