-
Notifications
You must be signed in to change notification settings - Fork 0
183 lines (151 loc) · 6.88 KB
/
replace.yml
File metadata and controls
183 lines (151 loc) · 6.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# Template created by https://github.com/XAOSTECH/dev-control
# See templates folder documentation for details.
name: Text Replacement
on:
workflow_dispatch:
inputs:
search_text:
description: 'Text to search for'
required: true
type: string
replace_text:
description: 'Text to replace with'
required: true
type: string
exclude_paths:
description: 'Comma-separated paths to exclude (e.g., ".github, node_modules")'
required: false
type: string
permissions:
contents: write
pull-requests: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
replace:
name: Replace Text
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Generate App Token
id: app_token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets['XB_AI'] }}
private-key: ${{ secrets['XB_PK'] }}
- name: Setup bot identity
uses: XAOSTECH/dev-control/.github/actions/identity@b067f72ca7f849b734a45634f23581a739d5146f # v2.0.0
with:
gpg-private-key: ${{ secrets['XB_GK'] }}
gpg-passphrase: ${{ secrets['XB_GP'] }}
user-token: ${{ secrets['XB_UT'] }}
bot-name: ${{ vars.BOT_NAME || 'xaos-bot' }}
- name: Validate inputs
run: |
if [[ -z "${{ inputs.search_text }}" ]]; then
echo "::error::Search text cannot be empty"
exit 1
fi
if [[ -z "${{ inputs.replace_text }}" ]]; then
echo "::error::Replace text cannot be empty"
exit 1
fi
echo "✅ Inputs validated"
echo "🔍 Search: ${{ inputs.search_text }}"
echo "🔄 Replace: ${{ inputs.replace_text }}"
echo "🚫 Exclude: ${{ inputs.exclude_paths }}"
- name: Perform text replacement
id: replace
run: |
SEARCH_TEXT="${{ inputs.search_text }}"
REPLACE_TEXT="${{ inputs.replace_text }}"
EXCLUDE_PATHS="${{ inputs.exclude_paths }}"
# Build find exclusion arguments
FIND_EXCLUDES="-path ./.git -prune"
if [[ -n "$EXCLUDE_PATHS" ]]; then
IFS=',' read -ra EXCLUDE_ARRAY <<< "$EXCLUDE_PATHS"
for exclude in "${EXCLUDE_ARRAY[@]}"; do
exclude=$(echo "$exclude" | xargs) # Trim whitespace
if [[ -n "$exclude" && "$exclude" != ".git" ]]; then
FIND_EXCLUDES="$FIND_EXCLUDES -o -path ./${exclude} -prune -o -path ./${exclude}/* -prune"
fi
done
fi
# Find all text files (excluding binary files and specified paths)
FILES=$(eval "find . $FIND_EXCLUDES -o -type f -print" | \
grep -vE '\.(png|jpg|jpeg|gif|ico|svg|pdf|zip|tar|gz|bz2|xz|exe|dll|so|dylib|a|o)$' | \
sort)
TOTAL_FILES=$(echo "$FILES" | wc -l)
CHANGED_FILES=0
TOTAL_REPLACEMENTS=0
echo "## Text Replacement Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "🔍 **Search:** \`$SEARCH_TEXT\`" >> $GITHUB_STEP_SUMMARY
echo "🔄 **Replace:** \`$REPLACE_TEXT\`" >> $GITHUB_STEP_SUMMARY
echo "🚫 **Excluded:** \`$EXCLUDE_PATHS\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "📊 Scanning $TOTAL_FILES files..." | tee -a $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Process each file
while IFS= read -r file; do
[[ -z "$file" ]] && continue
[[ ! -f "$file" ]] && continue
# Check if file contains search text
if grep -qF "$SEARCH_TEXT" "$file" 2>/dev/null; then
# Count occurrences in this file
COUNT=$(grep -oF "$SEARCH_TEXT" "$file" | wc -l)
# Perform replacement using sed
sed -i "s|$(echo "$SEARCH_TEXT" | sed 's/[\/&]/\\&/g')|$(echo "$REPLACE_TEXT" | sed 's/[\/&]/\\&/g')|g" "$file"
echo " ✓ $file ($COUNT replacement(s))"
echo "- \`$file\` - $COUNT occurrence(s)" >> $GITHUB_STEP_SUMMARY
CHANGED_FILES=$((CHANGED_FILES + 1))
TOTAL_REPLACEMENTS=$((TOTAL_REPLACEMENTS + COUNT))
fi
done <<< "$FILES"
echo "" >> $GITHUB_STEP_SUMMARY
if [[ $CHANGED_FILES -gt 0 ]]; then
echo "✅ Replaced $TOTAL_REPLACEMENTS occurrence(s) in $CHANGED_FILES file(s)"
echo "### Summary" >> $GITHUB_STEP_SUMMARY
echo "✅ **$TOTAL_REPLACEMENTS** replacement(s) in **$CHANGED_FILES** file(s)" >> $GITHUB_STEP_SUMMARY
echo "needs_pr=true" >> $GITHUB_OUTPUT
else
echo "ℹ️ No occurrences found"
echo "ℹ️ **No occurrences found**" >> $GITHUB_STEP_SUMMARY
echo "needs_pr=false" >> $GITHUB_OUTPUT
fi
- name: Setup bot identity (if replacement needed)
id: import_gpg
if: steps.replace.outputs.needs_pr == 'true'
uses: XAOSTECH/dev-control/.github/actions/identity@b067f72ca7f849b734a45634f23581a739d5146f # v2.0.0
with:
gpg-private-key: ${{ secrets['XB_GK'] }}
gpg-passphrase: ${{ secrets['XB_GP'] }}
user-token: ${{ secrets['XB_UT'] }}
bot-name: ${{ vars.BOT_NAME || 'xaos-bot' }}
- name: Create Pull Request
if: steps.replace.outputs.needs_pr == 'true'
env:
GH_TOKEN: ${{ steps.app_token.outputs.token }}
run: |
git add -A
if git diff --cached --quiet; then
echo "ℹ️ No changes to commit"
exit 0
fi
BRANCH_NAME="replace/$(date +%Y%m%d-%H%M%S)"
git checkout -b "$BRANCH_NAME"
SEARCH_TEXT="${{ inputs.search_text }}"
REPLACE_TEXT="${{ inputs.replace_text }}"
git commit -m "chore: replace text across repository" \
-m "Search: $SEARCH_TEXT" \
-m "Replace: $REPLACE_TEXT"
git push origin "$BRANCH_NAME"
gh pr create \
--title "chore: Replace text - automated update" \
--body "## Automated Text Replacement\n\n**Search:** \`$SEARCH_TEXT\` \n**Replace:** \`$REPLACE_TEXT\` \n**Excluded paths:** \`${{ inputs.exclude_paths }}\`\n\nThis PR was automatically generated by the [Text Replacement workflow](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}).\n\nPlease review the changes carefully before merging." \
--base "${{ github.ref_name }}" \
--head "$BRANCH_NAME"
echo "✅ Pull request created successfully"