Octokit Webhooks

repository·main·Indexed 42 days ago

https://github.com/octokit/webhooks

A collection of machine-readable GitHub Webhooks specifications, including payload examples and JSON schemas. Provides Node modules for schemas (@octokit/webhooks-schemas) and TypeScript types (@octokit/webhooks-types). Note: This repository is out of date and no longer maintained; users are advised to migrate to the official OpenAPI specification at octokit/openapi-webhooks.

Tokens
5.6K
Snippets
25
Records
29
Agent score
53%

What's inside Octokit Webhooks

  1. Understand the structure of a webhook definition

    main

    A webhook definition describes the available events for a specific resource. It typically includes:

    • name: The name of the webhook event (e.g., issues).
    • actions: A list of specific actions that trigger this webhook (e.g., opened, edited, closed).
    • examples: An array of example payloads that demonstrate the data structure for different actions within that event.

    Each example payload contains the specific data related to the action, such as the resource being modified, the repository context, and the sender of the event.

    {
      "name": "issues",
      "actions": [
        "opened",
        "edited",
        "deleted"
      ],
      "examples": [
        {
          "action": "edited",
          "issue": { ... },
          "repository": { ... },
          "sender": { ... }
        }
      ]
    }
  2. Use interface property paths to select schemas

    main

    To select a schema for comparison, you must provide an interface property path. This path consists of the name of the interface, followed by a dot-separated path to the specific property you want to inspect.

    Selection Patterns

    • Specific Property: InterfaceName.property.subProperty
    • Entire Interface: InterfaceName (selects the schema for the whole interface)

    Example

    If you have the following interfaces:

    interface PullRequest {
      id: string;
      title: string;
      number: string;
      state: "open";
    }
    
    interface PullRequestCloseEvent {
      action: "close";
      pull_request: {
        id: string;
        title: string;
        number: string;
        state: "closed";
      };
    }

    To compare the pull_request property of the close event against the base PullRequest interface, run:

    bin/diff-interface-schemas.mts PullRequest PullRequestCloseEvent.pull_request
  3. Use webhook event types from @octokit/webhooks-types

    main

    The @octokit/webhooks-types package provides TypeScript types for GitHub webhook events based on their JSON schemas. You can use the generic WebhookEvent type for polymorphic event handling or specific event types (like IssuesOpenedEvent) for type-safe access to event-specific payloads.

    Important Requirement: You must enable strictNullChecks: true in your tsconfig.json. If this option is disabled, TypeScript may incorrectly infer the type as never in certain use cases.

    import { WebhookEvent, IssuesOpenedEvent } from "@octokit/webhooks-types";
    
    // Handling a generic webhook event with type narrowing
    const handleWebhookEvent = (event: WebhookEvent) => {
      if ("action" in event && event.action === "completed") {
        console.log(`${event.sender.login} completed something!`);
      }
    };
    
    // Handling a specific event type for full type safety
    const handleIssuesOpenedEvent = (event: IssuesOpenedEvent) => {
      console.log(
        `${event.sender.login} opened "${event.issue.title}" on ${event.repository.full_name}`,
      );
    };
  4. Validate webhook payloads with Ajv in strict mode

    main

    When using ajv in strict: true mode to validate webhook events, you must manually add support for specific custom keywords used in the Octokit schemas. Specifically, you need to include ajv-formats for standard formats and manually register the tsAdditionalProperties keyword to prevent "unknown keyword" errors.

    import type { WebhookEvent } from "@octokit/webhooks-types";
    import * as githubWebhookSchema from "@octokit/webhooks-schemas";
    import Ajv from "ajv";
    import addFormats from "ajv-formats";
    
    const ajv = new Ajv({ strict: true });
    
    addFormats(ajv);
    // Required to prevent 'unknown keyword' errors in strict mode
    avj.addKeyword("tsAdditionalProperties");
    
    const validate = ajv.compile<WebhookEvent>(githubWebhookSchema);
  5. Generate the unified schema.json using bin/octokit-schema.mts

    main
    The bin/octokit-schema.mts script is a utility used to generate a single, consolidated schema.json file. This file aggregates all individual JSON schemas located within the payload-schemas/schemas directory. This generated schema is the core component included in the @octokit/webhooks-schemas package.
    bin/octokit-schema.mts
  6. Use @octokit/webhooks-schemas as a Node module

    main

    To access the JSON schema for GitHub webhook payloads, install and import the @octokit/webhooks-schemas package. This provides the machine-readable specifications for all GitHub webhook events.

    // Use Node.js require:
    const SCHEMA = require("@octokit/webhooks-schemas");
    
    // Or ESM/TypeScript import:
    import SCHEMA from "@octokit/webhooks-schemas";
  7. Format JSON payloads and schemas with bin/format-with-prettier.mts

    main
    Use the bin/format-with-prettier.mts script to format all JSON payloads and schemas in the repository. This script ensures consistency by first stripping all whitespace and newlines before applying prettier. This differs from running prettier --write directly, as this script prevents prettier from preserving multiline objects, ensuring a more compact format.
    bin/format-with-prettier.mts
  8. Extract a common schema using bin/extract-common-schema.mts

    main

    The bin/extract-common-schema.mts utility extracts a specific property schema from an existing interface and saves it as a new "common" schema in schemas/common/. This is useful for deduplicating shared structures across different webhook event interfaces.

    To use the tool, provide an "interface property path" (the interface name followed by a dot-separated path to the property) and the desired name for the new interface. By default, the tool will throw an error if a schema with the generated name already exists. Use the --overwrite flag to replace an existing schema.

    bin/extract-common-schema.mts <interface property path> <interface name> [--overwrite]
    
    # Example: Extracting the pull_request property from PullRequestOpenEvent into a PullRequest interface
    bin/extract-common-schema.mts PullRequestOpenEvent.pull_request PullRequest
  9. Validate webhooks with `ajv` in `strict` mode

    main

    When using ajv in strict: true mode, it will throw an "unknown keyword" error for any keywords not explicitly defined. The Octokit webhook schemas use custom keywords provided by ajv-formats and a custom keyword tsAdditionalProperties. To prevent validation errors, you must register these keywords with your Ajv instance.

    import type { WebhookEvent } from "@octokit/webhooks-types";
    import * as githubWebhookSchema from "@octokit/webhooks-schemas";
    import Ajv from "ajv";
    import addFormats from "ajv-formats";
    
    const ajv = new Ajv({ strict: true });
    
    addFormats(ajv);
    // Register the custom keyword used in the schemas
    avj.addKeyword("tsAdditionalProperties");
    
    const validate = ajv.compile<WebhookEvent>(githubWebhookSchema);
  10. Optimize webhook schemas with bin/optimize-schemas.mts

    main

    The bin/optimize-schemas.mts script applies a series of structural optimizations to all JSON schemas located in payload-schemas/schemas. This is used to ensure consistency and strictness across the webhook definition files.

    Optimizations performed include:

    • Sorting type arrays: Ensures consistent ordering (e.g., "type": [null, "array"] becomes "type": ["array", null]).
    • Inlining single-item type properties: Converts "type": ["array"] to "type": "array".
    • Inlining single-item oneOf properties: Simplifies the schema by removing the oneOf wrapper when only one schema is present.
    • Merging oneOf elements: Combines elements where applicable, specifically for types like x | null.
    • Strictness enforcement: Replaces anyOf with oneOf to ensure stricter validation.
    • Object property enforcement: Ensures all object type schemas include tsAdditionalProperties or additionalProperties.
    bin/optimize-schemas.mts