Skip to content

feat: CI pipeline integration (JUnit/SARIF output, --ci flag, container entrypoint)#520

Open
ian-flores wants to merge 12 commits into
mainfrom
worktree-ci-pipeline-integration-149
Open

feat: CI pipeline integration (JUnit/SARIF output, --ci flag, container entrypoint)#520
ian-flores wants to merge 12 commits into
mainfrom
worktree-ci-pipeline-integration-149

Conversation

@ian-flores

Copy link
Copy Markdown
Collaborator

Summary

Makes VIP consumable by customer security-ops and CI/CD pipelines (issue #149, driven by FSI feedback). Adds machine-readable output formats, a one-flag CI preset, and a CLI-based container entrypoint.

Design + plan: thoughts/shared/plans/2026-07-21-issue-149-ci-integration-design.md.

What's included

  • JUnit XML outputwrite_junit_xml() in reporting.py, standard testsuites/testsuite/testcase schema with VIP's concise_error + scenario metadata; consumed by CI test dashboards.
  • SARIF 2.1.0 outputwrite_sarif(), every check emitted as a result (fail=error, pass=none, skip=note) for a full compliance audit trail; ingested by GitHub code scanning / secops tooling.
  • vip verify --format json,junit,sarif — comma-separated, additive. results.json/failures.json are always written (the HTML report depends on them); JUnit/SARIF land as siblings in the report dir.
  • vip verify --ci — preset bundling --format json,junit,sarif + --tb=short + non-interactive.
  • Container entrypoint — Dockerfile ENTRYPOINT ["uv","run","vip"] / CMD ["verify"]. Note: docker run args replace CMD, so the CI recipe is docker run <img> verify --ci.
  • Docs — README "CI / pipeline integration" section.

Issue #149 checklist advanced

  • JUnit XML output format
  • SARIF output format
  • CI-friendly entrypoint (--ci, exit codes, non-interactive)
  • Container entrypoint reworked to the vip CLI (GHCR build/push already existed via docker.yml)

Testing

  • 259 tests pass across test_reporting, test_plugin, test_cli_verify, test_cli_report (TDD throughout).
  • End-to-end verified: a live pytest session with --vip-format=json,junit,sarif emits all sibling files; --format json emits no extras.
  • ruff + mypy clean on changed files.

Follow-ups (deferred, non-blocking)

  • SARIF unknown-outcome default (currently dead code — pytest constrains outcomes).
  • --ci regression test pinning non-interactive flags absent.
  • --format value de-duplication (cosmetic; plugin folds to a set anyway).
  • Multi-arch image; per-format path override flags.

Copilot AI review requested due to automatic review settings July 21, 2026 22:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds CI/pipeline-focused integration features to VIP so it can emit machine-readable artifacts (JUnit XML + SARIF) and run cleanly in containerized CI workflows via a CLI-based entrypoint.

Changes:

  • Implement JUnit XML and SARIF 2.1.0 writers off the existing ReportData model.
  • Wire format emission into the pytest plugin via a new --vip-format option, and expose vip verify --format ... plus a --ci preset in the CLI.
  • Update the container entrypoint to run the vip CLI (defaulting to verify) and document the workflow in the README.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
thoughts/shared/plans/2026-07-21-issue-149-ci-integration-plan.md Implementation plan describing writers, plugin/CLI wiring, container changes, and test strategy.
thoughts/shared/plans/2026-07-21-issue-149-ci-integration-design.md Design notes and decisions for CI outputs and container invocation semantics.
src/vip/reporting.py Adds write_junit_xml() and write_sarif() output writers.
src/vip/plugin.py Adds --vip-format and emits JUnit/SARIF siblings at session end.
src/vip/cli.py Adds vip verify --format and --ci, forwarding into pytest as --vip-format.
selftests/test_reporting.py Adds unit tests for JUnit XML and SARIF writers (including XML sanitization).
selftests/test_plugin.py Adds tests for plugin extra-format emission behavior.
selftests/test_cli_verify.py Adds tests for CLI forwarding/validation of --format and --ci.
README.md Documents CI/pipeline integration usage, artifacts, and container invocation.
Dockerfile Switches ENTRYPOINT/CMD to uv run vip / verify for container-friendly CLI usage.
Comments suppressed due to low confidence (1)

src/vip/cli.py:507

  • --ci is documented as running “strictly non-interactively”, but run_verify() will still forward --interactive-auth / --headless-auth if the user also passes them, which defeats the guarantee implied by --ci.

If --ci is meant to be a strict preset, consider rejecting those interactive flags when --ci is set (or explicitly overriding them off) so the behavior matches the help text.

    _VALID_FORMATS = {"json", "junit", "sarif"}
    fmt = "json,junit,sarif" if getattr(args, "ci", False) else getattr(args, "format", "json")
    requested = [f.strip().lower() for f in fmt.split(",") if f.strip()]
    unknown = [f for f in requested if f not in _VALID_FORMATS]
    if unknown:
        print(
            f"Error: unknown --format value(s): {', '.join(unknown)}. "
            f"Valid: {', '.join(sorted(_VALID_FORMATS))}.",
            file=sys.stderr,
        )
        sys.exit(2)
    cmd.append(f"--vip-format={','.join(requested)}")
    if args.interactive_auth:
        cmd.append("--interactive-auth")
    if args.headless_auth:
        cmd.append("--headless-auth")

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/vip/plugin.py
Comment on lines +1127 to +1129
formats = {f.strip().lower() for f in fmt.split(",") if f.strip()}
if not (formats & {"junit", "sarif"}):
return
@ian-flores
ian-flores marked this pull request as ready for review July 21, 2026 22:57
@github-actions

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants