Git Repositories
Clone git repositories into your VMs automatically.
Overview
Freestyle automatically clones git repositories into your VMs during creation. Repositories are cloned using a read-only mechanism optimized for fast startup times.
Basic Usage
import { freestyle } from "freestyle-sandboxes";
const { vm } = await freestyle.vms.create({
gitRepos: [
{
repo: "https://github.com/owner/repo-name",
path: "/app",
},
],
});
// Repository is ready to use
await vm.exec("ls /app");Specifying Repository Format
You can use several formats to specify repositories:
Full GitHub URL
gitRepos: [
{
repo: "https://github.com/facebook/react",
path: "/repos/react",
},
]Freestyle Repository ID
If you've imported a repository into Freestyle, use its ID:
gitRepos: [
{
repo: "repo_abc123",
path: "/app",
},
]Branches, Tags, and Commits
Clone specific branches, tags, or commits using the rev parameter:
Branch
gitRepos: [
{
repo: "https://github.com/owner/repo",
path: "/app",
rev: "develop",
},
]Tag
gitRepos: [
{
repo: "https://github.com/owner/repo",
path: "/app",
rev: "v1.2.3",
},
]Commit SHA
gitRepos: [
{
repo: "https://github.com/owner/repo",
path: "/app",
rev: "a1b2c3d4e5f6",
},
]If rev is not specified, the default branch (usually main or master) is cloned.
Multiple Repositories
Clone multiple repositories into different paths:
const { vm } = await freestyle.vms.create({
gitRepos: [
{
repo: "https://github.com/company/frontend",
path: "/app/frontend",
},
{
repo: "https://github.com/company/backend",
path: "/app/backend",
},
{
repo: "https://github.com/company/shared-lib",
path: "/app/shared",
},
],
});With Templates
Include git repositories in templates for caching:
import { freestyle, VmTemplate } from "freestyle-sandboxes";
const template = new VmTemplate({
gitRepos: [
{
repo: "https://github.com/owner/repo",
path: "/app",
},
],
systemd: {
services: [
{
name: "install-deps",
mode: "oneshot",
exec: ["npm install"],
workdir: "/app",
after: ["freestyle-git-sync.service"], // Wait for git clone
wantedBy: ["multi-user.target"],
},
],
},
});
const { vm } = await freestyle.vms.create({ template });Timing and Dependencies
Repositories are cloned by the freestyle-git-sync.service systemd service. If your services need repositories to be present, add a dependency:
systemd: {
services: [
{
name: "my-service",
mode: "service",
exec: ["npm start"],
workdir: "/app",
after: ["freestyle-git-sync.service"], // Ensure git clone completes first
},
],
}Read-Only Access
Repositories are cloned in read-only mode. To make changes:
Temporary changes (lost on restart)
await vm.exec("git config --global --add safe.directory /app");
await vm.exec("cd /app && git checkout -b my-branch");
await vm.exec("cd /app && echo 'hello' > test.txt");Persistent changes
For development workflows, consider:
- Making changes and pushing to a branch
- Forking the VM to preserve state
- Using persistent storage
Working Directory
Set the working directory to your repository path:
const { vm } = await freestyle.vms.create({
gitRepos: [
{
repo: "https://github.com/owner/repo",
path: "/app",
},
],
workdir: "/app", // Commands execute here by default
});
// No need to cd
await vm.exec("npm install");
await vm.exec("npm start");Private Repositories
To access private repositories, you need to import them into Freestyle first:
// Import the repository (one-time setup)
const { repo } = await freestyle.repos.create({
url: "https://github.com/company/private-repo",
// Authentication handled via GitHub App or OAuth
});
// Use in VMs
const { vm } = await freestyle.vms.create({
gitRepos: [
{
repo: repo.id, // Use the Freestyle repository ID
path: "/app",
},
],
});Common Patterns
Monorepo structure
gitRepos: [
{
repo: "https://github.com/company/monorepo",
path: "/workspace",
},
],
workdir: "/workspace/packages/api", // Work in specific packageDev server setup
gitRepos: [
{
repo: "https://github.com/owner/webapp",
path: "/app",
},
],
systemd: {
services: [
{
name: "install",
mode: "oneshot",
exec: ["npm install"],
workdir: "/app",
after: ["freestyle-git-sync.service"],
wantedBy: ["multi-user.target"],
},
{
name: "dev-server",
mode: "service",
exec: ["npm run dev"],
workdir: "/app",
after: ["install.service"],
env: {
PORT: "3000",
},
},
],
}Testing specific commits
// Test a specific commit
const { vm } = await freestyle.vms.create({
gitRepos: [
{
repo: "https://github.com/owner/repo",
path: "/app",
rev: process.env.COMMIT_SHA, // From CI/CD
},
],
});