diff --git a/.github/workflows/release-singleimage.yml b/.github/workflows/release-singleimage.yml index 92f21bd649..5b75c20d29 100644 --- a/.github/workflows/release-singleimage.yml +++ b/.github/workflows/release-singleimage.yml @@ -1,4 +1,4 @@ -name: Deploy Budibase Single Container Image to DockerHub +name: release-singleimage on: workflow_dispatch: @@ -8,8 +8,8 @@ env: PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} REGISTRY_URL: registry.hub.docker.com jobs: - build: - name: "build" + build-amd64: + name: "build-amd64" runs-on: ubuntu-latest strategy: matrix: @@ -27,14 +27,12 @@ jobs: submodules: true token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} fetch-depth: 0 - - name: Fail if tag is not in master run: | if ! git merge-base --is-ancestor ${{ github.sha }} origin/master; then echo "Tag is not in master. This pipeline can only execute tags that are present on the master branch" exit 1 fi - - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: @@ -70,9 +68,139 @@ jobs: with: context: . push: true - platforms: linux/amd64,linux/arm64 - tags: budibase/budibase,budibase/budibase:${{ env.RELEASE_VERSION }} + platforms: linux/amd64 + tags: budibase/budibase,budibase/budibase:v${{ env.RELEASE_VERSION }} file: ./hosting/single/Dockerfile + + - name: Tag and release Budibase Azure App Service docker image + uses: docker/build-push-action@v2 + with: + context: . + push: true + platforms: linux/amd64 + build-args: TARGETBUILD=aas + tags: budibase/budibase-aas,budibase/budibase-aas:v${{ env.RELEASE_VERSION }} + file: ./hosting/single/Dockerfile + + build-arm64: + name: "build-arm64" + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [14.x] + steps: + - name: Fail if not a tag + run: | + if [[ $GITHUB_REF != refs/tags/* ]]; then + echo "Workflow Dispatch can only be run on tags" + exit 1 + fi + - name: "Checkout" + uses: actions/checkout@v2 + with: + submodules: true + token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} + fetch-depth: 0 + - name: Fail if tag is not in master + run: | + if ! git merge-base --is-ancestor ${{ github.sha }} origin/master; then + echo "Tag is not in master. This pipeline can only execute tags that are present on the master branch" + exit 1 + fi + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - name: Setup QEMU + uses: docker/setup-qemu-action@v1 + - name: Setup Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v1 + - name: Run Yarn + run: yarn + - name: Update versions + run: ./scripts/updateVersions.sh + - name: Runt Yarn Lint + run: yarn lint + - name: Update versions + run: ./scripts/updateVersions.sh + - name: Run Yarn Build + run: yarn build:docker:pre + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_API_KEY }} + - name: Get the latest release version + id: version + run: | + release_version=$(cat lerna.json | jq -r '.version') + echo $release_version + echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV + - name: Tag and release Budibase service docker image + uses: docker/build-push-action@v2 + with: + context: . + push: true + platforms: linux/arm64 + tags: budibase/budibase,budibase/budibase:v${{ env.RELEASE_VERSION }} + file: ./hosting/single/Dockerfile + + build-aas: + name: "build-aas" + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [14.x] + steps: + - name: Fail if not a tag + run: | + if [[ $GITHUB_REF != refs/tags/* ]]; then + echo "Workflow Dispatch can only be run on tags" + exit 1 + fi + - name: "Checkout" + uses: actions/checkout@v2 + with: + submodules: true + token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} + fetch-depth: 0 + - name: Fail if tag is not in master + run: | + if ! git merge-base --is-ancestor ${{ github.sha }} origin/master; then + echo "Tag is not in master. This pipeline can only execute tags that are present on the master branch" + exit 1 + fi + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - name: Setup QEMU + uses: docker/setup-qemu-action@v1 + - name: Setup Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v1 + - name: Run Yarn + run: yarn + - name: Update versions + run: ./scripts/updateVersions.sh + - name: Runt Yarn Lint + run: yarn lint + - name: Update versions + run: ./scripts/updateVersions.sh + - name: Run Yarn Build + run: yarn build:docker:pre + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_API_KEY }} + - name: Get the latest release version + id: version + run: | + release_version=$(cat lerna.json | jq -r '.version') + echo $release_version + echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV - name: Tag and release Budibase Azure App Service docker image uses: docker/build-push-action@v2 with: diff --git a/lerna.json b/lerna.json index b327205215..4c6e771bce 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.8.22-alpha.4", + "version": "2.8.28-alpha.0", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/package.json b/package.json index 3afe279e00..6a678f1bf3 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "@nx/js": "16.4.3", "@rollup/plugin-json": "^4.0.2", "@typescript-eslint/parser": "5.45.0", - "esbuild": "^0.17.18", - "esbuild-node-externals": "^1.7.0", + "esbuild": "^0.18.17", + "esbuild-node-externals": "^1.8.0", "eslint": "^8.44.0", "eslint-plugin-cypress": "^2.11.3", "husky": "^8.0.3", @@ -51,9 +51,9 @@ "kill-builder": "kill-port 3000", "kill-server": "kill-port 4001 4002", "kill-all": "yarn run kill-builder && yarn run kill-server", - "dev": "yarn run kill-all && lerna run --stream dev:builder --stream", - "dev:noserver": "yarn run kill-builder && lerna run --stream dev:stack:up && lerna run --stream dev:builder --ignore @budibase/backend-core --ignore @budibase/server --ignore @budibase/worker", - "dev:server": "yarn run kill-server && lerna run --stream dev:builder --scope @budibase/worker --scope @budibase/server", + "dev": "yarn run kill-all && yarn nx run-many --target=dev:builder", + "dev:noserver": "yarn run kill-builder && lerna run --stream dev:stack:up && yarn nx run-many --target=dev:builder --exclude=@budibase/backend-core,@budibase/server,@budibase/worker", + "dev:server": "yarn run kill-server && yarn nx run-many --target=dev:builder --projects=@budibase/worker,@budibase/server", "dev:built": "yarn run kill-all && cd packages/server && yarn dev:stack:up && cd ../../ && lerna run --stream dev:built", "dev:docker": "yarn build:docker:pre && docker-compose -f hosting/docker-compose.build.yaml -f hosting/docker-compose.dev.yaml --env-file hosting/.env up --build --scale proxy-service=0", "test": "lerna run --stream test --stream", diff --git a/packages/backend-core/src/db/constants.ts b/packages/backend-core/src/db/constants.ts new file mode 100644 index 0000000000..aea485e3e3 --- /dev/null +++ b/packages/backend-core/src/db/constants.ts @@ -0,0 +1,10 @@ +export const CONSTANT_INTERNAL_ROW_COLS = [ + "_id", + "_rev", + "type", + "createdAt", + "updatedAt", + "tableId", +] as const + +export const CONSTANT_EXTERNAL_ROW_COLS = ["_id", "_rev", "tableId"] as const diff --git a/packages/backend-core/src/db/couch/index.ts b/packages/backend-core/src/db/couch/index.ts index c731d20d6c..932efed3f7 100644 --- a/packages/backend-core/src/db/couch/index.ts +++ b/packages/backend-core/src/db/couch/index.ts @@ -2,3 +2,4 @@ export * from "./connections" export * from "./DatabaseImpl" export * from "./utils" export { init, getPouch, getPouchDB, closePouchDB } from "./pouchDB" +export * from "../constants" diff --git a/packages/backend-core/tests/core/utilities/jestUtils.ts b/packages/backend-core/tests/core/utilities/jestUtils.ts index d84eac548c..4a3da8db8c 100644 --- a/packages/backend-core/tests/core/utilities/jestUtils.ts +++ b/packages/backend-core/tests/core/utilities/jestUtils.ts @@ -1,3 +1,5 @@ +import { db } from "../../../src" + export function expectFunctionWasCalledTimesWith( jestFunction: any, times: number, @@ -7,3 +9,22 @@ export function expectFunctionWasCalledTimesWith( jestFunction.mock.calls.filter((call: any) => call[0] === argument).length ).toBe(times) } + +export const expectAnyInternalColsAttributes: { + [K in (typeof db.CONSTANT_INTERNAL_ROW_COLS)[number]]: any +} = { + tableId: expect.anything(), + type: expect.anything(), + _id: expect.anything(), + _rev: expect.anything(), + createdAt: expect.anything(), + updatedAt: expect.anything(), +} + +export const expectAnyExternalColsAttributes: { + [K in (typeof db.CONSTANT_EXTERNAL_ROW_COLS)[number]]: any +} = { + tableId: expect.anything(), + _id: expect.anything(), + _rev: expect.anything(), +} diff --git a/packages/bbui/src/Actions/position_dropdown.js b/packages/bbui/src/Actions/position_dropdown.js index 01555446d9..8fa02bb8f3 100644 --- a/packages/bbui/src/Actions/position_dropdown.js +++ b/packages/bbui/src/Actions/position_dropdown.js @@ -64,7 +64,7 @@ export default function positionDropdown(element, opts) { // Apply styles Object.entries(styles).forEach(([style, value]) => { - if (value) { + if (value != null) { element.style[style] = `${value.toFixed(0)}px` } else { element.style[style] = null diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index e9c8643bce..bbe116721a 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -491,6 +491,7 @@ const getSelectedRowsBindings = asset => { readableBinding: `${table._instanceName}.Selected rows`, category: "Selected rows", icon: "ViewRow", + display: { name: table._instanceName }, })) ) @@ -506,6 +507,7 @@ const getSelectedRowsBindings = asset => { )}.${makePropSafe("selectedRows")}`, readableBinding: `${block._instanceName}.Selected rows`, category: "Selected rows", + display: { name: block._instanceName }, })) ) } diff --git a/packages/builder/src/components/backend/DataTable/TableDataTable.svelte b/packages/builder/src/components/backend/DataTable/TableDataTable.svelte index 7a03564ba1..bd8ee258fd 100644 --- a/packages/builder/src/components/backend/DataTable/TableDataTable.svelte +++ b/packages/builder/src/components/backend/DataTable/TableDataTable.svelte @@ -1,5 +1,5 @@ @@ -231,7 +236,9 @@ @@ -262,7 +269,7 @@ >
- {index + 1}. {action[EVENT_TYPE_KEY]} + {index + 1}. {toDisplay(action[EVENT_TYPE_KEY])}
- import { Select, Label, Checkbox, Input } from "@budibase/bbui" + import { Select, Label, Checkbox, Input, Body } from "@budibase/bbui" import { tables } from "stores/backend" import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte" @@ -10,47 +10,59 @@
- - Please specify one or more rows to delete. +
+ + + {/if} +
diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ExecuteQuery.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ExecuteQuery.svelte index ba72fd2ed7..a085d86507 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ExecuteQuery.svelte +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ExecuteQuery.svelte @@ -73,9 +73,12 @@ {#if query?.parameters?.length > 0}
{ + parameters.queryParams = { ...v.detail } + }} /> { - tmpQueryParams = value.queryParams + tmpQueryParams = { ...value.queryParams } drawer.show() } const getQueryValue = queries => { - value = queries.find(q => q._id === value._id) || value - return value + return queries.find(q => q._id === value._id) || value } const saveQueryParams = () => { @@ -176,7 +175,10 @@ {#if getQueryParams(value).length > 0} { + tmpQueryParams = { ...v.detail } + }} queryBindings={getQueryParams(value)} bind:bindings /> diff --git a/packages/builder/src/components/integration/QueryBindingBuilder.svelte b/packages/builder/src/components/integration/QueryBindingBuilder.svelte index 3a89c4b968..af890302b0 100644 --- a/packages/builder/src/components/integration/QueryBindingBuilder.svelte +++ b/packages/builder/src/components/integration/QueryBindingBuilder.svelte @@ -5,6 +5,9 @@ runtimeToReadableBinding, } from "builderStore/dataBinding" import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte" + import { createEventDispatcher } from "svelte" + + const dispatch = createEventDispatcher() export let bindable = true export let queryBindings = [] @@ -20,7 +23,10 @@ // The readable binding in the UI gets converted to a UUID value that the client understands // for parsing, then converted back so we can display it the readable form in the UI function onBindingChange(param, valueToParse) { - customParams[param] = readableToRuntimeBinding(bindings, valueToParse) + dispatch("change", { + ...customParams, + [param]: readableToRuntimeBinding(bindings, valueToParse), + }) } diff --git a/packages/builder/src/components/integration/QueryViewer.svelte b/packages/builder/src/components/integration/QueryViewer.svelte index 3377ff3a88..4683bc6335 100644 --- a/packages/builder/src/components/integration/QueryViewer.svelte +++ b/packages/builder/src/components/integration/QueryViewer.svelte @@ -14,8 +14,9 @@ Tab, Modal, ModalContent, + notifications, + Divider, } from "@budibase/bbui" - import { notifications, Divider } from "@budibase/bbui" import ExtraQueryConfig from "./ExtraQueryConfig.svelte" import IntegrationQueryEditor from "components/integration/index.svelte" import ExternalDataSourceTable from "components/backend/DataTable/ExternalDataSourceTable.svelte" @@ -28,6 +29,7 @@ import KeyValueBuilder from "./KeyValueBuilder.svelte" import { fieldsToSchema, schemaToFields } from "helpers/data/utils" import AccessLevelSelect from "./AccessLevelSelect.svelte" + import { ValidQueryNameRegex } from "@budibase/shared-core" export let query @@ -47,6 +49,7 @@ let saveModal let override = false let navigateTo = null + let nameError = null // seed the transformer if (query && !query.transformer) { @@ -77,7 +80,7 @@ $: queryConfig = integrationInfo?.query $: shouldShowQueryConfig = queryConfig && query.queryVerb $: readQuery = query.queryVerb === "read" || query.readable - $: queryInvalid = !query.name || (readQuery && data.length === 0) + $: queryInvalid = !query.name || nameError || (readQuery && data.length === 0) //Cast field in query preview response to number if specified by schema $: { @@ -139,9 +142,10 @@ queryStr = JSON.stringify(query) } + notifications.success("Query saved successfully") return response } catch (error) { - notifications.error("Error saving query") + notifications.error(error.message || "Error saving query") } } @@ -183,8 +187,14 @@ value={query.name} on:input={e => { let newValue = e.target.value || "" - query.name = newValue.trim() + if (newValue.match(ValidQueryNameRegex)) { + query.name = newValue.trim() + nameError = null + } else { + nameError = "Invalid query name" + } }} + error={nameError} />
{#if queryConfig} @@ -250,9 +260,9 @@ size="L" /> - Add a JavaScript function to transform the query result. + + Add a JavaScript function to transform the query result. +
Results - +