Skip to content

Commit

Permalink
SALTO-1242 - Add dedicated command for re-generating the cache (#1966)
Browse files Browse the repository at this point in the history
  • Loading branch information
netama authored Apr 1, 2021
1 parent 16d8f07 commit 5aa9e58
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 5 deletions.
30 changes: 27 additions & 3 deletions packages/cli/src/commands/clean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import _ from 'lodash'
import { EOL } from 'os'
import { cleanWorkspace } from '@salto-io/core'
import { WorkspaceComponents } from '@salto-io/workspace'
Expand All @@ -22,30 +23,42 @@ import { formatCleanWorkspace, formatCancelCommand, header, formatStepStart, for
import Prompts from '../prompts'
import { CliExitCode } from '../types'
import { WorkspaceCommandAction, createWorkspaceCommand } from '../command_builder'
import { validateWorkspace } from '../workspace/workspace'

type CleanArgs = {
force: boolean
regenerateCache: boolean
} & WorkspaceComponents

export const action: WorkspaceCommandAction<CleanArgs> = async ({
input: { force, ...cleanArgs },
input: { force, ...allCleanArgs },
output,
workspace,
}): Promise<CliExitCode> => {
const shouldCleanAnything = Object.values(cleanArgs).some(shouldClean => shouldClean)
const shouldCleanAnything = Object.values(allCleanArgs).some(shouldClean => shouldClean)
if (!shouldCleanAnything) {
outputLine(header(Prompts.EMPTY_PLAN), output)
outputLine(EOL, output)
return CliExitCode.UserInputError
}
if (allCleanArgs.regenerateCache && allCleanArgs.cache) {
errorOutputLine('Cannot re-generate and clear the cache in the same operation', output)
outputLine(EOL, output)
return CliExitCode.UserInputError
}
const cleanArgs = {
..._.omit(allCleanArgs, 'regenerateCache', 'cache'),
// should still clear the cache before re-generating it
cache: allCleanArgs.cache || allCleanArgs.regenerateCache,
}
if (cleanArgs.staticResources && !(cleanArgs.state && cleanArgs.cache && cleanArgs.nacl)) {
errorOutputLine('Cannot clear static resources without clearing the state, cache and nacls', output)
outputLine(EOL, output)
return CliExitCode.UserInputError
}

outputLine(header(
formatCleanWorkspace(cleanArgs)
formatCleanWorkspace(allCleanArgs)
), output)
if (!(force || await getUserBooleanInput(Prompts.SHOULD_EXECUTE_PLAN))) {
outputLine(formatCancelCommand, output)
Expand All @@ -56,6 +69,10 @@ export const action: WorkspaceCommandAction<CleanArgs> = async ({

try {
await cleanWorkspace(workspace, cleanArgs)
if (allCleanArgs.regenerateCache) {
await validateWorkspace(workspace)
await workspace.flush()
}
} catch (e) {
errorOutputLine(formatStepFailed(Prompts.CLEAN_FAILED(e.toString())), output)
return CliExitCode.AppError
Expand Down Expand Up @@ -119,6 +136,13 @@ const cleanDef = createWorkspaceCommand({
type: 'boolean',
default: false,
},
{
name: 'regenerateCache',
alias: 'x',
description: 'Regenerate the cache',
type: 'boolean',
default: false,
},
],
},
action,
Expand Down
4 changes: 3 additions & 1 deletion packages/cli/src/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,9 @@ export const formatInvalidElementCommand = (command: string): string => [
emptyLine(),
].join('\n')

export const formatCleanWorkspace = (cleanArgs: WorkspaceComponents): string => {
export const formatCleanWorkspace = (
cleanArgs: WorkspaceComponents & { regenerateCache: boolean }
): string => {
const componentsToClean = Object.entries(cleanArgs)
.filter(([_comp, shouldClean]) => shouldClean)
.map(([comp]) => _.startCase(comp).toLowerCase())
Expand Down
75 changes: 74 additions & 1 deletion packages/cli/test/commands/clean.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ describe('clean command', () => {
staticResources: false,
credentials: false,
serviceConfig: false,
regenerateCache: false,
},
workspace: mocks.mockWorkspace({}),
})).toBe(CliExitCode.UserInputError)
Expand All @@ -74,13 +75,32 @@ describe('clean command', () => {
staticResources: true,
credentials: true,
serviceConfig: true,
regenerateCache: false,
},
workspace: mocks.mockWorkspace({}),
})).toBe(CliExitCode.Success)
expect(callbacks.getUserBooleanInput).toHaveBeenCalledWith('Do you want to perform these actions?')
expect(output.stdout.content.search('Canceling...')).toBeGreaterThan(0)
})
it('should prompt user and exit if no (regenerate-cache)', async () => {
jest.spyOn(callbacks, 'getUserBooleanInput').mockImplementationOnce(() => Promise.resolve(false))
expect(await action({
...cliCommandArgs,
input: {
force: false,
nacl: true,
state: false,
cache: false,
staticResources: false,
credentials: false,
serviceConfig: false,
regenerateCache: true,
},
workspace: mocks.mockWorkspace({}),
})).toBe(CliExitCode.Success)
expect(callbacks.getUserBooleanInput).toHaveBeenCalledWith('Do you want to perform these actions?')
expect(output.stdout.content.search('Canceling...')).toBeGreaterThan(0)
})

it('should fail if trying to clean static resources without all dependent components', async () => {
expect(await action({
...cliCommandArgs,
Expand All @@ -92,13 +112,32 @@ describe('clean command', () => {
staticResources: true,
credentials: true,
serviceConfig: true,
regenerateCache: false,
},
workspace: mocks.mockWorkspace({}),
})).toBe(CliExitCode.UserInputError)
expect(callbacks.getUserBooleanInput).not.toHaveBeenCalled()
expect(output.stderr.content.search('Cannot clear static resources without clearing the state, cache and nacls')).toBeGreaterThanOrEqual(0)
})

it('should fail if attempting to regenerate and clean the cache at the same time', async () => {
expect(await action({
...cliCommandArgs,
input: {
force: false,
nacl: false,
state: false,
cache: true,
staticResources: false,
credentials: false,
serviceConfig: false,
regenerateCache: true,
},
workspace: mocks.mockWorkspace({}),
})).toBe(CliExitCode.UserInputError)
expect(callbacks.getUserBooleanInput).not.toHaveBeenCalled()
expect(output.stderr.content.search('Cannot re-generate and clear the cache in the same operation')).toBeGreaterThanOrEqual(0)
})
it('should prompt user and continue if yes', async () => {
const workspace = mocks.mockWorkspace({})
expect(await action({
Expand All @@ -111,6 +150,7 @@ describe('clean command', () => {
staticResources: true,
credentials: true,
serviceConfig: true,
regenerateCache: false,
},
workspace,
})).toBe(CliExitCode.Success)
Expand All @@ -127,7 +167,38 @@ describe('clean command', () => {
expect(output.stdout.content.search('Starting to clean')).toBeGreaterThan(0)
expect(output.stdout.content.search('Finished cleaning')).toBeGreaterThan(0)
})
it('should prompt user and continue if yes (regenerate-cache)', async () => {
const workspace = mocks.mockWorkspace({})
expect(await action({
...cliCommandArgs,
input: {
force: false,
nacl: false,
state: false,
cache: false,
staticResources: false,
credentials: false,
serviceConfig: false,
regenerateCache: true,
},
workspace,
})).toBe(CliExitCode.Success)
expect(callbacks.getUserBooleanInput).toHaveBeenCalledWith('Do you want to perform these actions?')
expect(core.cleanWorkspace).toHaveBeenCalledWith(workspace, {
nacl: false,
state: false,
cache: true,
staticResources: false,
credentials: false,
serviceConfig: false,
})
expect(workspace.errors).toHaveBeenCalledTimes(1)
// expecting 1 because there is no call from the mocked cleanWorkspace
expect(workspace.flush).toHaveBeenCalledTimes(1)

expect(output.stdout.content.search('Starting to clean')).toBeGreaterThan(0)
expect(output.stdout.content.search('Finished cleaning')).toBeGreaterThan(0)
})
it('should exit cleanly on error', async () => {
jest.spyOn(core, 'cleanWorkspace').mockImplementationOnce(
() => { throw new Error('something bad happened') }
Expand All @@ -142,6 +213,7 @@ describe('clean command', () => {
staticResources: true,
credentials: true,
serviceConfig: true,
regenerateCache: false,
},
workspace: mocks.mockWorkspace({}),
})).toBe(CliExitCode.AppError)
Expand All @@ -167,6 +239,7 @@ describe('clean command', () => {
staticResources: true,
credentials: true,
serviceConfig: true,
regenerateCache: false,
},
workspace,
})).toBe(CliExitCode.Success)
Expand Down

0 comments on commit 5aa9e58

Please sign in to comment.