Skip to content

Ruleset

Source: src/GitHub/Ruleset.ts

A GitHub repository ruleset.

Ruleset manages branch and tag protection rules at the repository level. Rulesets replace the legacy branch protection API with a more flexible system that can target multiple branches or tags with a single ruleset.

Rulesets default to retain on removal — destroying the stack does NOT delete the ruleset on GitHub, protecting production branches from accidental removal. Opt in to actual deletion by wrapping the resource in destroy() from alchemy/RemovalPolicy.

Authentication is resolved via the GitHubCredentials service supplied by GitHub.providers() (env, stored PAT, gh CLI, or OAuth). The token needs repo scope, or repository Administration write permission for a fine-grained token. Ruleset deletion does not require delete_repo.

Protect Main Branch

yield* GitHub.Ruleset("main-protection", {
owner: "my-org",
repository: "my-repo",
name: "main protection",
target: "branch",
conditions: {
include: ["refs/heads/main"],
},
rules: {
nonFastForward: true,
deletion: true,
requiredLinearHistory: true,
},
})

Require PR Reviews

yield* GitHub.Ruleset("pr-reviews", {
owner: "my-org",
repository: "my-repo",
name: "require reviews",
target: "branch",
conditions: {
include: ["refs/heads/main", "refs/heads/release/*"],
},
rules: {
pullRequest: {
requiredApprovingReviewCount: 2,
requireCodeOwnerReview: true,
dismissStaleReviewsOnPush: true,
requiredReviewThreadResolution: true,
},
},
})
yield* GitHub.Ruleset("ci-checks", {
owner: "my-org",
repository: "my-repo",
name: "CI required",
target: "branch",
conditions: {
include: ["refs/heads/main"],
},
rules: {
requiredStatusChecks: {
checks: [
{ context: "ci/test" },
{ context: "ci/lint" },
],
strictRequiredStatusChecksPolicy: true,
},
},
})
yield* GitHub.Ruleset("protected-with-bypass", {
owner: "my-org",
repository: "my-repo",
name: "protected with bypass",
target: "branch",
conditions: {
include: ["refs/heads/main"],
},
bypassActors: [
{ actorType: "RepositoryRole", actorId: 5 },
],
rules: {
nonFastForward: true,
},
})