@@ -7,11 +7,9 @@ name: "python / emitter diff"
77# how an emitter change affects generated SDKs. Powered by the language-agnostic
88# eng/emitter-diff tool.
99#
10- # The check fails while generated output differs from the baseline UNTIL a
11- # maintainer adds the `emitter-diff-approved` label to the PR. The label (not a
12- # committed SHA) is the approval token, so it survives squash-merge / rebase /
13- # force-push, and the check re-runs automatically when the label is added or
14- # removed.
10+ # This check is informational: it always passes unless the tool hits a real
11+ # tool/build error. A generated-output diff does not fail the PR — it is only
12+ # reported (job summary + PR comment + HTML artifact) for reviewers to eyeball.
1513#
1614# Python's generator uses a native two-phase pipeline (TypeSpec emits YAML, then
1715# a batched Python subprocess writes the .py files) with a venv co-located with
@@ -20,7 +18,6 @@ name: "python / emitter diff"
2018
2119on :
2220 pull_request :
23- types : [opened, synchronize, reopened, labeled, unlabeled]
2421 branches :
2522 - main
2623 - release/*
@@ -112,42 +109,29 @@ jobs:
112109 # propagates. `pnpm --filter <pkg> exec` collapses any non-zero child exit
113110 # into pnpm's own generic exit 1 (ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL),
114111 # which would mask the "diff present" code (2) as a hard error (1).
112+ # No `--fail-on-diff`: this check is informational and never fails on a
113+ # diff. A real tool/build error still surfaces via a non-zero exit code
114+ # (checked in the "Fail on tool error" step below).
115115 pnpm exec tsx src/cli.ts \
116116 --emitter python \
117117 --baseline "$BASELINE_REF" \
118118 --work-dir "$RUNNER_TEMP/emitter-diff" \
119119 --html "$RUNNER_TEMP/emitter-diff.html" \
120120 --patch "$RUNNER_TEMP/emitter-diff.patch" \
121- --fail-on-diff \
122121 | tee "$RUNNER_TEMP/emitter-diff.log"
123122 echo "status=${PIPESTATUS[0]}" >> "$GITHUB_OUTPUT"
124123
125124 - name : Write job summary
126125 if : always()
127126 env :
128127 BASELINE_SHA : ${{ steps.baseline.outputs.sha }}
129- STATUS : ${{ steps.diff.outputs.status }}
130- APPROVED : ${{ contains(github.event.pull_request.labels.*.name, 'emitter-diff-approved') }}
131128 RUNNER_TEMP : ${{ runner.temp }}
132129 run : |
133130 {
134131 echo "## Emitter diff"
135132 echo ""
136133 echo "Baseline (merge-base): \`$BASELINE_SHA\` vs current checkout."
137134 echo ""
138- if [ "$STATUS" = "2" ]; then
139- if [ "$APPROVED" = "true" ]; then
140- echo "**Generated output changed** — approved via the \`emitter-diff-approved\` label."
141- else
142- echo "**Generated output changed vs the baseline.**"
143- echo ""
144- echo "If this change is intended, add the \`emitter-diff-approved\` label to this PR"
145- echo "to accept it."
146- fi
147- elif [ "$STATUS" = "0" ]; then
148- echo "Generated output matches the baseline."
149- fi
150- echo ""
151135 echo '```'
152136 grep -E "Diff summary:" "$RUNNER_TEMP/emitter-diff.log" || echo "No summary captured."
153137 echo '```'
@@ -171,7 +155,6 @@ jobs:
171155 env :
172156 BASELINE : ${{ steps.baseline.outputs.sha }}
173157 STATUS : ${{ steps.diff.outputs.status }}
174- APPROVED : ${{ contains(github.event.pull_request.labels.*.name, 'emitter-diff-approved') }}
175158 PATCH_FILE : ${{ runner.temp }}/emitter-diff.patch
176159 HTML_FILE : ${{ runner.temp }}/emitter-diff.html
177160 with :
@@ -180,7 +163,6 @@ jobs:
180163 const marker = "<!-- emitter-diff-python -->";
181164 const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
182165 const status = process.env.STATUS;
183- const approved = process.env.APPROVED === "true";
184166
185167 // Parse the unified patch directly so the numbers match the tool exactly.
186168 let patch = "";
@@ -194,32 +176,27 @@ jobs:
194176 else if (line.startsWith("+") && !line.startsWith("+++")) insertions++;
195177 else if (line.startsWith("-") && !line.startsWith("---")) deletions++;
196178 }
179+ const hasChanges = patch.trim().length > 0;
197180 const htmlExists = fs.existsSync(process.env.HTML_FILE);
198181
199182 let body = `${marker}\n## Python emitter diff\n\n` +
200183 `Baseline \`${process.env.BASELINE}\` (merge-base) vs this PR's checkout.\n\n`;
201- if (status !== "0" && status !== "2" ) {
184+ if (status !== "0") {
202185 // Hard error (build/venv/generate threw) — not a diff. Don't claim "no changes".
203186 body += `**emitter-diff failed to run** (exit \`${status}\`). This is a tool/build ` +
204187 `error, not a generated-output diff. See the ` +
205188 `[workflow run](${runUrl}) logs` +
206189 (htmlExists ? ` and the **emitter-diff-html** artifact` : "") + `.\n`;
207- } else if (status === "0" ) {
190+ } else if (!hasChanges ) {
208191 body += `**No changes** — generated output matches the baseline.\n`;
209192 } else {
210193 body += `**${files.length} file(s) changed** · +${insertions} / -${deletions}\n\n`;
211194 if (htmlExists) {
212195 body += `Download the **emitter-diff-html** artifact from the ` +
213- `[workflow run](${runUrl}) for the full side-by-side rendered diff.\n\n`;
214- }
215- if (approved) {
216- body += `This change is **approved** via the \`emitter-diff-approved\` label.\n`;
217- } else {
218- body += `**This check fails until the change is approved.** If the new output is ` +
219- `intended, add the \`emitter-diff-approved\` label to this PR to accept it.\n`;
196+ `[workflow run](${runUrl}) for the full side-by-side rendered diff.\n`;
220197 }
221198 }
222- body += `\n_Generated by \`eng/emitter-diff\`._`;
199+ body += `\n_Generated by \`eng/emitter-diff\`. This check is informational and does not block the PR. _`;
223200
224201 const { owner, repo } = context.repo;
225202 const issue_number = context.issue.number;
@@ -231,32 +208,16 @@ jobs:
231208 await github.rest.issues.createComment({ owner, repo, issue_number, body });
232209 }
233210
234- - name : Enforce approval
211+ - name : Fail on tool error
235212 if : always()
236213 env :
237214 STATUS : ${{ steps.diff.outputs.status }}
238- APPROVED : ${{ contains(github.event.pull_request.labels.*.name, 'emitter-diff-approved') }}
239- BASELINE_SHA : ${{ steps.baseline.outputs.sha }}
240215 run : |
241- # Hard tool/build failure (not a diff) always fails.
242- if [ "$STATUS" != "0" ] && [ "$STATUS" != "2" ]; then
243- echo "::error::emitter-diff failed (exit $STATUS). See the log and artifact."
244- exit 1
245- fi
246- # Only PRs carry the approval label; manual/dispatch runs are informational.
247- if [ "$GITHUB_EVENT_NAME" != "pull_request" ]; then
248- echo "Not a pull_request event; skipping the approval gate."
249- exit 0
250- fi
251- if [ "$STATUS" = "2" ]; then
252- if [ "$APPROVED" = "true" ]; then
253- echo "Generated output differs from the baseline ($BASELINE_SHA), but the PR carries"
254- echo "the 'emitter-diff-approved' label. Passing."
255- exit 0
256- fi
257- echo "::error::Generated output differs from the baseline ($BASELINE_SHA)."
258- echo "Review the emitter-diff-html artifact. If the change is intended, add the"
259- echo "'emitter-diff-approved' label to this PR to accept it."
216+ # Informational check: a generated-output diff does NOT fail the PR
217+ # (the tool is run without --fail-on-diff, so a diff still exits 0).
218+ # Only a real tool/build error (non-zero exit) fails the job.
219+ if [ "$STATUS" != "0" ]; then
220+ echo "::error::emitter-diff failed (exit $STATUS). See the log and the emitter-diff-html artifact."
260221 exit 1
261222 fi
262- echo "Generated output matches the baseline ."
223+ echo "emitter-diff ran successfully (informational; diffs are reported, not enforced) ."
0 commit comments