Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(terraform): create pr only if workflow files content is different #19

Merged
Merged
Show file tree
Hide file tree
Changes from 3 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
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.
rgildein marked this conversation as resolved.
Show resolved Hide resolved
20 changes: 20 additions & 0 deletions terraform-plans/main.tf
chanchiwai-ray marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,23 @@ 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 "changed_files" {
value = module.github_workflow_files.changed_files
}
84 changes: 79 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
}

chanchiwai-ray marked this conversation as resolved.
Show resolved Hide resolved

# 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
chanchiwai-ray marked this conversation as resolved.
Show resolved Hide resolved
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,30 @@ 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
]
}