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
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

Expand Down
133 changes: 88 additions & 45 deletions scripts/setup-github.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@
# Run this after creating the repository and pushing initial code
# Requirements: gh cli installed and authenticated (gh auth login)

param(
[string]$RepoOverride = ""
)

$ErrorActionPreference = "Stop"

# =============================================================================
# CONFIGURATION - Update these values
# =============================================================================
$REPO = "OWNER/REPO" # Update this!
if ($RepoOverride) {
$REPO = $RepoOverride
} else {
$REPO = "OWNER/REPO" # Update this!
}
$BRANCH = "main"

# -----------------------------------------------------------------------------
Expand Down Expand Up @@ -42,7 +50,7 @@ $REQUIRE_LAST_PUSH_APPROVAL = $false
$REQUIRE_REVIEW_THREAD_RESOLUTION = $false
$REQUIRE_STATUS_CHECKS = $true
$REQUIRE_BRANCHES_UP_TO_DATE = $true
$STATUS_CHECKS = @("lint", "type-check", "test (3.12)")
$STATUS_CHECKS = @("lint", "type-check", "test (3.11)", "test (3.12)", "test (3.13)", "test (3.14)")

# -----------------------------------------------------------------------------
# LABELS
Expand All @@ -57,18 +65,13 @@ $LABELS = @(
@{name="good first issue"; desc="Good for newcomers"; color="7057ff"}
)

# ... (rest of the script same as previous version)
# For brevity, I'll only include the configuration part in the template
# but in a real scenario, the full script should be here.
# I will write the full script to be safe.

# =============================================================================
# SCRIPT START
# =============================================================================
Write-Host "🔧 Configuring GitHub repository: $REPO" -ForegroundColor Cyan
Write-Host "Configuring GitHub repository: $REPO" -ForegroundColor Cyan

# 1. General Settings
Write-Host "`n📋 Updating general settings..." -ForegroundColor Yellow
Write-Host "`nUpdating general settings..." -ForegroundColor Yellow
$repoEditArgs = @($REPO)
if ($DELETE_BRANCH_ON_MERGE) { $repoEditArgs += "--delete-branch-on-merge" }
if ($ENABLE_AUTO_MERGE) { $repoEditArgs += "--enable-auto-merge" }
Expand All @@ -78,54 +81,94 @@ $repoEditArgs += "--enable-merge-commit=$ENABLE_MERGE_COMMIT"
gh repo edit @repoEditArgs

# 2. Security Settings
Write-Host "`n🔒 Enabling security features..." -ForegroundColor Yellow
if ($ENABLE_VULNERABILITY_ALERTS) { try { gh api -X PUT "/repos/$REPO/vulnerability-alerts" 2>$null } catch {} }
if ($ENABLE_DEPENDABOT_SECURITY_UPDATES) { try { gh api -X PUT "/repos/$REPO/automated-security-fixes" 2>$null } catch {} }
if ($ENABLE_SECRET_SCANNING) { try { gh api -X PATCH "/repos/$REPO" -f security_and_analysis='{"secret_scanning":{"status":"enabled"},"secret_scanning_push_protection":{"status":"enabled"}}' 2>$null } catch {} }
Write-Host "`nEnabling security features..." -ForegroundColor Yellow
if ($ENABLE_VULNERABILITY_ALERTS) {
try { gh api -X PUT "/repos/$REPO/vulnerability-alerts" 2>$null } catch {}
}
if ($ENABLE_DEPENDABOT_SECURITY_UPDATES) {
try { gh api -X PUT "/repos/$REPO/automated-security-fixes" 2>$null } catch {}
}
if ($ENABLE_SECRET_SCANNING) {
$securityPayload = '{"secret_scanning":{"status":"enabled"},"secret_scanning_push_protection":{"status":"enabled"}}'
try { gh api -X PATCH "/repos/$REPO" -f security_and_analysis=$securityPayload 2>$null } catch {}
}

# 3. Branch Ruleset
if ($CREATE_BRANCH_RULESET) {
Write-Host "`n🛡️ Creating branch ruleset..." -ForegroundColor Yellow
Write-Host "`nCreating branch ruleset..." -ForegroundColor Yellow
$rules = @()
if ($RESTRICT_DELETIONS) { $rules += '{"type": "deletion"}' }
if ($BLOCK_FORCE_PUSHES) { $rules += '{"type": "non_fast_forward"}' }
if ($REQUIRE_LINEAR_HISTORY) { $rules += '{"type": "required_linear_history"}' }
if ($REQUIRE_SIGNED_COMMITS) { $rules += '{"type": "required_signatures"}' }

if ($RESTRICT_DELETIONS) { $rules += '{"type":"deletion"}' }
if ($BLOCK_FORCE_PUSHES) { $rules += '{"type":"non_fast_forward"}' }
if ($REQUIRE_LINEAR_HISTORY) { $rules += '{"type":"required_linear_history"}' }
if ($REQUIRE_SIGNED_COMMITS) { $rules += '{"type":"required_signatures"}' }

if ($REQUIRE_PULL_REQUEST) {
$rules += @"
{
"type": "pull_request",
"parameters": {
"required_approving_review_count": $REQUIRED_APPROVING_REVIEWS,
"dismiss_stale_reviews_on_push": $($DISMISS_STALE_REVIEWS.ToString().ToLower()),
"require_code_owner_review": $($REQUIRE_CODE_OWNER_REVIEW.ToString().ToLower()),
"require_last_push_approval": $($REQUIRE_LAST_PUSH_APPROVAL.ToString().ToLower()),
"required_review_thread_resolution": $($REQUIRE_REVIEW_THREAD_RESOLUTION.ToString().ToLower())
}
}
"@
$prRule = @{
type = "pull_request"
parameters = @{
required_approving_review_count = $REQUIRED_APPROVING_REVIEWS
dismiss_stale_reviews_on_push = $DISMISS_STALE_REVIEWS
require_code_owner_review = $REQUIRE_CODE_OWNER_REVIEW
require_last_push_approval = $REQUIRE_LAST_PUSH_APPROVAL
required_review_thread_resolution = $REQUIRE_REVIEW_THREAD_RESOLUTION
}
}
$rules += ($prRule | ConvertTo-Json -Compress -Depth 5)
}

if ($REQUIRE_STATUS_CHECKS) {
$statusChecksJson = ($STATUS_CHECKS | ForEach-Object { "{`"context`":`"$_`"}" }) -join ","
$rules += @"
{
"type": "required_status_checks",
"parameters": {
"strict_required_status_checks_policy": $($REQUIRE_BRANCHES_UP_TO_DATE.ToString().ToLower()),
"required_status_checks": [$statusChecksJson]
}
}
"@
$checksArray = $STATUS_CHECKS | ForEach-Object { @{context = $_} }
$statusRule = @{
type = "required_status_checks"
parameters = @{
strict_required_status_checks_policy = $REQUIRE_BRANCHES_UP_TO_DATE
required_status_checks = $checksArray
}
}
$rules += ($statusRule | ConvertTo-Json -Compress -Depth 5)
}

$rulesJson = $rules -join ","
$rulesetJson = "{`"name`":`"Main Branch Protection`",`"target`":`"branch`",`"enforcement`":`"active`",`"conditions`":{`"ref_name`":{`"include`":[`"refs/heads/$BRANCH`"],`"exclude`":[]}},`"bypass_actors`":[{`"actor_id`":5,`"actor_type`":`"RepositoryRole`",`"bypass_mode`":`"always`"}],`"rules`":[$rulesJson]}"
try { $rulesetJson | gh api -X POST "/repos/$REPO/rulesets" --input - } catch { Write-Host " ⚠️ Ruleset error" }

$ruleset = @{
name = "Main Branch Protection"
target = "branch"
enforcement = "active"
conditions = @{
ref_name = @{
include = @("refs/heads/$BRANCH")
exclude = @()
}
}
bypass_actors = @(
@{
actor_id = 5
actor_type = "RepositoryRole"
bypass_mode = "always"
}
)
}

# Convert to JSON and insert rules manually (to preserve array of mixed types)
$rulesetBase = $ruleset | ConvertTo-Json -Compress -Depth 10
$rulesetJson = $rulesetBase -replace '}$', ",`"rules`":[$rulesJson]}"

try {
$rulesetJson | gh api -X POST "/repos/$REPO/rulesets" --input -
} catch {
Write-Host " Warning: Ruleset creation failed (may already exist or permission issue)" -ForegroundColor DarkYellow
}
}

# 4. Labels
if ($CREATE_LABELS) {
Write-Host "`n🏷️ Creating labels..." -ForegroundColor Yellow
foreach ($label in $LABELS) { try { gh label create $label.name --description $label.desc --color $label.color --repo $REPO 2>$null } catch {} }
Write-Host "`nCreating labels..." -ForegroundColor Yellow
foreach ($label in $LABELS) {
try {
gh label create $label.name --description $label.desc --color $label.color --repo $REPO --force 2>$null
} catch {}
}
}

Write-Host "`n🎉 Done!" -ForegroundColor Green
Write-Host "`nDone!" -ForegroundColor Green
Loading