Skip to content

Commit c16ea38

Browse files
committed
feat: update deploy command to provision db
1 parent 93d3d4f commit c16ea38

4 files changed

Lines changed: 167 additions & 6 deletions

File tree

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ USAGE
297297
$ aio app create [PATH] [-v] [--version] [-i <value>]
298298
299299
ARGUMENTS
300-
PATH [default: .] Path to the app directory
300+
[PATH] [default: .] Path to the app directory
301301
302302
FLAGS
303303
-i, --import=<value> Import an Adobe I/O Developer Console configuration file
@@ -337,7 +337,7 @@ USAGE
337337
$ aio app delete action [ACTION-NAME] [-v] [--version] [-y]
338338
339339
ARGUMENTS
340-
ACTION-NAME Action `pkg/name` to delete, you can specify multiple actions via a comma separated list
340+
[ACTION-NAME] Action `pkg/name` to delete, you can specify multiple actions via a comma separated list
341341
342342
FLAGS
343343
-v, --verbose Verbose output
@@ -543,7 +543,7 @@ USAGE
543543
<value> | | ] [--confirm-new-workspace] [--use-jwt] [--github-pat <value> ] [--linter none|basic|adobe-recommended]
544544
545545
ARGUMENTS
546-
PATH [default: .] Path to the app directory
546+
[PATH] [default: .] Path to the app directory
547547
548548
FLAGS
549549
-e, --extension=<value>... Extension point(s) to implement
@@ -674,7 +674,7 @@ USAGE
674674
$ aio app pack [PATH] [-v] [--version] [--lock-file] [-o <value>]
675675
676676
ARGUMENTS
677-
PATH [default: .] Path to the app directory to package
677+
[PATH] [default: .] Path to the app directory to package
678678
679679
FLAGS
680680
-o, --output=<value> [default: dist/app.zip] The packaged app output file path
@@ -773,7 +773,7 @@ USAGE
773773
[--confirm-new-workspace] [--no-service-sync | --confirm-service-sync] [--no-input] [--use-jwt]
774774
775775
ARGUMENTS
776-
CONFIG_FILE_PATH path to an Adobe I/O Developer Console configuration file
776+
[CONFIG_FILE_PATH] path to an Adobe I/O Developer Console configuration file
777777
778778
FLAGS
779779
-g, --global Use the global Adobe Developer Console Org / Project / Workspace configuration,

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"author": "Adobe Inc.",
66
"bugs": "https://github.com/adobe/aio-cli-plugin-app/issues",
77
"dependencies": {
8-
"@adobe/aio-cli-lib-app-config": "^4.0.3",
8+
"@adobe/aio-cli-lib-app-config": "../aio-cli-lib-app-config",
99
"@adobe/aio-cli-lib-console": "^5.0.3",
1010
"@adobe/aio-lib-core-config": "^5",
1111
"@adobe/aio-lib-core-logging": "^3",

src/commands/app/deploy.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,11 @@ class Deploy extends BuildCommand {
203203
this.error(err)
204204
}
205205

206+
// provision database if configured
207+
if (config.manifest?.full?.database?.['auto-provision'] === true) {
208+
await this.provisionDatabase(config, spinner, flags)
209+
}
210+
206211
if (flags.actions) {
207212
if (config.app.hasBackend) {
208213
let filterEntities
@@ -299,6 +304,32 @@ class Deploy extends BuildCommand {
299304
}
300305
}
301306

307+
async provisionDatabase (config, spinner, flags) {
308+
const region = config.manifest?.full?.database?.region || 'amer'
309+
310+
if (!config.manifest?.full?.database?.region) {
311+
spinner.info(chalk.green('No region is configured for the database, deploying in default region amer'))
312+
}
313+
314+
const message = `Deploying database for region '${region}'`
315+
316+
try {
317+
spinner.start(message)
318+
319+
if (flags.verbose) {
320+
spinner.info(chalk.dim(`Running: aio app db provision --region ${region} --yes`))
321+
spinner.start(message)
322+
}
323+
324+
await this.config.runCommand('app:db:provision', ['--region', region, '--yes'])
325+
326+
spinner.succeed(chalk.green(`Deployed database for application in region '${region}'`))
327+
} catch (error) {
328+
spinner.fail(chalk.red('Database deployment failed'))
329+
throw error
330+
}
331+
}
332+
302333
async publishExtensionPoints (deployConfigs, aioConfig, force) {
303334
const libConsoleCLI = await this.getLibConsoleCLI()
304335

test/commands/app/deploy.test.js

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const helpersActual = jest.requireActual('../../../src/lib/app-helper.js')
1818
const authHelpersActual = jest.requireActual('../../../src/lib/auth-helper')
1919

2020
const open = require('open')
21+
const ora = require('ora')
2122
const mockBundleFunc = jest.fn()
2223

2324
jest.mock('../../../src/lib/app-helper.js')
@@ -203,6 +204,7 @@ beforeEach(() => {
203204
command = new TheCommand([])
204205
command.error = jest.fn()
205206
command.log = jest.fn()
207+
command.warn = jest.fn()
206208
command.appConfig = cloneDeep(mockConfigData)
207209
command.appConfig.actions = { dist: 'actions' }
208210
command.appConfig.web.distProd = 'dist'
@@ -1628,4 +1630,132 @@ describe('run', () => {
16281630
expect(mockRuntimeLib.deployActions).toHaveBeenCalledTimes(1)
16291631
expect(mockWebLib.deployWeb).toHaveBeenCalledTimes(1)
16301632
})
1633+
1634+
test('should deploy successfully when auto-provision database is configured', async () => {
1635+
// Create app config with database auto-provision enabled
1636+
const appConfigWithDb = createAppConfig({
1637+
...command.appConfig,
1638+
manifest: {
1639+
full: {
1640+
database: {
1641+
'auto-provision': true
1642+
}
1643+
},
1644+
database: {
1645+
region: 'emea'
1646+
}
1647+
}
1648+
})
1649+
1650+
command.getAppExtConfigs.mockResolvedValueOnce(appConfigWithDb)
1651+
command.provisionDatabase = jest.fn().mockResolvedValue()
1652+
1653+
await command.run()
1654+
1655+
expect(command.error).toHaveBeenCalledTimes(0)
1656+
expect(command.provisionDatabase).toHaveBeenCalledTimes(1)
1657+
expect(command.provisionDatabase).toHaveBeenCalledWith(
1658+
appConfigWithDb.application,
1659+
expect.any(Object), // spinner
1660+
expect.objectContaining({ 'force-build': true }) // flags
1661+
)
1662+
expect(mockRuntimeLib.deployActions).toHaveBeenCalledTimes(1)
1663+
expect(mockWebLib.deployWeb).toHaveBeenCalledTimes(1)
1664+
})
1665+
})
1666+
1667+
describe('database provisioning', () => {
1668+
const createDatabaseConfig = (region = null, autoProvision = true) => ({
1669+
manifest: {
1670+
full: {
1671+
database: {
1672+
'auto-provision': autoProvision,
1673+
...(region && { region })
1674+
}
1675+
}
1676+
}
1677+
})
1678+
1679+
// Helper function to set up and run test
1680+
const runProvisionTest = async (config, flags, mockResult) => {
1681+
const spinner = ora()
1682+
1683+
if (mockResult instanceof Error) {
1684+
command.config.runCommand.mockRejectedValueOnce(mockResult)
1685+
} else {
1686+
command.config.runCommand.mockResolvedValueOnce(mockResult)
1687+
}
1688+
1689+
return {
1690+
result: await command.provisionDatabase(config, spinner, flags).catch(e => { throw e }),
1691+
spinner
1692+
}
1693+
}
1694+
1695+
test('should use default region when not specified in manifest', async () => {
1696+
const config = createDatabaseConfig()
1697+
const flags = { verbose: false }
1698+
1699+
const { spinner } = await runProvisionTest(config, flags)
1700+
1701+
expect(spinner.info).toHaveBeenCalledWith(expect.stringContaining('No region is configured for the database, deploying in default region amer'))
1702+
expect(spinner.start).toHaveBeenCalledWith('Deploying database for region \'amer\'')
1703+
expect(command.config.runCommand).toHaveBeenCalledWith('app:db:provision', ['--region', 'amer', '--yes'])
1704+
expect(spinner.succeed).toHaveBeenCalledWith(expect.stringContaining('Deployed database for application in region \'amer\''))
1705+
})
1706+
1707+
test('should use configured region when specified in manifest', async () => {
1708+
const config = createDatabaseConfig('emea')
1709+
const flags = { verbose: false }
1710+
1711+
const { spinner } = await runProvisionTest(config, flags)
1712+
1713+
expect(spinner.info).not.toHaveBeenCalledWith(expect.stringContaining('No region is configured for the database'))
1714+
expect(spinner.start).toHaveBeenCalledWith('Deploying database for region \'emea\'')
1715+
expect(command.config.runCommand).toHaveBeenCalledWith('app:db:provision', ['--region', 'emea', '--yes'])
1716+
expect(spinner.succeed).toHaveBeenCalledWith(expect.stringContaining('Deployed database for application in region \'emea\''))
1717+
})
1718+
1719+
test('should show verbose output when verbose flag is true', async () => {
1720+
const config = createDatabaseConfig('amer')
1721+
const flags = { verbose: true }
1722+
1723+
const { spinner } = await runProvisionTest(config, flags)
1724+
1725+
expect(spinner.info).toHaveBeenCalledWith(expect.stringContaining('Running: aio app db provision --region amer --yes'))
1726+
expect(spinner.info).not.toHaveBeenCalledWith(expect.stringContaining('No region is configured for the database'))
1727+
expect(spinner.start).toHaveBeenCalledTimes(2) // Once initially, once after verbose info
1728+
expect(spinner.succeed).toHaveBeenCalledWith(expect.stringContaining('Deployed database for application in region \'amer\''))
1729+
})
1730+
1731+
test('should handle provision command failure', async () => {
1732+
const config = createDatabaseConfig('amer')
1733+
const flags = { verbose: false }
1734+
const error = new Error('Database provision failed')
1735+
1736+
await expect(runProvisionTest(config, flags, error))
1737+
.rejects.toThrow('Database provision failed')
1738+
1739+
expect(command.warn).not.toHaveBeenCalled()
1740+
})
1741+
1742+
test('should show verbose error details when verbose flag is true and provision fails', async () => {
1743+
const config = createDatabaseConfig('amer')
1744+
const flags = { verbose: true }
1745+
const error = new Error('Database provision failed')
1746+
1747+
await expect(runProvisionTest(config, flags, error))
1748+
.rejects.toThrow('Database provision failed')
1749+
1750+
expect(command.warn).not.toHaveBeenCalled()
1751+
})
1752+
1753+
test('should fail if invalid region specified', async () => {
1754+
const config = createDatabaseConfig('invalid-region')
1755+
const flags = { verbose: false }
1756+
const error = new Error('Invalid region: invalid-region')
1757+
1758+
await expect(runProvisionTest(config, flags, error))
1759+
.rejects.toThrow('Invalid region: invalid-region')
1760+
})
16311761
})

0 commit comments

Comments
 (0)