Files
cacti/tests/tools/test_released_dependency_audit.py

75 lines
3.6 KiB
Python

"""Exercise the workflow's audit commands without calling package registries."""
import json
import os
from pathlib import Path
import subprocess
import tempfile
import unittest
import yaml
ROOT = Path(__file__).resolve().parents[2]
WORKFLOW = ROOT / '.github/workflows/released-dependency-audit.yml'
class ReleasedDependencyAuditTest(unittest.TestCase):
def audit(self, ecosystem, report, status=0):
workflow = yaml.safe_load(WORKFLOW.read_text())
command = next(step['run'] for step in workflow['jobs']['audit']['steps']
if step['name'] == 'Audit committed dependencies')
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
executable = root / ecosystem
executable.write_text('#!/bin/sh\ncat "$FIXTURE_REPORT"\nexit "$FIXTURE_STATUS"\n')
executable.chmod(0o755)
fixture = root / 'fixture.json'
fixture.write_text(report if isinstance(report, str) else json.dumps(report))
result = subprocess.run(['bash', '-c', command], text=True, capture_output=True,
env={**os.environ, 'PATH': f'{root}{os.pathsep}{os.environ["PATH"]}',
'PACKAGE_ECOSYSTEM': ecosystem, 'GITHUB_WORKSPACE': directory,
'FIXTURE_REPORT': str(fixture), 'FIXTURE_STATUS': str(status)})
self.assertEqual((root / 'dependency-audit.json').read_text(), fixture.read_text())
return result
def test_clean_locks_pass(self):
for ecosystem, report in [('composer', {'advisories': [], 'abandoned': {}}),
('npm', {'metadata': {'vulnerabilities': {'total': 0}}})]:
with self.subTest(ecosystem=ecosystem):
result = self.audit(ecosystem, report)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertNotIn('::warning', result.stdout)
def test_composer_advisories_are_reported(self):
result = self.audit('composer', {'advisories': {'vendor/package': [{'title': 'fixture'}]},
'abandoned': {}}, 1)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn('1 advisory or abandoned-package records', result.stdout)
def test_abandoned_packages_are_reported(self):
result = self.audit('composer', {'advisories': [], 'abandoned': {'vendor/package': None}}, 2)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn('1 advisory or abandoned-package records', result.stdout)
def test_npm_advisories_are_reported(self):
result = self.audit('npm', {'metadata': {'vulnerabilities': {'total': 3}}}, 1)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn('3 advisory or abandoned-package records', result.stdout)
def test_invalid_reports_fail(self):
for ecosystem in ['composer', 'npm']:
for report in ['registry unavailable', {'error': {'message': 'fixture'}}]:
with self.subTest(ecosystem=ecosystem, report=report):
self.assertNotEqual(self.audit(ecosystem, report, 1).returncode, 0)
def test_tool_failures_without_findings_fail(self):
for ecosystem, report in [('composer', {'advisories': [], 'abandoned': {}}),
('npm', {'metadata': {'vulnerabilities': {'total': 0}}})]:
with self.subTest(ecosystem=ecosystem):
self.assertEqual(self.audit(ecosystem, report, 42).returncode, 42)
if __name__ == '__main__':
unittest.main()