Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions config/copilot-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Explicit, narrowly-targeted Copilot code-review pilot -- opt-in
# (branch -> repos) pairs, NOT a property match against the full gitflow
# fleet. Each review bills AI credits directly (0 assigned Copilot seats,
# so no pooled allowance) -- keep this list small and grow it deliberately,
# one repo at a time, only after confirming headroom.
#
# Decoded with yamldecode(file(...)) in locals.tf and consumed by
# copilot-review.tf via for_each -- one github_organization_ruleset PER
# branch key, so a future repo that needs a different target branch is a
# new top-level key here, not a change to the resource shape.
copilot_review:
develop:
- ansible-proxmox-apps
33 changes: 33 additions & 0 deletions copilot-review.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copilot code review -- narrowly targeted pilot, bound to explicit
# (branch, repo-list) pairs from config/copilot-review.yml, NOT a property
# match against every gitflow repo. The org has already exhausted its
# Copilot review capacity once from unrelated usage, and each review bills
# AI credits directly with no pooled seat allowance -- growing this pilot
# is a one-line YAML edit, never a broader property match.
# review_on_push = false caps spend at ~1 review per PR regardless of push
# count.
resource "github_organization_ruleset" "org_copilot_review" {
for_each = local.copilot_review_targets

name = "org-copilot-review-${each.key}"
target = "branch"
enforcement = var.org_copilot_review_enforcement

conditions {
ref_name {
include = ["refs/heads/${each.key}"]
exclude = []
}
repository_name {
include = each.value
exclude = []
}
}

rules {
copilot_code_review {
review_on_push = false
review_draft_pull_requests = false
}
}
}
4 changes: 4 additions & 0 deletions locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ locals {
# Merge Gate required-check inventory: check context per repo group, decoded
# from config/merge-gate.yml and consumed by merge-gate.tf.
merge_gate_contexts = yamldecode(file("${path.module}/config/merge-gate.yml")).merge_gate.contexts

# Copilot code-review pilot targets: branch -> explicit repo list,
# decoded from config/copilot-review.yml and consumed by copilot-review.tf.
copilot_review_targets = yamldecode(file("${path.module}/config/copilot-review.yml")).copilot_review
}
36 changes: 0 additions & 36 deletions rulesets.tf
Original file line number Diff line number Diff line change
Expand Up @@ -392,39 +392,3 @@ resource "github_organization_ruleset" "org_gitflow_develop" {
}
}
}

# Git-flow Copilot code review — automatic Copilot review on PRs into
# develop only (not main) for opted-in repos.
#
# develop-only, not org_gitflow_base's main+develop pattern: develop is the
# high-volume integration branch where feature PRs land; main on gitflow
# repos is release/hotfix-only and low-volume. Unlike the native rulesets
# above, Copilot review bills per review in AI credits — scoping to develop
# and setting review_on_push = false bound that to roughly one review per PR,
# on the branch that actually needs it.
resource "github_organization_ruleset" "org_gitflow_copilot_review" {
name = "org-gitflow-copilot-review"
target = "branch"
enforcement = var.org_gitflow_copilot_review_enforcement

conditions {
ref_name {
include = ["refs/heads/develop"]
exclude = []
}
repository_property {
include = [{
name = "gitflow"
property_values = ["true"]
source = "custom"
}]
}
}

rules {
copilot_code_review {
review_on_push = false
review_draft_pull_requests = false
}
}
}
30 changes: 16 additions & 14 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -166,28 +166,30 @@ variable "org_gitflow_develop_enforcement" {
}
}

variable "org_gitflow_copilot_review_enforcement" {
variable "org_copilot_review_enforcement" {
description = <<-EOT
Enforcement mode for automatic Copilot code review on git-flow repos'
develop branch only (not main, which is release-only and low-volume).
Binds only local.gitflow_repos via the gitflow custom property.
Enforcement mode for the Copilot code-review pilot ruleset(s) --
explicit (branch, repo-list) targets from config/copilot-review.yml,
not a property match. Growing the pilot is a config edit there, never
a variable change here.

Cost note: unlike the native rulesets in this repo, Copilot code review
bills per review in AI credits — it is the one ruleset here that costs
money to run. review_on_push = false caps it at roughly one review per
PR. Current rates and the org's seat position are point-in-time facts
that belong in the PR that changes them, not in this description.

One of: disabled, evaluate, active. Defaults to "active" — new rulesets
apply enabled per the convention; set to "disabled" with `-var` to stop
the spend without a code change.
bills AI credits directly per review (0 assigned Copilot seats, so no
pooled allowance) -- it is the one ruleset here that costs money to
run. review_on_push = false caps it at roughly one review per PR.
Current rates and usage headroom are point-in-time facts that belong
in the PR that changes the target list, not in this description.

One of: disabled, evaluate, active. Defaults to "active" -- new
rulesets apply enabled per the convention; set to "disabled" with
`-var` to stop the spend without a code change.
EOT
type = string
default = "active"

validation {
condition = contains(["disabled", "evaluate", "active"], var.org_gitflow_copilot_review_enforcement)
error_message = "org_gitflow_copilot_review_enforcement must be one of: disabled, evaluate, active."
condition = contains(["disabled", "evaluate", "active"], var.org_copilot_review_enforcement)
error_message = "org_copilot_review_enforcement must be one of: disabled, evaluate, active."
}
}

Expand Down