|
1 | | -name: Template Compatibility |
| 1 | +name: Template Compatibility Check |
2 | 2 |
|
3 | 3 | on: |
4 | 4 | pull_request: |
|
13 | 13 |
|
14 | 14 | permissions: |
15 | 15 | contents: read |
16 | | - pull-requests: write |
17 | 16 |
|
18 | 17 | jobs: |
19 | 18 | template-compatibility: |
20 | 19 | runs-on: ubuntu-latest |
21 | | - # Only run on PRs (not push to main) |
22 | | - if: github.event_name == 'pull_request' |
23 | 20 |
|
24 | 21 | defaults: |
25 | 22 | run: |
26 | 23 | shell: bash {0} |
27 | 24 |
|
28 | 25 | env: |
29 | 26 | TEMPLATES_REPO: smartcontractkit/cre-templates |
30 | | - # Convention: a matching branch in cre-templates named compat/<sdk-branch> |
31 | | - # allows coordinated breaking changes without blocking the SDK PR. |
32 | | - COMPAT_BRANCH: compat/${{ github.head_ref }} |
33 | 27 |
|
34 | 28 | steps: |
35 | 29 | - name: Checkout SDK |
|
74 | 68 | id: detect-ref |
75 | 69 | env: |
76 | 70 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 71 | + HEAD_REF: ${{ github.head_ref }} |
77 | 72 | run: | |
| 73 | + SAFE_HEAD_REF="${HEAD_REF//[^a-zA-Z0-9._\/-]/}" |
| 74 | + COMPAT_BRANCH="compat/$SAFE_HEAD_REF" |
| 75 | +
|
78 | 76 | if gh api "repos/$TEMPLATES_REPO/branches/$COMPAT_BRANCH" &>/dev/null; then |
79 | 77 | echo "ref=$COMPAT_BRANCH" >> "$GITHUB_OUTPUT" |
80 | 78 | echo "Using compat branch: $COMPAT_BRANCH" |
@@ -106,102 +104,40 @@ jobs: |
106 | 104 | EXIT_CODE=$? |
107 | 105 | set -e |
108 | 106 |
|
109 | | - # Save output to a file for the comment step |
110 | 107 | echo "$OUTPUT" > /tmp/template-check-output.txt |
111 | 108 |
|
112 | 109 | # Surface it in the action log regardless |
113 | 110 | echo "$OUTPUT" |
114 | 111 |
|
115 | 112 | echo "exit_code=$EXIT_CODE" >> "$GITHUB_OUTPUT" |
116 | 113 |
|
117 | | - # Only post a comment when templates are broken. |
118 | | - # The comment is updated (not duplicated) on subsequent pushes. |
119 | | - - name: Post failure comment on PR |
120 | | - if: steps.template-check.outputs.exit_code != '0' |
121 | | - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 |
122 | | - with: |
123 | | - script: | |
124 | | - const fs = require('fs'); |
125 | | - const fullOutput = fs.readFileSync('/tmp/template-check-output.txt', 'utf8'); |
126 | | -
|
127 | | - // Extract just the "Results" and "Failure Details" sections |
128 | | - const resultsMatch = fullOutput.match(/={8,}\nResults:.*\n={8,}[\s\S]*/); |
129 | | - const failureSummary = resultsMatch ? resultsMatch[0].trim() : fullOutput.trim(); |
130 | | -
|
131 | | - const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; |
132 | | - const templatesRef = '${{ steps.detect-ref.outputs.ref }}'; |
133 | | - const refNote = templatesRef === 'main' |
134 | | - ? 'tested against `cre-templates:main`' |
135 | | - : `tested against \`cre-templates:${templatesRef}\` (compat branch)`; |
136 | | -
|
137 | | - const body = [ |
138 | | - '## ⚠️ Template Compatibility Failures', |
139 | | - '', |
140 | | - `This PR breaks one or more templates in [cre-templates](https://github.com/${{ env.TEMPLATES_REPO }}) (${refNote}).`, |
141 | | - '', |
142 | | - '```', |
143 | | - failureSummary, |
144 | | - '```', |
145 | | - '', |
146 | | - `[View full output →](${runUrl})`, |
147 | | - '', |
148 | | - '<details>', |
149 | | - '<summary>What should I do?</summary>', |
150 | | - '', |
151 | | - '- **Accidental break:** Fix the SDK change so existing templates continue to compile.', |
152 | | - '- **Intentional breaking change:** Create a branch in `cre-templates` named `compat/${{ github.head_ref }}` with the template fixes applied. This job will automatically retest against that branch.', |
153 | | - '', |
154 | | - '</details>', |
155 | | - ].join('\n'); |
156 | | -
|
157 | | - const marker = '<!-- template-compat-comment -->'; |
158 | | - const commentBody = `${marker}\n${body}`; |
159 | | -
|
160 | | - // Update existing comment if present, otherwise create a new one |
161 | | - const { data: comments } = await github.rest.issues.listComments({ |
162 | | - owner: context.repo.owner, |
163 | | - repo: context.repo.repo, |
164 | | - issue_number: context.issue.number, |
165 | | - }); |
166 | | -
|
167 | | - const existing = comments.find(c => c.body.includes(marker)); |
168 | | - if (existing) { |
169 | | - await github.rest.issues.updateComment({ |
170 | | - owner: context.repo.owner, |
171 | | - repo: context.repo.repo, |
172 | | - comment_id: existing.id, |
173 | | - body: commentBody, |
174 | | - }); |
175 | | - } else { |
176 | | - await github.rest.issues.createComment({ |
177 | | - owner: context.repo.owner, |
178 | | - repo: context.repo.repo, |
179 | | - issue_number: context.issue.number, |
180 | | - body: commentBody, |
181 | | - }); |
182 | | - } |
183 | | -
|
184 | | - # If a prior push had failures but this push fixes them, remove the stale comment |
185 | | - - name: Remove stale failure comment (if now passing) |
186 | | - if: steps.template-check.outputs.exit_code == '0' |
187 | | - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 |
| 114 | + # Bundle everything the comment workflow needs into an artifact. |
| 115 | + # The comment workflow runs with pull-requests: write but must never |
| 116 | + # execute external code — it only reads these files. |
| 117 | + - name: Save results for comment workflow |
| 118 | + if: always() |
| 119 | + env: |
| 120 | + PR_NUMBER: ${{ github.event.pull_request.number }} |
| 121 | + TEMPLATES_REF: ${{ steps.detect-ref.outputs.ref }} |
| 122 | + HEAD_REF: ${{ github.head_ref }} |
| 123 | + EXIT_CODE: ${{ steps.template-check.outputs.exit_code }} |
| 124 | + run: | |
| 125 | + mkdir -p /tmp/compat-results |
| 126 | + printf '%s' "$PR_NUMBER" > /tmp/compat-results/pr-number.txt |
| 127 | + printf '%s' "$TEMPLATES_REF" > /tmp/compat-results/templates-ref.txt |
| 128 | + printf '%s' "$HEAD_REF" > /tmp/compat-results/head-ref.txt |
| 129 | + printf '%s' "$EXIT_CODE" > /tmp/compat-results/exit-code.txt |
| 130 | + if [ -f /tmp/template-check-output.txt ]; then |
| 131 | + cp /tmp/template-check-output.txt /tmp/compat-results/output.txt |
| 132 | + fi |
| 133 | +
|
| 134 | + - name: Upload results artifact |
| 135 | + if: always() |
| 136 | + uses: actions/upload-artifact@ea165f8d68b2b1dc5da8e1af90a2a8f427aa4185 # v4.6.2 |
188 | 137 | with: |
189 | | - script: | |
190 | | - const marker = '<!-- template-compat-comment -->'; |
191 | | - const { data: comments } = await github.rest.issues.listComments({ |
192 | | - owner: context.repo.owner, |
193 | | - repo: context.repo.repo, |
194 | | - issue_number: context.issue.number, |
195 | | - }); |
196 | | -
|
197 | | - const existing = comments.find(c => c.body.includes(marker)); |
198 | | - if (existing) { |
199 | | - await github.rest.issues.deleteComment({ |
200 | | - owner: context.repo.owner, |
201 | | - repo: context.repo.repo, |
202 | | - comment_id: existing.id, |
203 | | - }); |
204 | | - } |
| 138 | + name: template-compat-results |
| 139 | + path: /tmp/compat-results/ |
| 140 | + retention-days: 7 |
205 | 141 |
|
206 | 142 | # Always exit 0 — this job is informational, not a merge gate |
207 | 143 | - name: Report result (non-blocking) |
|
0 commit comments