This repository has been archived on 2026-11-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
qqq-orb/tests/test_mobile_policy_profiles.py
james.maesandCodex a50b07d927 fix: escape Android heredoc in continued Circle configuration (#51)
Circle accepts the continuation request before reporting an unescaped heredoc as a pipeline configuration error. Escape the template marker and emulate Circle unescaping in executable publisher tests. Validate the actual continued config with CircleCI.

Co-authored-by: Codex <noreply@openai.com>
2026-10-20 22:00:56 -05:00

117 lines
6.3 KiB
Python

"""Protect existing Android gates and execute the centralized policy validator."""
import contextlib
import io
import json
import os
from pathlib import Path, PurePosixPath
import subprocess
import tempfile
import unittest
from unittest import mock
import yaml
ROOT = Path(__file__).resolve().parents[1]
class MobilePolicyTests(unittest.TestCase):
def test_android_preserves_executed_jobs_and_repairs_main_dependencies(self):
before = yaml.safe_load((ROOT / "tests/fixtures/android-circle.yml").read_text())
after = json.loads((ROOT / "src/scripts/templates/android.json").read_text())
self.assertEqual(after["orbs"], before["orbs"])
self.assertEqual(set(after["jobs"]), {"unit-test", "android-test", "maven-deploy"})
for name in ("unit-test", "android-test"):
self.assertEqual(after["jobs"][name], before["jobs"][name])
self.assertEqual(after["jobs"]["maven-deploy"]["executor"], before["jobs"]["maven-deploy"]["executor"])
self.assertEqual(after["jobs"]["maven-deploy"]["steps"][:2], before["jobs"]["maven-deploy"]["steps"][:2])
entries = after["workflows"]["test-and-build"]["jobs"]
self.assertEqual(entries[0], "unit-test")
self.assertEqual(entries[1], {"android-test": {}})
publish = entries[2]["maven-deploy"]
self.assertEqual(publish["context"], ["qqq-maven-registry-credentials"])
self.assertEqual(publish["requires"], ["unit-test", "android-test"])
self.assertEqual(publish["filters"], {"branches": {"only": "main"}})
# No new dormant Firebase benchmark or nonexistent app module build.
self.assertNotIn("benchmarks-ftl", after["jobs"])
def test_android_publication_uses_shared_credentials_without_persisting_them(self):
data = json.loads((ROOT / "src/scripts/templates/android.json").read_text())
steps = data["jobs"]["maven-deploy"]["steps"]
self.assertEqual(len(steps), 3)
raw = steps[2]["run"]["command"]
self.assertIn("python3 \\<<'PYTHON'", raw)
command = raw.replace("\\<<", "<<")
with tempfile.TemporaryDirectory() as folder:
root = Path(folder)
runner = root / "gradlew"
runner.write_text('''#!/bin/bash
set -eu
test "$1" = --console=plain
test "$2" = publishMavenPublicationToGithubQqqMavenRegistryRepository
test "$ORG_GRADLE_PROJECT_githubQqqMavenRegistryUsername" = fixture-user
test "$ORG_GRADLE_PROJECT_githubQqqMavenRegistryPassword" = fixture-password
touch invoked
''')
runner.chmod(0o755)
python = root / "python3"
python.write_text("#!/bin/bash\ncat >/dev/null\n[[ ${DENY_ACCESS:-0} == 0 ]] || exit 1\necho fixture-user\n")
python.chmod(0o755)
base = {**os.environ, "GITHUB_TOKEN": "fixture-password",
"PATH": str(root) + os.pathsep + os.environ["PATH"]}
for mode in ("missing", "denied", "success"):
env = dict(base)
if mode == "missing":
env.pop("GITHUB_TOKEN")
elif mode == "denied":
env["DENY_ACCESS"] = "1"
result = subprocess.run(["bash", "-c", command], cwd=root, env=env, capture_output=True, text=True)
self.assertEqual(result.returncode == 0, mode == "success")
self.assertEqual((root / "invoked").exists(), mode == "success")
self.assertFalse((root / "gradle.properties").exists())
self.assertNotIn("fixture-password", result.stdout + result.stderr)
def test_android_registry_preflight_fails_closed(self):
data = json.loads((ROOT / "src/scripts/templates/android.json").read_text())
command = data["jobs"]["maven-deploy"]["steps"][2]["run"]["command"]
script = command.split("<<'PYTHON'\n", 1)[1].split("\nPYTHON", 1)[0]
for identity, permissions, allowed in (({"login": "fixture-user"}, {"push": True}, True),
({"login": "fixture-user"}, {"push": False}, False),
({}, {"push": True}, False)):
opener = mock.Mock()
responses = [json.dumps(identity), json.dumps({"permissions": permissions})]
opener.open.side_effect = lambda *args, **kwargs: io.StringIO(responses.pop(0))
with mock.patch("urllib.request.build_opener", return_value=opener), \
mock.patch.dict(os.environ, {"GITHUB_TOKEN": "fixture-password"}), \
contextlib.redirect_stdout(io.StringIO()) as output:
if allowed:
exec(compile(script, "registry-preflight", "exec"), {})
self.assertEqual(output.getvalue().strip(), "fixture-user")
else:
with self.assertRaises(SystemExit):
exec(compile(script, "registry-preflight", "exec"), {})
self.assertNotIn("fixture-password", output.getvalue())
def test_policy_stays_small_and_validates_actual_pattern_content(self):
data = json.loads((ROOT / "src/scripts/templates/mcp-policy.json").read_text())
job = data["jobs"]["validate-patterns"]
self.assertEqual(job["resource_class"], "small")
self.assertIn("PyYAML==6.0.3", job["steps"][1]["run"]["command"])
command = job["steps"][2]["run"]["command"]
self.assertTrue(command.startswith("python3 \\<< 'EOF'\n"), "CircleCI requires escaped heredoc interpolation markers")
script = command.split("\n", 1)[1].rsplit("\nEOF", 1)[0]
valid = "id: example\ntitle: Example\ncategory: test\ndescription: test\ncontent: test\n"
for text, expected in ((valid, 0), ("id: incomplete\n", 1), ("[invalid", 1)):
with self.subTest(text=text), mock.patch.object(Path, "rglob", return_value=[PurePosixPath("patterns/example.yaml")]), \
mock.patch("builtins.open", return_value=io.StringIO(text)), \
contextlib.redirect_stdout(io.StringIO()):
if expected:
with self.assertRaises(SystemExit) as raised:
exec(compile(script, "policy-validator", "exec"), {})
self.assertEqual(raised.exception.code, expected)
else:
exec(compile(script, "policy-validator", "exec"), {})
if __name__ == "__main__":
unittest.main()