Skip to content

Commit 68a0989

Browse files
committed
add workflow for hybridcloud domain migration
1 parent 90c1391 commit 68a0989

File tree

1 file changed

+196
-0
lines changed

1 file changed

+196
-0
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
name: Org-Wide Domain Migration
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
organization:
7+
description: 'The GitHub Organization name'
8+
required: true
9+
repo_filter:
10+
description: 'Specific repositories to target (comma-separated). Leave empty for ALL.'
11+
required: false
12+
type: string
13+
mode:
14+
description: 'Choose Action Mode'
15+
required: true
16+
default: 'apply'
17+
type: choice
18+
options:
19+
- apply
20+
- revert
21+
dry_run:
22+
description: 'Dry Run (logs only, no push)'
23+
required: true
24+
default: 'false'
25+
type: boolean
26+
27+
jobs:
28+
manage-migration:
29+
runs-on: ubuntu-latest
30+
steps:
31+
- name: Checkout Controller Repo
32+
uses: actions/checkout@v4
33+
34+
- name: Setup Python
35+
uses: actions/setup-python@v4
36+
with:
37+
python-version: '3.9'
38+
39+
- name: Initialize Report
40+
run: |
41+
echo "# Domain Migration Report (${{ inputs.mode }})" > migration_summary.md
42+
echo "**User:** ${{ github.actor }} | **Mode:** ${{ inputs.mode }}" >> migration_summary.md
43+
echo "" >> migration_summary.md
44+
echo "| Repository | Status | Detail |" >> migration_summary.md
45+
echo "| :--- | :--- | :--- |" >> migration_summary.md
46+
47+
- name: Process Repositories
48+
env:
49+
GH_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}
50+
ORG_NAME: ${{ inputs.organization }}
51+
REPO_FILTER: ${{ inputs.repo_filter }}
52+
MODE: ${{ inputs.mode }}
53+
DRY_RUN: ${{ inputs.dry_run }}
54+
run: |
55+
# 1. Fetch all repos (we filter later in the loop)
56+
echo "Fetching repositories for $ORG_NAME..."
57+
repos=$(gh repo list $ORG_NAME --limit 2000 --json name --jq '.[] | .name')
58+
59+
# 2. Define the Python Script (Only needed for Apply mode)
60+
cat << 'EOF' > process_repo.py
61+
import os
62+
import re
63+
import sys
64+
65+
# --- CONFIGURATION ---
66+
OLD_DOMAIN = 'hybrid-cloud-patterns.io'
67+
NEW_DOMAIN = 'validatedpatterns.io'
68+
NEW_TEAM_ALIAS = 'team-validatedpatterns'
69+
IGNORE_MARKER = 'apiVersion: hybrid-cloud-patterns.io'
70+
71+
mailto_pattern = re.compile(r'(mailto:)([a-zA-Z0-9._%+-]+)(@' + re.escape(OLD_DOMAIN) + r')')
72+
73+
files_changed = 0
74+
extensions_to_check = ['.yaml', '.yml', '.md', '.txt', '.json', '.sh', '.html', '.rst']
75+
76+
for root, dirs, files in os.walk('.'):
77+
if '.git' in dirs: dirs.remove('.git')
78+
for file in files:
79+
if not any(file.endswith(ext) for ext in extensions_to_check): continue
80+
file_path = os.path.join(root, file)
81+
try:
82+
with open(file_path, 'r', encoding='utf-8') as f: lines = f.readlines()
83+
except: continue
84+
85+
new_lines = []
86+
file_modified = False
87+
for line in lines:
88+
if IGNORE_MARKER in line:
89+
new_lines.append(line)
90+
continue
91+
92+
original_line = line
93+
if 'mailto:' in line and OLD_DOMAIN in line:
94+
line = mailto_pattern.sub(r'\1' + NEW_TEAM_ALIAS + '@' + NEW_DOMAIN, line)
95+
if OLD_DOMAIN in line:
96+
line = line.replace(OLD_DOMAIN, NEW_DOMAIN)
97+
if line != original_line:
98+
file_modified = True
99+
new_lines.append(line)
100+
101+
if file_modified:
102+
with open(file_path, 'w', encoding='utf-8') as f: f.writelines(new_lines)
103+
files_changed += 1
104+
105+
sys.exit(0 if files_changed > 0 else 1)
106+
EOF
107+
108+
# 3. Loop through repositories
109+
BRANCH_NAME="migration/update-domain-references"
110+
111+
for NAME in $repos; do
112+
113+
# --- FILTER LOGIC ---
114+
# If repo_filter is set, skip if NAME is not in the list
115+
if [[ ! -z "$REPO_FILTER" ]]; then
116+
if [[ ",$REPO_FILTER," != *",$NAME,"* ]]; then
117+
continue
118+
fi
119+
fi
120+
121+
echo "------------------------------------------------"
122+
echo "Processing: $NAME"
123+
124+
# Clone
125+
git clone "https://x-access-token:${GH_TOKEN}@github.com/$ORG_NAME/$NAME.git" work_dir
126+
cd work_dir
127+
128+
if [ "$MODE" == "revert" ]; then
129+
# --- REVERT MODE ---
130+
echo "Attempting to revert changes in $NAME..."
131+
132+
# Check if PR exists
133+
PR_LIST=$(gh pr list --head $BRANCH_NAME --json number --jq '.[].number')
134+
135+
if [ ! -z "$PR_LIST" ]; then
136+
if [ "$DRY_RUN" = "false" ]; then
137+
for pr_num in $PR_LIST; do
138+
gh pr close $pr_num --delete-branch --comment "Closing via automated cleanup."
139+
done
140+
echo "| $NAME | 🧹 Reverted | Closed PRs and deleted branch |" >> ../migration_summary.md
141+
else
142+
echo "| $NAME | ⚠️ Dry Run | Would close PRs and delete branch |" >> ../migration_summary.md
143+
fi
144+
else
145+
# Attempt to delete branch even if no PR exists
146+
if git ls-remote --exit-code --heads origin $BRANCH_NAME; then
147+
if [ "$DRY_RUN" = "false" ]; then
148+
git push origin --delete $BRANCH_NAME
149+
echo "| $NAME | 🧹 Cleaned | Branch deleted (No PR found) |" >> ../migration_summary.md
150+
else
151+
echo "| $NAME | ⚠️ Dry Run | Would delete orphan branch |" >> ../migration_summary.md
152+
fi
153+
else
154+
echo "| $NAME | 💨 Skipped | No PR or Branch found |" >> ../migration_summary.md
155+
fi
156+
fi
157+
158+
else
159+
# --- APPLY MODE ---
160+
git checkout -b $BRANCH_NAME || git checkout $BRANCH_NAME
161+
162+
# Run Python
163+
python3 ../process_repo.py
164+
CHANGES_MADE=$?
165+
166+
if [ $CHANGES_MADE -eq 0 ]; then
167+
if [ "$DRY_RUN" = "false" ]; then
168+
git config user.name "Migration Bot"
169+
git config user.email "[email protected]"
170+
git add .
171+
git commit -m "refactor: migrate hybrid-cloud-patterns.io to validatedpatterns.io"
172+
git push origin $BRANCH_NAME --force
173+
174+
PR_URL=$(gh pr create --title "Migrate domain references" --body "Automated migration." --head $BRANCH_NAME --base main 2>/dev/null || echo "PR already exists")
175+
echo "| $NAME | ✅ Migrated | PR Created/Updated |" >> ../migration_summary.md
176+
else
177+
echo "| $NAME | ⚠️ Dry Run | Changes detected |" >> ../migration_summary.md
178+
fi
179+
else
180+
echo "| $NAME | 💤 Skipped | No patterns found |" >> ../migration_summary.md
181+
fi
182+
fi
183+
184+
# Cleanup local dir
185+
cd ..
186+
rm -rf work_dir
187+
done
188+
189+
- name: Create Summary Issue
190+
if: always()
191+
env:
192+
GH_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }}
193+
run: |
194+
if [ -f migration_summary.md ]; then
195+
gh issue create --repo ${{ github.repository }} --title "Migration Report: ${{ inputs.organization }} ($MODE)" --body-file migration_summary.md
196+
fi

0 commit comments

Comments
 (0)