@gravityforms/gulp-tasks
Version:
Configurable Gulp tasks for use in Gravity Forms projects.
187 lines (164 loc) • 6.92 kB
JavaScript
const simpleGit = require( 'simple-git' );
const getConfig = require('../../config');
const { config } = getConfig();
const rootPath = config?.paths?.root || '';
const path = require( 'path' );
const fs = require( 'fs' );
const { exec } = require( 'child_process' );
const { moduleExists, trailingSlashIt } = require( './util' );
let packagesCloned = false;
const clonePath = path.resolve( rootPath, '../gravitypackages-clone' );
const eslintDependencies = [
"@babel/cli",
"@babel/core",
"@babel/eslint-parser",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-decorators",
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-transform-object-assign",
"@babel/plugin-transform-regenerator",
"@babel/plugin-transform-runtime",
"@babel/preset-env",
"@babel/preset-react",
"babel-loader",
"babel-plugin-istanbul",
"babel-plugin-module-resolver",
"eslint",
"eslint-import-resolver-webpack",
"eslint-plugin-jsdoc",
"eslint-plugin-jsx-a11y",
"eslint-plugin-react",
"eslint-plugin-react-hooks",
];
// Function to execute shell commands
function execShellCommand( cmd, printOutput = false ) {
return new Promise( ( resolve, reject ) => {
exec( cmd, ( error, stdout, stderr ) => {
if ( error ) {
console.error( `exec error: ${ error }` );
reject( error );
return;
}
if ( stderr ) {
console.error( `stderr: ${ stderr }` );
}
if ( stdout && printOutput ) {
console.log( `stdout: ${ stdout }` );
}
resolve( stdout );
} );
} );
}
const updatePeerDependencies = async ( projectPackageJsonPath, monorepoPackageJsonPath ) => {
const monorepoPackageJson = require( monorepoPackageJsonPath );
const projectPackageJson = require( projectPackageJsonPath );
const dependenciesToAdd = Object.fromEntries(
Object.entries( monorepoPackageJson.dependencies || {} )
.filter( ( [ key ] ) => eslintDependencies.includes( key ) )
);
console.log( 'Adding the following peer dependencies to package.json:', dependenciesToAdd );
projectPackageJson.dependencies = projectPackageJson.dependencies || {};
Object.assign( projectPackageJson.dependencies, dependenciesToAdd );
projectPackageJson.scripts = projectPackageJson.scripts || {};
fs.writeFileSync( projectPackageJsonPath, JSON.stringify( projectPackageJson, null, 2 ) );
};
async function getCurrentBranch( localPath ) {
const git = simpleGit( localPath );
const branchSummary = await git.branchLocal();
return branchSummary.current;
}
async function fetchRemotePackagesBranches() {
const git = simpleGit();
try {
const remoteInfo = await git.listRemote( [
'--heads',
`https://x-access-token:${ process.env.GITHUB_TOKEN }@github.com/gravityforms/gravitypackages.git`,
] );
return remoteInfo.split( '\n' )
.filter( ( line ) => !! line.trim() ) // Remove any empty lines
.map( ( line ) => {
const parts = line.split( '\t' );
const ref = parts[ 1 ];
return ref.replace( 'refs/heads/', '' ); // Clean up the ref to show just the branch name
} );
} catch ( error ) {
console.error( 'Failed to fetch branches:', error );
throw error;
}
}
async function cloneIfBranchMatches() {
const localBranchName = await getCurrentBranch( rootPath );
if ( localBranchName === 'master' || localBranchName === 'main' ) {
console.log( `Current branch is ${ localBranchName }, skipping monorepo link checking.` );
return;
}
const remoteBranches = await fetchRemotePackagesBranches();
if ( remoteBranches.includes( localBranchName ) ) {
console.log( `Cloning gravitypackages repo on branch ${ localBranchName } to ${ clonePath }` );
if ( ! fs.existsSync( clonePath ) ) {
packagesCloned = true;
fs.mkdirSync( clonePath, { recursive: true } );
const git = simpleGit( clonePath );
const repoUrl = `https://x-access-token:${ process.env.GITHUB_TOKEN }@github.com/gravityforms/gravitypackages.git`;
await git.clone( repoUrl, clonePath, [ '--branch', localBranchName ] );
console.log( `Cloned gravitypackages repo on branch ${ localBranchName } into ${ clonePath }` );
} else {
console.log( `Target directory ${ clonePath } already exists.` );
}
} else {
console.log( `No matching branch found in Gravity Packages during monorepo linking.` );
}
}
async function linkPackages() {
const packageJsonSrc = path.join( rootPath, 'package.json' );
const packageJson = require( packageJsonSrc );
if ( ! packageJson?.dependencies ) {
console.log( 'Package.json not found during linking, exiting.' );
return;
}
const gulpTasksPackageJsonSrc = trailingSlashIt( clonePath ) + 'packages/npm/gulp-tasks/package.json';
const gulpTasksPackageJson = moduleExists( gulpTasksPackageJsonSrc ) ? require( gulpTasksPackageJsonSrc ) : {};
// the following script is temporary. Added in 4.5.0 of storybooks. Once all systems have migrated to 4.5.0, this can be removed and npm run packages:dist becomes default.
const hasGenerateDistScript = gulpTasksPackageJson?.scripts?.[ 'generate:dist' ];
const targets = Object.keys( packageJson.dependencies )
.filter( ( dep ) => dep.startsWith( '@gravityforms/' ) )
.map( ( dep ) => `${ trailingSlashIt( clonePath ) }packages/npm/${ dep.slice( 14 ) }` );
if ( targets.length === 0 ) {
console.log( 'No packages to link, exiting.' );
return;
}
console.log( 'Updating peer dependencies...' );
await updatePeerDependencies( packageJsonSrc, gulpTasksPackageJsonSrc );
console.log( 'Installing packages root...' );
await execShellCommand( `cd '${ trailingSlashIt( clonePath ) }' && npm install`, true ); // eslint-disable-line
console.log( 'Installing gulp tasks...' );
await execShellCommand( `cd '${ trailingSlashIt( clonePath ) }packages/npm/gulp-tasks' && npm install`, true ); // eslint-disable-line
if ( ! hasGenerateDistScript ) {
console.log( 'Exporting components...' );
await execShellCommand( `cd '${ trailingSlashIt( clonePath ) }' && npm run export:components`, true ); // eslint-disable-line
} else {
console.log( 'Generating packages dist and exporting components...' );
await execShellCommand( `cd '${ trailingSlashIt( clonePath ) }' && npm run packages:dist`, true ); // eslint-disable-line
}
const cmd = `cd ${ rootPath } && npm link ${ targets.map( ( target ) => `'${ target }'` ).join( ' ' ) }`; // eslint-disable-line
console.log( `Executing link command: `, cmd );
await execShellCommand( cmd, true );
}
( async () => {
try {
// Check if not in production mode and exit early
if ( process.env.GULP_PRODUCTION_MODE !== 'true' ) {
console.log( 'Skipping linking packages repo because GULP_PRODUCTION_MODE is not set to true.' );
return;
}
await cloneIfBranchMatches();
if ( packagesCloned ) {
await linkPackages();
}
} catch ( err ) {
console.error( 'An error occurred during linking:', err );
}
} )();