Skip to content

Commit a6f6529

Browse files
committed
Merge branch 'main' into feat/visual-editor-api
2 parents c63a253 + fad0e58 commit a6f6529

575 files changed

Lines changed: 32663 additions & 26068 deletions

File tree

Some content is hidden

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

.claude/settings.json

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,58 @@
11
{
2-
"plansDirectory": "./.claude/plans"
2+
"plansDirectory": "./.claude/plans",
3+
"permissions": {
4+
"allow": [
5+
"mcp__figma__whoami",
6+
"mcp__figma__get_design_context",
7+
"mcp__figma__get_screenshot",
8+
"mcp__figma__get_metadata",
9+
"mcp__figma__get_figjam",
10+
"mcp__figma__get_code_connect_map",
11+
"mcp__figma__get_code_connect_suggestions",
12+
"mcp__figma__get_variable_defs",
13+
"mcp__linear__get_issue",
14+
"mcp__linear__get_issue_status",
15+
"mcp__linear__get_project",
16+
"mcp__linear__get_team",
17+
"mcp__linear__get_user",
18+
"mcp__linear__get_initiative",
19+
"mcp__linear__get_milestone",
20+
"mcp__linear__get_document",
21+
"mcp__linear__get_attachment",
22+
"mcp__linear__get_status_updates",
23+
"mcp__linear__list_issues",
24+
"mcp__linear__list_issue_labels",
25+
"mcp__linear__list_issue_statuses",
26+
"mcp__linear__list_projects",
27+
"mcp__linear__list_project_labels",
28+
"mcp__linear__list_teams",
29+
"mcp__linear__list_users",
30+
"mcp__linear__list_cycles",
31+
"mcp__linear__list_documents",
32+
"mcp__linear__list_initiatives",
33+
"mcp__linear__list_milestones",
34+
"mcp__linear__list_comments",
35+
"mcp__linear__list_customers",
36+
"mcp__linear__extract_images",
37+
"mcp__linear__search_documentation",
38+
"mcp__slack__conversations_history",
39+
"mcp__slack__conversations_replies",
40+
"mcp__slack__conversations_search_messages",
41+
"mcp__slack__conversations_unreads",
42+
"mcp__slack__channels_list",
43+
"mcp__slack__users_search",
44+
"mcp__slack__usergroups_list",
45+
"mcp__slack__usergroups_me",
46+
"mcp__notion__notion-fetch",
47+
"mcp__notion__notion-get-comments",
48+
"mcp__notion__notion-get-users",
49+
"mcp__notion__notion-get-teams",
50+
"mcp__notion__notion-search",
51+
"mcp__notion__notion-query-data-sources",
52+
"mcp__notion__notion-query-meeting-notes",
53+
"mcp__ide__getDiagnostics",
54+
"mcp__ide__executeCode"
55+
],
56+
"deny": []
57+
}
358
}

.github/workflows/go-cover.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ jobs:
4848
RILL_RUNTIME_REDSHIFT_TEST_AWS_SECRET_ACCESS_KEY: ${{ secrets.RILL_RUNTIME_S3_TEST_AWS_SECRET_ACCESS_KEY }}
4949
RILL_RUNTIME_MOTHERDUCK_TEST_PATH: ${{ secrets.RILL_RUNTIME_MOTHERDUCK_TEST_PATH }}
5050
RILL_RUNTIME_MOTHERDUCK_TEST_TOKEN: ${{ secrets.RILL_RUNTIME_MOTHERDUCK_TEST_TOKEN }}
51+
RILL_TEST_GH_TOKEN: ${{ secrets.RILL_TEST_GH_TOKEN }}
5152
RILL_ADMIN_TEST_GITHUB_APP_ID: ${{ secrets.RILL_ADMIN_TEST_GITHUB_APP_ID }}
5253
RILL_ADMIN_TEST_GITHUB_APP_PRIVATE_KEY: ${{ secrets.RILL_ADMIN_TEST_GITHUB_APP_PRIVATE_KEY }}
5354
RILL_ADMIN_TEST_GITHUB_MANAGED_ACCOUNT: ${{ secrets.RILL_ADMIN_TEST_GITHUB_MANAGED_ACCOUNT }}

.mcp.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
{
22
"mcpServers": {
3+
"figma": {
4+
"type": "http",
5+
"url": "https://mcp.figma.com/mcp"
6+
},
37
"linear": {
48
"type": "http",
59
"url": "https://mcp.linear.app/mcp"
610
},
11+
"notion": {
12+
"type": "http",
13+
"url": "https://mcp.notion.com/mcp"
14+
},
715
"slack": {
816
"type": "stdio",
917
"command": "npx",

Makefile

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,22 @@ docs.generate:
4747
# Sets version to the latest tag to simulate a production build, where certain commands are hidden.
4848
rm -rf docs/docs/reference/cli/*.md docs/docs/reference/project-files/*.md
4949
if [ -f ~/.rill/config.yaml ]; then mv ~/.rill/config.yaml ~/.rill/config.yaml.tmp; fi;
50-
go run -ldflags="-X main.Version=$(shell git describe --tags `git rev-list --tags --max-count=1`)" ./cli docs generate-cli docs/docs/reference/cli/
51-
go run -ldflags="-X main.Version=$(shell git describe --tags `git rev-list --tags --max-count=1`)" ./cli docs generate-project docs/docs/reference/project-files/
50+
go run -ldflags="-X main.Version=$(shell git describe --tags `git rev-list --tags='v*' --max-count=1`)" ./cli docs generate-cli docs/docs/reference/cli/
51+
go run -ldflags="-X main.Version=$(shell git describe --tags `git rev-list --tags='v*' --max-count=1`)" ./cli docs generate-project docs/docs/reference/project-files/
5252
if [ -f ~/.rill/config.yaml.tmp ]; then mv ~/.rill/config.yaml.tmp ~/.rill/config.yaml; fi;
5353

5454
.PHONY: proto.generate
5555
proto.generate:
5656
cd proto && buf generate --exclude-path rill/ui
5757
cd proto && buf generate --template buf.gen.openapi-admin.yaml --path rill/admin
5858
cd proto && buf generate --template buf.gen.openapi-runtime.yaml --path rill/runtime
59+
cd proto && buf generate --template buf.gen.runtime.yaml --path rill/runtime
5960
cd proto && buf generate --template buf.gen.local.yaml --path rill/local
6061
cd proto && buf generate --template buf.gen.ui.yaml
61-
go run -ldflags="-X main.Version=$(shell git describe --tags $(shell git rev-list --tags --max-count=1))" \
62+
go run -ldflags="-X main.Version=$(shell git describe --tags $(shell git rev-list --tags='v*' --max-count=1))" \
6263
scripts/convert-openapi-v2-to-v3/convert.go --force \
6364
proto/gen/rill/admin/v1/admin.swagger.yaml proto/gen/rill/admin/v1/openapi.yaml
64-
go run -ldflags="-X main.Version=$(shell git describe --tags $(shell git rev-list --tags --max-count=1))" \
65+
go run -ldflags="-X main.Version=$(shell git describe --tags $(shell git rev-list --tags='v*' --max-count=1))" \
6566
scripts/convert-openapi-v2-to-v3/convert.go --force --public-only \
6667
proto/gen/rill/admin/v1/admin.swagger.yaml proto/gen/rill/admin/v1/public.openapi.yaml
6768
npm run generate:runtime-client -w web-common

admin/client/client.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"net/url"
7+
"strings"
78

89
adminv1 "github.com/rilldata/rill/proto/gen/rill/admin/v1"
910
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
@@ -58,6 +59,9 @@ func New(adminHost, bearerToken, userAgent string) (*Client, error) {
5859
}
5960

6061
if bearerToken != "" {
62+
if strings.ContainsAny(bearerToken, "\r\n") { // Prevents a very cryptic HTTP protocol error
63+
return nil, fmt.Errorf("bearer token contains invalid newline characters")
64+
}
6165
secure := uri.Scheme != "http"
6266
opts = append(opts, grpc.WithPerRPCCredentials(bearerAuth{token: bearerToken, secure: secure}))
6367
}

admin/server/deployment.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,13 @@ func (s *Server) GetIFrame(ctx context.Context, req *adminv1.GetIFrameRequest) (
819819
iframeQuery[k] = v
820820
}
821821

822-
iFrameURL, err := s.admin.URLs.Embed(iframeQuery)
822+
// Fetch the org to apply its custom domain (if any) to the embed URL
823+
org, err := s.admin.DB.FindOrganization(ctx, proj.OrganizationID)
824+
if err != nil {
825+
return nil, status.Errorf(codes.Internal, "could not find organization: %s", err.Error())
826+
}
827+
828+
iFrameURL, err := s.admin.URLs.WithCustomDomain(org.CustomDomain).Embed(iframeQuery)
823829
if err != nil {
824830
return nil, status.Errorf(codes.Internal, "could not construct iframe url: %s", err.Error())
825831
}

admin/testadmin/testadmin.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ func NewWithOptionalRuntime(t *testing.T, startRt bool) *Fixture {
133133
}))
134134

135135
// Initialize mock AI using drivers.Open pattern
136-
mockAIHandle, err := drivers.Open("mock_ai", "test", map[string]any{}, storage.MustNew(os.TempDir(), nil), activity.NewNoopClient(), logger)
136+
mockAIHandle, err := drivers.Open("mock_ai", "", "test", map[string]any{}, storage.MustNew(os.TempDir(), nil), activity.NewNoopClient(), logger)
137137
require.NoError(t, err)
138138
t.Cleanup(func() { mockAIHandle.Close() })
139139
mockAI, ok := mockAIHandle.AsAI("test")

cli/cmd/admin/start.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ func StartCmd(ch *cmdutil.Helper) *cobra.Command {
270270
default:
271271
logger.Fatal("unknown AI driver", zap.String("driver", aiDriver))
272272
}
273-
aiHandle, err := drivers.Open(aiDriver, "", aiConfig, rillstorage.MustNew(os.TempDir(), nil), activity.NewNoopClient(), logger)
273+
aiHandle, err := drivers.Open(aiDriver, "", "", aiConfig, rillstorage.MustNew(os.TempDir(), nil), activity.NewNoopClient(), logger)
274274
if err != nil {
275275
logger.Fatal("error creating AI client", zap.Error(err))
276276
}

cli/cmd/deploy/deploy_test.go

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package deploy_test
33
import (
44
"context"
55
"fmt"
6+
"net/url"
67
"os"
78
"os/exec"
89
"path/filepath"
@@ -127,8 +128,7 @@ func TestManagedDeployWithPrimaryBranch(t *testing.T) {
127128

128129
// This test require gh cli to be installed on the system.
129130
// Alternatively a personal access token can be set via RILL_TEST_GH_TOKEN environment variable.
130-
// TODO: Set personal acccess token for CI/CD tests.
131-
func NoCICDTestGithubDeploy(t *testing.T) {
131+
func TestGithubDeploy(t *testing.T) {
132132
testmode.Expensive(t)
133133
personalAccessToken := getGithubAuthToken(t)
134134
// github client
@@ -150,15 +150,15 @@ func NoCICDTestGithubDeploy(t *testing.T) {
150150
u1 := testcli.New(t, adm, c.Token)
151151

152152
t.Run("self-hosted git deploy", func(t *testing.T) {
153-
testSelfHostedDeploy(t, c, ghClient, u1)
153+
testSelfHostedDeploy(t, c, ghClient, u1, personalAccessToken)
154154
})
155155

156156
t.Run("self-hosted git deploy with monorepo", func(t *testing.T) {
157-
testSelfHostedMonorepoDeploy(t, c, ghClient, u1)
157+
testSelfHostedMonorepoDeploy(t, c, ghClient, u1, personalAccessToken)
158158
})
159159
}
160160

161-
func testSelfHostedDeploy(t *testing.T, adminClient *client.Client, ghClient *github.Client, adm *testcli.Fixture) {
161+
func testSelfHostedDeploy(t *testing.T, adminClient *client.Client, ghClient *github.Client, adm *testcli.Fixture, token string) {
162162
testmode.Expensive(t)
163163
result := adm.Run(t, "org", "create", "github-test")
164164
require.Equal(t, 0, result.ExitCode)
@@ -184,9 +184,11 @@ func testSelfHostedDeploy(t *testing.T, adminClient *client.Client, ghClient *gi
184184
author := &object.Signature{
185185
Name: "Rill test user",
186186
Email: "test.user@rilldata.com",
187+
When: time.Now(),
187188
}
189+
authCloneURL := authGitURL(t, *repo.CloneURL, token)
188190
err = gitutil.CommitAndPush(t.Context(), tempDir, &gitutil.Config{
189-
Remote: *repo.CloneURL,
191+
Remote: authCloneURL,
190192
DefaultBranch: "main",
191193
}, "", author)
192194
require.NoError(t, err, "failed to push to github repo")
@@ -204,10 +206,12 @@ func testSelfHostedDeploy(t *testing.T, adminClient *client.Client, ghClient *gi
204206
require.Equal(t, "self-hosted-deploy", resp.Project.Name)
205207
require.Empty(t, resp.Project.ManagedGitId)
206208

207-
// check remote configured in directory
209+
// check remote configured in directory (normalize to strip any embedded credentials)
208210
remote, err := gitutil.ExtractGitRemote(tempDir, "origin", false)
209211
require.NoError(t, err)
210-
require.Equal(t, *repo.CloneURL, remote.URL)
212+
normalizedRemoteURL, err := gitutil.NormalizeGithubRemote(remote.URL)
213+
require.NoError(t, err)
214+
require.Equal(t, *repo.CloneURL, normalizedRemoteURL)
211215

212216
result = adm.Run(t, "deploy", "--interactive=false", "--org=github-test", "--project=self-hosted-deploy", "--skip-deploy=true", "--path="+tempDir)
213217
require.Equal(t, 0, result.ExitCode, result.Output)
@@ -224,7 +228,7 @@ func testSelfHostedDeploy(t *testing.T, adminClient *client.Client, ghClient *gi
224228
verifyGithubRepoContents(t, ghClient, resp.Project.GitRemote, changes)
225229
}
226230

227-
func testSelfHostedMonorepoDeploy(t *testing.T, adminClient *client.Client, ghClient *github.Client, adm *testcli.Fixture) {
231+
func testSelfHostedMonorepoDeploy(t *testing.T, adminClient *client.Client, ghClient *github.Client, adm *testcli.Fixture, token string) {
228232
testmode.Expensive(t)
229233
result := adm.Run(t, "org", "create", "github-monorepo-test")
230234
require.Equal(t, 0, result.ExitCode)
@@ -250,24 +254,34 @@ func testSelfHostedMonorepoDeploy(t *testing.T, adminClient *client.Client, ghCl
250254
author := &object.Signature{
251255
Name: "Rill test user",
252256
Email: "test.user@rilldata.com",
257+
When: time.Now(),
253258
}
254259
err = gitutil.CommitAndPush(t.Context(), tempDir, &gitutil.Config{
255-
Remote: *repo.CloneURL,
260+
Remote: authGitURL(t, *repo.CloneURL, token),
256261
DefaultBranch: "main",
257262
}, "", author)
258263
require.NoError(t, err, "failed to push to github repo")
259264

260265
// Clone two separate copies of the same repo to simulate independent working directories
261266
// This demonstrates that different subpaths can be worked on independently
267+
cloneRepo := func(ctx context.Context, repoURL, path, token string) error {
268+
cmd := exec.CommandContext(ctx, "git", "clone", authGitURL(t, repoURL, token), path)
269+
out, err := cmd.CombinedOutput()
270+
if err != nil {
271+
return fmt.Errorf("git clone failed: %s(%s)", out, err)
272+
}
273+
return nil
274+
}
275+
262276
clone1Dir := t.TempDir()
263277
clone2Dir := t.TempDir()
264278

265279
// Clone repo to first directory
266-
err = cloneRepo(t.Context(), *repo.CloneURL, clone1Dir)
280+
err = cloneRepo(t.Context(), *repo.CloneURL, clone1Dir, token)
267281
require.NoError(t, err, "failed to clone repo to first directory")
268282

269283
// Clone repo to second directory
270-
err = cloneRepo(t.Context(), *repo.CloneURL, clone2Dir)
284+
err = cloneRepo(t.Context(), *repo.CloneURL, clone2Dir, token)
271285
require.NoError(t, err, "failed to clone repo to second directory")
272286

273287
// deploy project1 from first clone
@@ -475,11 +489,9 @@ func initGitWithTwoBranches(t *testing.T, dir string) {
475489
runGitCmd("commit", "-m", "staging changes")
476490
}
477491

478-
func cloneRepo(ctx context.Context, repoURL, path string) error {
479-
cmd := exec.CommandContext(ctx, "git", "clone", repoURL, path)
480-
out, err := cmd.CombinedOutput()
481-
if err != nil {
482-
return fmt.Errorf("clone repo failed with error: %s(%s)", out, err)
483-
}
484-
return nil
492+
func authGitURL(t *testing.T, repoURL, token string) string {
493+
u, err := url.Parse(repoURL)
494+
require.NoError(t, err)
495+
u.User = url.UserPassword("x-access-token", token)
496+
return u.String()
485497
}

0 commit comments

Comments
 (0)