Skip to content

Commit

Permalink
first POC with GH settings and CODEOWNERS (#14)
Browse files Browse the repository at this point in the history
This is an enhancement for trying to GitHub repo settings via terraform
and providing also files like CODEOWNER.
  • Loading branch information
rgildein authored May 30, 2024
1 parent 61d9726 commit f368238
Show file tree
Hide file tree
Showing 12 changed files with 377 additions and 0 deletions.
60 changes: 60 additions & 0 deletions .github/workflows/terraform-apply.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Apply new changes to SolEng repositories

on:
workflow_dispatch:
pull_request:
branches:
- main
paths:
- terraform-plans/**
push:
branches:
- main
paths:
- terraform-plans/**

jobs:
terraform:
name: Run Terraform
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
repository:
- soleng-tf-test-repo
steps:
- name: Checkout branch
uses: actions/checkout@v4
- name: Install Terraform
run: sudo snap install terraform --classic
- name: Terraform init
working-directory: ./terraform-plans
run: terraform init
- name: Terraform validate
working-directory: ./terraform-plans
env:
GITHUB_APP_ID: ${{ secrets.SOLENG_APP_ID }}
GITHUB_APP_INSTALLATION_ID: ${{ secrets.SOLENG_APP_INSTALLATION_ID }}
GITHUB_APP_PEM_FILE: ${{ secrets.SOLENG_APP_PEM_FILE }}
run: terraform validate -no-color
- name: Terraform plan
working-directory: ./terraform-plans
env:
GITHUB_APP_ID: ${{ secrets.SOLENG_APP_ID }}
GITHUB_APP_INSTALLATION_ID: ${{ secrets.SOLENG_APP_INSTALLATION_ID }}
GITHUB_APP_PEM_FILE: ${{ secrets.SOLENG_APP_PEM_FILE }}
run: |
terraform plan -no-color \
-var-file=configs/github.tfvars \
-var-file=configs/${{ matrix.repository }}.tfvars
- name: Terraform Apply only on merge to main
if: ${{ github.event_name == 'push' }}
working-directory: ./terraform-plans
env:
GITHUB_APP_ID: ${{ secrets.SOLENG_APP_ID }}
GITHUB_APP_INSTALLATION_ID: ${{ secrets.SOLENG_APP_INSTALLATION_ID }}
GITHUB_APP_PEM_FILE: ${{ secrets.SOLENG_APP_PEM_FILE }}
run: |
terraform apply -no-color -auto-approve \
-var-file=configs/github.tfvars \
-var-file=configs/${{ matrix.repository }}.tfvars
48 changes: 48 additions & 0 deletions terraform-plans/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Terraform plans for Solution Engineering

Currently these plans are only for setting GitHub repos and to add workflow files.

## How to start

1. Initialize Terraform.

```bash
terraform init
```

1. [Optional] If it's used locally for multiple repos. Create a workspace for each repo, otherwise terraform will try to overwrite the existing resource, e.g. repo.

```bash
terraform workspace new <repo-name>
```

1. Set GitHub authenetication for GitHub application.
```bash
export GITHUB_APP_ID="1234"
export GITHUB_APP_INSTALLATION_ID="56789"
export GITHUB_APP_PEM_FILE=$(cat ./my-app.private-key.pem)
```

1. [Optional] Create custom configuration or use one of defined in config directory.

```tfvars
owner = "<owner/org name>"
repository = "<repo name>"
branch = "main"
workflow_files = {
jira_sync_config = {
source = "./files/workflows/jira_sync_config.yaml"
destination = ".github/workflows/jira_sync_config.yaml"
}
codeowners = {
source = "./files/workflows/CODEOWNERS"
destination = ".github/CODEOWNERS"
}
}
```

1. Generate Terraform plan to validate it.

```bash
terraform plan -var-file=configs/github.tfvars -var-file=configs/soleng-tf-test-repo.tfvars
```
1 change: 1 addition & 0 deletions terraform-plans/configs/github.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
owner = "canonical"
8 changes: 8 additions & 0 deletions terraform-plans/configs/soleng-tf-test-repo.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
repository = "soleng-tf-test-repo"
branch = "main"
workflow_files = {
codeowners = {
source = "./files/github/CODEOWNERS"
destination = ".github/CODEOWNERS"
}
}
4 changes: 4 additions & 0 deletions terraform-plans/files/github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# These owners will be the default owners for everything in the repo. Unless a
# later match takes precedence, @canonical/soleng-reviewers will be requested for
# review when someone opens a pull request.
@canonical/soleng-reviewers
9 changes: 9 additions & 0 deletions terraform-plans/imports.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {
to = module.github_settings.github_repository.repo
id = var.repository
}

import {
to = module.github_settings.github_branch_protection.branch_protection
id = "${var.repository}:${var.branch}"
}
17 changes: 17 additions & 0 deletions terraform-plans/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module "github_settings" {
source = "./modules/GitHub/settings"
owner = var.owner
repository = var.repository
branch = var.branch
force_push_bypassers = ["${var.owner}/soleng-admin"]
dismissal_restrictions = ["${var.owner}/soleng-admin", "${var.owner}/soleng-reviewers"]
pull_request_bypassers = ["${var.owner}/soleng-admin"]
}

module "github_workflow_files" {
source = "./modules/GitHub/workflows"
owner = var.owner
repository = var.repository
branch = var.branch
workflow_files = var.workflow_files
}
87 changes: 87 additions & 0 deletions terraform-plans/modules/GitHub/settings/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
terraform {
required_providers {
github = {
source = "integrations/github"
version = "~> 6.0"
}
}
}

provider "github" {
owner = var.owner
app_auth {} # using environmet variables for auth
}

resource "github_repository" "repo" {
name = var.repository

has_issues = true
has_projects = false
has_wiki = false
has_discussions = false

allow_merge_commit = false
allow_squash_merge = true
allow_rebase_merge = false
allow_auto_merge = false

allow_update_branch = true
delete_branch_on_merge = false

}

data "github_team" "admins" {
slug = "soleng-admin"
}

data "github_team" "reviewers" {
slug = "soleng-reviewers"
}

data "github_team" "engineering" {
slug = "solutions-engineering"
}

resource "github_repository_collaborators" "repo_collaborators" {
repository = var.repository

team {
permission = "admin"
team_id = data.github_team.admins.id
}

team {
permission = "maintain"
team_id = data.github_team.reviewers.id
}

team {
permission = "push"
team_id = data.github_team.engineering.id
}
}

resource "github_branch_protection" "branch_protection" {
repository_id = github_repository.repo.node_id
pattern = var.branch
enforce_admins = true
require_signed_commits = true
required_linear_history = true
require_conversation_resolution = true
allows_deletions = false

allows_force_pushes = false
force_push_bypassers = var.force_push_bypassers

required_status_checks {
strict = true
}

required_pull_request_reviews {
dismiss_stale_reviews = true
dismissal_restrictions = var.dismissal_restrictions
pull_request_bypassers = var.pull_request_bypassers
require_code_owner_reviews = true
required_approving_review_count = 2
}
}
30 changes: 30 additions & 0 deletions terraform-plans/modules/GitHub/settings/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
variable "owner" {
type = string
description = "GitHub repository owner"
}

variable "repository" {
type = string
description = "GitHub repository name"
}

variable "branch" {
type = string
description = "Branch name"
default = "main"
}

variable "force_push_bypassers" {
type = list(any)
description = "List of user / groups that are allowed to bypass force push restrictions."
}

variable "dismissal_restrictions" {
type = list(any)
description = "List of user / groups with dismissal access."
}

variable "pull_request_bypassers" {
type = list(any)
description = "List of user / groups that are allowed to bypass pull request requirements."
}
49 changes: 49 additions & 0 deletions terraform-plans/modules/GitHub/workflows/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
terraform {
required_providers {
github = {
source = "integrations/github"
version = "~> 6.0"
}
}
}

provider "github" {
owner = var.owner
app_auth {} # using environmet variables for auth
}


resource "random_string" "update_uid" {
length = 8
numeric = true
special = false
}

resource "github_branch" "workflows_branch" {
repository = var.repository
branch = "${var.pr_branch}-${random_string.update_uid.id}"
source_branch = var.branch
}

resource "github_repository_file" "workflows_files" {
for_each = var.workflow_files
repository = var.repository
branch = github_branch.workflows_branch.branch
file = each.value.destination
content = file(each.value.source)
commit_message = "update ${each.value.destination}"
overwrite_on_create = true
}

resource "github_repository_pull_request" "workflows_update_pr" {
base_repository = var.repository
base_ref = var.branch
head_ref = github_branch.workflows_branch.branch
title = var.pr_title
body = var.pr_body

depends_on = [
github_branch.workflows_branch,
github_repository_file.workflows_files
]
}
41 changes: 41 additions & 0 deletions terraform-plans/modules/GitHub/workflows/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
variable "owner" {
type = string
description = "GitHub repository owner"
}

variable "repository" {
type = string
description = "GitHub repository name."
}

variable "branch" {
type = string
description = "Default branch name."
default = "main"
}

variable "pr_branch" {
type = string
description = "Pull request branch name."
default = "chore/update-workflows"
}

variable "pr_title" {
type = string
description = "Pull request title."
default = "Updating workflows files"
}

variable "pr_body" {
type = string
description = "Pull request body message."
default = "Updates workflows files by SolEng bot."
}

variable "workflow_files" {
type = map(object({
source = string
destination = string
}))
description = "GitHub workflow files"
}
23 changes: 23 additions & 0 deletions terraform-plans/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
variable "owner" {
type = string
description = "GitHub repository owner"
}

variable "repository" {
type = string
description = "GitHub repository name"
}

variable "branch" {
type = string
description = "git branch name"
default = "main"
}

variable "workflow_files" {
type = map(object({
source = string
destination = string
}))
description = "GitHub workflow files"
}

0 comments on commit f368238

Please sign in to comment.