Skip to content

Commit

Permalink
Call in-process hook for deploy-action with parameters (#610)
Browse files Browse the repository at this point in the history
* feat: Call oclif hooks for `deploy-action` during run/deploy and pass it the actions being deployed
  • Loading branch information
purplecabbage authored Jan 25, 2023
1 parent 7fd11c0 commit c00e8af
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 22 deletions.
7 changes: 6 additions & 1 deletion src/commands/app/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class Deploy extends BuildCommand {

// if there are no extensions, then set publish to false
flags.publish = flags.publish && !isStandaloneApp
let libConsoleCLI
let libConsoleCLI // <= this can be undefined later on, and it was not checked
if (flags.publish) {
// force login at beginning (if required)
libConsoleCLI = await this.getLibConsoleCLI()
Expand Down Expand Up @@ -158,6 +158,11 @@ class Deploy extends BuildCommand {
try {
const script = await runScript(config.hooks['deploy-actions'])
if (!script) {
await this.config.runHook('deploy-actions', {
appConfig: config,
filterEntities: filterActions || [],
isLocalDev: false
})
deployedRuntimeEntities = await rtLib.deployActions(config, { filterEntities }, onProgress)
}

Expand Down
4 changes: 2 additions & 2 deletions src/commands/app/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ class Run extends BaseCommand {
spinner.info(chalk.dim(`${info}`))
spinner.start()
}

const frontendUrl = await runDev(config, this.config.dataDir, runOptions, onProgress)
const inprocHook = this.config.runHook.bind(this.config)
const frontendUrl = await runDev(config, this.config.dataDir, runOptions, onProgress, inprocHook)
try {
await runScript(config.hooks['post-app-run'])
} catch (err) {
Expand Down
5 changes: 2 additions & 3 deletions src/lib/actions-watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,9 @@ module.exports = async (watcherOptions) => {
* @param {Array<string>} filterActions add filters to deploy only specified OpenWhisk actions
*/
async function buildAndDeploy (watcherOptions, filterActions) {
const { config, isLocal, log } = watcherOptions

const { config, isLocal, log, inprocHook } = watcherOptions
await buildActions(config, filterActions)
await deployActions(config, isLocal, log, filterActions)
await deployActions(config, isLocal, log, filterActions, inprocHook)
}

/**
Expand Down
10 changes: 9 additions & 1 deletion src/lib/deploy-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const { deployActions } = require('@adobe/aio-lib-runtime')
* @param {boolean} filter true if a filter by built actions is desired.
*/
/** @private */
module.exports = async (config, isLocalDev = false, log = () => {}, filter = false) => {
module.exports = async (config, isLocalDev = false, log = () => {}, filter = false, inprocHook) => {
utils.runScript(config.hooks['pre-app-deploy'])
const script = await utils.runScript(config.hooks['deploy-actions'])
if (!script) {
Expand All @@ -32,6 +32,14 @@ module.exports = async (config, isLocalDev = false, log = () => {}, filter = fal
byBuiltActions: filter
}
}
if (inprocHook) {
const hookFilterEntities = Array.isArray(filter) ? filter : []
await inprocHook('deploy-actions', {
appConfig: config,
filterEntities: hookFilterEntities,
isLocalDev
})
}
const entities = await deployActions(config, deployConfig, log)
if (entities.actions) {
const web = entities.actions.filter(utils.createWebExportFilter(true))
Expand Down
8 changes: 5 additions & 3 deletions src/lib/run-dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ const { run: logPoller } = require('./log-poller')
const getPort = require('get-port')

/** @private */
async function runDev (config, dataDir, options = {}, log = () => {}) {
async function runDev (config, dataDir, options = {}, log = () => {}, inprocHook) {
/* parcel bundle options */
const bundleOptions = {
shouldDisableCache: true,
shouldContentHash: true,
shouldOptimize: false,
...options.parcel
}

/* skip actions */
const skipActions = !!options.skipActions
/* fetch logs for actions option */
Expand All @@ -48,6 +49,7 @@ async function runDev (config, dataDir, options = {}, log = () => {}) {
const withBackend = config.app.hasBackend && !skipActions
const isLocal = options.isLocal // applies only for backend
const portToUse = parseInt(process.env.PORT) || SERVER_DEFAULT_PORT

const uiPort = await getPort({ port: portToUse })
if (uiPort !== portToUse) {
log(`Could not use port:${portToUse}, using port:${uiPort} instead`)
Expand Down Expand Up @@ -82,7 +84,7 @@ async function runDev (config, dataDir, options = {}, log = () => {}) {
log('building actions..')
await buildActions(devConfig, null, true /* force build */)

const { cleanup: watcherCleanup } = await actionsWatcher({ config: devConfig, isLocal, log })
const { cleanup: watcherCleanup } = await actionsWatcher({ config: devConfig, isLocal, log, inprocHook })
cleanup.add(() => watcherCleanup(), 'stopping action watcher...')
}

Expand Down Expand Up @@ -121,7 +123,7 @@ async function runDev (config, dataDir, options = {}, log = () => {}) {
// Deploy Phase - deploy actions
if (withBackend) {
log('redeploying actions..')
await deployActions(devConfig, isLocal, log, true)
await deployActions(devConfig, isLocal, log, true, inprocHook)
}

// Deploy Phase - serve the web UI
Expand Down
9 changes: 8 additions & 1 deletion test/commands/app/deploy.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ describe('run', () => {
command.appConfig = cloneDeep(mockConfigData)
command.appConfig.actions = { dist: 'actions' }
command.appConfig.web.distProd = 'dist'
command.config = { runCommand: jest.fn() }
command.config = { runCommand: jest.fn(), runHook: jest.fn() }
command.buildOneExt = jest.fn()
command.getAppExtConfigs = jest.fn()
command.getLibConsoleCLI = jest.fn(() => mockLibConsoleCLI)
Expand Down Expand Up @@ -727,6 +727,13 @@ describe('run', () => {

command.argv = []
await command.run()
expect(command.config.runHook).toHaveBeenCalledTimes(1)
expect(command.config.runHook).toHaveBeenCalledWith('deploy-actions',
expect.objectContaining({
appConfig: expect.any(Object),
filterEntities: [],
isLocalDev: false
}))
expect(mockRuntimeLib.deployActions).toHaveBeenCalledTimes(1)
expect(mockWebLib.deployWeb).toHaveBeenCalledTimes(1)
expect(command.error).toHaveBeenCalledTimes(0)
Expand Down
23 changes: 12 additions & 11 deletions test/commands/app/run.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ beforeEach(() => {
command.error = jest.fn()
command.log = jest.fn()
command.config = {
runHook: jest.fn(),
findCommand: jest.fn().mockReturnValue({
load: mockFindCommandLoad
}),
Expand Down Expand Up @@ -280,7 +281,7 @@ describe('run', () => {
logLevel: 'warn'
}),
isLocal: undefined
}), expect.any(Function))
}), expect.any(Function), expect.any(Function))
})

test('app:run check if fetchLogs flag is set when calling scripts', async () => {
Expand All @@ -292,7 +293,7 @@ describe('run', () => {
await command.run()
expect(mockRunDev).toHaveBeenCalledWith(appConfig.application, expect.any(String), expect.objectContaining({
fetchLogs: true
}), expect.any(Function))
}), expect.any(Function), expect.any(Function))
})

test('app:run with --verbose', async () => {
Expand All @@ -309,7 +310,7 @@ describe('run', () => {
logLevel: 'verbose'
}),
isLocal: undefined
}), expect.any(Function))
}), expect.any(Function), expect.any(Function))
})

test('app:run with --local', async () => {
Expand Down Expand Up @@ -339,7 +340,7 @@ describe('run', () => {
logLevel: 'verbose'
}),
isLocal: true
}), expect.any(Function))
}), expect.any(Function), expect.any(Function))
})

test('app:run where scripts.runDev throws', async () => {
Expand Down Expand Up @@ -423,7 +424,7 @@ describe('run', () => {
key: PRIVATE_KEY_PATH
}
}
}), expect.any(Function))
}), expect.any(Function), expect.any(Function))
})

test('app:run with UI and no cert files but has cert config', async () => {
Expand All @@ -446,7 +447,7 @@ describe('run', () => {
key: PRIVATE_KEY_PATH
}
}
}), expect.any(Function))
}), expect.any(Function), expect.any(Function))
expect(mockFS.ensureDir).toHaveBeenCalledWith(DEV_KEYS_DIR)
expect(mockFS.writeFile).toHaveBeenCalledTimes(2)
expect(mockFS.writeFile).toHaveBeenCalledWith(PUB_CERT_PATH, 'pub cert')
Expand Down Expand Up @@ -477,7 +478,7 @@ describe('run', () => {
key: PRIVATE_KEY_PATH
}
}
}), expect.any(Function))
}), expect.any(Function), expect.any(Function))
expect(mockFS.ensureDir).toHaveBeenCalledWith(DEV_KEYS_DIR)
expect(command.config.findCommand).toHaveBeenCalledWith('certificate:generate')
expect(mockFindCommandRun).toHaveBeenCalledWith([`--keyout=${PRIVATE_KEY_PATH}`, `--out=${PUB_CERT_PATH}`, '-n=DeveloperSelfSigned.cert'])
Expand Down Expand Up @@ -515,7 +516,7 @@ describe('run', () => {
key: PRIVATE_KEY_PATH
}
}
}), expect.any(Function))
}), expect.any(Function), expect.any(Function))
expect(mockConfig.set).toHaveBeenCalledTimes(2)
expect(mockConfig.set).toHaveBeenCalledWith(CONFIG_KEY + '.privateKey', 'private key')
expect(mockConfig.set).toHaveBeenCalledWith(CONFIG_KEY + '.publicCert', 'public cert')
Expand Down Expand Up @@ -555,7 +556,7 @@ describe('run', () => {
key: PRIVATE_KEY_PATH
}
}
}), expect.any(Function))
}), expect.any(Function), expect.any(Function))
expect(https.createServer).toHaveBeenCalledWith({ key: 'private key', cert: 'public cert' }, expect.any(Function))
expect(getPort).toHaveBeenCalledWith({ port: SERVER_DEFAULT_PORT })
expect(mockHttpsServerInstance.listen).toHaveBeenCalledWith(1111)
Expand Down Expand Up @@ -593,7 +594,7 @@ describe('run', () => {
key: PRIVATE_KEY_PATH
}
}
}), expect.any(Function))
}), expect.any(Function), expect.any(Function))
expect(getPort).toHaveBeenCalledWith({ port: 9999 })
expect(mockHttpsServerInstance.listen).toHaveBeenCalledWith(1111)
expect(cli.open).toHaveBeenCalledWith('https://localhost:1111')
Expand Down Expand Up @@ -632,7 +633,7 @@ describe('run', () => {
key: PRIVATE_KEY_PATH
}
}
}), expect.any(Function))
}), expect.any(Function), expect.any(Function))
expect(mockHttpsServerInstance.listen).toHaveBeenCalledWith(1111)
expect(mockHttpsServerInstance.close).toHaveBeenCalledTimes(1)
expect(cli.open).toHaveBeenCalledWith('https://localhost:1111')
Expand Down
41 changes: 41 additions & 0 deletions test/commands/lib/deploy-actions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,48 @@ test('it should deploy actions with filter param, (coverage)', async () => {

test('no deploy-actions app hook available (use inbuilt)', async () => {
await deployActions({ hooks: {} })
expect(rtDeployActions).toHaveBeenCalled()
expect(utils.runScript).toHaveBeenNthCalledWith(1, undefined) // pre-app-deploy
expect(utils.runScript).toHaveBeenNthCalledWith(2, undefined) // deploy-actions
expect(utils.runScript).toHaveBeenNthCalledWith(3, undefined) // post-app-deploy
})

test('call inprocHook no filter', async () => {
const mockHook = jest.fn()
await deployActions({ hooks: {} }, false, null, false, mockHook)
expect(mockHook).toHaveBeenCalledWith('deploy-actions', expect.objectContaining({
appConfig: { hooks: {} },
filterEntities: [],
isLocalDev: false
}))
expect(rtDeployActions).toHaveBeenCalled()
expect(utils.runScript).toHaveBeenNthCalledWith(1, undefined) // pre-app-deploy
expect(utils.runScript).toHaveBeenNthCalledWith(2, undefined) // deploy-actions
expect(utils.runScript).toHaveBeenNthCalledWith(3, undefined) // post-app-deploy
})

test('call inprocHook with filter : isLocalDev false', async () => {
const mockHook = jest.fn()
await deployActions({ hooks: {} }, false, null, ['boomer'], mockHook)
expect(mockHook).toHaveBeenCalledWith('deploy-actions', expect.objectContaining({
appConfig: { hooks: {} },
filterEntities: ['boomer'],
isLocalDev: false
}))
expect(rtDeployActions).toHaveBeenCalled()
expect(utils.runScript).toHaveBeenNthCalledWith(1, undefined) // pre-app-deploy
expect(utils.runScript).toHaveBeenNthCalledWith(2, undefined) // deploy-actions
expect(utils.runScript).toHaveBeenNthCalledWith(3, undefined) // post-app-deploy
})

test('call inprocHook with filter : isLocalDev true', async () => {
const mockHook = jest.fn()
await deployActions({ hooks: {} }, true, null, ['action-1', 'action-2'], mockHook)
expect(mockHook).toHaveBeenCalledWith('deploy-actions', expect.objectContaining({
appConfig: { hooks: {} },
filterEntities: ['action-1', 'action-2'],
isLocalDev: true
}))
expect(rtDeployActions).toHaveBeenCalled()
expect(utils.runScript).toHaveBeenNthCalledWith(1, undefined) // pre-app-deploy
expect(utils.runScript).toHaveBeenNthCalledWith(2, undefined) // deploy-actions
Expand Down

0 comments on commit c00e8af

Please sign in to comment.