mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-07 22:24:06 -05:00
feat: implement native ARM64 Docker builds with CDN support (#791)
* feat: implement native ARM64 Docker builds with CDN support - Replace QEMU emulation with native ARM64/AMD64 runners (linux-arm64-8-core, linux-x64-8-core) - Fix manifest creation with proper error handling and image existence checks - Add CDN video support with getVideoUrl function and Video component - Update all docs MDX files to use Video component instead of raw video tags - Update GitHub Actions workflow to use architecture-specific builds - Remove QEMU setup to eliminate emulation timeout issues - Maintain multi-arch Docker image support through manifests * Update .github/workflows/build.yml Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
5028930b9f
commit
eeb1a340b2
111
.github/workflows/build.yml
vendored
111
.github/workflows/build.yml
vendored
@@ -7,17 +7,43 @@ on:
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest-8-cores
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# AMD64 builds on x86 runners
|
||||
- dockerfile: ./docker/app.Dockerfile
|
||||
image: ghcr.io/simstudioai/simstudio
|
||||
platform: linux/amd64
|
||||
arch: amd64
|
||||
runner: linux-x64-8-core
|
||||
- dockerfile: ./docker/db.Dockerfile
|
||||
image: ghcr.io/simstudioai/migrations
|
||||
platform: linux/amd64
|
||||
arch: amd64
|
||||
runner: linux-x64-8-core
|
||||
- dockerfile: ./docker/realtime.Dockerfile
|
||||
image: ghcr.io/simstudioai/realtime
|
||||
platform: linux/amd64
|
||||
arch: amd64
|
||||
runner: linux-x64-8-core
|
||||
# ARM64 builds on native ARM64 runners
|
||||
- dockerfile: ./docker/app.Dockerfile
|
||||
image: ghcr.io/simstudioai/simstudio
|
||||
platform: linux/arm64
|
||||
arch: arm64
|
||||
runner: linux-arm64-8-core
|
||||
- dockerfile: ./docker/db.Dockerfile
|
||||
image: ghcr.io/simstudioai/migrations
|
||||
platform: linux/arm64
|
||||
arch: arm64
|
||||
runner: linux-arm64-8-core
|
||||
- dockerfile: ./docker/realtime.Dockerfile
|
||||
image: ghcr.io/simstudioai/realtime
|
||||
platform: linux/arm64
|
||||
arch: arm64
|
||||
runner: linux-arm64-8-core
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
@@ -26,9 +52,6 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
@@ -41,6 +64,53 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ matrix.image }}
|
||||
tags: |
|
||||
type=raw,value=latest-${{ matrix.arch }},enable=${{ github.ref == 'refs/heads/main' }}
|
||||
type=ref,event=pr,suffix=-${{ matrix.arch }}
|
||||
type=semver,pattern={{version}},suffix=-${{ matrix.arch }}
|
||||
type=semver,pattern={{major}}.{{minor}},suffix=-${{ matrix.arch }}
|
||||
type=semver,pattern={{major}}.{{minor}}.{{patch}},suffix=-${{ matrix.arch }}
|
||||
type=sha,format=long,suffix=-${{ matrix.arch }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ${{ matrix.dockerfile }}
|
||||
platforms: ${{ matrix.platform }}
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha,scope=build-v2
|
||||
cache-to: type=gha,mode=max,scope=build-v2
|
||||
|
||||
create-manifests:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-and-push
|
||||
if: github.event_name != 'pull_request'
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- image: ghcr.io/simstudioai/simstudio
|
||||
- image: ghcr.io/simstudioai/migrations
|
||||
- image: ghcr.io/simstudioai/realtime
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for manifest
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
@@ -53,14 +123,25 @@ jobs:
|
||||
type=semver,pattern={{major}}.{{minor}}.{{patch}}
|
||||
type=sha,format=long
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ${{ matrix.dockerfile }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
- name: Create and push manifest
|
||||
run: |
|
||||
# Extract the tags from metadata
|
||||
TAGS="${{ steps.meta.outputs.tags }}"
|
||||
|
||||
# Create manifest for each tag
|
||||
for tag in $TAGS; do
|
||||
echo "Creating manifest for $tag"
|
||||
echo "Looking for images: ${tag}-amd64 and ${tag}-arm64"
|
||||
|
||||
# Check if both architecture images exist before creating manifest
|
||||
if docker manifest inspect ${tag}-amd64 >/dev/null 2>&1 && docker manifest inspect ${tag}-arm64 >/dev/null 2>&1; then
|
||||
docker manifest create $tag \
|
||||
${tag}-amd64 \
|
||||
${tag}-arm64
|
||||
docker manifest push $tag
|
||||
echo "Successfully created and pushed manifest for $tag"
|
||||
else
|
||||
echo "Warning: One or both architecture images not found for $tag"
|
||||
echo "Skipping manifest creation for this tag"
|
||||
fi
|
||||
done
|
||||
30
apps/docs/components/ui/video.tsx
Normal file
30
apps/docs/components/ui/video.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import { getVideoUrl } from '@/lib/utils'
|
||||
|
||||
interface VideoProps {
|
||||
src: string
|
||||
className?: string
|
||||
autoPlay?: boolean
|
||||
loop?: boolean
|
||||
muted?: boolean
|
||||
playsInline?: boolean
|
||||
}
|
||||
|
||||
export function Video({
|
||||
src,
|
||||
className = 'w-full -mb-2 rounded-lg',
|
||||
autoPlay = true,
|
||||
loop = true,
|
||||
muted = true,
|
||||
playsInline = true,
|
||||
}: VideoProps) {
|
||||
return (
|
||||
<video
|
||||
autoPlay={autoPlay}
|
||||
loop={loop}
|
||||
muted={muted}
|
||||
playsInline={playsInline}
|
||||
className={className}
|
||||
src={getVideoUrl(src)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import { Callout } from 'fumadocs-ui/components/callout'
|
||||
import { Step, Steps } from 'fumadocs-ui/components/steps'
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
|
||||
import { ThemeImage } from '@/components/ui/theme-image'
|
||||
import { Video } from '@/components/ui/video'
|
||||
|
||||
The Evaluator block uses AI to score and assess content quality based on metrics you define. Perfect for quality control, A/B testing, and ensuring your AI outputs meet specific standards.
|
||||
|
||||
@@ -63,7 +64,7 @@ Choose an AI model to perform the evaluation:
|
||||
**Local Models**: Any model running on Ollama
|
||||
|
||||
<div className="w-full max-w-2xl mx-auto overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/models.mp4"></video>
|
||||
<Video src="models.mp4" />
|
||||
</div>
|
||||
|
||||
**Recommendation**: Use models with strong reasoning capabilities like GPT-4o or Claude 3.7 Sonnet for more accurate evaluations.
|
||||
|
||||
@@ -7,11 +7,12 @@ import { Card, Cards } from 'fumadocs-ui/components/card'
|
||||
import { Step, Steps } from 'fumadocs-ui/components/steps'
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
|
||||
import { BlockTypes } from '@/components/ui/block-types'
|
||||
import { Video } from '@/components/ui/video'
|
||||
|
||||
Blocks are the building components you connect together to create AI workflows. Think of them as specialized modules that each handle a specific task—from chatting with AI models to making API calls or processing data.
|
||||
|
||||
<div className="w-full max-w-2xl mx-auto overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/connections.mp4"></video>
|
||||
<Video src="connections.mp4" />
|
||||
</div>
|
||||
|
||||
## Core Block Types
|
||||
@@ -62,7 +63,7 @@ You create workflows by connecting blocks together. The output of one block beco
|
||||
- **Branching paths**: Some blocks can route to different paths based on conditions
|
||||
|
||||
<div className="w-full max-w-2xl mx-auto overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/connections.mp4"></video>
|
||||
<Video src="connections.mp4" />
|
||||
</div>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Step, Steps } from 'fumadocs-ui/components/steps'
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
|
||||
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion'
|
||||
import { ThemeImage } from '@/components/ui/theme-image'
|
||||
import { Video } from '@/components/ui/video'
|
||||
|
||||
The Router block uses AI to intelligently decide which path your workflow should take next. Unlike Condition blocks that use simple rules, Router blocks can understand context and make smart routing decisions based on content analysis.
|
||||
|
||||
@@ -103,7 +104,7 @@ Choose an AI model to power the routing decision:
|
||||
**Local Models**: Any model running on Ollama
|
||||
|
||||
<div className="w-full max-w-2xl mx-auto overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/router-model-dropdown.mp4"></video>
|
||||
<Video src="router-model-dropdown.mp4" />
|
||||
</div>
|
||||
|
||||
**Recommendation**: Use models with strong reasoning capabilities like GPT-4o or Claude 3.7 Sonnet for more accurate routing decisions.
|
||||
|
||||
@@ -6,6 +6,7 @@ description: Connect your blocks to one another.
|
||||
import { Callout } from 'fumadocs-ui/components/callout'
|
||||
import { Card, Cards } from 'fumadocs-ui/components/card'
|
||||
import { ConnectIcon } from '@/components/icons'
|
||||
import { Video } from '@/components/ui/video'
|
||||
|
||||
Connections are the pathways that allow data to flow between blocks in your workflow. They define how information is passed from one block to another, enabling you to create sophisticated, multi-step processes.
|
||||
|
||||
@@ -15,7 +16,7 @@ Connections are the pathways that allow data to flow between blocks in your work
|
||||
</Callout>
|
||||
|
||||
<div className="mx-auto w-full overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/connections.mp4"></video>
|
||||
<Video src="connections.mp4" />
|
||||
</div>
|
||||
|
||||
## Connection Types
|
||||
|
||||
@@ -4,11 +4,12 @@ description: Using connection tags to reference data between blocks
|
||||
---
|
||||
|
||||
import { Callout } from 'fumadocs-ui/components/callout'
|
||||
import { Video } from '@/components/ui/video'
|
||||
|
||||
Connection tags are visual representations of the data available from connected blocks. They provide an easy way to reference outputs from previous blocks in your workflow.
|
||||
|
||||
<div className="mx-auto w-full overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/connections.mp4"></video>
|
||||
<Video src="connections.mp4" />
|
||||
</div>
|
||||
|
||||
### What Are Connection Tags?
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
LoopIcon,
|
||||
ParallelIcon,
|
||||
} from '@/components/icons'
|
||||
import { Video } from '@/components/ui/video'
|
||||
|
||||
When you run a workflow in Sim Studio, the execution engine follows a systematic process to ensure blocks are executed in the correct order with proper data flow.
|
||||
|
||||
@@ -162,7 +163,7 @@ Run workflows on-demand through the Sim Studio interface by clicking the "Run" b
|
||||
- Workflows that need human supervision
|
||||
|
||||
<div className="mx-auto w-full overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/input-format.mp4"></video>
|
||||
<Video src="input-format.mp4" />
|
||||
</div>
|
||||
|
||||
### Scheduled Execution
|
||||
@@ -175,7 +176,7 @@ Configure workflows to run automatically on a specified schedule:
|
||||
- Set minimum and maximum execution intervals
|
||||
|
||||
<div className="mx-auto w-full overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/configure-schedule.mp4"></video>
|
||||
<Video src="configure-schedule.mp4" />
|
||||
</div>
|
||||
|
||||
### API Endpoints
|
||||
@@ -188,7 +189,7 @@ Each workflow can be exposed as an API endpoint:
|
||||
- Receive execution results as JSON responses
|
||||
|
||||
<div className="mx-auto w-full overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/api-deployment.mp4"></video>
|
||||
<Video src="api-deployment.mp4" />
|
||||
</div>
|
||||
|
||||
#### Viewing Deployed APIs
|
||||
@@ -196,7 +197,7 @@ Each workflow can be exposed as an API endpoint:
|
||||
Monitor your deployed workflow APIs and their current state:
|
||||
|
||||
<div className="mx-auto w-full overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/api-redeployment.mp4"></video>
|
||||
<Video src="api-redeployment.mp4" />
|
||||
</div>
|
||||
|
||||
This shows how to view the deployed state and compare with the original deployed API configuration.
|
||||
@@ -211,7 +212,7 @@ Configure workflows to execute in response to external events:
|
||||
- Support for specialized webhooks (GitHub, Stripe, etc.)
|
||||
|
||||
<div className="mx-auto w-full overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/webhooks.mp4"></video>
|
||||
<Video src="webhooks.mp4" />
|
||||
</div>
|
||||
|
||||
<Callout type="info">
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
PerplexityIcon,
|
||||
SlackIcon,
|
||||
} from '@/components/icons'
|
||||
import { Video } from '@/components/ui/video'
|
||||
|
||||
This tutorial will guide you through building your first AI workflow in Sim Studio. We'll create a people research agent that can find information about individuals using state-of-the-art LLM-Search tools.
|
||||
|
||||
@@ -63,7 +64,7 @@ A people research agent that:
|
||||
- **User Prompt**: Drag the connection from the Start block's output into this field (this connects `<start.input>` to the user prompt)
|
||||
|
||||
<div className="mx-auto w-full overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/static/examples/started/started-2.mp4"></video>
|
||||
<Video src="examples/started-2.mp4" />
|
||||
</div>
|
||||
</Step>
|
||||
|
||||
@@ -77,7 +78,7 @@ A people research agent that:
|
||||
- Add your API keys for both tools (this allows the agent to search the web and access additional information)
|
||||
|
||||
<div className="mx-auto w-3/5 overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/static/examples/started/started-3.mp4"></video>
|
||||
<Video src="examples/started-3.mp4" />
|
||||
</div>
|
||||
</Step>
|
||||
|
||||
@@ -92,7 +93,7 @@ A people research agent that:
|
||||
You should see the agent's response analyzing the person described in your text.
|
||||
|
||||
<div className="mx-auto w-full overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/static/examples/started/started-4.mp4"></video>
|
||||
<Video src="examples/started-4.mp4" />
|
||||
</div>
|
||||
</Step>
|
||||
|
||||
@@ -105,7 +106,7 @@ A people research agent that:
|
||||
- The AI will generate a JSON schema for you automatically
|
||||
|
||||
<div className="mx-auto w-full overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/static/examples/started/started-5.mp4"></video>
|
||||
<Video src="examples/started-5.mp4" />
|
||||
</div>
|
||||
</Step>
|
||||
|
||||
@@ -120,7 +121,7 @@ A people research agent that:
|
||||
You should now see structured JSON output with the person's information organized into location, profession, and education fields.
|
||||
|
||||
<div className="mx-auto w-full overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/static/examples/started/started-6.mp4"></video>
|
||||
<Video src="examples/started-6.mp4" />
|
||||
</div>
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
@@ -6,11 +6,12 @@ description: Trigger workflow execution from external webhooks
|
||||
import { Callout } from 'fumadocs-ui/components/callout'
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
|
||||
import { ThemeImage } from '@/components/ui/theme-image'
|
||||
import { Video } from '@/components/ui/video'
|
||||
|
||||
The Webhook block allows external services to automatically trigger your workflow execution through HTTP webhooks.
|
||||
|
||||
<div className="mx-auto w-full overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/webhooks.mp4"></video>
|
||||
<Video src="webhooks.mp4" />
|
||||
</div>
|
||||
|
||||
## Supported Providers
|
||||
|
||||
@@ -7,11 +7,12 @@ import { Callout } from 'fumadocs-ui/components/callout'
|
||||
import { Step, Steps } from 'fumadocs-ui/components/steps'
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
|
||||
import { ThemeImage } from '@/components/ui/theme-image'
|
||||
import { Video } from '@/components/ui/video'
|
||||
|
||||
Variables in Sim Studio act as a global store for data that can be accessed and modified by any block in your workflow. They provide a powerful way to share information between different parts of your workflow, maintain state, and create more dynamic applications.
|
||||
|
||||
<div className="mx-auto w-full overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/variables.mp4"></video>
|
||||
<Video src="variables.mp4" />
|
||||
</div>
|
||||
|
||||
<Callout type="info">
|
||||
@@ -57,7 +58,7 @@ Variables can be accessed from any block in your workflow using the variable dro
|
||||
3. Select the variable you want to use
|
||||
|
||||
<div className="mx-auto w-full overflow-hidden rounded-lg">
|
||||
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/variables-dropdown.mp4"></video>
|
||||
<Video src="variables-dropdown.mp4" />
|
||||
</div>
|
||||
|
||||
<Callout>
|
||||
|
||||
@@ -7,3 +7,15 @@ import { twMerge } from 'tailwind-merge'
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full URL for a video asset stored in Vercel Blob
|
||||
*/
|
||||
export function getVideoUrl(filename: string) {
|
||||
const baseUrl = process.env.NEXT_PUBLIC_BLOB_BASE_URL
|
||||
if (!baseUrl) {
|
||||
console.warn('NEXT_PUBLIC_BLOB_BASE_URL not configured, falling back to local path')
|
||||
return `/${filename}`
|
||||
}
|
||||
return `${baseUrl}/${filename}`
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@ RUN bun install --omit dev --ignore-scripts
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
|
||||
# Install turbo globally in builder stage
|
||||
RUN bun install -g turbo
|
||||
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
|
||||
|
||||
Reference in New Issue
Block a user