1---
2title: GitHub
3description: Repositories, Actions secrets and variables, webhooks, and repository event sources as Stack resources — the glue for CI/CD.
4---
5
6The GitHub provider manages repositories, Actions secrets and
7variables, and webhooks as resources. It's the glue for CI/CD: your
8Stack can mint a scoped cloud credential and store it as an Actions
9secret in the same deploy — no pasting tokens into repo settings.
10Workers can even subscribe to repository events directly.
11
12New here? [Set up credentials](/github/setup) first.
13
14## Resources
15
16`Repository` creates and converges a repo's settings — see
17[Repositories](/github/repository). Destroying the stack retains the
18repository by default, protecting its history:
19
20```typescript
21const repo = yield* GitHub.Repository("api", {
22 owner: "my-org",
23 name: "api",
24 description: "API service",
25 autoInit: true,
26});
27```
28
29`Secrets` and `Variables` bulk-seed GitHub Actions configuration —
30values can be outputs of other resources. See
31[Actions secrets & variables](/github/actions-config):
32
33```typescript
34yield* GitHub.Secrets({
35 owner: "my-org",
36 repository: "api",
37 secrets: {
38 AXIOM_INGEST_TOKEN: tokenValue,
39 },
40});
41
42yield* GitHub.Variables({
43 owner: "my-org",
44 repository: "api",
45 variables: {
46 AWS_ROLE_ARN: role.roleArn,
47 AWS_REGION: region,
48 },
49});
50```
51
52`Environment` manages a deployment environment and its protection
53rules; secrets and variables scope to it via their `environment` prop:
54
55```typescript
56const production = yield* GitHub.Environment("production", {
57 owner: "my-org",
58 repository: "api",
59 name: "production",
60 reviewers: { teams: ["platform"] },
61});
62```
63
64`Webhook` manages a repository webhook pointed at any URL, and
65`consumeRepositoryEvents` subscribes a host (e.g. a Cloudflare
66Worker) to repository webhooks with typed payloads — see
67[Webhooks & events](/github/events) and
68[React to GitHub events from a Worker](/cloudflare/messaging/github-events):
69
70```typescript
71yield* GitHub.consumeRepositoryEvents(
72 {
73 owner: "my-org",
74 repository: "my-repo",
75 events: ["push", "pull_request"],
76 secret,
77 },
78 (event) => Effect.log(`received ${event.name} (${event.id})`),
79);
80```
81
82## PR comments
83
84`Comment` posts a sticky comment on an issue or pull request:
85created on the first deploy, updated in place on every subsequent
86deploy because the logical ID stays the same, and never deleted on
87destroy by default (set `allowDelete: true` to opt in). Use
88`Output.interpolate` to embed attributes that aren't resolved yet —
89like a preview URL:
90
91```typescript
92if (process.env.PULL_REQUEST) {
93 yield* GitHub.Comment("preview-comment", {
94 owner: "my-org",
95 repository: "my-repo",
96 issueNumber: Number(process.env.PULL_REQUEST),
97 body: Output.interpolate`
98 ## Preview Deployed
99
100 **URL:** ${website.url}
101 `,
102 });
103}
104```
105
106The body is dedented automatically, so indented template literals
107render as clean Markdown. [CI](/environments/ci) walks through the full
108workflow: a `pr-{n}` stage per pull request, with this comment
109tracking its preview URL on each push.
110
111## Compose with your cloud
112
113The canonical pattern: a one-shot stack mints a scoped cloud
114credential and stores it as an Actions secret, so CI deploys with a
115credential that was itself provisioned as code. Walk through it in
116[Part 5: CI/CD (Cloudflare)](/cloudflare/tutorial/part-5) or
117[Part 5: CI/CD (AWS)](/aws/tutorial/part-5), and see
118[CI](/environments/ci) for the general GitHub Actions setup.
119
120## Reference
121
122[Repository](/providers/github/repository) ·
123[Environment](/providers/github/environment) ·
124[Secret](/providers/github/secret) ·
125[Secrets](/providers/github/secrets) ·
126[Variable](/providers/github/variable) ·
127[Variables](/providers/github/variables) ·
128[Webhook](/providers/github/webhook) ·
129[Comment](/providers/github/comment)