Skip to content

Commit

Permalink
fix(terraform): create pr only if workflow files content is different (
Browse files Browse the repository at this point in the history
…#19)

- Fix: #17
- Add document for branch production rule if it's not exists.
- Update terraform workflow to use plan output instead re-plan when
apply.
  • Loading branch information
jneo8 authored Jun 4, 2024
1 parent 7fc9c39 commit 7ff5054
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 9 deletions.
7 changes: 3 additions & 4 deletions .github/workflows/terraform-apply.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ jobs:
run: |
terraform plan -no-color \
-var-file=configs/github.tfvars \
-var-file=configs/${{ matrix.repository }}.tfvars
-var-file=configs/${{ matrix.repository }}.tfvars \
-out ./tf.plan
- name: Terraform Apply only on merge to main
if: ${{ github.event_name == 'push' }}
working-directory: ./terraform-plans
Expand All @@ -55,6 +56,4 @@ jobs:
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
terraform apply ./tf.plan -no-color
6 changes: 6 additions & 0 deletions terraform-plans/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ The permissions required for the github application are:
> This Github Application need to be installed on every repositories we want to manage. Please ask people who has Github Organization permission for help.
>
> For how to create the github application, please check [Creating Github Apps](https://docs.github.com/en/apps/creating-github-apps)
## Known limitation

### branch_protection

The Terraform Github provider does not support creating a branch protection rule if it does not already exist. Initially, an admin user must manually create the branch protection rule.
24 changes: 24 additions & 0 deletions terraform-plans/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,27 @@ module "github_workflow_files" {
branch = var.branch
workflow_files = var.workflow_files
}

output "repository" {
value = module.github_workflow_files.repository
}

output "branch" {
value = module.github_workflow_files.branch
}

output "pr_branch" {
value = module.github_workflow_files.pr_branch
}

output "pr_created" {
value = module.github_workflow_files.pr_created
}

output "pr_url" {
value = module.github_workflow_files.pr_url
}

output "changed_files" {
value = module.github_workflow_files.changed_files
}
92 changes: 87 additions & 5 deletions terraform-plans/modules/GitHub/workflows/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,83 @@ terraform {

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


# Generate a unique string to append to the branch name
resource "random_string" "update_uid" {
length = 8
numeric = true
special = false
}

# Flatten the repository and file information into a single list of maps based on the workflow_files variable
locals {
repo_files = flatten([
for file_key, file_info in var.workflow_files : {
file = file_info.destination
source = file_info.source
}
])
}

# Fetch the current content of the files from the repository
data "github_repository_file" "files" {
for_each = {
for item in local.repo_files : "${item.file}" => item
}

repository = var.repository
file = each.value.file
branch = var.branch
}

# Store the fetched content in a local variable, defaulting to an empty string if the file does not exist
locals {
repository_files_content = {
for file_key, file_info in var.workflow_files : file_info.destination =>
try(data.github_repository_file.files["${file_info.destination}"].content, "")
}
}

# Compare the fetched content with the local content to create a map of changed files
locals {
changed_files = {
for file_key, file_info in var.workflow_files : file_key => file_info
if file(file_info.source) != local.repository_files_content[file_info.destination]
}
}

# Create a new branch only if there are changed files
resource "github_branch" "workflows_branch" {
count = length(local.changed_files) > 0 ? 1 : 0

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

# Create or update files in the repository only if they have changed
resource "github_repository_file" "workflows_files" {
for_each = var.workflow_files
for_each = local.changed_files

repository = var.repository
branch = github_branch.workflows_branch.branch
branch = github_branch.workflows_branch[0].branch
file = each.value.destination
content = file(each.value.source)
commit_message = "update ${each.value.destination}"
overwrite_on_create = true

depends_on = [github_branch.workflows_branch]
}

# Create a pull request only if there are changed files
resource "github_repository_pull_request" "workflows_update_pr" {
count = length(local.changed_files) > 0 ? 1 : 0

base_repository = var.repository
base_ref = var.branch
head_ref = github_branch.workflows_branch.branch
head_ref = github_branch.workflows_branch[0].branch
title = var.pr_title
body = var.pr_body

Expand All @@ -47,3 +94,38 @@ resource "github_repository_pull_request" "workflows_update_pr" {
github_repository_file.workflows_files
]
}

# Outputs for debugging and verification
output "repository" {
value = var.repository
}

output "branch" {
value = var.branch
}

output "changed_files" {
value = local.changed_files
}

# Output to indicate if PR was created
output "pr_created" {
value = length(local.changed_files) > 0 ? true : false
}

# Output the PR branch if PR was created
output "pr_branch" {
value = length(local.changed_files) > 0 ? github_repository_pull_request.workflows_update_pr[0].head_ref : "No PR created"

depends_on = [
github_repository_pull_request.workflows_update_pr
]
}

output "pr_url" {
value = length(local.changed_files) > 0 ? "https://github.com/${var.owner}/${var.repository}/pull/${github_repository_pull_request.workflows_update_pr[0].number}" : "No PR created"

depends_on = [
github_repository_pull_request.workflows_update_pr
]
}

0 comments on commit 7ff5054

Please sign in to comment.