Skip to content

Commit 4300f54

Browse files
authored
chore(os): add a task to create PRs for OS sync (#29)
## what - Adds a task to create PR for open-source TF modules sync operations. - Example: masterpointio/terraform-spacelift-policies#15 ## why - Speeds up bulk sync. ## references - N/A <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced automated creation of GitHub pull requests from the sync branch to main for selected modules. - Added a composite workflow to streamline syncing, pushing, and PR creation for specified modules. - **Improvements** - Enhanced branch synchronization logic to better handle existing branches and ensure local and remote branches stay aligned. - Updated push operations to ensure changes are committed and pushed from the correct branch. - **Chores** - Updated configuration to include a new package dependency. - Removed an unused module from the default modules list. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent bd3c5fa commit 4300f54

File tree

4 files changed

+192
-110
lines changed

4 files changed

+192
-110
lines changed

.github/workflows/trunk-upgrade.yaml

Lines changed: 5 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -19,93 +19,10 @@ jobs:
1919
- name: Checkout
2020
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
2121

22-
- name: Create Token for MasterpointBot App
23-
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a #v2.1.0
24-
id: generate-token
22+
- name: Run Trunk Upgrade
23+
uses: masterpointio/github-action-trunk-upgrade@v0.1.0
2524
with:
26-
app_id: ${{ secrets.MP_BOT_APP_ID }}
27-
private_key: ${{ secrets.MP_BOT_APP_PRIVATE_KEY }}
28-
29-
- name: Upgrade
30-
id: trunk-upgrade
31-
uses: trunk-io/trunk-action/upgrade@4d5ecc89b2691705fd08c747c78652d2fc806a94 # v1.1.19
32-
with:
33-
github-token: ${{ steps.generate-token.outputs.token }}
25+
app-id: ${{ secrets.MP_BOT_APP_ID }}
26+
app-private-key: ${{ secrets.MP_BOT_APP_PRIVATE_KEY }}
27+
github-token: ${{ secrets.MASTERPOINT_TEAM_PAT }}
3428
reviewers: "@masterpointio/masterpoint-internal"
35-
prefix: "chore: "
36-
37-
- name: Wait for checks to pass + Merge PR
38-
if: steps.trunk-upgrade.outputs.pull-request-number != ''
39-
env:
40-
GH_TOKEN: ${{ secrets.MASTERPOINT_TEAM_PAT }}
41-
PR_NUMBER: ${{ steps.trunk-upgrade.outputs.pull-request-number }}
42-
run: |
43-
echo "Waiting for status checks to pass on PR #$PR_NUMBER..."
44-
45-
# Wait a bit for checks to start
46-
echo "Waiting 30 seconds for checks to initialize..."
47-
sleep 30
48-
49-
# Try to get all checks first to see if any exist
50-
ALL_CHECKS_JSON=$(gh pr checks "$PR_NUMBER" --json state,bucket || echo "[]")
51-
echo "All checks: $ALL_CHECKS_JSON"
52-
53-
# Get required checks
54-
REQUIRED_CHECKS_JSON=$(gh pr checks "$PR_NUMBER" --required --json state,bucket || echo "[]")
55-
echo "Required checks: $REQUIRED_CHECKS_JSON"
56-
57-
# Check if we have any required checks
58-
REQUIRED_CHECKS_COUNT=$(echo "$REQUIRED_CHECKS_JSON" | jq '. | length')
59-
ALL_CHECKS_COUNT=$(echo "$ALL_CHECKS_JSON" | jq '. | length')
60-
61-
if [ "$REQUIRED_CHECKS_COUNT" -eq 0 ] && [ "$ALL_CHECKS_COUNT" -eq 0 ]; then
62-
echo "No status checks found. This might be expected if no checks are configured."
63-
echo "Proceeding with auto-approval and merge..."
64-
65-
# Auto-approve the PR
66-
gh pr review "$PR_NUMBER" --approve --body "Auto-approved by trunk upgrade workflow (no status checks configured)"
67-
68-
# Merge the PR
69-
gh pr merge "$PR_NUMBER" --squash --delete-branch --admin
70-
exit 0
71-
fi
72-
73-
# If we have required checks, wait for them. Otherwise, wait for all checks.
74-
if [ "$REQUIRED_CHECKS_COUNT" -gt 0 ]; then
75-
echo "Waiting for $REQUIRED_CHECKS_COUNT required status checks..."
76-
CHECKS_TO_MONITOR="required"
77-
else
78-
echo "No required checks configured. Waiting for all $ALL_CHECKS_COUNT status checks..."
79-
CHECKS_TO_MONITOR="all"
80-
fi
81-
82-
# Wait for checks to complete
83-
while true; do
84-
if [ "$CHECKS_TO_MONITOR" = "required" ]; then
85-
CHECKS_JSON=$(gh pr checks "$PR_NUMBER" --required --json state,bucket)
86-
else
87-
CHECKS_JSON=$(gh pr checks "$PR_NUMBER" --json state,bucket)
88-
fi
89-
90-
echo "Current checks status: $CHECKS_JSON"
91-
92-
if echo "$CHECKS_JSON" | jq -e '.[] | select(.bucket=="fail")' > /dev/null; then
93-
echo "One or more checks have failed. Exiting..."
94-
exit 1
95-
fi
96-
97-
FAILED_OR_PENDING_CHECKS=$(echo "$CHECKS_JSON" | jq '[.[] | select(.state!="SUCCESS" or .bucket!="pass")] | length')
98-
if [ "$FAILED_OR_PENDING_CHECKS" -eq 0 ]; then
99-
echo "All checks passed. Auto-approving and merging PR https://github.com/${{ github.repository }}/pull/$PR_NUMBER..."
100-
101-
# Auto-approve the PR
102-
gh pr review "$PR_NUMBER" --approve --body "Auto-approved by trunk upgrade workflow"
103-
104-
# Merge the PR
105-
gh pr merge "$PR_NUMBER" --squash --delete-branch --admin
106-
break
107-
else
108-
echo "Some checks are still running or pending. Retrying in 30s..."
109-
sleep 30
110-
fi
111-
done

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
# Therefore, configs specific to their coding practices are their responsibilty to judiciously manage.
55
.claude/*
66

7+
.tmp-template-sync/

aqua.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ packages:
77
- name: TomWright/dasel@v2.4.1
88
- name: stedolan/jq@jq-1.7.1
99
tags: [cursor]
10+
- name: cli/cli@v2.74.2
11+
tags: [gh]

lib/os-modules/Taskfile.yaml

Lines changed: 184 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ vars:
66
terraform-aws-tailscale \
77
terraform-aws-identity-center-users \
88
terraform-datadog-users \
9-
terraform-github-organization \
109
terraform-github-teams \
1110
terraform-googleworkspace-users-groups-automation \
1211
terraform-postgres-config-dbs-users-roles \
@@ -15,9 +14,33 @@ vars:
1514
terraform-spacelift-aws-integrations \
1615
terraform-spacelift-events-collector-audit-trail \
1716
terraform-spacelift-policies
17+
18+
# Configuration constants
1819
SYNC_BRANCH: chore/sync-with-template
1920
SHARED_TMP_DIR: .tmp-template-sync
21+
TEMPLATE_REPO: https://github.com/masterpointio/terraform-module-template.git
22+
TEMPLATE_OWNER: masterpointio
23+
SYNC_MESSAGE: "chore: sync with latest template state"
24+
25+
# Files to synchronize
26+
SYNC_FILES: >-
27+
.checkov.yaml
28+
.coderabbit.yaml
29+
.editorconfig
30+
.gitignore
31+
.github
32+
.markdownlint.yaml
33+
.terraform-docs.yaml
34+
.tflint.hcl
35+
.trunk
36+
.yamllint.yaml
37+
LICENSE
38+
aqua.yaml
2039
tasks:
40+
# ============================================================================
41+
# File Synchronization Tasks
42+
# ============================================================================
43+
2144
sync:
2245
desc: |
2346
Sync files from `terraform-module-template` to specified Terraform open-source module repos.
@@ -32,33 +55,24 @@ tasks:
3255
3356
vars:
3457
MODULES: "{{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}{{.DEFAULT_MODULES}}{{end}}"
35-
FILES: >-
36-
.checkov.yaml
37-
.coderabbit.yaml
38-
.editorconfig
39-
.gitignore
40-
.github
41-
.markdownlint.yaml
42-
.terraform-docs.yaml
43-
.tflint.hcl
44-
.trunk
45-
.yamllint.yaml
46-
LICENSE
47-
aqua.yaml
4858
cmds:
4959
- |
5060
# Convert newlines to spaces and remove backslashes
5161
modules=$(echo "{{.MODULES}}" | tr '\n' ' ' | sed 's/\\//g')
5262
for module in $modules
5363
do
5464
echo "Syncing files to ../$module ..."
55-
for file in {{.FILES}}
65+
for file in {{.SYNC_FILES}}
5666
do
5767
echo " Syncing $file"
5868
rsync -av --delete {{.SHARED_TMP_DIR}}/$file ../$module/
5969
done
6070
done
6171
72+
# ============================================================================
73+
# Git Branch Management Tasks
74+
# ============================================================================
75+
6276
pull-and-branch:
6377
desc: |
6478
Pull main branch and create a sync branch for specified Terraform open-source module repos.
@@ -82,7 +96,7 @@ tasks:
8296
echo -e "\n\n🚀 Processing ---------------- $module \n"
8397
if [ ! -d ../$module ]; then
8498
echo "🧲 Cloning repository..."
85-
git clone "git@github.com:masterpointio/$module.git" ../$module
99+
git clone "git@github.com:{{.TEMPLATE_OWNER}}/$module.git" ../$module
86100
fi
87101
cd ../$module
88102
@@ -94,7 +108,15 @@ tasks:
94108
95109
# If branch exists and delete option is turned off - skip creation
96110
if git branch --list "{{.SYNC_BRANCH}}" | grep -q "{{.SYNC_BRANCH}}" && [ "{{.DELETE_EXISTING_SYNC_BRANCH}}" = "false" ]; then
97-
echo "⏭️ Branch {{.SYNC_BRANCH}} already exists, skipping creation."
111+
echo "⏭️ Branch {{.SYNC_BRANCH}} already exists, checking it out."
112+
git checkout {{.SYNC_BRANCH}}
113+
114+
# Check if local and remote branches have diverged
115+
if git status --porcelain -b | grep -q "ahead\|behind\|diverged"; then
116+
echo "⚠️ Local and remote branches have diverged. Resetting to remote branch..."
117+
git fetch origin {{.SYNC_BRANCH}}
118+
git reset --hard origin/{{.SYNC_BRANCH}}
119+
fi
98120
99121
# If branch exists and delete option is turned on - delete and create new branch
100122
elif git branch --list "{{.SYNC_BRANCH}}" | grep -q "{{.SYNC_BRANCH}}" && [ "{{.DELETE_EXISTING_SYNC_BRANCH}}" = "true" ]; then
@@ -110,6 +132,10 @@ tasks:
110132
cd -
111133
done
112134
135+
# ============================================================================
136+
# Commit and Push Tasks
137+
# ============================================================================
138+
113139
push:
114140
desc: |
115141
Commit and push changes with the specified commit message.
@@ -131,25 +157,138 @@ tasks:
131157
do
132158
echo "🚀 Processing ../$module..."
133159
cd ../$module
134-
echo "📝 Committing changes..."
160+
echo "🔄 Checking out {{.SYNC_BRANCH}} branch..."
161+
git checkout {{.SYNC_BRANCH}}
162+
echo "📝 Staging changes..."
135163
git add .
136-
git commit -m "chore: update with the latest template state"
137-
echo "⬆️ Pushing changes..."
138-
git push origin {{.SYNC_BRANCH}}
164+
165+
# Check if there are any changes to commit
166+
if git diff --staged --quiet; then
167+
echo "⚠️ No changes to commit in $module, skipping..."
168+
else
169+
echo "📝 Committing changes..."
170+
git commit -m "{{.SYNC_MESSAGE}}"
171+
echo "⬆️ Pushing changes..."
172+
git push origin {{.SYNC_BRANCH}}
173+
fi
174+
cd -
175+
done
176+
177+
# ============================================================================
178+
# Pull Request Management Tasks
179+
# ============================================================================
180+
181+
pr:
182+
desc: |
183+
Create pull requests for the changes pushed to SYNC_BRANCH.
184+
Example: `task os:pr -- terraform-spacelift-automation`
185+
summary: |
186+
This will create pull requests from the SYNC_BRANCH to main for each of the specified
187+
Terraform module repositories using GitHub CLI.
188+
To create PRs for specific repositories, pass their names as arguments:
189+
`task os:pr -- terraform-custom-module`
190+
or for multiple modules: `task os:pr -- "terraform-custom-module terraform-another-module"`
191+
192+
vars:
193+
MODULES: "{{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}{{.DEFAULT_MODULES}}{{end}}"
194+
cmds:
195+
- |
196+
# Get the latest commit SHA from terraform-module-template
197+
echo "🔍 Fetching latest commit SHA from terraform-module-template..."
198+
template_sha=$(git ls-remote {{.TEMPLATE_REPO}} HEAD | cut -f1)
199+
template_short_sha=$(echo $template_sha | cut -c1-7)
200+
201+
# Try to get the latest tag from terraform-module-template
202+
echo "🏷️ Fetching latest tag from terraform-module-template..."
203+
template_tag=$(git ls-remote --tags --sort=-version:refname {{.TEMPLATE_REPO}} | head -n1 | sed 's/.*refs\/tags\///' | sed 's/\^{}//')
204+
205+
# If no tag found, use "no tags"
206+
if [ -z "$template_tag" ]; then
207+
template_tag="no tags"
208+
fi
209+
210+
echo "📝 Template info: Tag: $template_tag, SHA: $template_short_sha"
211+
212+
# Convert newlines to spaces and remove backslashes
213+
modules=$(echo "{{.MODULES}}" | tr '\n' ' ' | sed 's/\\//g')
214+
for module in $modules
215+
do
216+
echo "🚀 Creating PR for ../$module..."
217+
cd ../$module
218+
219+
current_branch=$(git branch --show-current)
220+
if [ "$current_branch" != "{{.SYNC_BRANCH}}" ]; then
221+
echo "⚠️ Warning: Not on {{.SYNC_BRANCH}} branch. Current branch: $current_branch"
222+
echo "🔄 Checking out {{.SYNC_BRANCH}}..."
223+
git checkout {{.SYNC_BRANCH}}
224+
fi
225+
226+
# Check if there are commits ahead of main
227+
commits_ahead=$(git rev-list --count main..{{.SYNC_BRANCH}})
228+
if [ "$commits_ahead" -eq 0 ]; then
229+
echo "⏭️ No commits ahead of main, skipping PR creation for $module"
230+
cd -
231+
continue
232+
fi
233+
234+
# Ensure remote branch exists
235+
if ! git ls-remote --heads origin {{.SYNC_BRANCH}} | grep -q {{.SYNC_BRANCH}}; then
236+
echo "📤 Remote branch doesn't exist, pushing {{.SYNC_BRANCH}} to origin..."
237+
git push origin {{.SYNC_BRANCH}}
238+
fi
239+
240+
# Check if PR already exists
241+
existing_pr=$(gh pr list --head {{.SYNC_BRANCH}} --base main --json number --jq '.[0].number' 2>/dev/null || echo "")
242+
if [ -n "$existing_pr" ]; then
243+
echo "📋 PR already exists (#$existing_pr), skipping PR creation for $module"
244+
cd -
245+
continue
246+
fi
247+
248+
# Create PR body with template version info
249+
echo "📋 Creating pull request..."
250+
251+
# Create PR body using printf to properly handle multi-line formatting
252+
pr_body=$(printf "%s\n\n%s\n%s\n%s\n\n%s\n%s\n%s\n%s\n%s" \
253+
"This PR syncs the repository with the latest state from [terraform-module-template]({{.TEMPLATE_REPO}})." \
254+
"**Template Version:**" \
255+
"- **Tag:** [$template_tag]({{.TEMPLATE_REPO}}/releases/tag/$template_tag)" \
256+
"- **Commit SHA:** $template_short_sha" \
257+
"**Changes include:**" \
258+
"- Updated configuration files (.checkov.yaml, .markdownlint.yaml, etc.)" \
259+
"- Updated GitHub workflows and templates" \
260+
"- Updated linting and formatting configurations" \
261+
"- Updated documentation templates")
262+
263+
gh pr create \
264+
--title "{{.SYNC_MESSAGE}}" \
265+
--body "$pr_body" \
266+
--base main \
267+
--head {{.SYNC_BRANCH}} \
268+
--repo "{{.TEMPLATE_OWNER}}/$module"
269+
139270
cd -
140271
done
141272
273+
# ============================================================================
274+
# Template Management Tasks
275+
# ============================================================================
276+
142277
setup-template:
143278
desc: Set up the template repository in a shared temporary directory
144279
cmds:
145280
- task: cleanup-template
146-
- git clone --depth 1 https://github.com/masterpointio/terraform-module-template.git {{.SHARED_TMP_DIR}}
281+
- git clone --depth 1 {{.TEMPLATE_REPO}} {{.SHARED_TMP_DIR}}
147282

148283
cleanup-template:
149284
desc: Clean up the shared temporary directory
150285
cmds:
151286
- rm -rf {{.SHARED_TMP_DIR}}
152287

288+
# ============================================================================
289+
# Composite Workflow Tasks
290+
# ============================================================================
291+
153292
sync-all:
154293
desc: |
155294
Pull main branch, create a sync branch, and sync with template for specified Terraform open-source module repos.
@@ -171,3 +310,26 @@ tasks:
171310
- task: pull-and-branch
172311
- task: sync
173312
- task: cleanup-template
313+
314+
sync-and-pr:
315+
desc: |
316+
Complete workflow: sync with template, push changes, and create pull requests.
317+
Example: `task os:sync-and-pr -- terraform-spacelift-automation`
318+
summary: |
319+
This will:
320+
1. Pull the main branch and create a new branch named 'chore/sync-with-template'
321+
2. Sync files from the template repository
322+
3. Commit and push changes
323+
4. Create pull requests for the changes
324+
for each of the default Terraform module repositories listed in DEFAULT_MODULES.
325+
To sync to a specific repository (or a custom list of repositories), pass their names as arguments:
326+
`task os:sync-and-pr -- terraform-custom-module`
327+
or for multiple modules: `task os:sync-and-pr -- "terraform-custom-module terraform-another-module"`
328+
329+
vars:
330+
MODULES: "{{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}{{.DEFAULT_MODULES}}{{end}}"
331+
DELETE_EXISTING_SYNC_BRANCH: "{{.DELETE_EXISTING_SYNC_BRANCH | default false}}"
332+
cmds:
333+
- task: sync-all
334+
- task: push
335+
- task: pr

0 commit comments

Comments
 (0)