diff --git a/nyx-scan/action.yml b/nyx-scan/action.yml index 289323f..03995ce 100644 --- a/nyx-scan/action.yml +++ b/nyx-scan/action.yml @@ -46,9 +46,10 @@ runs: run: | .nyx-src/target/release/nyx scan --format json > nyx-results-raw.json 2>&1 - # Apply suppression rules from triage.json python3 -c " - import json + import json, os + + workspace = os.environ.get('GITHUB_WORKSPACE', os.getcwd()) with open('nyx-results-raw.json') as f: findings = json.load(f) @@ -56,7 +57,6 @@ runs: if isinstance(findings, dict): findings = findings.get('findings', []) - # Load suppression rules try: with open('.nyx/triage.json') as f: triage = json.load(f) @@ -64,34 +64,46 @@ runs: except: rules = [] + def rel_path(p): + p = p.replace(workspace, '').lstrip('/') + return p + def is_suppressed(f): rule_id = f.get('id', '') + path = rel_path(f.get('path', '')) for r in rules: by = r.get('by', '') value = r.get('value', '') if by == 'rule' and rule_id == value: return True - if by == 'file' and f.get('path', '').endswith(value): + if by == 'file' and path == value: return True if by == 'rule_in_file': parts = value.split(':', 1) - if len(parts) == 2 and rule_id == parts[0] and f.get('path','').endswith(parts[1]): + if len(parts) == 2 and rule_id == parts[0] and path == parts[1]: return True return False filtered = [f for f in findings if not is_suppressed(f)] - print(f'Suppressed {len(findings) - len(filtered)} of {len(findings)} findings', flush=True) + print(f'Suppressed {len(findings) - len(filtered)} of {len(findings)} findings') + + fail_on = os.environ.get('NYX_FAIL_ON', 'high').lower() + severity_order = ['low', 'medium', 'high', 'critical'] + fail_idx = severity_order.index(fail_on) if fail_on in severity_order else 2 - # Convert to minimal SARIF results = [] for f in filtered: + sev = f.get('severity', '').lower() results.append({ - 'level': 'error' if f.get('severity','').lower() in ['high','critical'] else 'warning', - 'message': {'text': f.get('message','')}, - 'ruleId': f.get('id',''), + 'level': 'error' if sev in ['high', 'critical'] else 'warning', + 'message': {'text': f.get('message', '')}, + 'ruleId': f.get('id', ''), 'locations': [{'physicalLocation': { - 'artifactLocation': {'uri': f.get('path','').replace('/workspace/nomyo-ai/nomyo-router/','')}, - 'region': {'startLine': f.get('line',0), 'startColumn': f.get('col',0)} + 'artifactLocation': {'uri': rel_path(f.get('path', ''))}, + 'region': { + 'startLine': f.get('line', 0), + 'startColumn': f.get('col', 0) + } }}] }) @@ -104,10 +116,16 @@ runs: with open('nyx-results.sarif', 'w') as f: json.dump(sarif, f, indent=2) - # Fail if any HIGH/CRITICAL remain - high = [f for f in filtered if f.get('severity','').lower() in ['${{ inputs.fail_on }}'.lower(), 'critical']] - exit(1 if high else 0) + should_fail = any( + severity_order.index(f.get('severity','low').lower()) >= fail_idx + for f in filtered + if f.get('severity','low').lower() in severity_order + ) + exit(1 if should_fail else 0) " + env: + GITHUB_WORKSPACE: ${{ github.workspace }} + NYX_FAIL_ON: ${{ inputs.fail_on }} continue-on-error: true - name: Post findings as PR comment