diff --git a/.github/workflows/budibase_ci.yml b/.github/workflows/budibase_ci.yml index ed19f2c37..21d735fcb 100644 --- a/.github/workflows/budibase_ci.yml +++ b/.github/workflows/budibase_ci.yml @@ -12,7 +12,6 @@ on: jobs: build: - runs-on: ubuntu-latest strategy: @@ -21,6 +20,7 @@ jobs: steps: - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: @@ -32,5 +32,4 @@ jobs: - run: yarn test env: CI: true - name: Budibase CI - + name: Budibase CI \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..e1081904a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,58 @@ +name: Budibase Release + +on: + # Trigger the workflow on push, + # but only for the release branch + push: + branches: + - master + tags: + - 'v*' + +jobs: + release: + runs-on: ${{ matrix.os }} + + # Platforms to build on/for + strategy: + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] + node-version: [10.x] + + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: yarn + # - run: yarn lint + - run: yarn bootstrap + - run: yarn build + # - run: yarn test + + - name: Prepare for app notarization (macOS) + if: startsWith(matrix.os, 'macos') + # Import Apple API key for app notarization on macOS + run: | + mkdir -p ~/private_keys/ + echo '${{ secrets.api_key }}' > ~/private_keys/AuthKey_${{ secrets.api_key_id }}.p8 + + + - name: Build/release Electron app + uses: samuelmeuli/action-electron-builder@v1 + with: + package_root: packages/server + + # GitHub token, automatically provided to the action + # (No need to define this secret in the repo settings) + github_token: ${{ secrets.github_token }} + + mac_certs: ${{ secrets.mac_certs }} + mac_certs_password: ${{ secrets.mac_certs_password }} + + # release the app after building + release: ${{ startsWith(github.ref, 'refs/tags/v') }} + env: + # macOS notarization API key + API_KEY_ID: ${{ secrets.api_key_id }} + API_KEY_ISSUER_ID: ${{ secrets.api_key_issuer_id }} diff --git a/.gitignore b/.gitignore index 24c031d95..3b81fd63d 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,6 @@ typings/ # Serverless directories .serverless + +# Mac files +.DS_Store diff --git a/packages/.DS_Store b/packages/.DS_Store deleted file mode 100644 index 80d62469c..000000000 Binary files a/packages/.DS_Store and /dev/null differ diff --git a/packages/builder/src/global.css b/packages/builder/src/global.css index 690c18e1d..999415931 100644 --- a/packages/builder/src/global.css +++ b/packages/builder/src/global.css @@ -1,4 +1,3 @@ -@import "./budibase.css"; :root { --primary100: #0055ff; diff --git a/packages/builder/src/main.js b/packages/builder/src/main.js index 0fadfc0bd..77dcc4e17 100644 --- a/packages/builder/src/main.js +++ b/packages/builder/src/main.js @@ -1,6 +1,6 @@ -import App from "./App.svelte" import "./global.css" import "./fonts.css" +import "./budibase.css"; import "/assets/roboto-v20-latin-ext_latin-300" import "/assets/roboto-v20-latin-ext_latin-400" import "/assets/roboto-v20-latin-ext_latin-500" @@ -12,6 +12,7 @@ import "uikit/dist/css/uikit.min.css" import "uikit/dist/js/uikit.min.js" import "codemirror/lib/codemirror.css" import "codemirror/theme/monokai.css" +import App from "./App.svelte" /* eslint-disable */ const app = new App({ diff --git a/packages/server/.DS_Store b/packages/server/.DS_Store deleted file mode 100644 index d7a28e728..000000000 Binary files a/packages/server/.DS_Store and /dev/null differ diff --git a/packages/server/build/.DS_Store b/packages/server/build/.DS_Store deleted file mode 100644 index 0199b6c9b..000000000 Binary files a/packages/server/build/.DS_Store and /dev/null differ diff --git a/packages/server/build/entitlements.mac.plist b/packages/server/build/entitlements.mac.plist new file mode 100644 index 000000000..181db8f1f --- /dev/null +++ b/packages/server/build/entitlements.mac.plist @@ -0,0 +1,14 @@ + + + + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.allow-dyld-environment-variables + + com.apple.security.cs.disable-library-validation + + + \ No newline at end of file diff --git a/packages/server/build/icon.png b/packages/server/build/icon.png new file mode 100644 index 000000000..dd06244d9 Binary files /dev/null and b/packages/server/build/icon.png differ diff --git a/packages/server/package.json b/packages/server/package.json index a501774a1..42d56712c 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -2,7 +2,26 @@ "name": "@budibase/server", "version": "0.0.32", "description": "Budibase Web Server", - "main": "src/index.js", + "main": "src/electron.js", + "repository": { + "type": "git", + "url": "https://github.com/Budibase/budibase.git" + }, + "build": { + "appId": "com.budibase.builder", + "productName": "Budibase Builder", + "afterSign": "electron-builder-notarize", + "mac": { + "category": "public.app-category.developer-tools", + "hardenedRuntime": true + }, + "linux": { + "target": [ + "AppImage" + ], + "category": "Development" + } + }, "scripts": { "test": "jest", "test:integration": "jest routes --runInBand", @@ -11,6 +30,9 @@ "budi": "node ../cli/bin/budi", "dev:builder": "nodemon ../cli/bin/budi run", "electron": "electron src/electron.js", + "build:electron": "electron-builder --dir", + "publish:electron": "electron-builder -mwl --publish always", + "postinstall": "electron-builder install-app-deps", "lint": "eslint --fix src/" }, "keywords": [ @@ -25,6 +47,9 @@ "ajv": "^6.12.2", "bcryptjs": "^2.4.3", "dotenv": "^8.2.0", + "electron-is-dev": "^1.2.0", + "electron-unhandled": "^3.0.2", + "electron-updater": "^4.3.1", "fs-extra": "^8.1.0", "jsonwebtoken": "^8.5.1", "koa": "^2.7.0", @@ -47,6 +72,7 @@ "@jest/test-sequencer": "^24.8.0", "electron": "^8.2.5", "electron-builder": "^22.6.0", + "electron-builder-notarize": "^1.1.2", "eslint": "^6.8.0", "jest": "^24.8.0", "nodemon": "^2.0.2", diff --git a/packages/server/src/api/controllers/static.js b/packages/server/src/api/controllers/static.js index aeaa4319f..32542de54 100644 --- a/packages/server/src/api/controllers/static.js +++ b/packages/server/src/api/controllers/static.js @@ -7,7 +7,7 @@ const { const env = require("../../environment") exports.serveBuilder = async function(ctx) { - let builderPath = resolve(process.cwd(), "builder") + let builderPath = resolve(__dirname, "../../../builder") ctx.cookies.set("builder:token", env.ADMIN_SECRET) await send(ctx, ctx.file, { root: ctx.devPath || builderPath }) } diff --git a/packages/server/src/electron.js b/packages/server/src/electron.js index 68350795d..b4bae9d70 100644 --- a/packages/server/src/electron.js +++ b/packages/server/src/electron.js @@ -1,15 +1,47 @@ -const { app, BrowserWindow } = require('electron'); -const { join } = require("path") -const { homedir } = require("os") +const { app, BrowserWindow } = require("electron"); +const { join } = require("path"); +const { homedir } = require("os"); +const isDev = require("electron-is-dev"); +const { autoUpdater } = require("electron-updater"); +const unhandled = require("electron-unhandled"); -require("dotenv").config({ path: join(homedir(), ".budibase", ".env") }) +require("dotenv").config({ path: join(homedir(), ".budibase", ".env") }); -const DEV_URL = "http://localhost:4001"; +if (isDev) { + unhandled({ + showDialog: true + }); +} + +const APP_URL = "http://localhost:4001"; +const APP_TITLE = "Budibase Builder"; + +let win function createWindow() { app.server = require("./app"); - let win = new BrowserWindow({ width: 1920, height: 1080 }); - win.loadURL(DEV_URL); + win = new BrowserWindow({ width: 1920, height: 1080 }); + win.setTitle(APP_TITLE); + win.loadURL(APP_URL); + if (isDev) { + win.webContents.openDevTools(); + } else { + autoUpdater.checkForUpdatesAndNotify(); + } } -app.whenReady().then(createWindow) \ No newline at end of file +app.whenReady().then(createWindow) + + +// Quit when all windows are closed. +app.on("window-all-closed", () => { + // On macOS it is common for applications and their menu bar + // to stay active until the user quits explicitly with Cmd + Q + if (process.platform !== "darwin") app.quit(); +}); + +app.on("activate", () => { + // On macOS it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + if (win === null) createWindow(); +}); \ No newline at end of file diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock index 6bba54959..449463063 100644 --- a/packages/server/yarn.lock +++ b/packages/server/yarn.lock @@ -523,6 +523,18 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.38.tgz#58841a382f231ad005dbb935c36d44aa1118a26b" integrity sha512-75eLjX0pFuTcUXnnWmALMzzkYorjND0ezNEycaKesbUBg9eGZp4GHPuDmkRc4mQQvIpe29zrzATNRA6hkYqwmA== +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== + +"@types/semver@^7.1.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.2.0.tgz#0d72066965e910531e1db4621c15d0ca36b8d83b" + integrity sha512-TbB0A8ACUWZt3Y6bQPstW9QNbhNeebdgLX4T/ZfkrswAfUzRiXrgd9seol+X379Wa589Pu4UEx9Uok0D4RjRCQ== + dependencies: + "@types/node" "*" + "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -1275,6 +1287,11 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +clean-stack@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + cli-boxes@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" @@ -1809,6 +1826,14 @@ ejs@^3.1.2: dependencies: jake "^10.6.1" +electron-builder-notarize@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/electron-builder-notarize/-/electron-builder-notarize-1.1.2.tgz#29939591c6edf133aadc8450d975e9ce94a15da3" + integrity sha512-IiuG+Wwky4EwekhJ9T5t9m00sFL9EGUrkyr4wqivXxrvtWIGAh2WCUwO6e47l3W8nE/4ng0v+VNJhZEIlCu1xg== + dependencies: + electron-notarize "^0.2.0" + read-pkg-up "^7.0.0" + electron-builder@^22.6.0: version "22.6.0" resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-22.6.0.tgz#3ac81634e27026892d66f3a52568e65a7d28d26a" @@ -1829,6 +1854,19 @@ electron-builder@^22.6.0: update-notifier "^4.1.0" yargs "^15.3.1" +electron-is-dev@^1.0.1, electron-is-dev@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/electron-is-dev/-/electron-is-dev-1.2.0.tgz#2e5cea0a1b3ccf1c86f577cee77363ef55deb05e" + integrity sha512-R1oD5gMBPS7PVU8gJwH6CtT0e6VSoD0+SzSnYpNm+dBkcijgA+K7VAMHDfnRq/lkKPZArpzplTW6jfiMYosdzw== + +electron-notarize@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/electron-notarize/-/electron-notarize-0.2.1.tgz#759e8006decae19134f82996ed910db26d9192cc" + integrity sha512-oZ6/NhKeXmEKNROiFmRNfytqu3cxqC95sjooG7kBXQVEUSQkZnbiAhxVh5jXngL881G197pbwpeVPJyM7Ikmxw== + dependencies: + debug "^4.1.1" + fs-extra "^8.1.0" + electron-publish@22.6.0: version "22.6.0" resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.6.0.tgz#11dca595cfe3c0fdbc364c28dbb8838a1c6ec799" @@ -1843,6 +1881,29 @@ electron-publish@22.6.0: lazy-val "^1.0.4" mime "^2.4.4" +electron-unhandled@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/electron-unhandled/-/electron-unhandled-3.0.2.tgz#e14a19c830ccf7b6e755191c8e78d23094d25112" + integrity sha512-IIqXnM5eNgV7k5sDA/GZ39ygJbpfF3WTArNGQ1TB4AI6ajQuuVztA0M6Mq9uEpmTh5gz4nR+YsTNWYsHLoM5rw== + dependencies: + clean-stack "^2.1.0" + electron-is-dev "^1.0.1" + ensure-error "^2.0.0" + lodash.debounce "^4.0.8" + +electron-updater@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.3.1.tgz#9d485b6262bc56fcf7ee62b1dc1b3b105a3e96a7" + integrity sha512-UDC5AHCgeiHJYDYWZG/rsl1vdAFKqI/Lm7whN57LKAk8EfhTewhcEHzheRcncLgikMcQL8gFo1KeX51tf5a5Wg== + dependencies: + "@types/semver" "^7.1.0" + builder-util-runtime "8.7.0" + fs-extra "^9.0.0" + js-yaml "^3.13.1" + lazy-val "^1.0.4" + lodash.isequal "^4.5.0" + semver "^7.1.3" + electron@^8.2.5: version "8.2.5" resolved "https://registry.yarnpkg.com/electron/-/electron-8.2.5.tgz#ae3cb23d5517b2189fd35298e487198d65d1a291" @@ -1891,6 +1952,11 @@ end-stream@~0.1.0: dependencies: write-stream "~0.4.3" +ensure-error@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ensure-error/-/ensure-error-2.1.0.tgz#f11fbe383c0cf4a54850ac77acceb7bc06e0f99d" + integrity sha512-+BMSJHw9gxiJAAp2ZR1E0TNcL09dD3lOvkl7WVm4+Y6xnes/pMetP/TzCHiDduh8ihNDjbGfuYxl7l4PA1xZ8A== + env-paths@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" @@ -4098,6 +4164,11 @@ lie@3.0.4: inline-process-browser "^1.0.0" unreachable-branch-transform "^0.3.0" +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" @@ -4123,6 +4194,11 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= + lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" @@ -4133,6 +4209,11 @@ lodash.isboolean@^3.0.3: resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= + lodash.isinteger@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" @@ -4729,6 +4810,16 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-json@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" + integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + lines-and-columns "^1.1.6" + parse5@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" @@ -5117,6 +5208,15 @@ read-pkg-up@^4.0.0: find-up "^3.0.0" read-pkg "^3.0.0" +read-pkg-up@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" @@ -5126,6 +5226,16 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + readable-stream@1.0.33: version "1.0.33" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.33.tgz#3a360dd66c1b1d7fd4705389860eda1d0f61126c" @@ -5490,7 +5600,7 @@ semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.1.2, semver@^7.3.2: +semver@^7.1.2, semver@^7.1.3, semver@^7.3.2: version "7.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== @@ -6197,6 +6307,11 @@ type-fest@^0.11.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + type-fest@^0.8.0, type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"