diff --git a/.github/workflows/release-master.yml b/.github/workflows/release-master.yml index 9ab8530341..df25182cd6 100644 --- a/.github/workflows/release-master.yml +++ b/.github/workflows/release-master.yml @@ -36,6 +36,7 @@ jobs: - uses: actions/setup-node@v1 with: node-version: 18.x + cache: yarn - run: yarn install --frozen-lockfile - name: Update versions @@ -63,14 +64,64 @@ jobs: echo "Using tag $version" echo "version=$version" >> "$GITHUB_OUTPUT" - - name: Build/release Docker images + - name: Setup Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v1 + + - name: Docker login run: | docker login -u $DOCKER_USER -p $DOCKER_PASSWORD - yarn build:docker env: DOCKER_USER: ${{ secrets.DOCKER_USERNAME }} DOCKER_PASSWORD: ${{ secrets.DOCKER_API_KEY }} - BUDIBASE_RELEASE_VERSION: ${{ steps.currenttag.outputs.version }} + + - name: Build worker docker + uses: docker/build-push-action@v5 + with: + context: . + push: true + platforms: linux/amd64,linux/arm64 + build-args: | + BUDIBASE_VERSION=${{ env.BUDIBASE_VERSION }} + tags: ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} + file: ./packages/worker/Dockerfile.v2 + cache-from: type=registry,ref=${{ env.IMAGE_NAME }}:latest + cache-to: type=inline + env: + IMAGE_NAME: budibase/worker + IMAGE_TAG: ${{ steps.currenttag.outputs.version }} + BUDIBASE_VERSION: ${{ steps.currenttag.outputs.version }} + + - name: Build server docker + uses: docker/build-push-action@v5 + with: + context: . + push: true + platforms: linux/amd64,linux/arm64 + build-args: | + BUDIBASE_VERSION=${{ env.BUDIBASE_VERSION }} + tags: ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} + file: ./packages/server/Dockerfile.v2 + cache-from: type=registry,ref=${{ env.IMAGE_NAME }}:latest + cache-to: type=inline + env: + IMAGE_NAME: budibase/apps + IMAGE_TAG: ${{ steps.currenttag.outputs.version }} + BUDIBASE_VERSION: ${{ steps.currenttag.outputs.version }} + + - name: Build proxy docker + uses: docker/build-push-action@v5 + with: + context: ./hosting/proxy + push: true + platforms: linux/amd64,linux/arm64 + tags: ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} + file: ./hosting/proxy/Dockerfile + cache-from: type=registry,ref=${{ env.IMAGE_NAME }}:latest + cache-to: type=inline + env: + IMAGE_NAME: budibase/proxy + IMAGE_TAG: ${{ steps.currenttag.outputs.version }} release-helm-chart: needs: [release-images] diff --git a/.github/workflows/release-singleimage.yml b/.github/workflows/release-singleimage.yml index f7f87f6e4c..4d35916f4d 100644 --- a/.github/workflows/release-singleimage.yml +++ b/.github/workflows/release-singleimage.yml @@ -67,7 +67,7 @@ jobs: push: true platforms: linux/amd64,linux/arm64 tags: budibase/budibase,budibase/budibase:${{ env.RELEASE_VERSION }} - file: ./hosting/single/Dockerfile + file: ./hosting/single/Dockerfile.v2 - name: Tag and release Budibase Azure App Service docker image uses: docker/build-push-action@v2 with: @@ -76,4 +76,4 @@ jobs: platforms: linux/amd64 build-args: TARGETBUILD=aas tags: budibase/budibase-aas,budibase/budibase-aas:${{ env.RELEASE_VERSION }} - file: ./hosting/single/Dockerfile + file: ./hosting/single/Dockerfile.v2 diff --git a/hosting/scripts/linux/release-to-docker-hub.sh b/hosting/scripts/linux/release-to-docker-hub.sh deleted file mode 100755 index 599a10f914..0000000000 --- a/hosting/scripts/linux/release-to-docker-hub.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -tag=$1 - -if [[ ! "$tag" ]]; then - echo "No tag present. You must pass a tag to this script" - exit 1 -fi - -echo "Tagging images with tag: $tag" - -docker tag proxy-service budibase/proxy:$tag -docker tag app-service budibase/apps:$tag -docker tag worker-service budibase/worker:$tag - -docker push --all-tags budibase/apps -docker push --all-tags budibase/worker -docker push --all-tags budibase/proxy diff --git a/lerna.json b/lerna.json index 384473120b..6df4a4c4cd 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.11.45", + "version": "2.12.1", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/package.json b/package.json index d3f4903e6c..417fb31e0e 100644 --- a/package.json +++ b/package.json @@ -54,10 +54,6 @@ "lint:fix:prettier": "prettier --write \"packages/**/*.{js,ts,svelte}\" && prettier --write \"examples/**/*.{js,ts,svelte}\" && prettier --write \"qa-core/**/*.{js,ts,svelte}\"", "lint:fix": "yarn run lint:fix:prettier && yarn run lint:fix:eslint", "build:specs": "lerna run --stream specs", - "build:docker": "lerna run --stream build:docker && yarn build:docker:proxy && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh $BUDIBASE_RELEASE_VERSION && cd -", - "build:docker:proxy": "docker build hosting/proxy -t proxy-service", - "build:docker:selfhost": "lerna run --stream build:docker && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh latest && cd -", - "build:docker:develop": "node scripts/pinVersions && lerna run --stream build:docker && yarn build:docker:proxy && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh develop && cd -", "build:docker:airgap": "node hosting/scripts/airgapped/airgappedDockerBuild", "build:docker:airgap:single": "SINGLE_IMAGE=1 node hosting/scripts/airgapped/airgappedDockerBuild", "build:digitalocean": "cd hosting/digitalocean && ./build.sh && cd -", diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index b23cd8e5b1..dc8d71b52c 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -21,7 +21,7 @@ "test:watch": "jest --watchAll" }, "dependencies": { - "@budibase/nano": "10.1.2", + "@budibase/nano": "10.1.3", "@budibase/pouchdb-replication-stream": "1.2.10", "@budibase/shared-core": "0.0.0", "@budibase/types": "0.0.0", diff --git a/packages/backend-core/src/db/constants.ts b/packages/backend-core/src/db/constants.ts index aea485e3e3..bfa7595d62 100644 --- a/packages/backend-core/src/db/constants.ts +++ b/packages/backend-core/src/db/constants.ts @@ -8,3 +8,7 @@ export const CONSTANT_INTERNAL_ROW_COLS = [ ] as const export const CONSTANT_EXTERNAL_ROW_COLS = ["_id", "_rev", "tableId"] as const + +export function isInternalColumnName(name: string): boolean { + return (CONSTANT_INTERNAL_ROW_COLS as readonly string[]).includes(name) +} diff --git a/packages/backend-core/src/docIds/params.ts b/packages/backend-core/src/docIds/params.ts index 36fd75622b..d9baee3dc6 100644 --- a/packages/backend-core/src/docIds/params.ts +++ b/packages/backend-core/src/docIds/params.ts @@ -6,6 +6,7 @@ import { ViewName, } from "../constants" import { getProdAppID } from "./conversions" +import { DatabaseQueryOpts } from "@budibase/types" /** * If creating DB allDocs/query params with only a single top level ID this can be used, this @@ -22,8 +23,8 @@ import { getProdAppID } from "./conversions" export function getDocParams( docType: string, docId?: string | null, - otherProps: any = {} -) { + otherProps: Partial = {} +): DatabaseQueryOpts { if (docId == null) { docId = "" } @@ -45,8 +46,8 @@ export function getDocParams( export function getRowParams( tableId?: string | null, rowId?: string | null, - otherProps = {} -) { + otherProps: Partial = {} +): DatabaseQueryOpts { if (tableId == null) { return getDocParams(DocumentType.ROW, null, otherProps) } @@ -88,7 +89,10 @@ export const isDatasourceId = (id: string) => { /** * Gets parameters for retrieving workspaces. */ -export function getWorkspaceParams(id = "", otherProps = {}) { +export function getWorkspaceParams( + id = "", + otherProps: Partial = {} +): DatabaseQueryOpts { return { ...otherProps, startkey: `${DocumentType.WORKSPACE}${SEPARATOR}${id}`, @@ -99,7 +103,10 @@ export function getWorkspaceParams(id = "", otherProps = {}) { /** * Gets parameters for retrieving users. */ -export function getGlobalUserParams(globalId: any, otherProps: any = {}) { +export function getGlobalUserParams( + globalId: any, + otherProps: Partial = {} +): DatabaseQueryOpts { if (!globalId) { globalId = "" } @@ -117,11 +124,17 @@ export function getGlobalUserParams(globalId: any, otherProps: any = {}) { /** * Gets parameters for retrieving users, this is a utility function for the getDocParams function. */ -export function getUserMetadataParams(userId?: string | null, otherProps = {}) { +export function getUserMetadataParams( + userId?: string | null, + otherProps: Partial = {} +): DatabaseQueryOpts { return getRowParams(InternalTable.USER_METADATA, userId, otherProps) } -export function getUsersByAppParams(appId: any, otherProps: any = {}) { +export function getUsersByAppParams( + appId: any, + otherProps: Partial = {} +): DatabaseQueryOpts { const prodAppId = getProdAppID(appId) return { ...otherProps, diff --git a/packages/backend-core/src/users/db.ts b/packages/backend-core/src/users/db.ts index daa09bee6f..c071064713 100644 --- a/packages/backend-core/src/users/db.ts +++ b/packages/backend-core/src/users/db.ts @@ -165,13 +165,9 @@ export class UserDB { } static async getUsersByAppAccess(opts: { appId?: string; limit?: number }) { - const params: any = { - include_docs: true, - limit: opts.limit || 50, - } let response: User[] = await usersCore.searchGlobalUsersByAppAccess( opts.appId, - params + { limit: opts.limit || 50 } ) return response } diff --git a/packages/backend-core/src/users/users.ts b/packages/backend-core/src/users/users.ts index bad108ab84..ea4a17214d 100644 --- a/packages/backend-core/src/users/users.ts +++ b/packages/backend-core/src/users/users.ts @@ -20,6 +20,7 @@ import { User, ContextUser, DatabaseQueryOpts, + CouchFindOptions, } from "@budibase/types" import { getGlobalDB } from "../context" import * as context from "../context" @@ -140,7 +141,7 @@ export const getGlobalUserByEmail = async ( export const searchGlobalUsersByApp = async ( appId: any, - opts: any, + opts: DatabaseQueryOpts, getOpts?: GetOpts ) => { if (typeof appId !== "string") { @@ -166,7 +167,10 @@ export const searchGlobalUsersByApp = async ( Return any user who potentially has access to the application Admins, developers and app users with the explicitly role. */ -export const searchGlobalUsersByAppAccess = async (appId: any, opts: any) => { +export const searchGlobalUsersByAppAccess = async ( + appId: any, + opts?: { limit?: number } +) => { const roleSelector = `roles.${appId}` let orQuery: any[] = [ @@ -187,7 +191,7 @@ export const searchGlobalUsersByAppAccess = async (appId: any, opts: any) => { orQuery.push(roleCheck) } - let searchOptions = { + let searchOptions: CouchFindOptions = { selector: { $or: orQuery, _id: { @@ -198,7 +202,7 @@ export const searchGlobalUsersByAppAccess = async (appId: any, opts: any) => { } const resp = await directCouchFind(context.getGlobalDBName(), searchOptions) - return resp?.rows + return resp.rows } export const getGlobalUserByAppPage = (appId: string, user: User) => { diff --git a/packages/bbui/src/Form/Core/Dropzone.svelte b/packages/bbui/src/Form/Core/Dropzone.svelte index e9ee75bd8b..0b6a9bb94f 100644 --- a/packages/bbui/src/Form/Core/Dropzone.svelte +++ b/packages/bbui/src/Form/Core/Dropzone.svelte @@ -159,8 +159,10 @@ {#if selectedImage.size}
{#if selectedImage.size <= BYTES_IN_MB} - {`${selectedImage.size / BYTES_IN_KB} KB`} - {:else}{`${selectedImage.size / BYTES_IN_MB} MB`}{/if} + {`${(selectedImage.size / BYTES_IN_KB).toFixed(1)} KB`} + {:else}{`${(selectedImage.size / BYTES_IN_MB).toFixed( + 1 + )} MB`}{/if}
{/if} {#if !disabled} @@ -203,8 +205,8 @@ {#if file.size}
{#if file.size <= BYTES_IN_MB} - {`${file.size / BYTES_IN_KB} KB`} - {:else}{`${file.size / BYTES_IN_MB} MB`}{/if} + {`${(file.size / BYTES_IN_KB).toFixed(1)} KB`} + {:else}{`${(file.size / BYTES_IN_MB).toFixed(1)} MB`}{/if}
{/if} {#if !disabled} diff --git a/packages/builder/.gitignore b/packages/builder/.gitignore index e5c961d509..acd1a70579 100644 --- a/packages/builder/.gitignore +++ b/packages/builder/.gitignore @@ -5,4 +5,4 @@ package-lock.json release/ dist/ routify -.routify/ \ No newline at end of file +.routify/ diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index a567caf87f..a4729b4a8a 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -580,7 +580,7 @@ export const getFrontendStore = () => { let table = validTables.find(table => { return ( table.sourceId !== BUDIBASE_INTERNAL_DB_ID && - table.type === DB_TYPE_INTERNAL + table.sourceType === DB_TYPE_INTERNAL ) }) if (table) { @@ -591,7 +591,7 @@ export const getFrontendStore = () => { table = validTables.find(table => { return ( table.sourceId === BUDIBASE_INTERNAL_DB_ID && - table.type === DB_TYPE_INTERNAL + table.sourceType === DB_TYPE_INTERNAL ) }) if (table) { @@ -599,7 +599,7 @@ export const getFrontendStore = () => { } // Finally try an external table - return validTables.find(table => table.type === DB_TYPE_EXTERNAL) + return validTables.find(table => table.sourceType === DB_TYPE_EXTERNAL) }, enrichEmptySettings: (component, opts) => { if (!component?._component) { diff --git a/packages/builder/src/components/backend/DataTable/RelationshipDataTable.svelte b/packages/builder/src/components/backend/DataTable/RelationshipDataTable.svelte index 8ef870caca..4e67a92443 100644 --- a/packages/builder/src/components/backend/DataTable/RelationshipDataTable.svelte +++ b/packages/builder/src/components/backend/DataTable/RelationshipDataTable.svelte @@ -16,7 +16,6 @@ $: linkedTable = $tables.list.find(table => table._id === linkedTableId) $: schema = linkedTable?.schema $: table = $tables.list.find(table => table._id === tableId) - $: type = table?.type $: fetchData(tableId, rowId) $: { let rowLabel = row?.[table?.primaryDisplay] @@ -41,5 +40,5 @@ {#if row && row._id === rowId} - +
{/if} diff --git a/packages/builder/src/components/backend/DataTable/TableDataTable.svelte b/packages/builder/src/components/backend/DataTable/TableDataTable.svelte index 5fee849afb..8dd685e766 100644 --- a/packages/builder/src/components/backend/DataTable/TableDataTable.svelte +++ b/packages/builder/src/components/backend/DataTable/TableDataTable.svelte @@ -16,6 +16,7 @@ import GridRelationshipButton from "components/backend/DataTable/buttons/grid/GridRelationshipButton.svelte" import GridEditColumnModal from "components/backend/DataTable/modals/grid/GridEditColumnModal.svelte" import GridUsersTableButton from "components/backend/DataTable/modals/grid/GridUsersTableButton.svelte" + import { DB_TYPE_EXTERNAL } from "constants/backend" const userSchemaOverrides = { firstName: { displayName: "First name", disabled: true }, @@ -27,7 +28,7 @@ $: id = $tables.selected?._id $: isUsersTable = id === TableNames.USERS - $: isInternal = $tables.selected?.type !== "external" + $: isInternal = $tables.selected?.sourceType !== DB_TYPE_EXTERNAL $: gridDatasource = { type: "table", tableId: id, @@ -46,10 +47,7 @@ tables.replaceTable(id, e.detail) // We need to refresh datasources when an external table changes. - // Type "external" may exist - sometimes type is "table" and sometimes it - // is "external" - it has different meanings in different endpoints. - // If we check both these then we hopefully catch all external tables. - if (e.detail?.type === "external" || e.detail?.sql) { + if (e.detail?.sourceType === DB_TYPE_EXTERNAL) { await datasources.fetch() } } diff --git a/packages/builder/src/components/backend/DataTable/ViewDataTable.svelte b/packages/builder/src/components/backend/DataTable/ViewDataTable.svelte index 6068439dbd..6fcba8d418 100644 --- a/packages/builder/src/components/backend/DataTable/ViewDataTable.svelte +++ b/packages/builder/src/components/backend/DataTable/ViewDataTable.svelte @@ -17,7 +17,6 @@ let hideAutocolumns = true let data = [] let loading = false - let type = "internal" $: name = view.name $: schema = view.schema @@ -66,7 +65,6 @@ tableId={view.tableId} {data} {loading} - {type} rowCount={10} allowEditing={false} bind:hideAutocolumns diff --git a/packages/builder/src/components/backend/DataTable/buttons/grid/GridImportButton.svelte b/packages/builder/src/components/backend/DataTable/buttons/grid/GridImportButton.svelte index 71d971891c..74e255cf7e 100644 --- a/packages/builder/src/components/backend/DataTable/buttons/grid/GridImportButton.svelte +++ b/packages/builder/src/components/backend/DataTable/buttons/grid/GridImportButton.svelte @@ -10,6 +10,6 @@ diff --git a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte index 467ae413c3..d5a9aba488 100644 --- a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte @@ -26,6 +26,7 @@ ALLOWABLE_NUMBER_TYPES, SWITCHABLE_TYPES, PrettyRelationshipDefinitions, + DB_TYPE_EXTERNAL, } from "constants/backend" import { getAutoColumnInformation, buildAutoColumn } from "builderStore/utils" import ConfirmDialog from "components/common/ConfirmDialog.svelte" @@ -254,10 +255,11 @@ !uneditable && editableColumn?.type !== AUTO_TYPE && !editableColumn.autocolumn - $: external = table.type === "external" + $: externalTable = table.sourceType === DB_TYPE_EXTERNAL // in the case of internal tables the sourceId will just be undefined $: tableOptions = $tables.list.filter( - opt => opt.type === table.type && table.sourceId === opt.sourceId + opt => + opt.sourceType === table.sourceType && table.sourceId === opt.sourceId ) $: typeEnabled = !originalName || @@ -409,7 +411,7 @@ editableColumn.type === FieldType.BB_REFERENCE && editableColumn.subtype === FieldSubtype.USERS - if (!external) { + if (!externalTable) { return [ FIELDS.STRING, FIELDS.BARCODEQR, @@ -441,7 +443,7 @@ isUsers ? FIELDS.USERS : FIELDS.USER, ] // no-sql or a spreadsheet - if (!external || table.sql) { + if (!externalTable || table.sql) { fields = [...fields, FIELDS.LINK, FIELDS.ARRAY] } return fields @@ -486,7 +488,7 @@ }) } const newError = {} - if (!external && fieldInfo.name?.startsWith("_")) { + if (!externalTable && fieldInfo.name?.startsWith("_")) { newError.name = `Column name cannot start with an underscore.` } else if (fieldInfo.name && !fieldInfo.name.match(ValidColumnNameRegex)) { newError.name = `Illegal character; must be alpha-numeric.` @@ -498,7 +500,7 @@ newError.name = `Column name already in use.` } - if (fieldInfo.type == "auto" && !fieldInfo.subtype) { + if (fieldInfo.type === "auto" && !fieldInfo.subtype) { newError.subtype = `Auto Column requires a type` } diff --git a/packages/builder/src/components/backend/TableNavigator/ExistingTableDataImport.svelte b/packages/builder/src/components/backend/TableNavigator/ExistingTableDataImport.svelte index 43751ad944..eb1e7bc7ff 100644 --- a/packages/builder/src/components/backend/TableNavigator/ExistingTableDataImport.svelte +++ b/packages/builder/src/components/backend/TableNavigator/ExistingTableDataImport.svelte @@ -1,6 +1,6 @@
-
+