Skip to content

Commit 1027992

Browse files
authored
Merge branch 'main' into feat/side-panel-object-filter-dropdown
2 parents 54b30a6 + d5b41b2 commit 1027992

File tree

760 files changed

+28758
-13553
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

760 files changed

+28758
-13553
lines changed

.claude/settings.json

Lines changed: 0 additions & 7 deletions
This file was deleted.

.github/actions/spawn-twenty-docker-image/action.yaml

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ description: >
33
Starts a full Twenty instance (server, worker, database, redis) using Docker
44
Compose. The server is available at http://localhost:3000 for subsequent steps
55
in the caller's job.
6-
Pulls the specified semver image tag from Docker Hub.
6+
Accepts "latest" (pulls the latest Docker Hub image, checks out main) or a
7+
semver tag (e.g., v0.40.0).
78
Designed to be consumed from external repositories (e.g., twenty-app).
89
910
inputs:
1011
twenty-version:
11-
description: 'Twenty Docker Hub image tag as semver (e.g., v0.40.0, v1.0.0).'
12+
description: 'Twenty Docker Hub image tag — either "latest" or a semver tag (e.g., v0.40.0).'
1213
required: true
1314
twenty-repository:
1415
description: 'Twenty repository to checkout docker compose files from.'
@@ -30,20 +31,27 @@ outputs:
3031
runs:
3132
using: 'composite'
3233
steps:
33-
- name: Validate version
34+
- name: Resolve version
35+
id: resolve
3436
shell: bash
3537
run: |
3638
VERSION="${{ inputs.twenty-version }}"
37-
if ! echo "$VERSION" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
38-
echo "::error::twenty-version must be a semver tag (e.g., v0.40.0). Got: '$VERSION'"
39+
if [ "$VERSION" = "latest" ]; then
40+
echo "docker-tag=latest" >> "$GITHUB_OUTPUT"
41+
echo "git-ref=main" >> "$GITHUB_OUTPUT"
42+
elif echo "$VERSION" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
43+
echo "docker-tag=$VERSION" >> "$GITHUB_OUTPUT"
44+
echo "git-ref=$VERSION" >> "$GITHUB_OUTPUT"
45+
else
46+
echo "::error::twenty-version must be \"latest\" or a semver tag (e.g., v0.40.0). Got: '$VERSION'"
3947
exit 1
4048
fi
4149
4250
- name: Checkout docker compose files
4351
uses: actions/checkout@v4
4452
with:
4553
repository: ${{ inputs.twenty-repository }}
46-
ref: ${{ inputs.twenty-version }}
54+
ref: ${{ steps.resolve.outputs.git-ref }}
4755
token: ${{ inputs.github-token }}
4856
sparse-checkout: |
4957
packages/twenty-docker
@@ -56,7 +64,7 @@ runs:
5664
run: |
5765
cp .env.example .env
5866
echo "" >> .env
59-
echo "TAG=${{ inputs.twenty-version }}" >> .env
67+
echo "TAG=${{ steps.resolve.outputs.docker-tag }}" >> .env
6068
echo "APP_SECRET=replace_me_with_a_random_string" >> .env
6169
echo "SERVER_URL=http://localhost:3000" >> .env
6270

.github/verdaccio-config.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ packages:
1010
'twenty-sdk':
1111
access: $all
1212
publish: $all
13+
'twenty-client-sdk':
14+
access: $all
15+
publish: $all
1316
'create-twenty-app':
1417
access: $all
1518
publish: $all

.github/workflows/ci-create-app-e2e.yaml

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ jobs:
2121
files: |
2222
packages/create-twenty-app/**
2323
packages/twenty-sdk/**
24+
packages/twenty-client-sdk/**
2425
packages/twenty-shared/**
2526
packages/twenty-server/**
2627
!packages/create-twenty-app/package.json
2728
!packages/twenty-sdk/package.json
29+
!packages/twenty-client-sdk/package.json
2830
!packages/twenty-shared/package.json
2931
!packages/twenty-server/package.json
3032
create-app-e2e:
@@ -64,11 +66,12 @@ jobs:
6466
run: |
6567
CI_VERSION="0.0.0-ci.$(date +%s)"
6668
echo "CI_VERSION=$CI_VERSION" >> $GITHUB_ENV
67-
npx nx run-many -t set-local-version -p twenty-sdk create-twenty-app --releaseVersion=$CI_VERSION
69+
npx nx run-many -t set-local-version -p twenty-sdk twenty-client-sdk create-twenty-app --releaseVersion=$CI_VERSION
6870
6971
- name: Build packages
7072
run: |
7173
npx nx build twenty-sdk
74+
npx nx build twenty-client-sdk
7275
npx nx build create-twenty-app
7376
7477
- name: Install and start Verdaccio
@@ -88,7 +91,7 @@ jobs:
8891
run: |
8992
npm set //localhost:4873/:_authToken "ci-auth-token"
9093
91-
for pkg in twenty-sdk create-twenty-app; do
94+
for pkg in twenty-sdk twenty-client-sdk create-twenty-app; do
9295
cd packages/$pkg
9396
npm publish --registry http://localhost:4873 --tag ci
9497
cd ../..
@@ -153,11 +156,15 @@ jobs:
153156
cd /tmp/e2e-test-workspace/test-app
154157
npx --no-install twenty remote add --token $SEED_API_KEY --url http://localhost:3000
155158
156-
- name: Build scaffolded app
159+
- name: Deploy scaffolded app
157160
run: |
158161
cd /tmp/e2e-test-workspace/test-app
159-
npx --no-install twenty build
160-
test -d .twenty/output
162+
npx --no-install twenty deploy
163+
164+
- name: Install scaffolded app
165+
run: |
166+
cd /tmp/e2e-test-workspace/test-app
167+
npx --no-install twenty install
161168
162169
- name: Execute hello-world logic function
163170
run: |
@@ -166,6 +173,13 @@ jobs:
166173
echo "$EXEC_OUTPUT"
167174
echo "$EXEC_OUTPUT" | grep -q "Hello, World!"
168175
176+
- name: Execute create-hello-world-company logic function
177+
run: |
178+
cd /tmp/e2e-test-workspace/test-app
179+
EXEC_OUTPUT=$(npx --no-install twenty exec --functionName create-hello-world-company)
180+
echo "$EXEC_OUTPUT"
181+
echo "$EXEC_OUTPUT" | grep -q "Created company"
182+
169183
- name: Run scaffolded app integration test
170184
env:
171185
TWENTY_API_URL: http://localhost:3000

.github/workflows/ci-front.yaml

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -151,40 +151,6 @@ jobs:
151151
# npx nyc merge coverage-artifacts ${{ env.PATH_TO_COVERAGE }}/coverage-storybook.json
152152
# - name: Checking coverage
153153
# run: npx nx storybook:coverage twenty-front --checkCoverage=true --configuration=${{ matrix.storybook_scope }}
154-
visual-regression-dispatch:
155-
needs: front-sb-build
156-
if: github.event_name == 'pull_request'
157-
timeout-minutes: 5
158-
runs-on: ubuntu-latest
159-
steps:
160-
- name: Download storybook build
161-
uses: actions/download-artifact@v4
162-
with:
163-
name: storybook-static
164-
path: storybook-static
165-
- name: Package storybook
166-
run: tar -czf /tmp/storybook-twenty-front.tar.gz -C storybook-static .
167-
- name: Upload storybook tarball
168-
uses: actions/upload-artifact@v4
169-
with:
170-
name: storybook-twenty-front-tarball
171-
path: /tmp/storybook-twenty-front.tar.gz
172-
retention-days: 1
173-
- name: Dispatch to ci-privileged
174-
uses: peter-evans/repository-dispatch@v2
175-
with:
176-
token: ${{ secrets.CI_PRIVILEGED_DISPATCH_TOKEN }}
177-
repository: twentyhq/ci-privileged
178-
event-type: visual-regression
179-
client-payload: >-
180-
{
181-
"pr_number": "${{ github.event.pull_request.number }}",
182-
"run_id": "${{ github.run_id }}",
183-
"repo": "${{ github.repository }}",
184-
"project": "twenty-front",
185-
"branch": "${{ github.head_ref }}",
186-
"commit": "${{ github.event.pull_request.head.sha }}"
187-
}
188154
front-task:
189155
needs: changed-files-check
190156
if: needs.changed-files-check.outputs.any_changed == 'true'

.github/workflows/ci-server.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
packages/twenty-server/**
2626
packages/twenty-front/src/generated/**
2727
packages/twenty-front/src/generated-metadata/**
28-
packages/twenty-sdk/src/clients/generated/metadata/**
28+
packages/twenty-client-sdk/**
2929
packages/twenty-emails/**
3030
packages/twenty-shared/**
3131
@@ -177,14 +177,14 @@ jobs:
177177
HAS_ERRORS=true
178178
fi
179179
180-
npx nx run twenty-sdk:generate-metadata-client
180+
npx nx run twenty-client-sdk:generate-metadata-client
181181
182-
if ! git diff --quiet -- packages/twenty-sdk/src/clients/generated/metadata; then
183-
echo "::error::SDK metadata client changes detected. Please run 'npx nx run twenty-sdk:generate-metadata-client' and commit the changes."
182+
if ! git diff --quiet -- packages/twenty-client-sdk/src/metadata/generated; then
183+
echo "::error::SDK metadata client changes detected. Please run 'npx nx run twenty-client-sdk:generate-metadata-client' and commit the changes."
184184
echo ""
185185
echo "The following SDK metadata client changes were detected:"
186186
echo "==================================================="
187-
git diff -- packages/twenty-sdk/src/clients/generated/metadata
187+
git diff -- packages/twenty-client-sdk/src/metadata/generated
188188
echo "==================================================="
189189
echo ""
190190
HAS_ERRORS=true

.github/workflows/ci-ui.yaml

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -95,40 +95,6 @@ jobs:
9595
npx http-server packages/twenty-ui/storybook-static --port 6007 --silent &
9696
timeout 30 bash -c 'until curl -sf http://localhost:6007 > /dev/null 2>&1; do sleep 1; done'
9797
npx nx storybook:test twenty-ui
98-
visual-regression-dispatch:
99-
needs: ui-sb-build
100-
if: github.event_name == 'pull_request'
101-
timeout-minutes: 5
102-
runs-on: ubuntu-latest
103-
steps:
104-
- name: Download storybook build
105-
uses: actions/download-artifact@v4
106-
with:
107-
name: storybook-twenty-ui
108-
path: storybook-static
109-
- name: Package storybook
110-
run: tar -czf /tmp/storybook-twenty-ui.tar.gz -C storybook-static .
111-
- name: Upload storybook tarball
112-
uses: actions/upload-artifact@v4
113-
with:
114-
name: storybook-twenty-ui-tarball
115-
path: /tmp/storybook-twenty-ui.tar.gz
116-
retention-days: 1
117-
- name: Dispatch to ci-privileged
118-
uses: peter-evans/repository-dispatch@v2
119-
with:
120-
token: ${{ secrets.CI_PRIVILEGED_DISPATCH_TOKEN }}
121-
repository: twentyhq/ci-privileged
122-
event-type: visual-regression
123-
client-payload: >-
124-
{
125-
"pr_number": "${{ github.event.pull_request.number }}",
126-
"run_id": "${{ github.run_id }}",
127-
"repo": "${{ github.repository }}",
128-
"project": "twenty-ui",
129-
"branch": "${{ github.head_ref }}",
130-
"commit": "${{ github.event.pull_request.head.sha }}"
131-
}
13298
ci-ui-status-check:
13399
if: always() && !cancelled()
134100
timeout-minutes: 5
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
name: Visual Regression Dispatch
2+
3+
# Uses workflow_run to dispatch visual regression to ci-privileged.
4+
# This runs in the context of the base repo (not the fork), so it has
5+
# access to secrets — making it work for external contributor PRs.
6+
7+
on:
8+
workflow_run:
9+
workflows: ['CI Front', 'CI UI']
10+
types: [completed]
11+
12+
permissions:
13+
actions: read
14+
pull-requests: read
15+
16+
jobs:
17+
dispatch:
18+
if: >-
19+
github.event.workflow_run.event == 'pull_request' &&
20+
github.event.workflow_run.conclusion == 'success'
21+
runs-on: ubuntu-latest
22+
timeout-minutes: 5
23+
steps:
24+
- name: Determine project and artifact name
25+
id: project
26+
uses: actions/github-script@v7
27+
with:
28+
script: |
29+
const workflowName = context.payload.workflow_run.name;
30+
if (workflowName === 'CI Front') {
31+
core.setOutput('project', 'twenty-front');
32+
core.setOutput('artifact_name', 'storybook-static');
33+
core.setOutput('tarball_name', 'storybook-twenty-front-tarball');
34+
core.setOutput('tarball_file', 'storybook-twenty-front.tar.gz');
35+
} else if (workflowName === 'CI UI') {
36+
core.setOutput('project', 'twenty-ui');
37+
core.setOutput('artifact_name', 'storybook-twenty-ui');
38+
core.setOutput('tarball_name', 'storybook-twenty-ui-tarball');
39+
core.setOutput('tarball_file', 'storybook-twenty-ui.tar.gz');
40+
} else {
41+
core.setFailed(`Unexpected workflow: ${workflowName}`);
42+
}
43+
44+
- name: Check if storybook artifact exists
45+
id: check-artifact
46+
uses: actions/github-script@v7
47+
with:
48+
script: |
49+
const artifactName = '${{ steps.project.outputs.artifact_name }}';
50+
const runId = context.payload.workflow_run.id;
51+
52+
const { data: artifacts } = await github.rest.actions.listWorkflowRunArtifacts({
53+
owner: context.repo.owner,
54+
repo: context.repo.repo,
55+
run_id: runId,
56+
});
57+
58+
const found = artifacts.artifacts.some(a => a.name === artifactName);
59+
core.setOutput('exists', found ? 'true' : 'false');
60+
61+
if (!found) {
62+
core.info(`Artifact "${artifactName}" not found in run ${runId} — storybook build was likely skipped`);
63+
}
64+
65+
- name: Get PR number
66+
if: steps.check-artifact.outputs.exists == 'true'
67+
id: pr-info
68+
uses: actions/github-script@v7
69+
with:
70+
script: |
71+
const headBranch = context.payload.workflow_run.head_branch;
72+
const headRepo = context.payload.workflow_run.head_repository;
73+
74+
// workflow_run.pull_requests is empty for fork PRs,
75+
// so fall back to searching by head label (owner:branch)
76+
let pullRequests = context.payload.workflow_run.pull_requests;
77+
let prNumber;
78+
79+
if (pullRequests && pullRequests.length > 0) {
80+
prNumber = pullRequests[0].number;
81+
} else {
82+
const headLabel = `${headRepo.owner.login}:${headBranch}`;
83+
core.info(`pull_requests is empty (likely a fork PR), searching by head label: ${headLabel}`);
84+
85+
const { data: prs } = await github.rest.pulls.list({
86+
owner: context.repo.owner,
87+
repo: context.repo.repo,
88+
state: 'open',
89+
head: headLabel,
90+
per_page: 1,
91+
});
92+
93+
if (prs.length > 0) {
94+
prNumber = prs[0].number;
95+
}
96+
}
97+
98+
if (!prNumber) {
99+
core.info('No pull request found for this workflow run — skipping');
100+
core.setOutput('has_pr', 'false');
101+
return;
102+
}
103+
104+
core.setOutput('pr_number', prNumber);
105+
core.setOutput('has_pr', 'true');
106+
core.info(`PR #${prNumber}`);
107+
108+
- name: Download storybook artifact from triggering run
109+
if: steps.check-artifact.outputs.exists == 'true' && steps.pr-info.outputs.has_pr == 'true'
110+
uses: actions/download-artifact@v4
111+
with:
112+
name: ${{ steps.project.outputs.artifact_name }}
113+
path: storybook-static
114+
run-id: ${{ github.event.workflow_run.id }}
115+
github-token: ${{ github.token }}
116+
117+
- name: Package storybook
118+
if: steps.check-artifact.outputs.exists == 'true' && steps.pr-info.outputs.has_pr == 'true'
119+
run: tar -czf /tmp/${{ steps.project.outputs.tarball_file }} -C storybook-static .
120+
121+
- name: Upload storybook tarball
122+
if: steps.check-artifact.outputs.exists == 'true' && steps.pr-info.outputs.has_pr == 'true'
123+
uses: actions/upload-artifact@v4
124+
with:
125+
name: ${{ steps.project.outputs.tarball_name }}
126+
path: /tmp/${{ steps.project.outputs.tarball_file }}
127+
retention-days: 1
128+
129+
- name: Dispatch to ci-privileged
130+
if: steps.check-artifact.outputs.exists == 'true' && steps.pr-info.outputs.has_pr == 'true'
131+
uses: peter-evans/repository-dispatch@v2
132+
with:
133+
token: ${{ secrets.CI_PRIVILEGED_DISPATCH_TOKEN }}
134+
repository: twentyhq/ci-privileged
135+
event-type: visual-regression
136+
client-payload: >-
137+
{
138+
"pr_number": "${{ steps.pr-info.outputs.pr_number }}",
139+
"run_id": "${{ github.run_id }}",
140+
"repo": "${{ github.repository }}",
141+
"project": "${{ steps.project.outputs.project }}",
142+
"branch": "${{ github.event.workflow_run.head_branch }}",
143+
"commit": "${{ github.event.workflow_run.head_sha }}"
144+
}

0 commit comments

Comments
 (0)