1name: (Runtime) Commit Artifacts for Meta WWW and fbsource V223on:4 workflow_run:5 workflows: ["(Runtime) Build and Test"]6 types: [completed]7 branches:8 - main9 workflow_dispatch:10 inputs:11 commit_sha:12 required: false13 type: string14 force:15 description: 'Force a commit to the builds/... branches'16 required: true17 default: false18 type: boolean19 dry_run:20 description: Perform a dry run (run everything except push)21 required: true22 default: false23 type: boolean2425permissions: {}2627env:28 TZ: /usr/share/zoneinfo/America/Los_Angeles29 # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout30 SEGMENT_DOWNLOAD_TIMEOUT_MINS: 13132jobs:33 download_artifacts:34 runs-on: ubuntu-latest35 permissions:36 # We use github.token to download the build artifact from a previous runtime_build_and_test.yml run37 actions: read38 steps:39 - uses: actions/checkout@v440 - name: Cache node_modules41 uses: actions/cache@v442 id: node_modules43 with:44 path: |45 **/node_modules46 key: runtime-release-node_modules-v6-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}47 - name: Ensure clean build directory48 run: rm -rf build49 - run: yarn install --frozen-lockfile50 if: steps.node_modules.outputs.cache-hit != 'true'51 - run: yarn --cwd scripts/release install --frozen-lockfile52 if: steps.node_modules.outputs.cache-hit != 'true'53 - name: Download artifacts for base revision54 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 build57 run: ls -R build58 - name: Archive build59 uses: actions/upload-artifact@v460 with:61 name: build62 path: build/63 if-no-files-found: error646566 process_artifacts:67 runs-on: ubuntu-latest68 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@v480 with:81 ref: builds/facebook-www82 - name: "Get last version string for www"83 id: get_last_version_www84 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@v493 with:94 ref: builds/facebook-fbsource95 - name: "Get last version string for rn"96 id: get_last_version_rn97 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@v4103 - name: "Check branches"104 id: check_branches105 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 build109 uses: actions/download-artifact@v4110 with:111 name: build112 path: build113 - name: Display structure of build114 run: ls -R build115 - name: Strip @license from eslint plugin and react-refresh116 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.js121 - name: Insert @headers into eslint plugin and react-refresh122 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.js127 - name: Move relevant files for React in www into compiled128 run: |129 # Move the facebook-www folder into compiled130 mkdir ./compiled131 mv build/facebook-www ./compiled132133 # Move ReactAllWarnings.js to facebook-www134 mkdir ./compiled/facebook-www/__test_utils__135 mv build/__test_utils__/ReactAllWarnings.js ./compiled/facebook-www/__test_utils__/ReactAllWarnings.js136137 # Copy eslint-plugin-react-hooks (www build with feature flags)138 mkdir ./compiled/eslint-plugin-react-hooks139 cp ./compiled/facebook-www/ESLintPluginReactHooks-dev.modern.js \140 ./compiled/eslint-plugin-react-hooks/index.js141142 # Move unstable_server-external-runtime.js into facebook-www143 mv build/oss-experimental/react-dom/unstable_server-external-runtime.js \144 ./compiled/facebook-www/unstable_server-external-runtime.js145146 # Move react-refresh-babel.development.js into babel-plugin-react-refresh147 mkdir ./compiled/babel-plugin-react-refresh148 mv build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js \149 ./compiled/babel-plugin-react-refresh/index.js150151 ls -R ./compiled152 - name: Move relevant files for React in fbsource into compiled-rn153 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}/157158 # Move React Native renderer159 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/166167 # 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}.js170171 # Copy eslint-plugin-react-hooks172 # NOTE: This is different from www, here we include the full package173 # 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"176177 # Move React Native version file178 mv build/facebook-react-native/VERSION_NATIVE_FB ./compiled-rn/VERSION_NATIVE_FB179180 ls -R ./compiled-rn181 - name: Add REVISION files182 run: |183 echo ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} >> ./compiled/facebook-www/REVISION184 cp ./compiled/facebook-www/REVISION ./compiled/facebook-www/REVISION_TRANSFORMS185 echo ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} >> ./compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/REVISION186 - name: "Get current version string"187 id: get_current_version188 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@v4199 with:200 name: compiled201 path: compiled/202 if-no-files-found: error203 - uses: actions/upload-artifact@v4204 with:205 name: compiled-rn206 path: compiled-rn/207 if-no-files-found: error208209 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-latest213 permissions:214 # Used to push a commit to builds/facebook-www215 contents: write216 steps:217 - uses: actions/checkout@v4218 with:219 ref: builds/facebook-www220 - name: Ensure clean directory221 run: rm -rf compiled222 - uses: actions/download-artifact@v4223 with:224 name: compiled225 path: compiled/226 - name: Revert version changes227 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 changes244 if: inputs.force != true245 id: check_should_commit246 run: |247 echo "Full git status"248 git add .249 git status250 echo "===================="251 if git status --porcelain | grep -qv '/REVISION'; then252 echo "Changes detected"253 echo "===== Changes ====="254 git --no-pager diff -U0 | grep '^[+-]' | head -n 50255 echo "==================="256 echo "should_commit=true" >> "$GITHUB_OUTPUT"257 else258 echo "No Changes detected"259 echo "should_commit=false" >> "$GITHUB_OUTPUT"260 fi261 - name: Re-apply version changes262 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 changes279 if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'280 run: |281 git add .282 git status283 - name: Check commit message284 if: inputs.dry_run285 run: |286 git fetch origin --quiet287 git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:"%B"288 - name: Commit changes to branch289 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 }}"293294 git fetch origin --quiet295 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 branch297 if: inputs.dry_run == false && (inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true')298 run: git push299300 commit_fbsource_artifacts:301 needs: [download_artifacts, process_artifacts]302 permissions:303 # Used to push a commit to builds/facebook-fbsource304 contents: write305 if: inputs.force == true || (github.ref == 'refs/heads/main' && needs.process_artifacts.outputs.fbsource_branch_count == '0')306 runs-on: ubuntu-latest307 steps:308 - uses: actions/checkout@v4309 with:310 ref: builds/facebook-fbsource311 - name: Ensure clean directory312 run: rm -rf compiled-rn313 - uses: actions/download-artifact@v4314 with:315 name: compiled-rn316 path: compiled-rn/317 - name: Revert version changes318 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 changes328 if: inputs.force != 'true'329 id: check_should_commit330 run: |331 echo "Full git status"332 git add .333 git --no-pager diff -U0 --cached | grep '^[+-]' | head -n 100334 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; then337 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 50340 echo "==================="341 echo "should_commit=true" >> "$GITHUB_OUTPUT"342 else343 echo "No Changes detected"344 echo "should_commit=false" >> "$GITHUB_OUTPUT"345 fi346 - name: Re-apply version changes347 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 signing357 if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'358 run: |359 echo ":"360 git add .361 - name: Signing files362 if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'363 uses: actions/github-script@v7364 with:365 script: |366 // TODO: Move this to a script file.367 // We currently can't call scripts from the repo because368 // at this point in the workflow, we're on the compiled369 // 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');375376 // 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})>>)`);381382 const TokenNotFoundError = new Error(383 `SignedSource.signFile(...): Cannot sign file without token: ${NEWTOKEN}`384 );385386 function hash(data, encoding) {387 const md5sum = crypto.createHash('md5');388 md5sum.update(data, encoding);389 return md5sum.digest('hex');390 }391392 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 };411412 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);417418 // Parse the git status output to get file paths!419 const files = result.split('\n').filter(file => file.endsWith('.js'));420421 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 originalContents440 // Need to add the header in, since it's not inserted at build time.441 .replace(' */\n', ` * ${SignedSource.getSigningToken()}\n */\n`)442 );443444 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 changes453 if: inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true'454 run: |455 git add .456 git status457 - name: Check commit message458 if: inputs.dry_run459 run: |460 git fetch origin --quiet461 git show ${{ inputs.commit_sha || github.event.workflow_run.head_sha || github.sha }} --no-patch --pretty=format:"%B"462 - name: Commit changes to branch463 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 }}"467468 git fetch origin --quiet469 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 branch471 if: inputs.dry_run == false && (inputs.force == true || steps.check_should_commit.outputs.should_commit == 'true')472 run: git push
Findings
✓ No findings reported for this file.