diff --git a/packages/builder/assets/deploy-rocket.jpg b/packages/builder/assets/deploy-rocket.jpg new file mode 100644 index 0000000000..497afe87af Binary files /dev/null and b/packages/builder/assets/deploy-rocket.jpg differ diff --git a/packages/builder/assets/deploy_rocket.jpg b/packages/builder/assets/deploy_rocket.jpg deleted file mode 100644 index dc4e198bd1..0000000000 Binary files a/packages/builder/assets/deploy_rocket.jpg and /dev/null differ diff --git a/packages/builder/src/pages/[application]/deploy/index.svelte b/packages/builder/src/pages/[application]/deploy/index.svelte index f9ea6bf776..df264423a9 100644 --- a/packages/builder/src/pages/[application]/deploy/index.svelte +++ b/packages/builder/src/pages/[application]/deploy/index.svelte @@ -1 +1,60 @@ - + + +
+
+

It's time to shine!

+ +
+ +
+ + diff --git a/packages/server/builder/assets/deploy-rocket.jpg b/packages/server/builder/assets/deploy-rocket.jpg new file mode 100644 index 0000000000..497afe87af Binary files /dev/null and b/packages/server/builder/assets/deploy-rocket.jpg differ diff --git a/packages/server/deploy.sh b/packages/server/deploy.sh index b027fd812a..85e851f5fa 100755 --- a/packages/server/deploy.sh +++ b/packages/server/deploy.sh @@ -1,3 +1,3 @@ -docker build -t prod-apps-budi-live . -docker tag prod-apps-budi-live:latest 545012296077.dkr.ecr.eu-west-1.amazonaws.com/prod-apps-budi-live:latest -docker push 545012296077.dkr.ecr.eu-west-1.amazonaws.com/prod-apps-budi-live:latest +docker build -t prod-budi-app-server . +docker tag prod-budi-app-server:latest 545012296077.dkr.ecr.eu-west-1.amazonaws.com/prod-budi-app-server:latest +docker push 545012296077.dkr.ecr.eu-west-1.amazonaws.com/prod-budi-app-server:latest diff --git a/packages/server/src/api/controllers/deploy.js b/packages/server/src/api/controllers/deploy.js deleted file mode 100644 index a7ee2333f8..0000000000 --- a/packages/server/src/api/controllers/deploy.js +++ /dev/null @@ -1,83 +0,0 @@ -const fs = require("fs") -const AWS = require("aws-sdk") -const CouchDB = require("../../db") -const { - budibaseAppsDir, -} = require("../../utilities/budibaseDir") - -const s3 = new AWS.S3({ - params: { - Bucket: process.env.BUDIBASE_APP_ASSETS_BUCKET - } -}) - -async function uploadAppAssets({ clientId, appId }) { - const appAssetsPath = `${budibaseAppsDir()}/${appId}/public` - - const appPages = fs.readdirSync(appAssetsPath) - - const uploads = [] - - for (let page of appPages) { - for (let filename of fs.readdirSync(`${appAssetsPath}/${page}`)) { - const filePath = `${appAssetsPath}/${page}/${filename}` - const stat = await fs.lstatSync(filePath) - - // TODO: need to account for recursively traversing dirs - if (stat.isFile()) { - const fileBytes = fs.readFileSync(`${appAssetsPath}/${page}/${filename}`) - - const upload = s3.upload({ - Key: `${clientId}/${appId}/${page}/${filename}`, - Body: fileBytes - }).promise() - - uploads.push(upload) - } - } - } - - try { - await Promise.all(uploads) - } catch (err) { - console.error("Error uploading budibase app assets to s3", err) - throw err - } -} - -function replicateCouch(instanceId) { - return new Promise((resolve, reject) => { - const localDb = new CouchDB(instanceId) - const remoteDb = new CouchDB(`${process.env.COUCH_DB_REMOTE}/${instanceId}`) - - const replication = localDb.replicate.to(remoteDb); - - replication.on("complete", () => resolve()) - replication.on("error", err => reject(err)) - }); - -} - -exports.deployApp = async function(ctx) { - const { - user = { - instanceId: "test_instance_id", - clientId: "test123", - appId: "24602c068a2d494cb09cb48f44bfdd8f" - } - } = ctx; - - // TODO: This should probably be async - it could take a while - try { - // upload all the assets to s3 - await uploadAppAssets(user) - - // replicate the DB to the couchDB cluster in prod - await replicateCouch(user.instanceId); - - ctx.body = "Deployment Successful!" - - } catch (err) { - ctx.throw(err.status || 500, `Deployment Failed: ${err.message}`); - } -} \ No newline at end of file diff --git a/packages/server/src/api/controllers/deploy/aws.js b/packages/server/src/api/controllers/deploy/aws.js new file mode 100644 index 0000000000..1c5d2a0602 --- /dev/null +++ b/packages/server/src/api/controllers/deploy/aws.js @@ -0,0 +1,79 @@ +const fs = require("fs") +const AWS = require("aws-sdk") +const fetch = require("node-fetch") +const { + budibaseAppsDir, +} = require("../../../utilities/budibaseDir") + +async function fetchTemporaryCredentials() { + const CREDENTIALS_URL = "https://dt4mpwwap8.execute-api.eu-west-1.amazonaws.com/prod/" + + const response = await fetch(CREDENTIALS_URL, { + method: "POST", + body: JSON.stringify({ + apiKey: "d498278c-4ab4-144b-c212-b8f9e6da5c2b" + }) + }) + + if (response.status !== 200) { + throw new Error + } + + const json = await response.json() + + return json +} + +exports.uploadAppAssets = async function ({ appId }) { + const { credentials, accountId } = await fetchTemporaryCredentials() + console.log({ + credentials, + accountId + }); + + AWS.config.update({ + accessKeyId: credentials.AccessKeyId, + secretAccessKey: credentials.SecretAccessKey, + sessionToken: credentials.SessionToken + }); + + const s3 = new AWS.S3({ + params: { + Bucket: process.env.BUDIBASE_APP_ASSETS_BUCKET + } + }) + + const appAssetsPath = `${budibaseAppsDir()}/${appId}/public` + + const appPages = fs.readdirSync(appAssetsPath) + + const uploads = [] + + for (let page of appPages) { + for (let filename of fs.readdirSync(`${appAssetsPath}/${page}`)) { + const filePath = `${appAssetsPath}/${page}/${filename}` + const stat = await fs.lstatSync(filePath) + + // TODO: need to account for recursively traversing dirs + if (stat.isFile()) { + const fileBytes = fs.readFileSync(`${appAssetsPath}/${page}/${filename}`) + + console.log(`${accountId}/${appId}/${page}/${filename}`) + + const upload = s3.upload({ + Key: `assets/${accountId}/${appId}/${page}/${filename}`, + Body: fileBytes + }).promise() + + uploads.push(upload) + } + } + } + + try { + await Promise.all(uploads) + } catch (err) { + console.error("Error uploading budibase app assets to s3", err) + throw err + } +} \ No newline at end of file diff --git a/packages/server/src/api/controllers/deploy/index.js b/packages/server/src/api/controllers/deploy/index.js new file mode 100644 index 0000000000..34c4dcbea8 --- /dev/null +++ b/packages/server/src/api/controllers/deploy/index.js @@ -0,0 +1,44 @@ +const CouchDB = require("pouchdb") +const PouchDB = require("../../../db") +const { + uploadAppAssets, +} = require("./aws") + +function replicateCouch(instanceId) { + return new Promise((resolve, reject) => { + const localDb = new PouchDB(instanceId) + const remoteDb = new CouchDB(`${process.env.COUCH_DB_REMOTE}/${instanceId}`) + + const replication = localDb.replicate.to(remoteDb); + + replication.on("complete", () => resolve()) + replication.on("error", err => reject(err)) + }); +} + +exports.deployApp = async function(ctx) { + // TODO: This should probably be async - it could take a while + try { + const clientAppLookupDB = new PouchDB("client_app_lookup") + console.log(ctx.user) + const { clientId } = await clientAppLookupDB.get(ctx.user.appId) + + ctx.log.info(`Uploading assets for appID ${ctx.user.appId} assets to s3..`); + await uploadAppAssets({ + clientId, + appId: ctx.user.appId + }) + + // replicate the DB to the couchDB cluster in prod + ctx.log.info("Replicating local PouchDB to remote.."); + await replicateCouch(ctx.user.instanceId); + + ctx.body = { + status: "SUCCESS", + completed: Date.now() + } + + } catch (err) { + ctx.throw(err.status || 500, `Deployment Failed: ${err.message}`); + } +} \ No newline at end of file diff --git a/packages/server/src/api/controllers/static.js b/packages/server/src/api/controllers/static.js index 2e1806ccaa..2b7090fed0 100644 --- a/packages/server/src/api/controllers/static.js +++ b/packages/server/src/api/controllers/static.js @@ -8,8 +8,7 @@ const setBuilderToken = require("../../utilities/builder/setBuilderToken") const { ANON_LEVEL_ID } = require("../../utilities/accessLevels") const jwt = require("jsonwebtoken") const fetch = require("node-fetch") - -const S3_URL_PREFIX = "https://s3-eu-west-1.amazonaws.com/apps.budibase.com" +const { S3 } = require("aws-sdk") exports.serveBuilder = async function(ctx) { let builderPath = resolve(__dirname, "../../../builder") @@ -47,15 +46,16 @@ exports.serveApp = async function(ctx) { const { file = "index.html" } = ctx + if (ctx.isCloud) { - const requestUrl = `${S3_URL_PREFIX}/${ctx.params.appId}/public/${mainOrAuth}/${file}` - console.log('request url:' , requestUrl) - const response = await fetch(requestUrl) + const S3_URL = `https://${ctx.params.appId}.app.budi.live/assets/${ctx.params.appId}/public/${mainOrAuth}/${file}` + const response = await fetch(S3_URL) const body = await response.text() ctx.body = body - } else { - await send(ctx, file, { root: ctx.devPath || appPath }) + return } + + await send(ctx, file, { root: ctx.devPath || appPath }) } exports.serveAppAsset = async function(ctx) { @@ -69,15 +69,15 @@ exports.serveAppAsset = async function(ctx) { mainOrAuth ) - if (ctx.isCloud) { - const requestUrl = `${S3_URL_PREFIX}/${appId}/public/${mainOrAuth}/${ctx.file || "index.html"}` - console.log('request url:' , requestUrl) - const response = await fetch(requestUrl) - const body = await response.text() - ctx.body = body - } else { + // if (ctx.isCloud) { + // const requestUrl = `${S3_URL_PREFIX}/${appId}/public/${mainOrAuth}/${ctx.file || "index.html"}` + // console.log('request url:' , requestUrl) + // const response = await fetch(requestUrl) + // const body = await response.text() + // ctx.body = body + // } else { await send(ctx, ctx.file, { root: ctx.devPath || appPath }) - } + // } } exports.serveComponentLibrary = async function(ctx) { @@ -98,16 +98,16 @@ exports.serveComponentLibrary = async function(ctx) { ) } - if (ctx.isCloud) { - const appId = ctx.user.appId - const requestUrl = encodeURI(`${S3_URL_PREFIX}/${appId}/node_modules/${ctx.query.library}/dist/index.js`) - console.log('request url components: ', requestUrl) - const response = await fetch(requestUrl) - const body = await response.text() - ctx.type = 'application/javascript' - ctx.body = body; - return - } + // if (ctx.isCloud) { + // const appId = ctx.user.appId + // const requestUrl = encodeURI(`${S3_URL_PREFIX}/${appId}/node_modules/${ctx.query.library}/dist/index.js`) + // console.log('request url components: ', requestUrl) + // const response = await fetch(requestUrl) + // const body = await response.text() + // ctx.type = 'application/javascript' + // ctx.body = body; + // return + // } await send(ctx, "/index.js", { root: componentLibraryPath }) } diff --git a/packages/server/src/api/index.js b/packages/server/src/api/index.js index d246b9e4f9..a3d7fbffc9 100644 --- a/packages/server/src/api/index.js +++ b/packages/server/src/api/index.js @@ -42,8 +42,8 @@ router jwtSecret: env.JWT_SECRET, useAppRootPath: true, } - // ctx.isDev = env.NODE_ENV !== "production" && env.NODE_ENV !== "jest" - ctx.isCloud = true + ctx.isDev = env.NODE_ENV !== "production" && env.NODE_ENV !== "jest" + // ctx.isCloud = true await next() }) .use(authenticated) diff --git a/packages/server/src/api/routes/deploy.js b/packages/server/src/api/routes/deploy.js index 4964d555e5..dcd9ecb00f 100644 --- a/packages/server/src/api/routes/deploy.js +++ b/packages/server/src/api/routes/deploy.js @@ -6,6 +6,6 @@ const { BUILDER } = require("../../utilities/accessLevels") const router = Router() // router.post("/:appId/deploy", authorized(BUILDER), controller.deployApp) -router.post("/:appId/deploy", controller.deployApp) +router.post("/deploy", controller.deployApp) module.exports = router diff --git a/packages/server/src/app.js b/packages/server/src/app.js index 3a298d854b..c3862567c3 100644 --- a/packages/server/src/app.js +++ b/packages/server/src/app.js @@ -16,7 +16,7 @@ app.use( prettyPrint: { levelFirst: true, }, - level: env.LOG_LEVEL || "error", + level: "info" || "info", }) )