fix: support gitea git remote uploads

This commit is contained in:
Tom Boullay
2026-05-15 01:08:44 +02:00
parent 23253c2277
commit f53f606daa
10 changed files with 258 additions and 76 deletions
+16 -16
View File
@@ -3,16 +3,16 @@
A secure web interface for uploading `model.gltf` with its associated `.bin` file and textures with two outputs:
- **Nextcloud Drive** — Archives the original files with automatic versioning (VF/V1/V2...), so artists always have a history of past versions
- **GitHub** — Delivers Draco-compressed GLB assets by default, with an optional GLTF delivery mode for specific models
- **Git remote** — Delivers Draco-compressed GLB assets by default, with an optional GLTF delivery mode for specific models
Built for La Fabrik Durable's internal use, but open-sourced for anyone looking for a similar solution. The app validates the upload locally, stages it server-side, then compares file diffs to avoid unnecessary uploads and commits. The Drive upload serves as the source of truth and version history, while the GitHub upload delivers the prepared assets to developers.
Built for La Fabrik Durable's internal use, but open-sourced for anyone looking for a similar solution. The app validates the upload locally, stages it server-side, then compares file diffs to avoid unnecessary uploads and commits. The Drive upload serves as the source of truth and version history, while the Git upload delivers the prepared assets to developers.
## Stack
- [**Next.js 16.2.5** (App Router)](https://nextjs.org/docs/app/getting-started/installation) + [React 19](https://react.dev/learn/creating-a-react-app) + [TypeScript](https://www.typescriptlang.org/docs/)
- [**Three.js**](https://threejs.org/docs/#manual/en/introduction/Creating-a-scene) ([React Three Fiber](https://r3f.docs.pmnd.rs/getting-started/introduction) + [Drei](https://drei.docs.pmnd.rs/getting-started/introduction)) for 3D preview
- [**Tailwind CSS**](https://v3.tailwindcss.com/docs/installation) for styling
- [**Octokit**](https://github.com/octokit/rest.js/#readme) for pushing via the GitHub API
- [**Octokit**](https://github.com/octokit/rest.js/#readme) for pushing via a GitHub-compatible API (GitHub or Gitea)
- [**Nextcloud WebDAV**](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/WebDAV/index.html) for Drive archiving with automatic versioning
- [**Sharp**](https://sharp.pixelplumbing.com/install/) for server-side texture compression
- [**npm lockfile + Coolify** (Docker)](https://coolify.io/docs/applications/build-packs/dockerfile) for hosting
@@ -39,7 +39,7 @@ This repo also keeps install-time package scripts disabled by default through `.
npm ci --ignore-scripts --no-audit --no-fund
```
When a dependency update is needed, prefer a lockfile-only update in a clean environment with no `.env`, no GitHub token, and no cloud credentials:
When a dependency update is needed, prefer a lockfile-only update in a clean environment with no `.env`, no Git token, and no cloud credentials:
```bash
mkdir -p /tmp/npm-clean-home /tmp/npm-clean-cache
@@ -118,7 +118,7 @@ All files are uploaded to `VF/` (not just diffs), because the move operation emp
- The server applies a lightweight per-folder lock on Drive and Git routes to avoid duplicate commits and concurrent writes
- The folder is staged server-side so the browser sends the payload only once during the full upload flow
- Invalid `model.gltf` JSON or malformed `buffers` entries block the upload before remote writes
- Git LFS uploads are batched in groups of 100 objects to stay within the GitHub LFS Batch API limit
- Git LFS uploads are batched in groups of 100 objects to stay within the LFS Batch API limit
### Commit messages
@@ -172,7 +172,7 @@ app/
│ ├── stage/route.ts # POST: upload folder once to temporary staging
│ ├── check/route.ts # POST: prepare staged Git assets and compare with remote files
│ ├── drive/route.ts # POST: upload staged originals to Nextcloud Drive (VF/Vx versioning)
│ └── git/route.ts # POST: push staged prepared assets to GitHub
│ └── git/route.ts # POST: push staged prepared assets to the Git remote
├── globals.css # Tailwind + CSS variable fonts
├── layout.tsx # Root layout (next/font/google)
└── page.tsx # Home page
@@ -206,7 +206,7 @@ lib/
├── diff-files.ts # File diff classification (new/changed/unchanged/deleted)
├── sanitize.ts # Filename sanitization
├── auth.ts # Upload secret validation (timing-safe)
├── github.ts # Octokit helpers (getRemoteFolder, pushAllToGitHub)
├── github.ts # Octokit helpers for GitHub-compatible remotes
├── nextcloud.ts # Nextcloud WebDAV client (native fetch, cached config)
├── upload-staging.ts # Temporary server-side staging and prepared asset reuse
├── upload-lock.ts # Lightweight in-memory per-folder upload lock
@@ -237,9 +237,9 @@ Copy `.env.example` to `.env.local` and fill in the values:
```env
UPLOAD_SECRET_KEY=your-secret-key-here
GITHUB_TOKEN=ghp_your-github-personal-access-token
GIT_TOKEN=your-git-provider-token
GIT_BRANCH=main
GIT_REPO_URL=https://github.com/your-org/your-repo.git
GIT_REPO_URL=https://git.example.com/your-org/your-repo
# Nextcloud Drive (public share WebDAV)
NEXTCLOUD_URL=https://cloud.example.com
NEXTCLOUD_SHARE_TOKEN=your-public-share-token
@@ -250,15 +250,15 @@ NEXTCLOUD_BASE_PATH=Models
| Variable | Description | Required |
|----------|-------------|----------|
| `UPLOAD_SECRET_KEY` | Secret key for upload authentication | Yes |
| `GITHUB_TOKEN` | GitHub Personal Access Token (fine-grained, `Contents: Read and write`) | Yes |
| `GIT_TOKEN` | Git provider token with repository read/write access. `GITHUB_TOKEN` is still accepted for backward compatibility. | Yes |
| `GIT_BRANCH` | Target branch (default: main) | No |
| `GIT_REPO_URL` | Target GitHub repository URL (`owner/repo`, HTTPS, or SSH) | Yes |
| `GIT_REPO_URL` | Target GitHub or Gitea repository URL (`owner/repo`, HTTPS, or SSH) | Yes |
| `NEXTCLOUD_URL` | Nextcloud instance URL | Yes |
| `NEXTCLOUD_SHARE_TOKEN` | Public share token (the part after `/s/` in the share link) | Yes |
| `NEXTCLOUD_SHARE_PASSWORD` | Public share password (empty if none) | No |
| `NEXTCLOUD_BASE_PATH` | Root folder on the Drive (default: `Models`) | No |
> To create a GitHub token: GitHub > Settings > Developer settings > Fine-grained personal access tokens > select the target repo > Permissions > Contents: Read and write
> GitHub tokens need `Contents: Read and write`. Gitea tokens need repository read/write access.
> To create a Nextcloud public share token: Nextcloud > Files > select folder > Share > Create public share > set permissions (write access required) > copy the share link and extract the token
@@ -278,8 +278,8 @@ After a security patch:
docker build -t upload-gltf .
docker run -p 3000:3000 \
-e UPLOAD_SECRET_KEY=your-key \
-e GITHUB_TOKEN=ghp_xxx \
-e GIT_REPO_URL=https://github.com/org/repo.git \
-e GIT_TOKEN=token_xxx \
-e GIT_REPO_URL=https://git.fabrik.mathieu-chavanel.fr/math-pixel/La-Fabrik \
-e NEXTCLOUD_URL=https://cloud.example.com \
-e NEXTCLOUD_SHARE_TOKEN=your-share-token \
upload-gltf
@@ -293,12 +293,12 @@ Rotate secrets after patching if the previous deployment exposed a vulnerable Ne
Recommended order:
1. Generate a new fine-grained `GITHUB_TOKEN` limited to the target model repository with `Contents: Read and write`.
1. Generate a new `GIT_TOKEN` limited to the target model repository with read/write access.
2. Generate a new long random `UPLOAD_SECRET_KEY`.
3. Regenerate the Nextcloud public share token or password when possible.
4. Update the variables in Coolify.
5. Redeploy the patched image.
6. Revoke the old GitHub token and old Nextcloud share credentials after the new deployment is healthy.
6. Revoke the old Git token and old Nextcloud share credentials after the new deployment is healthy.
Do not commit real `.env` files. `.dockerignore` excludes `.env` and `.env.*`, while keeping `.env.example` as documentation.