Skip to content

Commit

Permalink
shopify support (#127)
Browse files Browse the repository at this point in the history
shopify support

Also:

* add --force option
* check to see if CMD ends with specified command - useful if there are entrypoints
* install and run litestream from npm if Dockerfile exists
  • Loading branch information
rubys authored Jan 13, 2025
1 parent 39ed3af commit 763f98d
Show file tree
Hide file tree
Showing 15 changed files with 362 additions and 70 deletions.
Binary file modified bun.lockb
Binary file not shown.
83 changes: 81 additions & 2 deletions fly.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,21 @@ GDF.extend(class extends GDF {
// create volume for sqlite3
if (this.sqlite3) this.flyMakeVolume()

if (this.sqlite3 && this.setupScriptType === 'dbsetup') {
this.flySetCmd()
}

// setup swap
if (this.options.swap != null) this.flySetSwap()

// attach consul for litefs
if (this.litefs) this.flyAttachConsul(this.flyApp)

// set secrets, healthcheck for remix apps
if (this.remix) {
if (this.shopify) {
this.flyShopifyEnv(this.flyApp)
this.flyShopifyConfig(this.flyApp)
} else if (this.remix) {
this.flyRemixSecrets(this.flyApp)
this.flyHealthCheck('/healthcheck')
}
Expand Down Expand Up @@ -62,7 +69,7 @@ GDF.extend(class extends GDF {
this.flyToml = fs.readFileSync(this.flyTomlFile, 'utf-8')

// parse app name from fly.toml
this.flyApp = this.flyToml.match(/^app\s*=\s*"?([-\w]+)"?/m)?.[1]
this.flyApp = this.flyToml.match(/^app\s*=\s*["']?([-\w]+)["']?/m)?.[1]

// see if flyctl is in the path
const paths = (process.env.PATH || '')
Expand Down Expand Up @@ -159,6 +166,27 @@ GDF.extend(class extends GDF {
}
}

// override command in fly.toml to include dbsetup.js
flySetCmd() {
if (this.flyToml.includes('[processes]')) return

let cmd = this.startCommand

const dockerfile = fs.readFileSync('Dockerfile', 'utf8')

const match = dockerfile.match(/^\s*CMD\s+(\[.*\]|".*")/mi)
if (match) {
try {
cmd = JSON.parse(match[1])
} catch { }
}

if (Array.isArray(cmd)) cmd = cmd.join(' ')
cmd = `${this.bun ? 'bun' : 'node'} ./dbsetup.js ${cmd}`
this.flyToml += `\n[processes]\n app = ${JSON.stringify(cmd)}\n`
fs.writeFileSync(this.flyTomlFile, this.flyToml)
}

// add volume to fly.toml and create it if app exists
flyAttachConsul(app) {
if (!app) return
Expand Down Expand Up @@ -283,6 +311,57 @@ GDF.extend(class extends GDF {
})
}

// set environment and secrets for Shopify apps
flyShopifyEnv(app) {
let toml = ''
if (fs.existsSync('shopify.app.toml')) {
toml = fs.readFileSync('shopify.app.toml', 'utf-8')
}

if (!toml.includes('client_id')) {
this.setExit(42)
console.log(`${chalk.bold.red('shopify.app.toml')} is not complete; run ${chalk.bold.blue('shopify app config create')} first.`)
return
}

const env = {
PORT: 3000,
SHOPIFY_APP_URL: `https://${app}.fly.dev`
}

try {
console.log(`${chalk.bold.green('execute'.padStart(11))} shopify app env show`)
const stdout = execSync('shopify app env show', { encoding: 'utf8' })
for (const match of stdout.matchAll(/^\s*(\w+)=(.*)/mg)) {
if (match[1] === 'SHOPIFY_API_SECRET') {
console.log(`${chalk.bold.green('execute'.padStart(11))} flyctl secrets set SHOPIFY_API_SECRET`)
execSync(`${this.flyctl} secrets set SHOPIFY_API_SECRET=${match[2]} --app ${app}`, { stdio: 'inherit' })
} else {
env[match[1]] = match[2]
}
}
} catch { }

if (this.flyToml.includes('[env]')) return
this.flyToml += '\n[env]\n' + Object.entries(env).map(([key, value]) => ` ${key} = ${JSON.stringify(value)}`).join('\n') + '\n'
fs.writeFileSync(this.flyTomlFile, this.flyToml)
}

// update config for Shopify apps
flyShopifyConfig(app) {
const original = fs.readFileSync('shopify.app.toml', 'utf-8')
const url = `https://${app}.fly.dev`
const config = original.replaceAll(/"https:\/\/[-\w.]+/g, '"' + url)
.replace(/(redirect_urls\s*=\s*\[).*?\]/s,
`$1\n "${url}/auth/callback",\n "${url}/auth/shopify/callback",\n "${url}/api/auth/callback"\n]`)
if (original !== config) {
console.log(`${chalk.bold.green('update'.padStart(11, ' '))} shopify.app.toml`)
fs.writeFileSync('shopify.app.toml', config)
console.log(`${chalk.bold.green('execute'.padStart(11))} shopify app deploy --force`)
execSync('shopify app deploy --force', { stdio: 'inherit' })
}
}

// prep for deployment via GitHub actions, including setting up a staging app
flyGitHubPrep() {
const deploy = fs.readFileSync('.github/workflows/deploy.yml', 'utf-8')
Expand Down
32 changes: 28 additions & 4 deletions gdf.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ export class GDF {
// exit code
#exitCode = 0

// dockerfile exists at the time of invocation
#dockerfileExists = false

get variant() {
return this.options.alpine ? 'alpine' : 'slim'
}
Expand Down Expand Up @@ -147,6 +150,11 @@ export class GDF {
this.#pj.dependencies?.['@remix-run/node'])
}

// Does this application use shopify?
get shopify() {
return fs.existsSync(path.join(this._appdir, 'shopify.app.toml'))
}

// Is this an EpicStack application?
get epicStack() {
return !!this.#pj['epic-stack']
Expand Down Expand Up @@ -633,6 +641,10 @@ export class GDF {
modules.push('@sveltejs/adapter-node')
}

if (this.litestream && !this.#pj.dependencies?.['@flydotio/litestream']) {
modules.push('@flydotio/litestream')
}

if (modules.length === 0) return
const add = this.packager === 'npm' ? 'install' : 'add'
for (const module of modules) {
Expand Down Expand Up @@ -934,6 +946,7 @@ export class GDF {
this.options = options
this._appdir = appdir
this.#pj = JSON.parse(fs.readFileSync(path.join(appdir, 'package.json'), 'utf-8'))
this.#dockerfileExists = fs.existsSync(path.join(appdir, 'Dockerfile'))

// backwards compatibility with previous definition of --build=defer
if (options.build === 'defer') {
Expand Down Expand Up @@ -967,7 +980,11 @@ export class GDF {
}

if (this.entrypoint) {
templates['docker-entrypoint.ejs'] = `${this.configDir}docker-entrypoint.js`
if (!this.#dockerfileExists || this.options.force) {
templates['docker-entrypoint.ejs'] = `${this.configDir}docker-entrypoint.js`
} else if (this.setupScriptType === 'dbsetup') {
templates['docker-entrypoint.ejs'] = `${this.configDir}dbsetup.js`
}
}

if (this.litefs) {
Expand All @@ -984,9 +1001,9 @@ export class GDF {
}

for (const [template, filename] of Object.entries(templates)) {
const dest = await this.#writeTemplateFile(template, filename)
await this.#writeTemplateFile(template, filename)

if (template === 'docker-entrypoint.ejs') fs.chmodSync(dest, 0o755)
if (template === 'docker-entrypoint.ejs') fs.chmodSync(path.join(this._appdir, filename), 0o755)
}

// ensure that there is a dockerignore file
Expand Down Expand Up @@ -1028,7 +1045,11 @@ export class GDF {
runner.apply(this)
}

process.exit(this.#exitCode)
if (this.#exitCode) process.exit(this.#exitCode)
}

get setupScriptType() {
return (this.options.skip && this.#dockerfileExists) ? 'dbsetup' : 'docker'
}

setExit(code) {
Expand All @@ -1046,6 +1067,9 @@ export class GDF {
if (current === proposed) {
console.log(`${chalk.bold.blue('identical'.padStart(11))} ${name}`)
return dest
} else if (this.options.skip) {
console.log(`${chalk.bold.yellow('skip'.padStart(11))} ${name}`)
return current
}

let prompt
Expand Down
6 changes: 6 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ const options = yargs((hideBin(process.argv)))
describe: 'expose port',
type: 'integer'
})
.option('skip', {
describe: 'skip overwrite of existing files',
type: 'boolean'
})
.option('swap', {
alias: 's',
describe: 'allocate swap space (eg. 1G, 1GiB, 1024M)',
Expand Down Expand Up @@ -334,4 +338,6 @@ if (pj) {
}
}

if (options.force) options.skip = false

new GDF().run(process.cwd(), { ...defaults, ...options })
87 changes: 85 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"node": ">=16.0.0"
},
"dependencies": {
"@flydotio/litestream": "^1.0.1",
"@sveltejs/adapter-node": "^5.2.11",
"chalk": "^5.3.0",
"diff": "^5.2.0",
Expand Down
Loading

0 comments on commit 763f98d

Please sign in to comment.