@@ -21,157 +21,180 @@ inputs:
2121 automerge :
2222 description : ' If true, enable auto-merge on the PR'
2323 default : ' false'
24-
24+ template-ref :
25+ description : ' Tag or branch to check out from the template repository (overrides template-branch)'
26+ required : false
27+
2528runs :
2629 using : " composite"
2730 steps :
31+
32+ # ------------------------------------------------------------
33+ # Checkout target repo
34+ # ------------------------------------------------------------
2835 - name : Checkout the target repo
2936 uses : actions/checkout@v6
3037 with :
3138 token : ${{ inputs.token }}
3239 fetch-depth : 0
33- # persist-credentials: 'false'
3440
3541 - name : Ensure inside a git repository
3642 shell : bash
37- run : git rev-parse --is-inside-work-tree >/dev/null || { echo "❌ Not in a git repository"; exit 1; }
43+ run : git rev-parse --is-inside-work-tree >/dev/null || {
44+ echo "❌ Not in a git repository";
45+ exit 1;
46+ }
3847
48+ # ------------------------------------------------------------
49+ # Parse configuration (repository, branch, ref, includes, excludes)
50+ # ------------------------------------------------------------
3951 - name : Parse configuration file
4052 shell : bash
4153 id : config
4254 run : |
4355 CONFIG_FILE="${{ inputs.source }}"
4456 echo "Reading configuration from ${CONFIG_FILE}"
45-
46- if [ ! -f "${CONFIG_FILE}" ]; then
57+
58+ if [[ ! -f "${CONFIG_FILE}" ] ]; then
4759 echo "::error::Configuration file not found: ${CONFIG_FILE}"
4860 exit 1
4961 fi
50-
51- # Install yq if not available
52- if ! command -v yq &> /dev/null; then
53- echo "Installing yq..."
54- wget -qO /tmp/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
62+
63+ # Install yq if needed
64+ if ! command -v yq &>/dev/null; then
65+ wget -qO /tmp/yq https://github.com/mikefarah/yq/releases/download/v4.44.3/yq_linux_amd64
5566 chmod +x /tmp/yq
56- YQ_CMD ="/tmp/yq"
67+ YQ ="/tmp/yq"
5768 else
58- YQ_CMD ="yq"
69+ YQ ="yq"
5970 fi
60-
61- # Read values from config file
62- TEMPLATE_REPO=$($YQ_CMD '.template-repository' "${CONFIG_FILE}")
63- if [ "$TEMPLATE_REPO" = "null" ] || [ -z "$TEMPLATE_REPO" ]; then
64- echo "::error::template-repository not found in ${CONFIG_FILE}"
71+
72+ TEMPLATE_REPO="$($YQ '.template-repository // ""' "$CONFIG_FILE")"
73+ if [[ -z "$TEMPLATE_REPO" ]]; then
74+ echo "::error::template-repository missing in ${CONFIG_FILE}"
6575 exit 1
6676 fi
6777 echo "template_repository=$TEMPLATE_REPO" >> $GITHUB_OUTPUT
68-
69- TEMPLATE_BRANCH=$($YQ_CMD '.template-branch // "main"' "${ CONFIG_FILE}")
78+
79+ TEMPLATE_BRANCH=" $($YQ '.template-branch // "main"' "$CONFIG_FILE")"
7080 echo "template_branch=$TEMPLATE_BRANCH" >> $GITHUB_OUTPUT
81+
82+ TEMPLATE_REF="$($YQ '.template-ref // ""' "$CONFIG_FILE")"
83+ echo "template_ref=$TEMPLATE_REF" >> $GITHUB_OUTPUT
7184
72- # Read include and exclude patterns if present
73- INCLUDE=$($YQ_CMD '.include // ""' "${CONFIG_FILE}")
85+ # New: Tag/Ref override
86+ #TEMPLATE_REF_INPUT="${{ inputs.template-ref }}"
87+ #TEMPLATE_REF_CONFIG="$($YQ '.template-ref // ""' "$CONFIG_FILE")"
88+ #TEMPLATE_REF="${TEMPLATE_REF_INPUT:-$TEMPLATE_REF_CONFIG}"
89+ #echo "template_ref=$TEMPLATE_REF" >> $GITHUB_OUTPUT
90+
91+ # Include patterns
92+ INCLUDE="$($YQ '.include // ""' "$CONFIG_FILE")"
7493 echo "include<<EOF" >> $GITHUB_OUTPUT
7594 echo "$INCLUDE" >> $GITHUB_OUTPUT
7695 echo "EOF" >> $GITHUB_OUTPUT
77-
78- EXCLUDE=$($YQ_CMD '.exclude // ""' "${CONFIG_FILE}")
96+
97+ # Exclude patterns
98+ EXCLUDE="$($YQ '.exclude // ""' "$CONFIG_FILE")"
7999 echo "exclude<<EOF" >> $GITHUB_OUTPUT
80100 echo "$EXCLUDE" >> $GITHUB_OUTPUT
81101 echo "EOF" >> $GITHUB_OUTPUT
82102
103+ # ------------------------------------------------------------
104+ # Sparse checkout template (branch or tag -> ref)
105+ # ------------------------------------------------------------
83106 - name : Sparse checkout template
84107 uses : actions/checkout@v6
85108 with :
86109 repository : ${{ steps.config.outputs.template_repository }}
87- ref : ${{ steps.config.outputs.template_branch }}
110+ ref : ${{ steps.config.outputs.template_ref || steps.config.outputs. template_branch }}
88111 path : .template-temp
112+ token : ${{ inputs.token }}
113+ fetch-depth : 0
89114 sparse-checkout : ${{ steps.config.outputs.include }}
90115 sparse-checkout-cone-mode : false
91- fetch-depth : 0
92- token : ${{ inputs.token }}
93- # persist-credentials: 'false'
94116
117+ # ------------------------------------------------------------
118+ # Clean template and apply excludes
119+ # ------------------------------------------------------------
95120 - name : Clean template and apply excludes
96121 shell : bash
97122 working-directory : .template-temp
98123 run : |
99124 rm -rf .git
100- if [[ -n "${{ steps.config.outputs.exclude }}" ]]; then
101- while IFS= read -r item; do
125+ EXCLUDES="${{ steps.config.outputs.exclude }}"
126+
127+ if [[ -n "$EXCLUDES" ]]; then
128+ echo "$EXCLUDES" | while IFS= read -r item; do
129+ [[ -z "$item" ]] && continue
102130 item="$(echo "$item" | xargs)"
103- [ -z "$item" ] || rm -rf "$item" 2>/dev/null || true
104- done <<< "${{ steps.config.outputs.exclude }}"
131+ rm -rf "$item" 2>/dev/null || true
132+ done
105133 fi
134+
106135 tree -L 2 || ls -R
107136
137+ # ------------------------------------------------------------
138+ # Apply template + commit & push
139+ # ------------------------------------------------------------
108140 - name : Commit and optionally push changes
109141 id : commit-changes
110142 shell : bash
111143 env :
112- GITHUB_TOKEN : ${{ inputs.token }}
113144 TEST_MODE : ${{ inputs.test-mode }}
114145 run : |
115146 cp -R .template-temp/. .
116147 rm -rf .template-temp
117148
118149 git add -A
119- git status
150+
120151 if git diff --cached --quiet; then
121- echo "✅ No changes to commit"
122152 echo "changes_detected=false" >> $GITHUB_OUTPUT
153+ echo "No changes."
123154 exit 0
124155 fi
125-
156+
126157 echo "changes_detected=true" >> $GITHUB_OUTPUT
127158
128- # Warn if workflow files are modified
129- if git diff --cached --name-only | grep -q "^\.github/workflows/"; then
130- echo "⚠️ Workflow files detected. Use PAT with 'workflow' scope."
159+ if git diff --cached --name-only | grep -q '^\.github/workflows/'; then
160+ echo "⚠️ Workflow files modified — PAT with workflow scope required."
131161 fi
132162
133- git config user.name " github-actions[bot]"
134- git config user.email " 41898282+github-actions[bot]@users.noreply.github.com"
163+ git config user.name ' github-actions[bot]'
164+ git config user.email ' 41898282+github-actions[bot]@users.noreply.github.com'
135165 git commit -m "${{ inputs.commit-message }}"
136166
137- # Configure remote with token
138- # git remote set-url origin "https://x-access-token:${{ inputs.token }}@github.com/${{ github.repository }}.git"
139-
140- echo "✅ Remote after reset (masked):"
141- git remote -v | sed -E 's@(https://)[^@]+@\\1****@g'
142-
143- echo "🔁 Testing ls-remote with this token..."
144- git ls-remote --heads origin || echo "❌ ls-remote failed"
145-
146- if [[ "${TEST_MODE}" == "true" ]]; then
147- echo "🧪 Test mode: skipping push and PR creation"
148- else
149- echo "🚀 Pushing changes to branch '${{ inputs.branch }}'..."
150- if git push origin "HEAD:${{ inputs.branch }}" --force-with-lease; then
151- echo "✅ Sync complete"
152- else
153- echo "⚠️ Push failed. Check permissions."
154- exit 1
155- fi
167+ if [[ "$TEST_MODE" == "true" ]]; then
168+ echo "🧪 Test mode: skipping push"
169+ exit 0
156170 fi
157171
158- - name : Create Pull Request (if not in test mode and there are changes)
172+ target_branch="${{ inputs.branch }}"
173+ git push origin "HEAD:$target_branch" --force-with-lease
174+
175+ # ------------------------------------------------------------
176+ # Create Pull Request
177+ # ------------------------------------------------------------
178+ - name : Create Pull Request
159179 id : create-pr
160180 if : ${{ inputs.test-mode != 'true' && steps.commit-changes.outputs.changes_detected == 'true' }}
161181 uses : peter-evans/create-pull-request@v7
162182 with :
163183 token : ${{ inputs.token }}
164184 branch : ${{ inputs.branch }}
165185 commit-message : ${{ inputs.commit-message }}
166- title : " chore: sync template from ${{ steps.config.outputs.template_repository }}@${{ steps.config.outputs.template_branch }}"
186+ delete-branch : false
187+ title : " chore: sync template from ${{ steps.config.outputs.template_repository }}@${{ steps.config.outputs.template_ref || steps.config.outputs.template_branch }}"
167188 body : |
168- This PR updates configuration files from
169- [${{ steps.config.outputs.template_repository }}@${{ steps.config.outputs.template_branch }}](https://github.com/${{ steps.config.outputs.template_repository }}/tree/${{ steps.config.outputs.template_branch }}).
170- delete-branch : true
189+ This PR syncs the template from:
190+ **${{ steps.config.outputs.template_repository }} @ ${{ steps.config.outputs.template_ref || steps.config.outputs.template_branch }}**
171191
192+ # ------------------------------------------------------------
193+ # Auto-merge
194+ # ------------------------------------------------------------
172195 - name : Enable auto-merge
196+ if : ${{ inputs.automerge == 'true' && steps.create-pr.outputs.pull-request-number }}
173197 shell : bash
174- if : ${{ inputs.automerge == 'true' && steps.create-pr.outputs.pull-request-number != '' }}
175198 env :
176199 GH_TOKEN : ${{ inputs.token }}
177200 run : |
0 commit comments