main
yml 472 lines 23.7 KB
Raw
1 name: (Runtime) Commit Artifacts for Meta WWW and fbsource V2
2
3 on:
4 workflow_run:
5 workflows: ["(Runtime) Build and Test"]
6 types: [completed]
7 branches:
8 - main
9 workflow_dispatch:
10 inputs:
11 commit_sha:
12 required: false
13 type: string
14 force:
15 description: 'Force a commit to the builds/... branches'
16 required: true
17 default: false
18 type: boolean
19 dry_run:
20 description: Perform a dry run (run everything except push)
21 required: true
22 default: false
23 type: boolean
24
25 permissions: {}
26
27 env:
28 TZ: /usr/share/zoneinfo/America/Los_Angeles
29 # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout
30 SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
31
32 jobs:
33 download_artifacts:
34 runs-on: ubuntu-latest
35 permissions:
36 # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run
37 actions: read
38 steps:
39 - uses: actions/checkout@v4
40 - name: Cache node_modules
41 uses: actions/cache@v4
42 id: node_modules
43 with:
44 path: |
45 **/node_modules
46 key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
47 - name: Ensure clean build directory
48 run: rm -rf build
49 - run: yarn install --frozen-lockfile
50 if: steps.node_modules.outputs.cache-hit != 'true'
51 - run: yarn --cwd scripts/release install --frozen-lockfile
52 if: steps.node_modules.outputs.cache-hit != 'true'
53 - name: Download artifacts for base revision
54 run: |
55 GH_TOKEN=${{ github.token }} scripts/release/download-experimental-build.js --commit=${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }}
56 - name: Display structure of build
57 run: ls -R build
58 - name: Archive build
59 uses: actions/upload-artifact@v4
60 with:
61 name: build
62 path: build/
63 if-no-files-found: error
64
65
66 process_artifacts:
67 runs-on: ubuntu-latest
68 needs: [download_artifacts]
69 outputs:
70 www_branch_count: ${{ steps.check_branches.outputs.www_branch_count }}
71 fbsource_branch_count: ${{ steps.check_branches.outputs.fbsource_branch_count }}
72 last_version_classic: ${{ steps.get_last_version_www.outputs.last_version_classic }}
73 last_version_modern: ${{ steps.get_last_version_www.outputs.last_version_modern }}
74 last_version_rn: ${{ steps.get_last_version_rn.outputs.last_version_rn }}
75 current_version_classic: ${{ steps.get_current_version.outputs.current_version_classic }}
76 current_version_modern: ${{ steps.get_current_version.outputs.current_version_modern }}
77 current_version_rn: ${{ steps.get_current_version.outputs.current_version_rn }}
78 steps:
79 - uses: actions/checkout@v4
80 with:
81 ref: builds/facebook-www
82 - name: "Get last version string for www"
83 id: get_last_version_www
84 run: |
85 # Empty checks only needed for backwards compatibility,can remove later.
86 VERSION_CLASSIC=$( [ -f ./compiled/facebook-www/VERSION_CLASSIC ] && cat ./compiled/facebook-www/VERSION_CLASSIC || echo '' )
87 VERSION_MODERN=$( [ -f ./compiled/facebook-www/VERSION_MODERN ] && cat ./compiled/facebook-www/VERSION_MODERN || echo '' )
88 echo "Last classic version is $VERSION_CLASSIC"
89 echo "Last modern version is $VERSION_MODERN"
90 echo "last_version_classic=$VERSION_CLASSIC" >> "$GITHUB_OUTPUT"
91 echo "last_version_modern=$VERSION_MODERN" >> "$GITHUB_OUTPUT"
92 - uses: actions/checkout@v4
93 with:
94 ref: builds/facebook-fbsource
95 - name: "Get last version string for rn"
96 id: get_last_version_rn
97 run: |
98 # Empty checks only needed for backwards compatibility,can remove later.
99 VERSION_NATIVE_FB=$( [ -f ./compiled-rn/VERSION_NATIVE_FB ] && cat ./compiled-rn/VERSION_NATIVE_FB || echo '' )
100 echo "Last rn version is $VERSION_NATIVE_FB"
101 echo "last_version_rn=$VERSION_NATIVE_FB" >> "$GITHUB_OUTPUT"
102 - uses: actions/checkout@v4
103 - name: "Check branches"
104 id: check_branches
105 run: |
106 echo "www_branch_count=$(git ls-remote --heads origin "refs/heads/meta-www" | wc -l)" >> "$GITHUB_OUTPUT"
107 echo "fbsource_branch_count=$(git ls-remote --heads origin "refs/heads/meta-fbsource" | wc -l)" >> "$GITHUB_OUTPUT"
108 - name: Restore downloaded build
109 uses: actions/download-artifact@v4
110 with:
111 name: build
112 path: build
113 - name: Display structure of build
114 run: ls -R build
115 - name: Strip @license from eslint plugin and react-refresh
116 run: |
117 sed -i -e 's/ @license React*//' \
118 build/oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js \
119 build/facebook-www/ESLintPluginReactHooks-dev.modern.js \
120 build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js
121 - name: Insert @headers into eslint plugin and react-refresh
122 run: |
123 sed -i -e 's/ LICENSE file in the root directory of this source tree./ LICENSE file in the root directory of this source tree.\n *\n * @noformat\n * @nolint\n * @lightSyntaxTransform\n * @preventMunge\n * @oncall react_core/' \
124 build/oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js \
125 build/facebook-www/ESLintPluginReactHooks-dev.modern.js \
126 build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js
127 - name: Move relevant files for React in www into compiled
128 run: |
129 # Move the facebook-www folder into compiled
130 mkdir ./compiled
131 mv build/facebook-www ./compiled
132
133 # Move ReactAllWarnings.js to facebook-www
134 mkdir ./compiled/facebook-www/__test_utils__
135 mv build/__test_utils__/ReactAllWarnings.js ./compiled/facebook-www/__test_utils__/ReactAllWarnings.js
136
137 # Copy eslint-plugin-react-hooks (www build with feature flags)
138 mkdir ./compiled/eslint-plugin-react-hooks
139 cp ./compiled/facebook-www/ESLintPluginReactHooks-dev.modern.js \
140 ./compiled/eslint-plugin-react-hooks/index.js
141
142 # Move unstable_server-external-runtime.js into facebook-www
143 mv build/oss-experimental/react-dom/unstable_server-external-runtime.js \
144 ./compiled/facebook-www/unstable_server-external-runtime.js
145
146 # Move react-refresh-babel.development.js into babel-plugin-react-refresh
147 mkdir ./compiled/babel-plugin-react-refresh
148 mv build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js \
149 ./compiled/babel-plugin-react-refresh/index.js
150
151 ls -R ./compiled
152 - name: Move relevant files for React in fbsource into compiled-rn
153 run: |
154 BASE_FOLDER='compiled-rn/facebook-fbsource/xplat/js'
155 mkdir -p ${BASE_FOLDER}/react-native-github/Libraries/Renderer/
156 mkdir -p ${BASE_FOLDER}/RKJSModules/vendor/react/{scheduler,react,react-dom,react-is,react-test-renderer}/
157
158 # Move React Native renderer
159 mv build/react-native/implementations/ $BASE_FOLDER/react-native-github/Libraries/Renderer/
160 mv build/react-native/shims/ $BASE_FOLDER/react-native-github/Libraries/Renderer/
161 mv build/facebook-react-native/scheduler/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/scheduler/
162 mv build/facebook-react-native/react/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/react/
163 mv build/facebook-react-native/react-dom/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/react-dom/
164 mv build/facebook-react-native/react-is/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/react-is/
165 mv build/facebook-react-native/react-test-renderer/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/react-test-renderer/
166
167 # Delete the OSS renderers, these are sync'd to RN separately.
168 RENDERER_FOLDER=$BASE_FOLDER/react-native-github/Libraries/Renderer/implementations/
169 rm $RENDERER_FOLDER/ReactFabric-{dev,prod,profiling}.js
170
171 # Copy eslint-plugin-react-hooks
172 # NOTE: This is different from www, here we include the full package
173 # including package.json to include dependencies in fbsource.
174 mkdir "$BASE_FOLDER/tools"
175 cp -r build/oss-experimental/eslint-plugin-react-hooks "$BASE_FOLDER/tools"
176
177 # Move React Native version file
178 mv build/facebook-react-native/VERSION_NATIVE_FB ./compiled-rn/VERSION_NATIVE_FB
179
180 ls -R ./compiled-rn
181 - name: Add REVISION files
182 run: |
183 echo ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} >> ./compiled/facebook-www/REVISION
184 cp ./compiled/facebook-www/REVISION ./compiled/facebook-www/REVISION_TRANSFORMS
185 echo ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} >> ./compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/REVISION
186 - name: "Get current version string"
187 id: get_current_version
188 run: |
189 VERSION_CLASSIC=$(cat ./compiled/facebook-www/VERSION_CLASSIC)
190 VERSION_MODERN=$(cat ./compiled/facebook-www/VERSION_MODERN)
191 VERSION_NATIVE_FB=$(cat ./compiled-rn/VERSION_NATIVE_FB)
192 echo "Current classic version is $VERSION_CLASSIC"
193 echo "Current modern version is $VERSION_MODERN"
194 echo "Current rn version is $VERSION_NATIVE_FB"
195 echo "current_version_classic=$VERSION_CLASSIC" >> "$GITHUB_OUTPUT"
196 echo "current_version_modern=$VERSION_MODERN" >> "$GITHUB_OUTPUT"
197 echo "current_version_rn=$VERSION_NATIVE_FB" >> "$GITHUB_OUTPUT"
198 - uses: actions/upload-artifact@v4
199 with:
200 name: compiled
201 path: compiled/
202 if-no-files-found: error
203 - uses: actions/upload-artifact@v4
204 with:
205 name: compiled-rn
206 path: compiled-rn/
207 if-no-files-found: error
208
209 commit_www_artifacts:
210 needs: [download_artifacts, process_artifacts]
211 if: inputs.force == true || (github.ref == 'refs/heads/main' && needs.process_artifacts.outputs.www_branch_count == '0')
212 runs-on: ubuntu-latest
213 permissions:
214 # Used to push a commit to builds/facebook-www
215 contents: write
216 steps:
217 - uses: actions/checkout@v4
218 with:
219 ref: builds/facebook-www
220 - name: Ensure clean directory
221 run: rm -rf compiled
222 - uses: actions/download-artifact@v4
223 with:
224 name: compiled
225 path: compiled/
226 - name: Revert version changes
227 if: needs.process_artifacts.outputs.last_version_classic != '' && needs.process_artifacts.outputs.last_version_modern != ''
228 env:
229 CURRENT_VERSION_CLASSIC: ${{ needs.process_artifacts.outputs.current_version_classic }}
230 CURRENT_VERSION_MODERN: ${{ needs.process_artifacts.outputs.current_version_modern }}
231 LAST_VERSION_CLASSIC: ${{ needs.process_artifacts.outputs.last_version_classic }}
232 LAST_VERSION_MODERN: ${{ needs.process_artifacts.outputs.last_version_modern }}
233 run: |
234 echo "Reverting $CURRENT_VERSION_CLASSIC to $LAST_VERSION_CLASSIC"
235 grep -rl "$CURRENT_VERSION_CLASSIC" ./compiled || echo "No files found with $CURRENT_VERSION_CLASSIC"
236 grep -rl "$CURRENT_VERSION_CLASSIC" ./compiled | xargs -r sed -i -e "s/$CURRENT_VERSION_CLASSIC/$LAST_VERSION_CLASSIC/g"
237 grep -rl "$CURRENT_VERSION_CLASSIC" ./compiled || echo "Classic version reverted"
238 echo "===================="
239 echo "Reverting $CURRENT_VERSION_MODERN to $LAST_VERSION_MODERN"
240 grep -rl "$CURRENT_VERSION_MODERN" ./compiled || echo "No files found with $CURRENT_VERSION_MODERN"
241 grep -rl "$CURRENT_VERSION_MODERN" ./compiled | xargs -r sed -i -e "s/$CURRENT_VERSION_MODERN/$LAST_VERSION_MODERN/g"
242 grep -rl "$CURRENT_VERSION_MODERN" ./compiled || echo "Modern version reverted"
243 - name: Check for changes
244 if: inputs.force != true
245 id: check_should_commit
246 run: |
247 echo "Full git status"
248 git add .
249 git status
250 echo "===================="
251 if git status --porcelain | grep -qv '/REVISION'; then
252 echo "Changes detected"
253 echo "===== Changes ====="
254 git --no-pager diff -U0 | grep '^[+-]' | head -n 50
255 echo "==================="
256 echo "should_commit=true" >> "$GITHUB_OUTPUT"
257 else
258 echo "No Changes detected"
259 echo "should_commit=false" >> "$GITHUB_OUTPUT"
260 fi
261 - name: Re-apply version changes
262 if: inputs.force == true || (steps.check_should_commit.outputs.should_commit == 'true' && needs.process_artifacts.outputs.last_version_classic != '' && needs.process_artifacts.outputs.last_version_modern != '')
263 env:
264 CURRENT_VERSION_CLASSIC: ${{ needs.process_artifacts.outputs.current_version_classic }}
265 CURRENT_VERSION_MODERN: ${{ needs.process_artifacts.outputs.current_version_modern }}
266 LAST_VERSION_CLASSIC: ${{ needs.process_artifacts.outputs.last_version_classic }}
267 LAST_VERSION_MODERN: ${{ needs.process_artifacts.outputs.last_version_modern }}
268 run: |
269 echo "Re-applying $LAST_VERSION_CLASSIC to $CURRENT_VERSION_CLASSIC"
270 grep -rl "$LAST_VERSION_CLASSIC" ./compiled || echo "No files found with $LAST_VERSION_CLASSIC"
271 grep -rl "$LAST_VERSION_CLASSIC" ./compiled | xargs -r sed -i -e "s/$LAST_VERSION_CLASSIC/$CURRENT_VERSION_CLASSIC/g"
272 grep -rl "$LAST_VERSION_CLASSIC" ./compiled || echo "Classic version re-applied"
273 echo "===================="
274 echo "Re-applying $LAST_VERSION_MODERN to $CURRENT_VERSION_MODERN"
275 grep -rl "$LAST_VERSION_MODERN" ./compiled || echo "No files found with $LAST_VERSION_MODERN"
276 grep -rl "$LAST_VERSION_MODERN" ./compiled | xargs -r sed -i -e "s/$LAST_VERSION_MODERN/$CURRENT_VERSION_MODERN/g"
277 grep -rl "$LAST_VERSION_MODERN" ./compiled || echo "Classic version re-applied"
278 - name: Will commit these changes
279 if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'
280 run: |
281 git add .
282 git status
283 - name: Check commit message
284 if: inputs.dry_run
285 run: |
286 git fetch origin --quiet
287 git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:"%B"
288 - name: Commit changes to branch
289 if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'
290 run: |
291 git config --global user.email "${{ format('{0}@users.noreply.github.com', github.triggering_actor) }}"
292 git config --global user.name "${{ github.triggering_actor }}"
293
294 git fetch origin --quiet
295 git commit -m "$(git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:'%B%n%nDiffTrain build for [${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }}](https://github.com/react/react/commit/${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha}})')" || echo "No changes to commit"
296 - name: Push changes to branch
297 if: inputs.dry_run == false && (inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true')
298 run: git push
299
300 commit_fbsource_artifacts:
301 needs: [download_artifacts, process_artifacts]
302 permissions:
303 # Used to push a commit to builds/facebook-fbsource
304 contents: write
305 if: inputs.force == true || (github.ref == 'refs/heads/main' && needs.process_artifacts.outputs.fbsource_branch_count == '0')
306 runs-on: ubuntu-latest
307 steps:
308 - uses: actions/checkout@v4
309 with:
310 ref: builds/facebook-fbsource
311 - name: Ensure clean directory
312 run: rm -rf compiled-rn
313 - uses: actions/download-artifact@v4
314 with:
315 name: compiled-rn
316 path: compiled-rn/
317 - name: Revert version changes
318 if: needs.process_artifacts.outputs.last_version_rn != ''
319 env:
320 CURRENT_VERSION: ${{ needs.process_artifacts.outputs.current_version_rn }}
321 LAST_VERSION: ${{ needs.process_artifacts.outputs.last_version_rn }}
322 run: |
323 echo "Reverting $CURRENT_VERSION to $LAST_VERSION"
324 grep -rl "$CURRENT_VERSION" ./compiled-rn || echo "No files found with $CURRENT_VERSION"
325 grep -rl "$CURRENT_VERSION" ./compiled-rn | xargs -r sed -i -e "s/$CURRENT_VERSION/$LAST_VERSION/g"
326 grep -rl "$CURRENT_VERSION" ./compiled-rn || echo "Version reverted"
327 - name: Check for changes
328 if: inputs.force != 'true'
329 id: check_should_commit
330 run: |
331 echo "Full git status"
332 git add .
333 git --no-pager diff -U0 --cached | grep '^[+-]' | head -n 100
334 echo "===================="
335 # Ignore REVISION or lines removing @generated headers.
336 if git diff --cached ':(exclude)*REVISION' ':(exclude)*/eslint-plugin-react-hooks/package.json' | grep -vE "^(@@|diff|index|\-\-\-|\+\+\+|\- \* @generated SignedSource)" | grep "^[+-]" > /dev/null; then
337 echo "Changes detected"
338 echo "===== Changes ====="
339 git --no-pager diff --cached ':(exclude)*REVISION' ':(exclude)*/eslint-plugin-react-hooks/package.json' | grep -vE "^(@@|diff|index|\-\-\-|\+\+\+|\- \* @generated SignedSource)" | grep "^[+-]" | head -n 50
340 echo "==================="
341 echo "should_commit=true" >> "$GITHUB_OUTPUT"
342 else
343 echo "No Changes detected"
344 echo "should_commit=false" >> "$GITHUB_OUTPUT"
345 fi
346 - name: Re-apply version changes
347 if: inputs.force == true || (steps.check_should_commit.outputs.should_commit == 'true' && needs.process_artifacts.outputs.last_version_rn != '')
348 env:
349 CURRENT_VERSION: ${{ needs.process_artifacts.outputs.current_version_rn }}
350 LAST_VERSION: ${{ needs.process_artifacts.outputs.last_version_rn }}
351 run: |
352 echo "Re-applying $LAST_VERSION to $CURRENT_VERSION"
353 grep -rl "$LAST_VERSION" ./compiled-rn || echo "No files found with $LAST_VERSION"
354 grep -rl "$LAST_VERSION" ./compiled-rn | xargs -r sed -i -e "s/$LAST_VERSION/$CURRENT_VERSION/g"
355 grep -rl "$LAST_VERSION" ./compiled-rn || echo "Version re-applied"
356 - name: Add files for signing
357 if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'
358 run: |
359 echo ":"
360 git add .
361 - name: Signing files
362 if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'
363 uses: actions/github-script@v7
364 with:
365 script: |
366 // TODO: Move this to a script file.
367 // We currently can't call scripts from the repo because
368 // at this point in the workflow, we're on the compiled
369 // artifact branch (so the scripts don't exist).
370 // We can fix this with a composite action in the main repo.
371 // This script is duplicated above.
372 const fs = require('fs');
373 const crypto = require('crypto');
374 const {execSync} = require('child_process');
375
376 // TODO: when we move this to a script, we can use this from npm.
377 // Copy of signedsource since we can't install deps on this branch.
378 const GENERATED = '@' + 'generated';
379 const NEWTOKEN = '<<SignedSource::*O*zOeWoEQle#+L!plEphiEmie@IsG>>';
380 const PATTERN = new RegExp(`${GENERATED} (?:SignedSource<<([a-f0-9]{32})>>)`);
381
382 const TokenNotFoundError = new Error(
383 `SignedSource.signFile(...): Cannot sign file without token: ${NEWTOKEN}`
384 );
385
386 function hash(data, encoding) {
387 const md5sum = crypto.createHash('md5');
388 md5sum.update(data, encoding);
389 return md5sum.digest('hex');
390 }
391
392 const SignedSource = {
393 getSigningToken() {
394 return `${GENERATED} ${NEWTOKEN}`;
395 },
396 isSigned(data) {
397 return PATTERN.exec(data) != null;
398 },
399 signFile(data) {
400 if (!data.includes(NEWTOKEN)) {
401 if (SignedSource.isSigned(data)) {
402 // Signing a file that was previously signed.
403 data = data.replace(PATTERN, SignedSource.getSigningToken());
404 } else {
405 throw TokenNotFoundError;
406 }
407 }
408 return data.replace(NEWTOKEN, `SignedSource<<${hash(data, 'utf8')}>>`);
409 },
410 };
411
412 const directory = './compiled-rn';
413 console.log('Signing files in directory:', directory);
414 try {
415 const result = execSync(`git status --porcelain ${directory}`, {encoding: 'utf8'});
416 console.log(result);
417
418 // Parse the git status output to get file paths!
419 const files = result.split('\n').filter(file => file.endsWith('.js'));
420
421 if (files.length === 0) {
422 throw new Error(
423 'git status returned no files to sign. this job should not have run.'
424 );
425 } else {
426 files.forEach(line => {
427 let file = null;
428 if (line.startsWith('D ')) {
429 return;
430 } else if (line.startsWith('R ')) {
431 file = line.slice(line.indexOf('->') + 3);
432 } else {
433 file = line.slice(3).trim();
434 }
435 if (file) {
436 console.log(' Signing file:', file);
437 const originalContents = fs.readFileSync(file, 'utf8');
438 const signedContents = SignedSource.signFile(
439 originalContents
440 // Need to add the header in, since it's not inserted at build time.
441 .replace(' */\n', ` * ${SignedSource.getSigningToken()}\n */\n`)
442 );
443
444 fs.writeFileSync(file, signedContents, 'utf8');
445 }
446 });
447 }
448 } catch (e) {
449 process.exitCode = 1;
450 console.error('Error signing files:', e);
451 }
452 - name: Will commit these changes
453 if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'
454 run: |
455 git add .
456 git status
457 - name: Check commit message
458 if: inputs.dry_run
459 run: |
460 git fetch origin --quiet
461 git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:"%B"
462 - name: Commit changes to branch
463 if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'
464 run: |
465 git config --global user.email "${{ format('{0}@users.noreply.github.com', github.triggering_actor) }}"
466 git config --global user.name "${{ github.triggering_actor }}"
467
468 git fetch origin --quiet
469 git commit -m "$(git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:'%B%n%nDiffTrain build for [${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }}](https://github.com/react/react/commit/${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha}})')" || echo "No changes to commit"
470 - name: Push changes to branch
471 if: inputs.dry_run == false && (inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true')
472 run: git push