11name : Reverse Sync on Push
22
3- env :
4- TARGET_REPO : alaudadevops/tektoncd-operator
5- # Ignoring the files or folders in this prefix (uses comma to split)
6- IGNORE_PATHS : .github/,README.md
7- # will check these files change to create a new patch
8- SYNCED_PATHS : " docs/ theme/ .yarn/ doom.config.yml yarn.lock tsconfig.json package.json sites.yaml"
9-
103on :
114 push :
125 branches :
@@ -22,333 +15,11 @@ permissions:
2215concurrency :
2316 group : reverse-sync-${{ github.ref }}
2417 cancel-in-progress : true
18+
2519jobs :
2620 reverse-sync :
27- runs-on : ubuntu-latest
28-
29- steps :
30- - name : Checkout devops-pipelines-docs repository
31- uses : actions/checkout@v4
32- with :
33- token : ${{ secrets.GH_TOKEN }}
34- fetch-depth : 0
35-
36- - name : Check if commit is from merged PR
37- id : check_pr_commit
38- run : |
39- # Get the latest commit
40- commit_sha="${{ github.sha }}"
41- echo "commit_sha=$commit_sha" >> $GITHUB_OUTPUT
42-
43- # Get commit message
44- commit_message=$(git log -1 --pretty=format:"%s" $commit_sha)
45- echo "commit_message=$commit_message" >> $GITHUB_OUTPUT
46-
47- # Get commit author
48- commit_author=$(git log -1 --pretty=format:"%an" $commit_sha)
49- commit_author_email=$(git log -1 --pretty=format:"%ae" $commit_sha)
50- echo "commit_author=$commit_author" >> $GITHUB_OUTPUT
51- echo "commit_author_email=$commit_author_email" >> $GITHUB_OUTPUT
52-
53- echo "=> Commit: $commit_sha"
54- echo "=> Message: $commit_message"
55- echo "=> Author: $commit_author <$commit_author_email>"
56-
57- # Check if this is a merge commit from GitHub (squash merge creates a single commit)
58- # Look for PR number in commit message (GitHub automatically adds this)
59- if [[ "$commit_message" =~ \(#([0-9]+)\)$ ]]; then
60- pr_number="${BASH_REMATCH[1]}"
61- echo "pr_number=$pr_number" >> $GITHUB_OUTPUT
62- echo "is_pr_commit=true" >> $GITHUB_OUTPUT
63- echo "✅ Detected commit from PR #$pr_number"
64- else
65- echo "is_pr_commit=false" >> $GITHUB_OUTPUT
66- echo "ℹ️ Not a PR commit - skipping reverse sync"
67- fi
68-
69- # Skip if the commit is from our sync bot
70- if [[ "$commit_author_email" == "[email protected] " ]] && [[ "$commit_message" == *"[reverse-sync]"* ]]; then 71- echo "skip_sync=true" >> $GITHUB_OUTPUT
72- echo "🤖 Commit is from sync bot - skipping reverse sync"
73- elif [[ "$commit_message" == *"Sync documentation"* ]] || [[ "$commit_message" == *"sync-docs"* ]]; then
74- echo "skip_sync=true" >> $GITHUB_OUTPUT
75- echo "🤖 Commit appears to be from sync process - skipping reverse sync"
76- else
77- echo "skip_sync=false" >> $GITHUB_OUTPUT
78- echo "👥 Commit is from external contributor - proceeding with reverse sync"
79- fi
80-
81- - name : Get PR information
82- if : steps.check_pr_commit.outputs.is_pr_commit == 'true' && steps.check_pr_commit.outputs.skip_sync == 'false'
83- id : get_pr_info
84- run : |
85- pr_number="${{ steps.check_pr_commit.outputs.pr_number }}"
86-
87- echo "👀 Looking for PR $pr_number ..."
88-
89-
90- # Get PR information using GitHub API
91- pr_info=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
92- "https://api.github.com/repos/${{ github.repository }}/pulls/$pr_number")
93-
94-
95- echo "👀 PR data $pr_info ..."
96-
97- pr_title=$(echo "$pr_info" | jq -r '.title')
98- pr_author=$(echo "$pr_info" | jq -r '.user.login')
99- pr_url=$(echo "$pr_info" | jq -r '.html_url')
100- pr_base_ref=$(echo "$pr_info" | jq -r '.base.ref')
101-
102- echo "pr_title=$pr_title" >> $GITHUB_OUTPUT
103- echo "pr_author=$pr_author" >> $GITHUB_OUTPUT
104- echo "pr_url=$pr_url" >> $GITHUB_OUTPUT
105- echo "pr_base_ref=$pr_base_ref" >> $GITHUB_OUTPUT
106-
107- echo "=> PR #$pr_number: $pr_title"
108- echo "=> Author: $pr_author"
109- echo "=> URL: $pr_url"
110-
111- - name : Get commit changes
112- if : steps.check_pr_commit.outputs.is_pr_commit == 'true' && steps.check_pr_commit.outputs.skip_sync == 'false'
113- id : get_changes
114- run : |
115- commit_sha="${{ steps.check_pr_commit.outputs.commit_sha }}"
116-
117- # Get the parent commit (previous commit before this one)
118- parent_commit=$(git rev-parse ${commit_sha}^)
119- echo "parent_commit=$parent_commit" >> $GITHUB_OUTPUT
120-
121- # Get list of changed files in the commit, excluding ignored paths
122- ignore_pattern=$(echo "$IGNORE_PATHS" | sed 's/,/|/g' | sed 's|/$||g')
123- echo "🙈 Ignored paths: $ignore_pattern"
124-
125- git diff --name-only $parent_commit $commit_sha | grep -v -E "^($ignore_pattern)" > changed_files.txt || true
126-
127- echo "📋 Changed files in commit:"
128- cat changed_files.txt
129-
130- # Check if any relevant files were changed
131- if [ -s changed_files.txt ]; then
132- echo "has_doc_changes=true" >> $GITHUB_OUTPUT
133- echo "✅ Documentation changes detected"
134- else
135- echo "has_doc_changes=false" >> $GITHUB_OUTPUT
136- echo "ℹ️ No documentation changes detected"
137- fi
138-
139- - name : Checkout target repository
140- if : steps.check_pr_commit.outputs.is_pr_commit == 'true' && steps.check_pr_commit.outputs.skip_sync == 'false' && steps.get_changes.outputs.has_doc_changes == 'true'
141- uses : actions/checkout@v4
142- with :
143- repository : ${{env.TARGET_REPO}}
144- token : ${{ secrets.GH_TOKEN }}
145- path : target-docs
146- fetch-depth : 0
147- ref : ${{ steps.get_pr_info.outputs.pr_base_ref }}
148-
149- - name : Create reverse sync branch
150- if : steps.check_pr_commit.outputs.is_pr_commit == 'true' && steps.check_pr_commit.outputs.skip_sync == 'false' && steps.get_changes.outputs.has_doc_changes == 'true'
151- id : create_branch
152- run : |
153- cd target-docs
154-
155- # Create a unique branch name
156- pr_number="${{ steps.check_pr_commit.outputs.pr_number }}"
157- branch_name="reverse-sync/pr-$pr_number-$(date +%s)"
158- echo "branch_name=$branch_name" >> $GITHUB_OUTPUT
159-
160- git checkout -b "$branch_name"
161-
162- # Configure git
163- git config user.name "Documentation Sync Bot"
164- git config user.email "[email protected] " 165-
166- echo "📝 Created branch: $branch_name"
167-
168- - name : Apply changes from devops-pipelines-docs
169- if : steps.check_pr_commit.outputs.is_pr_commit == 'true' && steps.check_pr_commit.outputs.skip_sync == 'false' && steps.get_changes.outputs.has_doc_changes == 'true'
170- run : |
171- commit_sha="${{ steps.check_pr_commit.outputs.commit_sha }}"
172- parent_commit="${{ steps.get_changes.outputs.parent_commit }}"
173-
174- # Create a patch with only the synced paths
175- echo "📑 Will only sync these paths: $SYNCED_PATHS"
176- git format-patch $parent_commit..$commit_sha --stdout -- $SYNCED_PATHS > changes.patch
177-
178- echo "📋 Generated Patch: "
179- cat changes.patch
180-
181- cd target-docs
182-
183- # Apply the patch
184- if [ -s ../changes.patch ]; then
185- echo "📦 Applying changes from devops-pipelines-docs..."
186- git apply ../changes.patch || {
187- echo "⚠️ Patch application failed, trying manual copy..."
188-
189- # Fallback: manual copy of changed files
190- while IFS= read -r file; do
191- if [ -f "../$file" ]; then
192- mkdir -p "$(dirname "$file")"
193- cp "../$file" "$file"
194- echo "✅ Copied: $file"
195- fi
196- done < ../changed_files.txt
197- }
198- else
199- echo "⚠️ No patch generated, using manual copy..."
200-
201- # Manual copy approach
202- while IFS= read -r file; do
203- if [ -f "../$file" ]; then
204- mkdir -p "$(dirname "$file")"
205- cp "../$file" "$file"
206- echo "✅ Copied: $file"
207- fi
208- done < ../changed_files.txt
209- fi
210-
211- - name : Commit changes
212- if : steps.check_pr_commit.outputs.is_pr_commit == 'true' && steps.check_pr_commit.outputs.skip_sync == 'false' && steps.get_changes.outputs.has_doc_changes == 'true'
213- id : commit_changes
214- run : |
215- cd target-docs
216-
217- echo "🔍 Checking for changes..."
218-
219- git status
220-
221- echo "=> Adding changes..."
222-
223- git add .
224-
225- echo "==> Checking if there are staged changes..."
226- if git diff --staged --quiet; then
227- echo "has_changes=false" >> $GITHUB_OUTPUT
228- echo "ℹ️ No changes to commit"
229- else
230- echo "=> Changes detected..."
231- echo "has_changes=true" >> $GITHUB_OUTPUT
232-
233- pr_number="${{ steps.check_pr_commit.outputs.pr_number }}"
234- pr_title="${{ steps.get_pr_info.outputs.pr_title }}"
235- pr_author="${{ steps.get_pr_info.outputs.pr_author }}"
236- pr_url="${{ steps.get_pr_info.outputs.pr_url }}"
237- commit_sha="${{ steps.check_pr_commit.outputs.commit_sha }}"
238-
239- echo "=> Creating commit message..."
240- echo " - PR Number: $pr_number"
241- echo " - PR Title: $pr_title"
242- echo " - PR Author: $pr_author"
243- echo " - PR URL: $pr_url"
244- echo " - Commit SHA: $commit_sha"
245-
246- # Create commit message with reverse sync marker
247-
248- echo "[reverse-sync] Sync documentation changes from devops-pipelines-docs PR #$pr_number" > commit_message.txt
249- echo "" >> commit_message.txt
250- echo "- Title: $pr_title" >> commit_message.txt
251- echo "- Author: $pr_author" >> commit_message.txt
252- echo "- URL: $pr_url" >> commit_message.txt
253- echo "- Commit: $commit_sha" >> commit_message.txt
254-
255- echo "=> Commit message:"
256- cat commit_message.txt
257-
258- echo "=> Committing changes..."
259-
260- git commit -F commit_message.txt
261- rm commit_message.txt
262-
263- echo "✅ Changes committed successfully"
264- fi
265-
266- - name : Push branch and create PR
267- if : steps.check_pr_commit.outputs.is_pr_commit == 'true' && steps.check_pr_commit.outputs.skip_sync == 'false' && steps.get_changes.outputs.has_doc_changes == 'true' && steps.commit_changes.outputs.has_changes == 'true'
268- run : |
269- cd target-docs
270- branch_name="${{ steps.create_branch.outputs.branch_name }}"
271- pr_base_ref="${{ steps.get_pr_info.outputs.pr_base_ref }}"
272- pr_number="${{ steps.check_pr_commit.outputs.pr_number }}"
273- pr_title="${{ steps.get_pr_info.outputs.pr_title }}"
274- pr_author="${{ steps.get_pr_info.outputs.pr_author }}"
275- pr_url="${{ steps.get_pr_info.outputs.pr_url }}"
276-
277- # Push the branch
278- git push origin "$branch_name"
279-
280- # Create PR body with proper JSON escaping
281- pr_body=$(cat << 'EOF'
282- ### 🔄 Reverse Sync from devops-pipelines-docs
283-
284- This PR incorporates documentation changes from external contributors to the devops-pipelines-docs repository.
285-
286- #### Original PR Details
287- - **Repository**: danielfbm/devops-pipelines-docs
288- - **PR**: #%PR_NUMBER% - %PR_TITLE%
289- - **Author**: @%PR_AUTHOR%
290- - **URL**: %PR_URL%
291-
292- #### Changes
293- This PR includes changes to documentation files that were contributed by external contributors to the public devops-pipelines-docs repository.
294-
295- #### Important Notes
296- - ⚠️ This PR contains the `[reverse-sync]` marker to prevent infinite sync loops
297- - ✅ Once merged, this will NOT trigger a forward sync back to devops-pipelines-docs
298- - 🔍 Please review the changes to ensure they align with internal documentation standards
299-
300- ---
301- *This PR was automatically created by the reverse sync workflow.*
302- EOF)
303-
304- # Replace placeholders in the PR body
305- pr_body=$(echo "$pr_body" | sed "s/%PR_NUMBER%/$pr_number/g")
306- pr_body=$(echo "$pr_body" | sed "s/%PR_TITLE%/$pr_title/g")
307- pr_body=$(echo "$pr_body" | sed "s/%PR_AUTHOR%/$pr_author/g")
308- pr_body=$(echo "$pr_body" | sed "s|%PR_URL%|$pr_url|g")
309-
310- # Create JSON payload with proper escaping
311- json_payload=$(jq -n \
312- --arg title "[reverse-sync] Documentation changes from devops-pipelines-docs PR #$pr_number" \
313- --arg head "$branch_name" \
314- --arg base "$pr_base_ref" \
315- --arg body "$pr_body" \
316- '{title: $title, head: $head, base: $base, body: $body}')
317-
318- # Create the PR using GitHub API
319- curl -X POST \
320- -H "Authorization: token ${{ secrets.GH_TOKEN }}" \
321- -H "Accept: application/vnd.github.v3+json" \
322- -H "Content-Type: application/json" \
323- https://api.github.com/repos/${{env.TARGET_REPO}}/pulls \
324- -d "$json_payload"
325-
326- - name : Create workflow summary
327- run : |
328- if [ "${{ steps.check_pr_commit.outputs.is_pr_commit }}" == "false" ]; then
329- echo "## ℹ️ Not a PR Commit" >> $GITHUB_STEP_SUMMARY
330- echo "" >> $GITHUB_STEP_SUMMARY
331- echo "This commit was not created from a merged PR, so no reverse sync was performed." >> $GITHUB_STEP_SUMMARY
332- elif [ "${{ steps.check_pr_commit.outputs.skip_sync }}" == "true" ]; then
333- echo "## 🤖 Sync Bot Commit - Reverse Sync Skipped" >> $GITHUB_STEP_SUMMARY
334- echo "" >> $GITHUB_STEP_SUMMARY
335- echo "This commit was created by the sync bot, so reverse sync was skipped to prevent loops." >> $GITHUB_STEP_SUMMARY
336- elif [ "${{ steps.get_changes.outputs.has_doc_changes }}" == "false" ]; then
337- echo "## ℹ️ No Documentation Changes" >> $GITHUB_STEP_SUMMARY
338- echo "" >> $GITHUB_STEP_SUMMARY
339- echo "This commit didn't contain any documentation changes, so no reverse sync was needed." >> $GITHUB_STEP_SUMMARY
340- elif [ "${{ steps.commit_changes.outputs.has_changes }}" == "false" ]; then
341- echo "## ℹ️ No Changes to Sync" >> $GITHUB_STEP_SUMMARY
342- echo "" >> $GITHUB_STEP_SUMMARY
343- echo "The documentation changes were already present in target-docs." >> $GITHUB_STEP_SUMMARY
344- else
345- echo "## 🎉 Reverse Sync Completed" >> $GITHUB_STEP_SUMMARY
346- echo "" >> $GITHUB_STEP_SUMMARY
347- echo "Successfully created a PR in target-docs with the documentation changes." >> $GITHUB_STEP_SUMMARY
348- echo "" >> $GITHUB_STEP_SUMMARY
349- echo "### Details:" >> $GITHUB_STEP_SUMMARY
350- echo "- **Source PR**: #${{ steps.check_pr_commit.outputs.pr_number }} by @${{ steps.get_pr_info.outputs.pr_author }}" >> $GITHUB_STEP_SUMMARY
351- echo "- **Branch**: ${{ steps.create_branch.outputs.branch_name }}" >> $GITHUB_STEP_SUMMARY
352- echo "- **Base ref**: ${{ steps.get_pr_info.outputs.pr_base_ref }}" >> $GITHUB_STEP_SUMMARY
353- echo "- **Target repository**: ${{env.TARGET_REPO}}" >> $GITHUB_STEP_SUMMARY
354- fi
21+ uses : alaudadevops/run-actions/.github/workflows/reverse-sync-push.yml@main
22+ with :
23+ target_repo : alaudadevops/tektoncd-operator
24+ secrets :
25+ GH_TOKEN : ${{ secrets.GH_TOKEN }}
0 commit comments