Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 50 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ jobs:
dockerfiles: ${{ steps.filter.outputs.dockerfiles }}
mjml: ${{ steps.filter.outputs.mjml }}
zapier: ${{ steps.filter.outputs.zapier }}
helm: ${{ steps.filter.outputs.helm }}
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down Expand Up @@ -216,7 +217,10 @@ jobs:
zapier:
- 'integrations/zapier/**'
- '.github/workflows/ci.yml'

helm:
- 'deploy/helm/**'
- '.github/workflows/ci.yml'
- '.github/workflows/trigger-helm-chart-upload.yml'
backend-lint:
name: Backend Lint
runs-on: ubuntu-latest
Expand Down Expand Up @@ -326,6 +330,44 @@ jobs:
path: reports/hadolint.json
retention-days: 7

helm-chart-lint:
name: Helm Chart Lint
runs-on: ubuntu-latest
needs:
- detect-changes
permissions:
contents: read
steps:
- name: Exit early if helm not changed and not develop/master
run: |
if [[ "${{ needs.detect-changes.outputs.helm }}" != "true" && \
"${{ github.ref_name }}" != "develop" && \
"${{ github.ref_name }}" != "master" ]]; then
echo "No backend changes detected — skipping backend lint."
exit 0
fi

- name: Checkout code
uses: actions/checkout@v4

- name: Set up Helm
uses: azure/setup-helm@v4

- name: Lint Helm Chart
run: |
cd deploy/helm
rm -f baserow/Chart.lock

# Add Helm repositories
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add caddy https://caddyserver.github.io/ingress

# Build dependencies
helm dependency build baserow

# Lint the chart with strict mode
helm lint baserow --strict

# ==========================================================================
# TEST STAGE - Run backend and frontend tests
# ==========================================================================
Expand Down Expand Up @@ -552,7 +594,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
node-version: "18"

- name: Run Zapier tests
run: |
Expand Down Expand Up @@ -585,7 +627,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
node-version: "18"

- name: Compile MJML templates
run: |
Expand Down Expand Up @@ -667,9 +709,9 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'yarn'
cache-dependency-path: 'e2e-tests/yarn.lock'
node-version: "18"
cache: "yarn"
cache-dependency-path: "e2e-tests/yarn.lock"

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
Expand Down Expand Up @@ -790,7 +832,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
node-version: "18"

- name: Download all E2E test results
uses: actions/download-artifact@v4
Expand Down Expand Up @@ -832,7 +874,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
python-version: "3.11"

- name: Install coverage tool
run: pip install coverage
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/trigger-helm-chart-upload.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ jobs:
# Build dependencies
helm dependency build baserow

# Lint the chart with strict mode
helm lint baserow --strict

# Package the chart
helm package baserow

Expand Down
9 changes: 6 additions & 3 deletions backend/src/baserow/contrib/automation/nodes/node_types.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, List, Optional
from typing import Any, Callable, Dict, List, Optional

from django.contrib.auth.models import AbstractUser
from django.db import router
Expand Down Expand Up @@ -341,14 +341,14 @@ def before_move(
def on_event(
self,
services: QuerySet[Service],
event_payload: Optional[List[Dict]] = None,
event_payload: List[Dict] | None | Callable = None,
user: Optional[AbstractUser] = None,
):
from baserow.contrib.automation.workflows.handler import (
AutomationWorkflowHandler,
)

triggers = (
triggers = list(
self.model_class.objects.filter(
service__in=services,
)
Expand All @@ -363,6 +363,9 @@ def on_event(
.select_related("workflow__automation__workspace")
)

if triggers and callable(event_payload):
event_payload = event_payload()

for trigger in triggers:
workflow = trigger.workflow

Expand Down
18 changes: 18 additions & 0 deletions backend/src/baserow/contrib/builder/elements/registries.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,24 @@ def get_pytest_params(self, pytest_data_fixture) -> Dict[str, Any]:
create related objects when the import / export functionality is tested.
"""

def formula_generator(
self, element: Element
) -> Generator[str | Instance, str, None]:
"""
Generator that returns formula fields for the LinkElementType.

Unlike other Element types, this one has its formula fields in the
page_parameters and query_prameters JSON fields.
"""

yield from super().formula_generator(element)

# Deal with visibility_condition
new_formula = yield element.visibility_condition
if new_formula is not None:
element.visibility_condition = new_formula
yield element


ElementTypeSubClass = TypeVar("ElementTypeSubClass", bound=ElementType)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2283,18 +2283,22 @@ def _handle_signal(
model: "GeneratedTableModel",
**kwargs,
):
serializer = get_row_serializer_class(
model, RowSerializer, is_response=True, user_field_names=True
)
def get_data():
# Make sure we have an up to date model
local_model = model.baserow_table.get_model()

data_to_process = {
"results": serializer(rows, many=True).data,
"has_next_page": False,
}
serializer = get_row_serializer_class(
local_model, RowSerializer, is_response=True, user_field_names=True
)

return {
"results": serializer(rows, many=True).data,
"has_next_page": False,
}

self._process_event(
self.model_class.objects.filter(table=table),
data_to_process,
get_data,
user=user,
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"type": "bug",
"message": "Don't show the Assistant panel if the LLM_MODEL env variable is not configured",
"issue_origin": "github",
"issue_number": 4280,
"domain": "core",
"bullet_points": [],
"created_at": "2025-11-18"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"type": "bug",
"message": "Fix visibility condition not working if data property wasn't used in page",
"issue_origin": "github",
"issue_number": null,
"domain": "builder",
"bullet_points": [],
"created_at": "2025-11-18"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"type": "bug",
"message": "Save data preparation for table that don't have trigger associated to it",
"issue_origin": "github",
"issue_number": null,
"domain": "automation",
"bullet_points": [],
"created_at": "2025-11-18"
}
4 changes: 2 additions & 2 deletions deploy/helm/baserow/templates/backend-configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ data:
AWS_S3_CUSTOM_DOMAIN: {{ .Values.global.baserow.objectsDomain }}/{{ (index .Values.minio.provisioning.buckets 0).name }}
AWS_S3_REGION_NAME: "us-east-1"
{{- end }}
{{- if .Values.global.baserow.assistantLLMModel -}}
BASEROW_ENTERPRISE_ASSISTANT_LLM_MODEL: "{{ .Values.baserow.assistantLLMModel }}"
{{- if .Values.global.baserow.assistantLLMModel }}
BASEROW_ENTERPRISE_ASSISTANT_LLM_MODEL: "{{ .Values.global.baserow.assistantLLMModel }}"
{{- end }}
{{- if (index .Values "baserow-embeddings").enabled }}
BASEROW_EMBEDDINGS_API_URL: http://{{ include "baserow.fullname" (index .Subcharts "baserow-embeddings") }}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div v-if="hasPermission">
<div v-if="hasPermission && isConfigured">
<li class="tree__item">
<div class="tree__action">
<a href="#" class="tree__link" @click.prevent="toggleRightSidebar">
Expand Down Expand Up @@ -39,10 +39,14 @@ export default {
this.workspace.id
)
},
isConfigured() {
return this.$config.BASEROW_ENTERPRISE_ASSISTANT_LLM_MODEL !== null
},
},
mounted() {
if (
this.hasPermission &&
this.isConfigured &&
localStorage.getItem('baserow.rightSidebarOpen') !== 'false'
) {
// open the right sidebar if the feature is available
Expand Down
5 changes: 5 additions & 0 deletions enterprise/web-frontend/modules/baserow_enterprise/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,9 @@ export default function () {
// imports the original. We do this so that we can use the existing variables,
// mixins, placeholders etc.
this.options.css[0] = path.resolve(__dirname, 'assets/scss/default.scss')

if (this.options.publicRuntimeConfig) {
this.options.publicRuntimeConfig.BASEROW_ENTERPRISE_ASSISTANT_LLM_MODEL =
process.env.BASEROW_ENTERPRISE_ASSISTANT_LLM_MODEL || null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,34 @@
{{ buttonLabel }}
</Button>

<Alert v-if="cantBeTestedReason" type="info-neutral">
<Alert
v-if="cantBeTestedReason"
type="info-neutral"
class="margin-bottom-0"
>
<p>{{ cantBeTestedReason }}</p>
</Alert>

<Alert v-else-if="showTestNodeDescription" type="info-neutral">
<p>{{ $t('simulateDispatch.testNodeDescription') }}</p>
<Alert
v-if="isLoading"
:type="nodeType.isTrigger ? 'warning' : 'info-neutral'"
>
<p>
{{
nodeType.isTrigger
? $t('simulateDispatch.triggerNodeAwaitingEvent')
: $t('simulateDispatch.simulationInProgress')
}}
</p>
</Alert>

<Alert v-else-if="isLoading" type="info-neutral">
<p>{{ $t('simulateDispatch.triggerNodeAwaitingEvent') }}</p>
<Alert v-else-if="!hasSampleData" type="info-neutral">
<p>
{{ $t('simulateDispatch.testNodeDescription') }}
</p>
</Alert>

<div
v-if="hasSampleData && !isSimulating"
v-if="hasSampleData && !isLoading"
:class="{
'simulate-dispatch-node__sample-data--error': isErrorSample,
}"
Expand Down Expand Up @@ -185,14 +199,6 @@ const buttonLabel = computed(() => {
: app.i18n.t('simulateDispatch.buttonLabelTest')
})

const showTestNodeDescription = computed(() => {
if (Boolean(cantBeTestedReason.value) || hasSampleData.value) {
return false
}

return true
})

const simulateDispatchNode = async () => {
queryInProgress.value = true

Expand Down
1 change: 1 addition & 0 deletions web-frontend/modules/automation/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@
"simulateDispatch": {
"sampleDataLabel": "Output",
"triggerNodeAwaitingEvent": "The node is waiting. Please manually trigger the event to populate the payload and complete the test.",
"simulationInProgress": "Node test is in progress...",
"errorNodeNotConfigured": "The node must be configured before it can be tested.",
"errorPreviousNodeNotConfigured": "The previous node \"{node}\" must be configured.",
"errorPreviousNodesNotTested": "The previous node \"{node}\" must be tested first.",
Expand Down
4 changes: 4 additions & 0 deletions web-frontend/modules/builder/elementTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,10 @@ export class ElementType extends Registerable {
element: mainElement,
})

if (!mainDataSource) {
return null
}

const mainDataSourceType = this.app.$registry.get(
'service',
mainDataSource.type
Expand Down
10 changes: 10 additions & 0 deletions web-frontend/modules/database/jobTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,13 @@ export class SyncDataSyncTableJobType extends JobType {
return 'syncDataSyncTable'
}
}

export class FileImportJobType extends JobType {
static getType() {
return 'file_import'
}

getName() {
return 'fileImport'
}
}
2 changes: 2 additions & 0 deletions web-frontend/modules/database/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { DatabaseApplicationType } from '@baserow/modules/database/applicationTy
import {
DuplicateTableJobType,
SyncDataSyncTableJobType,
FileImportJobType,
} from '@baserow/modules/database/jobTypes'
import {
GridViewType,
Expand Down Expand Up @@ -411,6 +412,7 @@ export default (context) => {

app.$registry.register('job', new DuplicateTableJobType(context))
app.$registry.register('job', new SyncDataSyncTableJobType(context))
app.$registry.register('job', new FileImportJobType(context))

app.$registry.register('view', new GridViewType(context))
app.$registry.register('view', new GalleryViewType(context))
Expand Down
Loading