trip-test 0.1.2

Contract testing & regression safety for MCP servers
Documentation
name: trip-test Contract Check

on:
  pull_request:
  push:
    branches:
      - main

jobs:
  contract-check:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Cache Rust dependencies
        uses: swatinem/rust-cache@v2

      - name: Build examples
        run: cargo build --release --examples

      - name: Install trip-test
        run: cargo install --path .

      - name: Run contract check
        id: check
        run: |
          trip-test diff --config trip-test.toml --format json > diff-report.json || true
          cat diff-report.json

      - name: Parse and comment on PR
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');

            let reportContent = '';
            try {
              reportContent = fs.readFileSync('diff-report.json', 'utf8');
            } catch (e) {
              console.log('No report file found');
              return;
            }

            const report = JSON.parse(reportContent);

            let comment = '## 🔍 trip-test Contract Check\n\n';

            if (report.overall_verdict === 'BREAKING') {
              comment += '### ❌ Breaking Changes Detected\n\n';
              comment += 'The following breaking changes were found:\n\n';
              comment += '| Tool | Change Type | Details |\n';
              comment += '|------|-------------|----------|\n';

              report.breaking_changes.forEach(change => {
                comment += `| \`${change.tool_name}\` | ${change.change_type} | ${change.details} |\n`;
              });
            } else {
              comment += '### ✅ No Breaking Changes\n\n';
              comment += 'The contract is safe to merge.\n\n';
            }

            if (report.non_breaking_changes.length > 0) {
              comment += '\n### ⚠️ Non-Breaking Changes\n\n';
              comment += '| Tool | Change | Details |\n';
              comment += '|------|--------|----------|\n';
              report.non_breaking_changes.forEach(change => {
                comment += `| \`${change.tool_name}\` | ${change.change_type} | ${change.details} |\n`;
              });
            }

            if (report.additive_changes.length > 0) {
              comment += '\n### ✨ Additive Changes\n\n';
              comment += '| Tool | Change | Details |\n';
              comment += '|------|--------|----------|\n';
              report.additive_changes.forEach(change => {
                comment += `| \`${change.tool_name}\` | ${change.change_type} | ${change.details} |\n`;
              });
            }

            comment += '\n---\n';
            comment += `**Verdict:** \`${report.overall_verdict}\`\n`;

            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: comment
            });

      - name: Fail if breaking changes
        run: |
          if grep -q '"overall_verdict": "BREAKING"' diff-report.json; then
            echo "Breaking changes detected - failing check"
            exit 1
          fi