mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
4eed12b7df
Summary: While releasing RN 0.73.0-RC3, we relaized that the e2e test script was bugged for Android when used to test RNTestProject with the `-c` option. There were 2 problems: - The downloaded maven-local was not actually used because it doesn't work with a zip. (We were always downloading a version from Maven) - The versions of React Native between maven-local and the locally packaged React Native were different. This change fixes the script by: - Downloading maven-local - Unzipping maven-local and passing the new folder to the Android app - Downloading the React Native version that has been packaged in CI By unzipping maven-local and using the unzipped folder, we make sure that Android is actually using the local repository. By downloading both the packaged react native and the maven-local from the same CI workflow, we ensure that the versions are aligned. This also speeds-up further the Android testing. While running this change, we also moved the `pod install` step inside the `if (iOS)` branch, so we do not install Cocoapods if we need to test Android. ## Changelog: [Internal] - Fix Android E2E test script when downloading artefacts from CI Pull Request resolved: https://github.com/facebook/react-native/pull/41172 Test Plan: Tested locally on both main and 0.73-stable, on both Android and iOS Reviewed By: cortinico Differential Revision: D50651448 Pulled By: cipolleschi fbshipit-source-id: 70a9ed19072119d19c5388e8a4309d7333a08e13
202 lines
5.2 KiB
JavaScript
202 lines
5.2 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.
|
|
*
|
|
* @format
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const {exec} = require('shelljs');
|
|
|
|
const util = require('util');
|
|
const asyncRequest = require('request');
|
|
const request = util.promisify(asyncRequest);
|
|
|
|
let circleCIHeaders;
|
|
let jobs;
|
|
let baseTemporaryPath;
|
|
|
|
async function initialize(circleCIToken, baseTempPath, branchName) {
|
|
console.info('Getting CircleCI information');
|
|
circleCIHeaders = {'Circle-Token': circleCIToken};
|
|
baseTemporaryPath = baseTempPath;
|
|
exec(`mkdir -p ${baseTemporaryPath}`);
|
|
const pipeline = await _getLastCircleCIPipelineID(branchName);
|
|
const testsWorkflow = await _getTestsWorkflow(pipeline.id);
|
|
const jobsResults = await _getCircleCIJobs(testsWorkflow.id);
|
|
|
|
jobs = jobsResults.flatMap(j => j);
|
|
}
|
|
|
|
function baseTmpPath() {
|
|
return baseTemporaryPath;
|
|
}
|
|
|
|
async function _getLastCircleCIPipelineID(branchName) {
|
|
const options = {
|
|
method: 'GET',
|
|
url: 'https://circleci.com/api/v2/project/gh/facebook/react-native/pipeline',
|
|
qs: {
|
|
branch: branchName,
|
|
},
|
|
headers: circleCIHeaders,
|
|
};
|
|
|
|
const response = await request(options);
|
|
if (response.error) {
|
|
throw new Error(error);
|
|
}
|
|
|
|
const items = JSON.parse(response.body).items;
|
|
|
|
if (!items || items.length === 0) {
|
|
throw new Error(
|
|
'No pipelines found on this branch. Make sure that the CI has run at least once, successfully',
|
|
);
|
|
}
|
|
|
|
const lastPipeline = items[0];
|
|
return {id: lastPipeline.id, number: lastPipeline.number};
|
|
}
|
|
|
|
async function _getSpecificWorkflow(pipelineId, workflowName) {
|
|
const options = {
|
|
method: 'GET',
|
|
url: `https://circleci.com/api/v2/pipeline/${pipelineId}/workflow`,
|
|
headers: circleCIHeaders,
|
|
};
|
|
const response = await request(options);
|
|
if (response.error) {
|
|
throw new Error(error);
|
|
}
|
|
|
|
const body = JSON.parse(response.body);
|
|
let workflow = body.items.find(w => w.name === workflowName);
|
|
_throwIfWorkflowNotFound(workflow, workflowName);
|
|
return workflow;
|
|
}
|
|
|
|
function _throwIfWorkflowNotFound(workflow, name) {
|
|
if (!workflow) {
|
|
throw new Error(
|
|
`Can't find a workflow named ${name}. Please check whether that workflow has started.`,
|
|
);
|
|
}
|
|
}
|
|
|
|
async function _getTestsWorkflow(pipelineId) {
|
|
return _getSpecificWorkflow(pipelineId, 'tests');
|
|
}
|
|
|
|
async function _getCircleCIJobs(workflowId) {
|
|
const options = {
|
|
method: 'GET',
|
|
url: `https://circleci.com/api/v2/workflow/${workflowId}/job`,
|
|
headers: circleCIHeaders,
|
|
};
|
|
const response = await request(options);
|
|
if (response.error) {
|
|
throw new Error(error);
|
|
}
|
|
|
|
const body = JSON.parse(response.body);
|
|
return body.items;
|
|
}
|
|
|
|
async function _getJobsArtifacts(jobNumber) {
|
|
const options = {
|
|
method: 'GET',
|
|
url: `https://circleci.com/api/v2/project/gh/facebook/react-native/${jobNumber}/artifacts`,
|
|
headers: circleCIHeaders,
|
|
};
|
|
const response = await request(options);
|
|
if (response.error) {
|
|
throw new Error(error);
|
|
}
|
|
|
|
const body = JSON.parse(response.body);
|
|
return body.items;
|
|
}
|
|
|
|
async function _findUrlForJob(jobName, artifactPath) {
|
|
const job = jobs.find(j => j.name === jobName);
|
|
_throwIfJobIsNull(job);
|
|
_throwIfJobIsUnsuccessful(job);
|
|
|
|
const artifacts = await _getJobsArtifacts(job.job_number);
|
|
let artifact = artifacts.find(a => a.path.indexOf(artifactPath) > -1);
|
|
if (!artifact) {
|
|
throw new Error(`I could not find the artifact with path ${artifactPath}`);
|
|
}
|
|
return artifact.url;
|
|
}
|
|
|
|
function _throwIfJobIsNull(job) {
|
|
if (!job) {
|
|
throw new Error(
|
|
`Can't find a job with name ${job.name}. Please verify that it has been executed and that all its dependencies completed successfully.`,
|
|
);
|
|
}
|
|
}
|
|
|
|
function _throwIfJobIsUnsuccessful(job) {
|
|
if (job.status !== 'success') {
|
|
throw new Error(
|
|
`The job ${job.name} status is ${job.status}. We need a 'success' status to proceed with the testing.`,
|
|
);
|
|
}
|
|
}
|
|
|
|
async function artifactURLHermesDebug() {
|
|
return _findUrlForJob('build_hermes_macos-Debug', 'hermes-ios-debug.tar.gz');
|
|
}
|
|
|
|
async function artifactURLForMavenLocal() {
|
|
return _findUrlForJob('build_npm_package', 'maven-local.zip');
|
|
}
|
|
|
|
async function artifactURLForReactNative() {
|
|
let shortCommit = exec('git rev-parse HEAD', {silent: true})
|
|
.toString()
|
|
.trim()
|
|
.slice(0, 9);
|
|
return _findUrlForJob(
|
|
'build_npm_package',
|
|
`react-native-1000.0.0-${shortCommit}.tgz`,
|
|
);
|
|
}
|
|
|
|
async function artifactURLForHermesRNTesterAPK(emulatorArch) {
|
|
return _findUrlForJob(
|
|
'test_android',
|
|
`rntester-apk/hermes/debug/app-hermes-${emulatorArch}-debug.apk`,
|
|
);
|
|
}
|
|
|
|
async function artifactURLForJSCRNTesterAPK(emulatorArch) {
|
|
return _findUrlForJob(
|
|
'test_android',
|
|
`rntester-apk/jsc/debug/app-jsc-${emulatorArch}-debug.apk`,
|
|
);
|
|
}
|
|
|
|
function downloadArtifact(artifactURL, destination) {
|
|
exec(`rm -rf ${destination}`);
|
|
exec(`curl ${artifactURL} -Lo ${destination}`);
|
|
}
|
|
|
|
module.exports = {
|
|
initialize,
|
|
downloadArtifact,
|
|
artifactURLForJSCRNTesterAPK,
|
|
artifactURLForHermesRNTesterAPK,
|
|
artifactURLForMavenLocal,
|
|
artifactURLHermesDebug,
|
|
artifactURLForReactNative,
|
|
baseTmpPath,
|
|
};
|