Export your source to GitHub
Initialize an empty GitHub repository with the source Volcano stores for your project, then deploy it from Git.
Export creates the first commit in an empty GitHub repository. It pushes the complete project directly to the configured production branch, which triggers the normal Git deployment flow.
curl -X POST "https://api.volcano.dev/projects/$PROJECT_ID/source-export" \
-H "Authorization: Bearer $VOLCANO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"production_branch":"main","repo_id":873345021}'{
"repo_full_name": "acme/storefront",
"branch": "main",
"commit_sha": "6f2b1c9a4e8d3f7b0a5c2e9d1f4b8a6c3e7d0b25",
"file_count": 12,
"skipped": [],
"omitted": [{ "kind": "migrations", "resource": "", "path": "volcano/migrations" }]
}Prepare the repository
-
Create a GitHub repository without a README, license,
.gitignore, or any other initial commit. -
Connect it to the project and export from the CLI. An empty repository has no default branch, so name the branch pushes will deploy from when you connect it:
volcano git connect https://github.com/acme/storefront --production-branch main volcano git exportvolcano git exportshows the repository and production branch and asks before it writes. In a script, pass the branch you expect and skip the prompt; the command refuses if the project's branch is different:volcano git export --branch main --yes --json
volcano git repos lists the repositories you can connect and marks the empty
ones.
For API clients, connect the repository and configure Git auto-deploy first.
Read repo_full_name, repo_id and production_branch from
GET /projects/{id}/git-connection, show the repository and branch for
confirmation, then send repo_id and production_branch to the export
endpoint. If either changed in the meantime, export returns 409 without
writing the repository. Read the connection again and ask the user to confirm
what it holds now. repo_id is optional, but without it export writes to
whatever repository is connected when the request arrives.
Export also returns 409 while a function or frontend deployment is queued or
provisioning. Wait for that deployment to finish, then export again. It returns
409 too while a preview is serving any of the
project's frontends, because the repository would not hold the source that
frontend serves. Roll each such frontend back to its own build, then export
again. Volcano checks both before creating or pushing the root commit.
Volcano does not create the repository. Export refuses any repository that already has a commit or branch. This avoids merges, conflict resolution, and overwriting existing history.
If your repository already contains the project, do not export. Push the complete project to its configured production branch instead. Git auto-deploy will deploy it, but it does not disable direct platform deploys. Source ownership changes only through the one-time export flow.
What export writes
The root commit uses the layout Git auto-deploy discovers:
volcano/
├── .gitignore
└── functions/
├── hello.js
└── checkout/
├── index.js
└── tax.js
volcano-config.yaml
package.json
frontends/
├── web/
│ └── package.json
└── admin/
└── package.json
.volcano/
└── source-layout.jsonExport supports multiple frontends and functions. Each frontend gets a
frontends/<name>/ workspace, including its dependencies and original app root.
Functions keep the existing single-file or directory layout.
The generated .volcano/source-layout.json records frontend names and app roots.
Keep it in Git: it tells Volcano to deploy every exported frontend instead of
using the single frontend in Git deploy settings. The Auto deploy and Deploy
functions switches still apply.
The initial export and every later production-branch push deploy all configured resources, including those whose code has not changed. Git takes over source ownership only after a deployment covers every exported serving resource.
Export takes source from each function and frontend's latest successful
deployment. A resource that has never deployed successfully appears in
skipped and is not written.
Both kinds of function are exported into the same volcano/functions/
directory. Durable functions are marked with kind: durable in
volcano-config.yaml, which is how the first push from the exported repository
recreates them as durable rather than standard.
Export refuses to push when a currently serving resource has no readable stored source or cannot be represented in the repository layout. This keeps the first Git deployment from waiting on source that the commit does not contain.
Stored .gitignore files are committed as ordinary files. Their patterns do
not remove other stored files from the export commit.
The omitted list reports content Volcano cannot or should not publish:
| Kind | Why |
|---|---|
migrations | Volcano does not retain the migration files. |
variable_values | Secret values are never committed. Configure them through Volcano. |
ignored_secret | Credential-shaped files such as .env are excluded. |
dependency_cache | Generated dependency directories such as node_modules are rebuilt. |
unsupported_entry | Symlinks and other unsupported archive entries are excluded. |
Export fails and names the path when stored source contains a file that should never be committed, such as a private key or credential store.
How ownership changes
Export is a one-time transition:
- Volcano verifies the confirmed repository and production branch still
match the project, pins the branch, and changes the project to
git_exporting. Direct source deploys and Git connection changes are frozen. - Volcano creates one root commit and pushes it to the production branch.
- GitHub's signed push event confirms that the root commit reached the
production branch. That commit or a newer production push starts the
ordinary Git deployment and changes the mode to
git_pending. - After a complete production deployment succeeds, the mode becomes
git.
The project stays locked if the deployment fails, or if a function holds only TypeScript, which isn't deployed. Fix the repository and push the production branch again. The latest complete successful deployment finishes the transition; the exported root commit does not need to deploy if a newer push supersedes it.
The pinned branch does not follow later GitHub default-branch changes. This
keeps a repository rename from moving production during or after handover.
After handover you can
return it to the default with an
empty production_branch.
To stop an incomplete transition and restore direct platform deploys, run
volcano git export cancel, or call the API:
curl -X DELETE "https://api.volcano.dev/projects/$PROJECT_ID/source-export" \
-H "Authorization: Bearer $VOLCANO_TOKEN"Cancellation does not delete the repository or a commit that already reached
it. If Volcano reserved the initial commit before cancellation, the one-time
export remains consumed and cannot be run again. The confirmed production
branch remains pinned. Once the repository has its first commit, send an empty
production_branch to
follow it again.
Check the state at any time. volcano git status reports it as the project's
source of truth; the API returns it as mode:
curl "https://api.volcano.dev/projects/$PROJECT_ID/source-export" \
-H "Authorization: Bearer $VOLCANO_TOKEN"{
"mode": "git_pending",
"transition_started_at": "2026-08-25T09:14:02Z",
"exported_at": "2026-08-25T09:14:04Z",
"handed_over_at": null
}After handover, push to the production branch to change or deploy source.
Direct function and frontend deploys return 409. Variables, databases,
storage, domains, and resource settings remain manageable through Volcano.
To deploy from another branch after handover, set it explicitly, then push it:
curl -X PUT "https://api.volcano.dev/projects/$PROJECT_ID/git-connection/production-branch" \
-H "Authorization: Bearer $VOLCANO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"production_branch":"release"}'Branch changes are refused while the project is git_exporting or
git_pending so the initial push and deployment always use the branch the user
confirmed.
Retry an uncertain push
If GitHub does not confirm whether the initial push succeeded, the endpoint
returns a retryable error and the project remains git_exporting. Call the
endpoint again, or rerun volcano git export. Volcano builds the same commit:
it adopts that commit if it is already on the production branch, or retries the
initial push while the repository is still empty.
If the commit reached GitHub but its push event never reaches Volcano, the
project remains git_exporting. Cancel the transition with
volcano git export cancel or DELETE /projects/{id}/source-export to restore
platform deploys. The root commit stays
in the repository and the one-time export remains consumed.
Related
| Guide | Description |
|---|---|
| Deploy from GitHub | Connect a repository and deploy on every push |
| Configuration manifest | volcano-config.yaml reference |
Creating Projects
Projects organize your functions, durable functions, databases, authentication, file storage, realtime, frontend hosting, and distributed locks.
Deploy from GitHub
Connect a GitHub repository to a Volcano project so every push to the production branch deploys your functions and frontend automatically.