Created
December 15, 2021 16:09
-
-
Save nielsmaerten/c1707b5c3882fcce7dba0d5c9430864b to your computer and use it in GitHub Desktop.
Deploy hooks for Firebase Functions + Yarn Workspaces
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
/** | |
* @description Firebase Functions Workspace Deploy Hooks | |
* @author Niels Maerten <https://github.com/nielsmaerten> | |
* @license MIT | |
* | |
* This script is designed for Yarn v3 workspaces. | |
* | |
* ### WHAT DOES THIS SCRIPT DO? ### | |
* Firebase Functions do not support 'monorepos'. This means that you can not | |
* have dependencies in package.json that point to 'workspace:my-package-name'. | |
* This script will find your workspace dependencies, package them, and copy the tgz-file | |
* into this project before deploying. | |
* | |
* When the deploy is complete and this script runs again, the original package.json is restored. | |
* | |
* By doing this, it is possible to slipstream workspace dependencies into your project | |
* and have it run on Cloud Functions | |
*/ | |
const logTag = "[GLOBAL]"; | |
const fs = require('fs'); | |
// Find all dependencies in package.json where the value starts with 'workspace:' | |
const workspaceDeps = Object.entries(require('./package.json').dependencies).filter(([key, value]) => value.startsWith('workspace:')); | |
// This is a preDeploy if workspaceDeps has any entries | |
const isPreDeploy = workspaceDeps.length > 0; | |
const prePostDeploy = isPreDeploy ? 'Pre-deploy' : 'Post-deploy'; | |
// If this is a preDeploy: backup the local package.json | |
// else: restore the backup | |
if (isPreDeploy) { | |
console.log(logTag, 'Backing up package.json'); | |
fs.copyFileSync('./package.json', './package.json.bak'); | |
} else { | |
console.log(logTag, 'Restoring package.json backup'); | |
fs.copyFileSync('./package.json.bak', './package.json'); | |
fs.unlinkSync('./package.json.bak'); | |
} | |
// If preDeploy: Package all workspace dependencies into this directory | |
workspaceDeps.forEach(([workspace]) => { | |
const logTag = `[${workspace}]`; | |
console.log(logTag, `Running yarn pack`); | |
const workspacePath = `../${workspace}`; | |
const packageFilename = `${workspace}.tgz`; | |
const packCommand = `yarn pack --filename ${packageFilename}`; | |
const packResult = require('child_process').execSync(packCommand, { cwd: workspacePath }); | |
// console.log(packResult.toString()); | |
// Copy the package into this directory using node fs | |
console.log(logTag,`Copying package into this directory`); | |
const packPath = `${workspacePath}/${packageFilename}`; | |
const targetPath = `${__dirname}/${packageFilename}`; | |
fs.copyFileSync(packPath, targetPath); | |
// Update the package in the local package.json | |
console.log(logTag, `Updating local package.json`); | |
const localPackageJson = require('./package.json'); | |
localPackageJson.dependencies[workspace] = `file:${packageFilename}`; | |
fs.writeFileSync('./package.json', JSON.stringify(localPackageJson, null, 2)); | |
console.log(logTag, `Workspace successfully packaged into this directory`); | |
}); | |
// If postDeploy, remove .tgz files in current dir | |
if (!isPreDeploy) { | |
console.log(logTag, 'Removing .tgz files'); | |
fs.readdirSync(__dirname).forEach(file => { | |
if (file.endsWith('.tgz')) { | |
fs.unlinkSync(`${__dirname}/${file}`); | |
} | |
}); | |
} | |
console.log(logTag, prePostDeploy, "hook ran successfully"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment