| 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 |