mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
f1a362d834
Summary: With the migration to GHA, we are updating the testing scripts to work with the new CI. There are a bit of shenanigans due to: * How GHA archives artifacts => they are all `.zip` files, so I had to play around with unzipping them * GHA seems to create a different commit, like if it is forking the repo instead of using it. I think that it is how the checkout action works. *Note:* this might be a problem for the `Create React Native Release` workflow because it has to commit on the stable branch! * Android is building only the simulator architecture when running from regular CI. The app is not configured to run only on that, so the RNTestProject was a failing because it was trying to build all the available architectures. It is an easy fix in the user project space when release testing. ## Changelog: [Internal] - Update the testing script to work with the new CI Pull Request resolved: https://github.com/facebook/react-native/pull/44923 Test Plan: Tested locally. * [iOS] RNTester - Hermes ✅ * [iOS] RNTester - JSC ✅ * [Android] RNTester - Hermes ✅ * [Android] RNTester - JSC ✅ * [iOS] RNTestProject - Hermes ✅ (The project is created correctly and it builds, crash at runtime for https://github.com/facebook/react-native/issues/44926) * [iOS] RNTestProject - JSC ✅ (The project is created correctly and it builds, crash at runtime for https://github.com/facebook/react-native/issues/44926) * [Android] RNTester - Hermes ✅ (Needed to build only the simulator architecture) * [Android] RNTester - JSC ✅ (Needed to build only the simulator architecture) Reviewed By: andrewdacenko Differential Revision: D58528432 Pulled By: cipolleschi fbshipit-source-id: 733065de4c532b13d8e95e2217f9aafd5a2ef8a0
196 lines
4.7 KiB
JavaScript
196 lines
4.7 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow strict-local
|
|
* @format
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const {execSync: exec} = require('child_process');
|
|
const fetch = require('node-fetch');
|
|
|
|
/*::
|
|
type CIHeaders = {
|
|
Authorization: string,
|
|
Accept: string,
|
|
'X-GitHub-Api-Version': string
|
|
}
|
|
|
|
type WorkflowRun = {
|
|
id: number,
|
|
name: string,
|
|
run_number: number,
|
|
status: string,
|
|
workflow_id: number,
|
|
url: string,
|
|
created_at: string,
|
|
};
|
|
|
|
|
|
type Artifact = {
|
|
id: number,
|
|
name: string,
|
|
url: string,
|
|
archive_download_url: string,
|
|
}
|
|
|
|
type WorkflowRuns = {
|
|
total_count: number,
|
|
workflow_runs: Array<WorkflowRun>,
|
|
}
|
|
|
|
type Artifacts = {
|
|
total_count: number,
|
|
artifacts: Array<Artifact>,
|
|
}
|
|
*/
|
|
|
|
let token;
|
|
let ciHeaders;
|
|
let artifacts;
|
|
let branch;
|
|
let baseTemporaryPath;
|
|
|
|
const reactNativeRepo = 'https://api.github.com/repos/facebook/react-native/';
|
|
const reactNativeActionsURL = `${reactNativeRepo}actions/runs`;
|
|
|
|
async function _getActionRunsOnBranch() /*: Promise<WorkflowRuns> */ {
|
|
const url = `${reactNativeActionsURL}?branch=${branch}`;
|
|
const options = {
|
|
method: 'GET',
|
|
headers: ciHeaders,
|
|
};
|
|
|
|
// $FlowIgnore[prop-missing] Conflicting .flowconfig in Meta's monorepo
|
|
// $FlowIgnore[incompatible-call]
|
|
const response = await fetch(url, options);
|
|
if (!response.ok) {
|
|
throw new Error(JSON.stringify(await response.json()));
|
|
}
|
|
|
|
const body = await response
|
|
// eslint-disable-next-line func-call-spacing
|
|
.json /*::<WorkflowRuns>*/
|
|
();
|
|
return body;
|
|
}
|
|
|
|
async function _getArtifacts(run_id /*: number */) /*: Promise<Artifacts> */ {
|
|
const url = `${reactNativeActionsURL}/${run_id}/artifacts`;
|
|
const options = {
|
|
method: 'GET',
|
|
headers: ciHeaders,
|
|
};
|
|
|
|
// $FlowIgnore[prop-missing] Conflicting .flowconfig in Meta's monorepo
|
|
// $FlowIgnore[incompatible-call]
|
|
const response = await fetch(url, options);
|
|
if (!response.ok) {
|
|
throw new Error(JSON.stringify(await response.json()));
|
|
}
|
|
|
|
const body = await response
|
|
// eslint-disable-next-line func-call-spacing
|
|
.json /*::<Artifacts>*/
|
|
();
|
|
return body;
|
|
}
|
|
|
|
// === Public Interface === //
|
|
async function initialize(
|
|
ciToken /*: string */,
|
|
baseTempPath /*: string */,
|
|
branchName /*: string */,
|
|
useLastSuccessfulPipeline /*: boolean */ = false,
|
|
) {
|
|
console.info('Getting GHA information');
|
|
baseTemporaryPath = baseTempPath;
|
|
exec(`mkdir -p ${baseTemporaryPath}`);
|
|
|
|
branch = branchName;
|
|
|
|
token = ciToken;
|
|
ciHeaders = {
|
|
Authorization: `Bearer ${token}`,
|
|
Accept: 'application/vnd.github+json',
|
|
'X-GitHub-Api-Version': '2022-11-28',
|
|
};
|
|
|
|
const testAllWorkflow = (await _getActionRunsOnBranch()).workflow_runs
|
|
.filter(w => w.name === 'Test All')
|
|
.sort((a, b) => (a.created_at > b.created_at ? -1 : 1))[0];
|
|
|
|
artifacts = await _getArtifacts(testAllWorkflow.id);
|
|
}
|
|
|
|
function downloadArtifact(
|
|
artifactURL /*: string */,
|
|
destination /*: string */,
|
|
) {
|
|
exec(`rm -rf ${destination}`);
|
|
|
|
const command = `curl ${artifactURL} \
|
|
-Lo ${destination} \
|
|
-H "Accept: application/vnd.github+json" \
|
|
-H "Authorization: Bearer ${token}" \
|
|
-H "X-GitHub-Api-Version: 2022-11-28"`;
|
|
|
|
exec(command, {stdio: 'inherit'});
|
|
}
|
|
|
|
async function artifactURLForJSCRNTesterAPK(
|
|
emulatorArch /*: string */,
|
|
) /*: Promise<string> */ {
|
|
const url = artifacts.artifacts.filter(a => a.name === 'rntester-apk')[0]
|
|
.archive_download_url;
|
|
return Promise.resolve(url);
|
|
}
|
|
|
|
async function artifactURLForHermesRNTesterAPK(
|
|
emulatorArch /*: string */,
|
|
) /*: Promise<string> */ {
|
|
const url = artifacts.artifacts.filter(a => a.name === 'rntester-apk')[0]
|
|
.archive_download_url;
|
|
return Promise.resolve(url);
|
|
}
|
|
|
|
async function artifactURLForMavenLocal() /*: Promise<string> */ {
|
|
const url = artifacts.artifacts.filter(a => a.name === 'maven-local')[0]
|
|
.archive_download_url;
|
|
return Promise.resolve(url);
|
|
}
|
|
|
|
async function artifactURLHermesDebug() /*: Promise<string> */ {
|
|
const url = artifacts.artifacts.filter(
|
|
a => a.name === 'hermes-darwin-bin-Debug',
|
|
)[0].archive_download_url;
|
|
return Promise.resolve(url);
|
|
}
|
|
|
|
async function artifactURLForReactNative() /*: Promise<string> */ {
|
|
const url = artifacts.artifacts.filter(
|
|
a => a.name === 'react-native-package',
|
|
)[0].archive_download_url;
|
|
return Promise.resolve(url);
|
|
}
|
|
|
|
function baseTmpPath() /*: string */ {
|
|
return baseTemporaryPath;
|
|
}
|
|
|
|
module.exports = {
|
|
initialize,
|
|
downloadArtifact,
|
|
artifactURLForJSCRNTesterAPK,
|
|
artifactURLForHermesRNTesterAPK,
|
|
artifactURLForMavenLocal,
|
|
artifactURLHermesDebug,
|
|
artifactURLForReactNative,
|
|
baseTmpPath,
|
|
};
|