Skip to content

Commit

Permalink
fix(deploy): Restore Render deploy setup script (#11857)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tobbe authored Dec 28, 2024
1 parent 8b0e58f commit b5f49a6
Showing 1 changed file with 108 additions and 100 deletions.
208 changes: 108 additions & 100 deletions packages/cli/src/commands/setup/deploy/providers/render.js
Original file line number Diff line number Diff line change
@@ -1,119 +1,127 @@
// import terminalLink from 'terminal-link'
import path from 'path'

import execa from 'execa'
import { getSchema, getConfig } from '@prisma/internals'
import fs from 'fs-extra'
import terminalLink from 'terminal-link'
import { Listr } from 'listr2'

import { recordTelemetryAttributes } from '@redwoodjs/cli-helpers'
import { getPaths } from '@redwoodjs/project-config'
import { errorTelemetry } from '@redwoodjs/telemetry'

// It's easy for the api side to exceed Render's free-plan limit.
// Because telemetryMiddleware is added to Yargs as middleware,
// we need to set the env var here outside the handler to correctly disable it.
if (process.argv.slice(2).includes('api')) {
process.env.REDWOOD_DISABLE_TELEMETRY = 1
}

export const command = 'render <side>'
export const description = 'Build, migrate, and serve command for Render deploy'

export const builder = (yargs) => {
yargs
.positional('side', {
choices: ['api', 'web'],
description: 'Side to deploy',
type: 'string',
})
.option('prisma', {
description: 'Apply database migrations',
type: 'boolean',
default: true,
})
.option('data-migrate', {
description: 'Apply data migrations',
type: 'boolean',
default: true,
alias: 'dm',
})
.epilogue(
`For more commands, options, and examples, see ${terminalLink(
'Redwood CLI Reference',
'https://redwoodjs.com/docs/cli-commands#deploy',
)}`,
)
}

export const handler = async ({ side, prisma, dataMigrate }) => {
recordTelemetryAttributes({
command: 'deploy render',
side,
prisma,
dataMigrate,
})
import { getPaths, writeFilesTask, printSetupNotes } from '../../../../lib'
import c from '../../../../lib/colors'
import { addFilesTask, updateApiURLTask } from '../helpers'
import {
POSTGRES_YAML,
RENDER_HEALTH_CHECK,
RENDER_YAML,
SQLITE_YAML,
} from '../templates/render'

const rwjsPaths = getPaths()
export const command = 'render'
export const description = 'Setup Render deploy'

const execaConfig = {
cwd: rwjsPaths.base,
shell: true,
stdio: 'inherit',
}

async function runApiCommands() {
if (prisma) {
console.log('Running database migrations...')
execa.commandSync(
`node_modules/.bin/prisma migrate deploy --schema "${rwjsPaths.api.dbSchema}"`,
execaConfig,
)
export const getRenderYamlContent = async (database) => {
if (database === 'none') {
return {
path: path.join(getPaths().base, 'render.yaml'),
content: RENDER_YAML(''),
}
}
if (!fs.existsSync('api/db/schema.prisma')) {
throw new Error("Could not find prisma schema at 'api/db/schema.prisma'")
}

if (dataMigrate) {
console.log('Running data migrations...')
const packageJson = fs.readJsonSync(
path.join(rwjsPaths.base, 'package.json'),
)
const hasDataMigratePackage =
!!packageJson.devDependencies['@redwoodjs/cli-data-migrate']
const schema = await getSchema('api/db/schema.prisma')
const config = await getConfig({ datamodel: schema })
const detectedDatabase = config.datasources[0].activeProvider

if (!hasDataMigratePackage) {
console.error(
[
"Skipping data migrations; your project doesn't have the `@redwoodjs/cli-data-migrate` package as a dev dependency.",
"Without it installed, you're likely to run into memory issues during deploy.",
"If you want to run data migrations, add the package to your project's root package.json and deploy again:",
'',
'```',
'yarn add -D @redwoodjs/cli-data-migrate',
'```',
].join('\n'),
)
} else {
execa.commandSync('yarn rw dataMigrate up', execaConfig)
}
if (detectedDatabase === database) {
switch (database) {
case 'postgresql':
return {
path: path.join(getPaths().base, 'render.yaml'),
content: RENDER_YAML(POSTGRES_YAML),
}
case 'sqlite':
return {
path: path.join(getPaths().base, 'render.yaml'),
content: RENDER_YAML(SQLITE_YAML),
}
default:
throw new Error(`
Unexpected datasource provider found: ${database}`)
}
} else {
throw new Error(`
Prisma datasource provider is detected to be ${detectedDatabase}.
const serverFilePath = path.join(rwjsPaths.api.dist, 'server.js')
const hasServerFile = fs.pathExistsSync(serverFilePath)
Option 1: Update your schema.prisma provider to be ${database}, then run
yarn rw prisma migrate dev
yarn rw setup deploy render --database ${database}
if (hasServerFile) {
execa(`yarn node ${serverFilePath}`, execaConfig)
} else {
const { handler } = await import(
'@redwoodjs/api-server/dist/apiCLIConfigHandler.js'
)
handler()
}
Option 2: Rerun setup deploy command with current schema.prisma provider:
yarn rw setup deploy render --database ${detectedDatabase}`)
}
}

async function runWebCommands() {
execa.commandSync('yarn install', execaConfig)
execa.commandSync('yarn rw build web --verbose', execaConfig)
}
export const builder = (yargs) =>
yargs.option('database', {
alias: 'd',
choices: ['none', 'postgresql', 'sqlite'],
description: 'Database deployment for Render only',
default: 'postgresql',
type: 'string',
})

// any notes to print out when the job is done
const notes = [
'You are ready to deploy to Render!\n',
'Go to https://dashboard.render.com/iacs to create your account and deploy to Render',
'Check out the deployment docs at https://render.com/docs/deploy-redwood for detailed instructions',
'Note: After first deployment to Render update the rewrite rule destination in `./render.yaml`',
]

const additionalFiles = [
{
path: path.join(getPaths().base, 'api/src/functions/healthz.js'),
content: RENDER_HEALTH_CHECK,
},
]

export const handler = async ({ force, database }) => {
recordTelemetryAttributes({
command: 'setup deploy render',
force,
database,
})
const tasks = new Listr(
[
{
title: 'Adding render.yaml',
task: async () => {
const fileData = await getRenderYamlContent(database)
let files = {}
files[fileData.path] = fileData.content
return writeFilesTask(files, { overwriteExisting: force })
},
},
updateApiURLTask('/.redwood/functions'),
// Add health check api function
addFilesTask({
files: additionalFiles,
force,
}),
printSetupNotes(notes),
],
{ rendererOptions: { collapseSubtasks: false } },
)

if (side === 'api') {
runApiCommands()
} else if (side === 'web') {
runWebCommands()
try {
await tasks.run()
} catch (e) {
errorTelemetry(process.argv, e.message)
console.error(c.error(e.message))
process.exit(e?.exitCode || 1)
}
}

0 comments on commit b5f49a6

Please sign in to comment.