Skip to content

Latest commit

 

History

History
421 lines (352 loc) · 11.7 KB

File metadata and controls

421 lines (352 loc) · 11.7 KB

🌐 HTTP Integration & Scheduling

Visor provides comprehensive HTTP integration capabilities including webhook reception, HTTP outputs, scheduled executions via cron, and TLS/HTTPS support.

HTTP Server for Webhook Reception

Configure an HTTP/HTTPS server to receive webhooks and trigger checks:

version: "1.0"

http_server:
  enabled: true
  port: 8080
  host: "0.0.0.0"

  # Optional TLS/HTTPS configuration
  tls:
    enabled: true
    cert: "${TLS_CERT}"  # From environment variable
    key: "${TLS_KEY}"
    ca: "${TLS_CA}"      # Optional CA certificate
    rejectUnauthorized: true

  # Authentication
  auth:
    type: bearer_token
    secret: "${WEBHOOK_SECRET}"

  # Webhook endpoints
  endpoints:
    - path: "/webhook/github"
      name: "github-events"
    - path: "/webhook/jenkins"
      name: "jenkins-builds"

Note: The HTTP server is automatically disabled when running in GitHub Actions to avoid conflicts.

Check Types for HTTP Integration

Important: HTTP steps that interact with external services should declare criticality: external and include assume/guarantee contracts for safety. See Criticality Modes for details.

1. HTTP Input (Webhook Receiver)

Receive data from configured webhook endpoints:

steps:
  github-webhook:
    type: http_input
    criticality: external  # Receives from external system
    assume: "true"         # Precondition guard (required for critical steps)
    schema: plain          # Output contract
    endpoint: "/webhook/github"
    on: [webhook_received]
    transform: |
      {
        "event": "{{ webhook.action }}",
        "repository": "{{ webhook.repository.full_name }}"
      }

HTTP Input Options:

Option Description Default
endpoint Webhook endpoint path (must match http_server endpoints) Required
on Event triggers (typically [webhook_received]) -
transform Liquid template to transform received webhook data -
group Grouping category for the step -

2. HTTP Output (Send Data)

Send check results to external services:

steps:
  notify-external:
    type: http
    criticality: external  # Sends to external system
    assume: "outputs['security-check']"  # Only run if dependency succeeded
    schema: plain
    depends_on: [security-check]
    url: "https://api.example.com/notify"
    method: POST
    headers:
      Content-Type: "application/json"
      Authorization: "Bearer ${API_TOKEN}"
    timeout: 30000  # Optional timeout in milliseconds (default: 30000)
    body: |
      {
        "results": {{ outputs['security-check'] | json }},
        "timestamp": "{{ 'now' | date: '%Y-%m-%d %H:%M:%S' }}"
      }

HTTP Output Options:

Option Description Default
url Target URL Required
body Request body template (Liquid) Required
method HTTP method POST
headers Request headers (supports env var substitution) {}
timeout Request timeout in milliseconds 30000
metadata Additional metadata available in templates {}

3. HTTP Client (Fetch Data)

Fetch data from external APIs:

steps:
  fetch-config:
    type: http_client
    criticality: external  # Fetches from external system
    assume: "env.API_TOKEN"  # Require API token to be set
    schema: plain
    url: "https://api.example.com/config"
    method: GET
    headers:
      Authorization: "Bearer ${API_TOKEN}"
    timeout: 30000  # Optional timeout in milliseconds (default: 30000)
    transform: |
      {
        "settings": {{ response.data | json }},
        "fetched_at": "{{ 'now' | date: '%Y-%m-%d' }}"
      }

HTTP Client Options:

Option Description Default
url Target URL (supports Liquid templates and env vars) Required
method HTTP method (GET, POST, PUT, DELETE, etc.) GET
headers Request headers (supports env var substitution) {}
body Request body for POST/PUT (supports Liquid templates) -
timeout Request timeout in milliseconds 30000
transform Liquid template to transform response -
transform_js JavaScript expression to transform response -
output_file Download response to file instead of returning data -
skip_if_exists Skip download if file exists (caching) true
rate_limit Rate limiting configuration (see below) -

Rate Limiting:

Throttle outgoing requests to avoid hitting API rate limits. Multiple steps sharing the same key share a single token bucket globally.

steps:
  fetch-data:
    type: http_client
    url: "https://api.example.com/data"
    headers:
      Authorization: "Bearer ${API_TOKEN}"
    rate_limit:
      key: example-api        # Shared bucket name (defaults to URL origin)
      requests: 30             # Max requests per window
      per: minute              # second | minute | hour
      max_retries: 3           # Retries on 429 (default: 3)
      backoff: exponential     # fixed | exponential (default: exponential)
      initial_delay_ms: 1000   # Base delay for backoff (default: 1000)

On a 429 response, the limiter automatically retries with backoff and respects the server's Retry-After header when present.

File Download Example:

steps:
  download-artifact:
    type: http_client
    url: "https://example.com/artifacts/{{ pr.number }}.zip"
    output_file: "./downloads/artifact.zip"
    skip_if_exists: true  # Use cached file if exists

JavaScript Transform Example:

steps:
  fetch-and-transform:
    type: http_client
    url: "https://api.example.com/data"
    transform_js: |
      // Access response via 'output' variable
      const items = output.items || [];
      return items.filter(i => i.status === 'active');

4. Log Provider (Debugging & Monitoring)

Output debugging information and monitor workflow execution:

steps:
  debug-start:
    type: log
    group: debugging
    level: info
    message: "Starting code review for PR #{{ pr.number }} by {{ pr.author }}"
    include_pr_context: true
    include_dependencies: false
    include_metadata: true

  debug-dependencies:
    type: log
    group: debugging
    level: debug
    depends_on: [security-check]
    message: |
      Dependency results summary:
      {% if dependencies %}
      - Security check found {{ dependencies['security-check'].issueCount }} issues
      {% else %}
      - No dependencies processed
      {% endif %}
    include_dependencies: true

  performance-monitor:
    type: log
    group: monitoring
    level: warn
    message: "Large PR detected: {{ pr.totalAdditions }} lines added"

Log Provider Options:

Option Description Default
message Log message template (Liquid) Required
level Log level: debug, info, warn, error info
group Grouping category (e.g., debugging, monitoring, chat) -
include_pr_context Include PR details in output true
include_dependencies Include dependency results in output true
include_metadata Include execution metadata in output true

Chat Group Example:

When group: chat is set, the log provider exposes a structured output.text field for chat-style integrations:

steps:
  chat-response:
    type: log
    group: chat
    level: info
    message: "Analysis complete for PR #{{ pr.number }}"

Cron Scheduling

steps:
  nightly-security-scan:
    type: ai
    schedule: "0 3 * * *"  # Every day at 3am
    prompt: "Run a deep security scan on the default branch"
steps:
  weekly-health-check:
    type: http_client
    url: "https://api.example.com/health"
    schedule: "0 0 * * 0"  # Every Sunday at midnight

TLS/HTTPS Configuration

You can configure TLS using environment variables, direct file paths, or Let's Encrypt.

Environment Variables

tls:
  enabled: true
  cert: "${TLS_CERT}"
  key: "${TLS_KEY}"

File Paths

tls:
  enabled: true
  cert: "/etc/ssl/certs/server.crt"
  key: "/etc/ssl/private/server.key"

Let's Encrypt

tls:
  enabled: true
  cert: "/etc/letsencrypt/live/example.com/fullchain.pem"
  key: "/etc/letsencrypt/live/example.com/privkey.pem"

HTTP Security Features

Visor's HTTP server includes comprehensive security protections:

Authentication Methods

# Bearer Token Authentication
auth:
  type: bearer_token
  secret: "${WEBHOOK_SECRET}"

# HMAC-SHA256 Signature Verification
auth:
  type: hmac
  secret: "${WEBHOOK_SECRET}"

# Basic Authentication
auth:
  type: basic
  username: "${HTTP_USERNAME}"
  password: "${HTTP_PASSWORD}"

# No Authentication (not recommended for production)
auth:
  type: none

HMAC Authentication Details

For hmac authentication, webhooks must include the x-webhook-signature header:

  • Signature format: sha256={hash}
  • Uses HMAC-SHA256 with the configured secret
  • Implements timing-safe comparison to prevent timing attacks
  • Compatible with GitHub webhook signatures

DoS Protection

  • Request size limits: Maximum 1MB request body size
  • Early rejection: Validates Content-Length header before processing
  • Graceful error handling: Returns proper HTTP status codes (413 Payload Too Large)

Security Best Practices

  • Environment detection: Automatically disables in GitHub Actions
  • TLS support: Full HTTPS configuration with custom certificates
  • Input validation: Validates all webhook payloads before processing
  • Error isolation: Security failures don't affect independent checks

Complete HTTP Pipeline Example

version: "1.0"

# HTTP server configuration
http_server:
  enabled: true
  port: 8443
  tls:
    enabled: true
    cert: "${TLS_CERT}"
    key: "${TLS_KEY}"
  auth:
    type: bearer_token
    secret: "${WEBHOOK_SECRET}"
  endpoints:
    - path: "/webhook/deployment"
      name: "deployment-trigger"

steps:
  # 1. Receive webhook
  deployment-webhook:
    type: http_input
    endpoint: "/webhook/deployment"
    on: [webhook_received]
    transform: |
      {
        "version": "{{ webhook.version }}",
        "environment": "{{ webhook.environment }}"
      }

  # 2. Analyze deployment
  deployment-analysis:
    type: ai
    depends_on: [deployment-webhook]
    prompt: |
      Analyze deployment for version {{ outputs['deployment-webhook'].suggestions | first }}
      Check for potential issues and risks

  # 3. Fetch current status
  current-status:
    type: http_client
    depends_on: [deployment-webhook]
    url: "https://api.example.com/status"
    method: GET

  # 4. Send results
  notify-team:
    type: http
    depends_on: [deployment-analysis, current-status]
    url: "https://slack.example.com/webhook"
    body: |
      {
        "text": "Deployment Analysis Complete",
        "analysis": {{ outputs['deployment-analysis'] | json }},
        "current_status": {{ outputs['current-status'] | json }}
      }

  # 5. Scheduled health check
  health-check:
    type: http_client
    url: "https://api.example.com/health"
    schedule: "*/5 * * * *"  # Every 5 minutes
    transform: |
      {
        "status": "{{ response.status }}",
        "checked_at": "{{ 'now' | date: '%Y-%m-%d %H:%M:%S' }}"
      }

Liquid Template Support

All HTTP configurations support Liquid templating for dynamic content. See Liquid Templates Guide for complete reference.

Common patterns:

  • Access webhook data: {{ webhook.field }}
  • Access headers: {{ headers['x-custom-header'] }}
  • Access previous outputs: {{ outputs['check-name'].suggestions | first }}
  • Date formatting: {{ 'now' | date: '%Y-%m-%d' }}
  • JSON encoding: {{ data | json }} (useful for debugging objects)