Skip to content

Commit

Permalink
Implement retry mechanism during yarn installation (facebook#39020)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: facebook#39020

Sometimes yarn fails to intall, we are implementing a retry mechanism

## Changelog:
[Internal] - Add retry mechanism in template jobs.

Reviewed By: cortinico

Differential Revision: D48234860

fbshipit-source-id: ece3c40051ff143837ed79db2390fbb599fa8ae2
  • Loading branch information
cipolleschi authored and facebook-github-bot committed Aug 16, 2023
1 parent 623f44c commit e7f6f07
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 60 deletions.
41 changes: 41 additions & 0 deletions scripts/circleci/retry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* 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
* @oncall react-native
*/

const {spawnSync} = require('child_process');

async function retry(command, options, maxRetries, delay, args) {
for (let i = 1; i <= maxRetries; i++) {
console.log(`Attempt ${i}: ${command}`);
const result = spawnSync(command, args ? args : [], options);

if (result.status === 0) {
console.log(`Command succeeded on attempt ${i}`);
return true;
}

console.log(`Command failed on attempt ${i}`);

if (i >= maxRetries) {
console.log('Maximum retries reached. Exiting.');
return false;
}

if (delay > 0) {
console.log(`Sleeping for ${delay} seconds...`);
await new Promise(resolve => setTimeout(resolve, delay));
}

console.log('Retrying...');
}
}

module.exports = {
retry,
};
28 changes: 10 additions & 18 deletions scripts/circleci/run_with_retry.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,17 @@
* @format
*/

const {spawnSync} = require('child_process');
const {retry} = require('./retry');

function retryCommand(maxRetries, command) {
for (let i = 1; i <= maxRetries; i++) {
console.log(`Attempt ${i}: ${command}`);
const result = spawnSync(command, {shell: true, stdio: 'inherit'});

if (result.status === 0) {
console.log(`Command succeeded on attempt ${i}`);
process.exit(0);
} else {
console.log(`Command failed on attempt ${i}`);
if (i < maxRetries) {
console.log('Retrying...');
} else {
console.log('Maximum retries reached. Exiting.');
process.exit(1);
}
}
async function retryCommand(maxRetries, command) {
const success = await retry(
command,
{shell: true, stdio: 'inherit'},
maxRetries,
0,
);
if (!success) {
process.exit(1);
}
}

Expand Down
100 changes: 58 additions & 42 deletions scripts/template/initialize.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@
'use strict';

const yargs = require('yargs');
const {execSync, spawnSync} = require('child_process');
const {execSync} = require('child_process');

const forEachPackage = require('../monorepo/for-each-package');
const setupVerdaccio = require('../setup-verdaccio');
const {retry} = require('../circleci/retry');

const {argv} = yargs
.option('r', {
Expand Down Expand Up @@ -42,54 +43,69 @@ const {reactNativeRootPath, templateName, templateConfigPath, directory} = argv;

const VERDACCIO_CONFIG_PATH = `${reactNativeRootPath}/.circleci/verdaccio.yml`;

function install() {
async function install() {
const VERDACCIO_PID = setupVerdaccio(
reactNativeRootPath,
VERDACCIO_CONFIG_PATH,
);
process.stdout.write('Bootstrapped Verdaccio \u2705\n');

process.stdout.write('Starting to publish every package...\n');
forEachPackage(
(packageAbsolutePath, packageRelativePathFromRoot, packageManifest) => {
if (packageManifest.private) {
return;
}

execSync('npm publish --registry http://localhost:4873 --access public', {
cwd: packageAbsolutePath,
try {
process.stdout.write('Bootstrapped Verdaccio \u2705\n');

process.stdout.write('Starting to publish every package...\n');
forEachPackage(
(packageAbsolutePath, packageRelativePathFromRoot, packageManifest) => {
if (packageManifest.private) {
return;
}

execSync(
'npm publish --registry http://localhost:4873 --access public',
{
cwd: packageAbsolutePath,
stdio: [process.stdin, process.stdout, process.stderr],
},
);

process.stdout.write(
`Published ${packageManifest.name} to proxy \u2705\n`,
);
},
);

process.stdout.write('Published every package \u2705\n');

execSync(
`node cli.js init ${templateName} --directory ${directory} --template ${templateConfigPath} --verbose --skip-install`,
{
cwd: `${reactNativeRootPath}/packages/react-native`,
stdio: [process.stdin, process.stdout, process.stderr],
});

process.stdout.write(
`Published ${packageManifest.name} to proxy \u2705\n`,
);
},
);

process.stdout.write('Published every package \u2705\n');
},
);
process.stdout.write('Completed initialization of template app \u2705\n');

execSync(
`node cli.js init ${templateName} --directory ${directory} --template ${templateConfigPath} --verbose --skip-install`,
{
cwd: `${reactNativeRootPath}/packages/react-native`,
process.stdout.write('Installing dependencies in template app folder...\n');
const options = {
cwd: directory,
stdio: [process.stdin, process.stdout, process.stderr],
},
);
process.stdout.write('Completed initialization of template app \u2705\n');

process.stdout.write('Installing dependencies in template app folder...\n');
spawnSync('yarn', ['install'], {
cwd: directory,
stdio: [process.stdin, process.stdout, process.stderr],
});
process.stdout.write('Installed dependencies via Yarn \u2705\n');
};
const success = await retry('yarn', options, 3, 500, ['install']);

process.stdout.write(`Killing verdaccio. PID — ${VERDACCIO_PID}...\n`);
execSync(`kill -9 ${VERDACCIO_PID}`);
process.stdout.write('Killed Verdaccio process \u2705\n');

process.exit();
if (!success) {
process.stdout.write(
'Failed to install dependencies in template app folder.',
);
throw new Error('Failed to install dependencies in template app folder.');
}

process.stdout.write('Installed dependencies via Yarn \u2705\n');
} finally {
process.stdout.write(`Killing verdaccio. PID — ${VERDACCIO_PID}...\n`);
execSync(`kill -9 ${VERDACCIO_PID}`);
process.stdout.write('Killed Verdaccio process \u2705\n');
}
}

install();
install().then(() => {
console.log('Done with preparing the project.');
process.exit();
});

0 comments on commit e7f6f07

Please sign in to comment.