Skip to content

Commit

Permalink
feat: Generator rollbacks (#6947)
Browse files Browse the repository at this point in the history
* Initial implementation

* Run generateTypes after files rolled back

* remove empty dirs

* initial tests for rollback.js

* Add some docs

* Remove throw error from testing

* Fix scaffold rollback execa call

* rollback flag added, tmp stop humanize-string rollback

* Regenerate types after rolling back files

* Rebuilt the test fixture to check

* Add generateType rollback to scaffold

* Remove grandparent directories if empty too

* add listr2 rollback test to unit tests

* add back reverting humanize-string

* Add --rollback to docs

* rename prepare function

* fix prepareForRollback in rollback tests

Co-authored-by: Rob Cameron <cannikin@fastmail.com>
  • Loading branch information
2 people authored and web-flow committed Dec 12, 2022
1 parent a27d66f commit 2001356
Show file tree
Hide file tree
Showing 16 changed files with 426 additions and 8 deletions.
21 changes: 17 additions & 4 deletions docs/docs/cli-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ Cells are signature to Redwood. We think they provide a simpler and more declara
| `--list` | Use this flag to generate a list cell. This flag is needed when dealing with irregular words whose plural and singular is identical such as equipment or pokemon |
| `--tests` | Generate test files [default: true] |
| `--stories` | Generate Storybook files [default: true] |
| `--rollback` | Rollback changes if an error occurs [default: true] |
**Usage**
Expand Down Expand Up @@ -519,6 +520,7 @@ Redwood loves function components and makes extensive use of React Hooks, which
| `--typescript, --ts` | Generate TypeScript files Enabled by default if we detect your project is TypeScript |
| `--tests` | Generate test files [default: true] |
| `--stories` | Generate Storybook files [default: true] |
| `--rollback` | Rollback changes if an error occurs [default: true] |
**Destroying**
Expand Down Expand Up @@ -568,6 +570,7 @@ Creates a data migration script in `api/db/dataMigrations`.
| Arguments & Options | Description |
| :------------------ | :----------------------------------------------------------------------- |
| `name` | Name of the data migration, prefixed with a timestamp at generation time |
| `--rollback` | Rollback changes if an error occurs [default: true] |
**Usage**
Expand All @@ -588,6 +591,7 @@ yarn redwood generate dbAuth
| Arguments & Options | Description |
| ------------------- | ------------------------------------------------------------------------------------------------ |
| `--webAuthn` | Whether or not to add webAuthn support to the log in page. If not specified you will be prompted |
| `--rollback` | Rollback changes if an error occurs [default: true] |
If you don't want to create your own log in, sign up, forgot password and
password reset pages from scratch you can use this generator. The pages will be
Expand All @@ -613,6 +617,7 @@ yarn redwood generate directive <name>
| `--force, -f` | Overwrite existing files |
| `--typescript, --ts` | Generate TypeScript files (defaults to your projects language target) |
| `--type` | Directive type [Choices: "validator", "transformer"] |
| `--rollback` | Rollback changes if an error occurs [default: true] |
**Usage**
Expand Down Expand Up @@ -651,6 +656,7 @@ Not to be confused with Javascript functions, Capital-F Functions are meant to b
| `name` | Name of the function |
| `--force, -f` | Overwrite existing files |
| `--typescript, --ts` | Generate TypeScript files Enabled by default if we detect your project is TypeScript |
| `--rollback` | Rollback changes if an error occurs [default: true] |
**Usage**
Expand Down Expand Up @@ -720,6 +726,7 @@ Layouts wrap pages and help you stay DRY.
| `--tests` | Generate test files [default: true] |
| `--stories` | Generate Storybook files [default: true] |
| `--skipLink` | Generate a layout with a skip link [default: false] |
| `--rollback` | Rollback changes if an error occurs [default: true] |
**Usage**
Expand Down Expand Up @@ -763,10 +770,11 @@ Generate a RedwoodRecord model.
yarn redwood generate model <name>
```
| Arguments & Options | Description |
| ------------------- | ------------------------------------ |
| `name` | Name of the model (in schema.prisma) |
| `--force, -f` | Overwrite existing files |
| Arguments & Options | Description |
| ------------------- | ----------------------------------------------------- |
| `name` | Name of the model (in schema.prisma) |
| `--force, -f` | Overwrite existing files |
| `--rollback` | Rollback changes if an error occurs [default: true] |
**Usage**
Expand Down Expand Up @@ -814,6 +822,7 @@ This also updates `Routes.js` in `./web/src`.
| `--typescript, --ts` | Generate TypeScript files Enabled by default if we detect your project is TypeScript |
| `--tests` | Generate test files [default: true] |
| `--stories` | Generate Storybook files [default: true] |
| `--rollback` | Rollback changes if an error occurs [default: true] |
**Destroying**
Expand Down Expand Up @@ -939,6 +948,7 @@ The content of the generated components is different from what you'd get by runn
| `--force, -f` | Overwrite existing files |
| `--tailwind` | Generate TailwindCSS version of scaffold.css (automatically set to `true` if TailwindCSS config exists) |
| `--typescript, --ts` | Generate TypeScript files Enabled by default if we detect your project is TypeScript |
| `--rollback` | Rollback changes if an error occurs [default: true] |
**Usage**
Expand Down Expand Up @@ -1075,6 +1085,7 @@ Generates an arbitrary Node.js script in `./scripts/<name>` that can be used wit
| -------------------- | ------------------------------------------------------------------------------------ |
| `name` | Name of the service |
| `--typescript, --ts` | Generate TypeScript files Enabled by default if we detect your project is TypeScript |
| `--rollback` | Rollback changes if an error occurs [default: true] |
Scripts have access to services and libraries used in your project. Some examples of how this can be useful:
Expand Down Expand Up @@ -1120,6 +1131,7 @@ https://community.redwoodjs.com/t/prisma-beta-2-and-redwoodjs-limited-generator-
| `--force, -f` | Overwrite existing files |
| `--tests` | Generate service test and scenario [default: true] |
| `--typescript, --ts` | Generate TypeScript files Enabled by default if we detect your project is TypeScript |
| `--rollback` | Rollback changes if an error occurs [default: true] |
> **Note:** The generated sdl will include the `@requireAuth` directive by default to ensure queries and mutations are secure. If your app's queries and mutations are all public, you can set up a custom SDL generator template to apply `@skipAuth` (or a custom validator directive) to suit you application's needs.
Expand Down Expand Up @@ -1303,6 +1315,7 @@ Services are where Redwood puts its business logic. They can be used by your Gra
| `--force, -f` | Overwrite existing files |
| `--typescript, --ts` | Generate TypeScript files Enabled by default if we detect your project is TypeScript |
| `--tests` | Generate test and scenario files [default: true] |
| `--rollback` | Rollback changes if an error occurs [default: true] |
**Destroying**
Expand Down
2 changes: 2 additions & 0 deletions packages/cli/src/commands/generate/cell/cell.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { generate as generateTypes } from '@redwoodjs/internal/dist/generate/gen

import { nameVariants, transformTSToJS } from '../../../lib'
import { isWordPluralizable } from '../../../lib/pluralHelpers'
import { addFunctionToRollback } from '../../../lib/rollback'
import { isPlural, singularize } from '../../../lib/rwPluralize'
import { getSchema } from '../../../lib/schemaHelpers'
import { yargsDefaults } from '../helpers'
Expand Down Expand Up @@ -185,6 +186,7 @@ export const { command, description, builder, handler } =

if (projectHasSdl) {
await generateTypes()
addFunctionToRollback(generateTypes, true)
} else {
task.skip(
`Skipping type generation: no SDL defined for "${queryFieldName}". To generate types, run 'yarn rw g sdl ${queryFieldName}'.`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import terminalLink from 'terminal-link'

import { getPaths, writeFilesTask } from '../../../lib'
import c from '../../../lib/colors'
import { prepareForRollback } from '../../../lib/rollback'
import { yargsDefaults } from '../helpers'

const POST_RUN_INSTRUCTIONS = `Next steps...\n\n ${c.warning(
Expand Down Expand Up @@ -42,6 +43,11 @@ export const builder = (yargs) => {
description: 'A descriptor of what this data migration does',
type: 'string',
})
.option('rollback', {
description: 'Revert all generator actions if an error occurs',
type: 'boolean',
default: true,
})
.epilogue(
`Also see the ${terminalLink(
'Redwood CLI Reference',
Expand Down Expand Up @@ -75,6 +81,9 @@ export const handler = async (args) => {
)

try {
if (args.rollback) {
prepareForRollback(tasks)
}
await tasks.run()
} catch (e) {
console.log(c.error(e.message))
Expand Down
9 changes: 9 additions & 0 deletions packages/cli/src/commands/generate/dbAuth/dbAuth.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
writeFilesTask,
} from '../../../lib'
import c from '../../../lib/colors'
import { prepareForRollback } from '../../../lib/rollback'
import { yargsDefaults } from '../helpers'
import { templateForComponentFile } from '../helpers'

Expand Down Expand Up @@ -92,6 +93,11 @@ export const builder = (yargs) => {
description: 'Include WebAuthn support (TouchID/FaceID)',
type: 'boolean',
})
.option('rollback', {
description: 'Revert all generator actions if an error occurs',
type: 'boolean',
default: true,
})

.epilogue(
`Also see the ${terminalLink(
Expand Down Expand Up @@ -272,6 +278,9 @@ export const handler = async (yargs) => {
const t = tasks({ ...yargs, webAuthn: includeWebAuthn })

try {
if (yargs.rollback) {
prepareForRollback(t)
}
await t.run()
} catch (e) {
console.log(c.error(e.message))
Expand Down
14 changes: 14 additions & 0 deletions packages/cli/src/commands/generate/directive/directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import { getConfig } from '@redwoodjs/internal/dist/config'

import { getPaths, writeFilesTask, transformTSToJS } from '../../../lib'
import c from '../../../lib/colors'
import {
prepareForRollback,
addFunctionToRollback,
} from '../../../lib/rollback'
import { yargsDefaults } from '../helpers'
import {
createYargsForComponentGeneration,
Expand Down Expand Up @@ -152,6 +156,13 @@ export const handler = async (args) => {
{
title: 'Generating TypeScript definitions and GraphQL schemas ...',
task: () => {
// Regenerate again at the end if we rollback changes
addFunctionToRollback(async () => {
await execa('yarn rw-gen', [], {
stdio: 'pipe',
shell: true,
})
}, true)
return execa('yarn rw-gen', [], {
stdio: 'pipe',
shell: true,
Expand All @@ -169,6 +180,9 @@ export const handler = async (args) => {
)

try {
if (args.rollback) {
prepareForRollback(tasks)
}
await tasks.run()
} catch (e) {
console.log(c.error(e.message))
Expand Down
9 changes: 9 additions & 0 deletions packages/cli/src/commands/generate/function/function.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { errorTelemetry } from '@redwoodjs/telemetry'

import { getPaths, transformTSToJS, writeFilesTask } from '../../../lib'
import c from '../../../lib/colors'
import { prepareForRollback } from '../../../lib/rollback'
import { yargsDefaults } from '../helpers'
import { templateForComponentFile } from '../helpers'

Expand Down Expand Up @@ -100,6 +101,11 @@ export const builder = (yargs) => {
description: 'Name of the Function',
type: 'string',
})
.option('rollback', {
description: 'Revert all generator actions if an error occurs',
type: 'boolean',
default: true,
})
.epilogue(
`Also see the ${terminalLink(
'Redwood CLI Reference',
Expand Down Expand Up @@ -131,6 +137,9 @@ export const handler = async ({ name, force, ...rest }) => {
)

try {
if (rest.rollback) {
prepareForRollback(tasks)
}
await tasks.run()

console.info('')
Expand Down
9 changes: 9 additions & 0 deletions packages/cli/src/commands/generate/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { errorTelemetry } from '@redwoodjs/telemetry'
import { generateTemplate, getPaths, writeFilesTask } from '../../lib'
import c from '../../lib/colors'
import { isTypeScriptProject } from '../../lib/project'
import { prepareForRollback } from '../../lib/rollback'
import { pluralize, isPlural, isSingular } from '../../lib/rwPluralize'

/**
Expand Down Expand Up @@ -182,6 +183,11 @@ export const createYargsForComponentGeneration = ({
type: 'boolean',
default: false,
})
.option('rollback', {
description: 'Revert all generator actions if an error occurs',
type: 'boolean',
default: true,
})

// Add in passed in positionals
Object.entries(positionalsObj).forEach(([option, config]) => {
Expand Down Expand Up @@ -221,6 +227,9 @@ export const createYargsForComponentGeneration = ({
}
)

if (options.rollback) {
prepareForRollback(tasks)
}
await tasks.run()
} catch (e) {
errorTelemetry(process.argv, e.message)
Expand Down
10 changes: 9 additions & 1 deletion packages/cli/src/commands/generate/model/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import terminalLink from 'terminal-link'

import { getPaths, writeFilesTask, generateTemplate } from '../../../lib'
import c from '../../../lib/colors'
import { prepareForRollback } from '../../../lib/rollback'
import { verifyModelName } from '../../../lib/schemaHelpers'
import { yargsDefaults } from '../helpers'

const TEMPLATE_PATH = path.resolve(__dirname, 'templates', 'model.js.template')

export const files = ({ name, typescript = false }) => {
Expand All @@ -27,6 +27,11 @@ export const builder = (yargs) => {
description: 'Name of the model to create',
type: 'string',
})
.option('rollback', {
description: 'Revert all generator actions if an error occurs',
type: 'boolean',
default: true,
})
.epilogue(
`Also see the ${terminalLink(
'RedwoodRecord Reference',
Expand Down Expand Up @@ -61,6 +66,9 @@ export const handler = async ({ force, ...args }) => {

try {
await verifyModelName({ name: args.name })
if (args.rollback) {
prepareForRollback(tasks)
}
await tasks.run()
} catch (e) {
console.log(c.error(e.message))
Expand Down
13 changes: 12 additions & 1 deletion packages/cli/src/commands/generate/page/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import {
writeFilesTask,
} from '../../../lib'
import c from '../../../lib/colors'
import {
prepareForRollback,
addFunctionToRollback,
} from '../../../lib/rollback'
import {
createYargsForComponentGeneration,
pathName,
Expand Down Expand Up @@ -165,6 +169,7 @@ export const handler = async ({
tests,
stories,
typescript = false,
rollback,
}) => {
const pageName = removeGeneratorName(name, 'page')

Expand Down Expand Up @@ -228,7 +233,10 @@ export const handler = async ({
},
{
title: `Generating types...`,
task: generateTypes,
task: async () => {
await generateTypes()
addFunctionToRollback(generateTypes, true)
},
},
{
title: 'One more thing...',
Expand All @@ -247,6 +255,9 @@ export const handler = async ({
)

try {
if (rollback) {
prepareForRollback(tasks)
}
await tasks.run()
} catch (e) {
errorTelemetry(process.argv, e.message)
Expand Down
Loading

0 comments on commit 2001356

Please sign in to comment.