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.
Before you start
Section titled “Before you start”- 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, runtype-cli spaces list --json.
With instructions
Section titled “With instructions”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.
Make an instruction automation
Section titled “Make an instruction automation”- Open the Space’s Automations page (or Space settings → Automations in the settings layout).
- Select New Synced Event.
- Choose GitHub as the source.
- If GitHub has more than one connection, choose the connection.
- Select Connect GitHub.
- 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:
type-cli synced-events create --space <space> --source github --integration <org-integration-id> --enableKeep triggers narrow
Section titled “Keep triggers narrow”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.
With code
Section titled “With code”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.
Post when a pull request is merged
Section titled “Post when a pull request is merged”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.
Test the example
Section titled “Test the example”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:
-
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"}] -
Test the post in a live run. First, set
repositoriesto a test repository. Merge a test pull request intomain. Then read the run:Terminal window type-cli automations history --space <space> --automation <automation-id> --include-activityWhen the run is correct, change
repositoriesto the real repository and deploy again.
Event names
Section titled “Event names”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:
| Goal | events | match |
|---|---|---|
| A pull request opened | github.pull_request.opened | github.pull_request |
| A pull request merged | github.pull_request.closed | github.pull_request with merged: true |
| A comment on a pull request | github.issue_comment.created | github.issue_comment with pullRequest: true |
| A review requested changes | github.pull_request_review.submitted | github.pull_request_review with states: ["changes_requested"] |
| CI failed | github.workflow_run.completed | github.workflow_run with conclusions: ["failure"] |
A push to main | github.push | github.push with refs: ["refs/heads/main"] |
| A release published | github.release.published | github.release |
Select repositories
Section titled “Select repositories”Use the repositories option of the matcher. The value is owner/repo, and the comparison is not case-sensitive.
Read more from GitHub
Section titled “Read more from GitHub”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.
Limitations
Section titled “Limitations”- 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, ormemberevents 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.