Skip to content
Changelog

Report a bug

GitHub

A GitHub trigger starts a managed agent automation when something changes in a repository. There are two ways to use GitHub events:

  • With instructions. The managed agent follows your instructions for each GitHub event.
  • With code. Your TypeScript runs for each GitHub event. It can filter events and read more with the GitHub CLI in the sandbox. It can also hand a step to the managed agent.
  • Connect GitHub to Type, and add the connection to the Space. In the CLI, run type-cli integrations connect github.
  • Make sure that the GitHub App can see the repository. It must also subscribe to the events that you need.
  • Make sure that the Space has the skills that the managed agent needs, for example a review skill.
  • For a code automation, get the GitHub connection ID (orgint_...) and the Space ID (ch_...). To see Space IDs, run type-cli spaces list --json.

In an instruction automation, a GitHub event starts work in the Space. The managed agent follows your instructions, with the Space’s connections and skills.

Examples:

  • Review new pull requests with the team’s review skill.
  • Summarize new issues and suggest an owner.
  • Post a short note when a release is published.
  1. Open the Space’s Automations page (or Space settings → Automations in the settings layout).
  2. Select New Synced Event.
  3. Choose GitHub as the source.
  4. If GitHub has more than one connection, choose the connection.
  5. Select Connect GitHub.
  6. Write instructions that tell the managed agent what to do with the event. To use a skill, write its handle, for example /pr-review.

In the CLI:

Terminal window
type-cli synced-events create --space <space> --source github --integration <org-integration-id> --enable

Do not use broad triggers. They make noisy work. Start with one event that has high value. Add more events when the managed agent gives useful results each time.

A code automation runs your TypeScript when a GitHub event comes. Code automations are in early access. To learn the basics, see Run code.

This example makes a code automation that posts in a Space when a pull request is merged into main.

src/main.ts
import type {
AutomationContext,
AutomationDeployment,
IntegrationEvent,
} from "@type-dot-com/sdk/automations";
import { TypeApiError } from "@type-dot-com/sdk";
import { err } from "neverthrow";
import { z } from "zod";
const github = "orgint_abc123";
const space = "ch_def456"; // the Space ID
const pullRequest = z.looseObject({
title: z.string(),
url: z.string(),
repositoryFullName: z.string(),
});
export const deployment = {
subscriptions: {
onMerged: {
title: "Announce merged pull requests",
description: "Post in the Space when a pull request is merged into main",
source: { kind: "integration", connectionId: github, events: ["github.pull_request.closed"] },
match: {
"github.pull_request": {
repositories: ["acme/project"],
actions: ["closed"],
merged: true,
baseBranches: ["main"],
},
},
},
},
} satisfies AutomationDeployment;
export default class {
async onMerged(ctx: AutomationContext, event: IntegrationEvent) {
const pr = pullRequest.safeParse(event.data);
if (!pr.success) return err(new TypeApiError("Unexpected pull request data", "invalid_response"));
const sent = await ctx.write.sendMessage(
{ channelId: space, content: `Merged in ${pr.data.repositoryFullName}: ${pr.data.title}\n${pr.data.url}` },
{ effectKey: `merged:${event.id}` },
);
if (sent.isErr()) return err(sent.error);
return ctx.setOutput({ messageId: sent.value.messageId });
}
}

The match field uses a GitHub matcher. It selects the repository, the action, merged pull requests, and the base branch.

The example posts with ctx.write.sendMessage. Fixtures cannot answer that call, so a fixture cannot test the path that posts. See Calls that fixtures cannot answer.

Test the example in two parts:

  1. Use fixtures for the paths that end before the post. Test a pull request that the matcher skips. Also test a pull request with data that the code rejects. The GitHub matcher needs the normalized fields that it checks, for example title, so a fixture payload must include them.

    fixtures.json
    [
    {
    "name": "skips a closed pull request that is not merged",
    "subscriptionId": "onMerged",
    "payload": {
    "type": "github.pull_request.closed",
    "id": "delivery-1",
    "resourceType": "pull_request",
    "resourceId": "42",
    "data": { "repositoryFullName": "acme/project", "merged": false, "baseBranch": "main", "title": "Draft idea", "url": "https://github.com/acme/project/pull/42" }
    },
    "toolResponses": []
    },
    {
    "name": "fails on pull request data without a URL",
    "subscriptionId": "onMerged",
    "payload": {
    "type": "github.pull_request.closed",
    "id": "delivery-2",
    "resourceType": "pull_request",
    "resourceId": "43",
    "data": { "repositoryFullName": "acme/project", "merged": true, "baseBranch": "main", "title": "Fix login" }
    },
    "toolResponses": [],
    "expectedError": "Unexpected pull request data"
    }
    ]
  2. Test the post in a live run. First, set repositories to a test repository. Merge a test pull request into main. Then read the run:

    Terminal window
    type-cli automations history --space <space> --automation <automation-id> --include-activity

    When the run is correct, change repositories to the real repository and deploy again.

GitHub event names have the form github.<event>.<action>. github.push and github.status have no action. See the Events reference for all events and their data fields.

Common choices:

Goaleventsmatch
A pull request openedgithub.pull_request.openedgithub.pull_request
A pull request mergedgithub.pull_request.closedgithub.pull_request with merged: true
A comment on a pull requestgithub.issue_comment.createdgithub.issue_comment with pullRequest: true
A review requested changesgithub.pull_request_review.submittedgithub.pull_request_review with states: ["changes_requested"]
CI failedgithub.workflow_run.completedgithub.workflow_run with conclusions: ["failure"]
A push to maingithub.pushgithub.push with refs: ["refs/heads/main"]
A release publishedgithub.release.publishedgithub.release

Use the repositories option of the matcher. The value is owner/repo, and the comparison is not case-sensitive.

The event has a summary of the change. To read more, for example the files of a pull request, use the GitHub CLI in the sandbox.

  • A GitHub instruction automation must be enabled when you make it, and you cannot pause it. To stop it, delete it.
  • Type does not send deployment, deployment_status, pull_request_review_thread, label, or member events to automations.
  • The GitHub App settings decide which events GitHub sends. Saving an automation does not change these settings.
  • In code automations, Type does not check <action> values against a list. A wrong action name deploys, but no event matches it.
  • In GitHub matchers, list filters are case-sensitive, except repositories.