From 2f0dc6a893b1b3ca3e8eac38ac043f018168936a Mon Sep 17 00:00:00 2001 From: KingKDot Date: Mon, 24 Aug 2026 10:06:19 -0500 Subject: [PATCH] get gitea ready --- .dockerignore | 3 +- .gitea/workflows/client-tests.yml | 48 +++++ .gitea/workflows/server-tests.yml | 71 +++++++ .gitignore | 3 + Dockerfile | 2 +- Overlord-Desktop/PLEASE_READ.txt | 2 +- Overlord-Desktop/README.md | 2 +- Overlord-Server/public/assets/onboarding.js | 10 +- .../test/e2e/file-transfer-api.e2e.ts | 13 +- Overlord-Server/test/e2e/global-setup.ts | 2 + README.md | 15 +- docker/agent-builder.Dockerfile | 2 +- docs/GITEA_MIGRATION.md | 183 ++++++++++++++++++ 13 files changed, 337 insertions(+), 19 deletions(-) create mode 100644 .gitea/workflows/client-tests.yml create mode 100644 .gitea/workflows/server-tests.yml create mode 100644 docs/GITEA_MIGRATION.md diff --git a/.dockerignore b/.dockerignore index 194942d..ae11372 100644 --- a/.dockerignore +++ b/.dockerignore @@ -39,7 +39,8 @@ Thumbs.db .gitignore .gitattributes -# GitLab CI metadata is not needed in container build contexts +# CI metadata is not needed in container build contexts +.gitea/ .gitlab/ .gitlab-ci.yml diff --git a/.gitea/workflows/client-tests.yml b/.gitea/workflows/client-tests.yml new file mode 100644 index 0000000..bfbb9ac --- /dev/null +++ b/.gitea/workflows/client-tests.yml @@ -0,0 +1,48 @@ +name: Client tests + +on: + push: + paths: + - "Overlord-Client/**" + - "protocol/**" + - "scripts/generate-wire-protocol.ts" + - "go.work" + - "go.work.sum" + - ".gitea/workflows/client-tests.yml" + pull_request: + paths: + - "Overlord-Client/**" + - "protocol/**" + - "scripts/generate-wire-protocol.ts" + - "go.work" + - "go.work.sum" + - ".gitea/workflows/client-tests.yml" + workflow_dispatch: + +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-latest + defaults: + run: + working-directory: Overlord-Client + steps: + - name: Checkout repository + uses: https://github.com/actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: Set up Go + uses: https://github.com/actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 + with: + go-version-file: Overlord-Client/go.mod + cache: true + cache-dependency-path: | + Overlord-Client/go.sum + go.work.sum + + - name: Download modules + run: go mod download + + - name: Run tests + run: go test ./... diff --git a/.gitea/workflows/server-tests.yml b/.gitea/workflows/server-tests.yml new file mode 100644 index 0000000..8760c51 --- /dev/null +++ b/.gitea/workflows/server-tests.yml @@ -0,0 +1,71 @@ +name: Server tests + +on: + push: + paths: + - "Overlord-Server/**" + - "Overlord-Client/cmd/agent/wire/wire_contract_generated.go" + - "protocol/**" + - "scripts/generate-wire-protocol.ts" + - ".gitea/workflows/server-tests.yml" + pull_request: + paths: + - "Overlord-Server/**" + - "Overlord-Client/cmd/agent/wire/wire_contract_generated.go" + - "protocol/**" + - "scripts/generate-wire-protocol.ts" + - ".gitea/workflows/server-tests.yml" + workflow_dispatch: + +permissions: + contents: read + +jobs: + unit: + runs-on: ubuntu-latest + defaults: + run: + working-directory: Overlord-Server + steps: + - name: Checkout repository + uses: https://github.com/actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: Set up Bun + uses: https://github.com/oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 + with: + bun-version: 1.3.14 + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Typecheck + run: bun run typecheck + + - name: Verify generated wire protocol + run: bun run protocol:check + + - name: Run unit tests + run: bun run test + + browser: + runs-on: ubuntu-latest + defaults: + run: + working-directory: Overlord-Server + steps: + - name: Checkout repository + uses: https://github.com/actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: Set up Bun + uses: https://github.com/oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 + with: + bun-version: 1.3.14 + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Install Chromium and system dependencies + run: bunx playwright install --with-deps chromium + + - name: Run browser tests + run: bun run test:e2e diff --git a/.gitignore b/.gitignore index 4111487..c5ff12d 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,9 @@ config.json .env .docker-cache/ +# Local Gitea Actions runner deployment +/deploy/gitea-runner/ + # Go bin/ *.exe diff --git a/Dockerfile b/Dockerfile index b57aa8c..9db8805 100644 --- a/Dockerfile +++ b/Dockerfile @@ -137,7 +137,7 @@ RUN test "$(wc -l < ./public/index.html)" -lt 20 \ # Stage 2: runtime (slim) # ============================================================ FROM oven/bun:1-slim AS runtime -LABEL org.opencontainers.image.source="https://gitlab.com/vxaboveground/overlord" +LABEL org.opencontainers.image.source="https://overlord.kyun.li/vxaboveground/overlord" WORKDIR /app # openssl/ca-certificates: TLS cert generation + HTTPS validation. diff --git a/Overlord-Desktop/PLEASE_READ.txt b/Overlord-Desktop/PLEASE_READ.txt index c2ef56b..38a90bf 100644 --- a/Overlord-Desktop/PLEASE_READ.txt +++ b/Overlord-Desktop/PLEASE_READ.txt @@ -15,7 +15,7 @@ show a connection error and nothing will work. That is expected. The server is a separate component that you must deploy yourself. 2. Full setup instructions are in the README: - https://gitlab.com/vxaboveground/overlord/-/blob/main/README.md + https://overlord.kyun.li/vxaboveground/overlord/src/branch/main/README.md 3. Once the server is running, open this desktop client and enter the server's IP address (or hostname) and port on the connection screen. diff --git a/Overlord-Desktop/README.md b/Overlord-Desktop/README.md index 2a6967c..bacfd24 100644 --- a/Overlord-Desktop/README.md +++ b/Overlord-Desktop/README.md @@ -49,7 +49,7 @@ bun run build:linux # Linux AppImage Or from the repo root: `./scripts/build-desktop.sh` (or `scripts\build-desktop.bat` on Windows) picks the right target for the current OS. -Output lands in `src-tauri/target/release/bundle/`. The CI workflow in `.gitlab/ci/desktop-release.yml` builds the Windows NSIS installer on every push to `main` that changes the desktop application or its build inputs, and publishes it as a GitLab Release tagged `Overlord-Desktop-v`. +Output lands in `src-tauri/target/release/bundle/`. The GitLab mirror's CI workflow in `.gitlab/ci/desktop-release.yml` builds the Windows NSIS installer on every mirrored push to `main` that changes the desktop application or its build inputs, and publishes it as a GitLab Release tagged `Overlord-Desktop-v`. ## Configuration diff --git a/Overlord-Server/public/assets/onboarding.js b/Overlord-Server/public/assets/onboarding.js index b1fe43b..360a038 100644 --- a/Overlord-Server/public/assets/onboarding.js +++ b/Overlord-Server/public/assets/onboarding.js @@ -1,5 +1,5 @@ const TELEGRAM_URL = "https://t.me/Onimai"; -const GITLAB_ISSUES_URL = "https://gitlab.com/vxaboveground/overlord/-/issues/new"; +const GITEA_ISSUES_URL = "https://overlord.kyun.li/vxaboveground/overlord/issues/new"; let mounted = false; @@ -90,11 +90,11 @@ export function showOnboardingIfNeeded(user) { stepContent.innerHTML = ` `; progressText.textContent = "Step 2 of 2"; diff --git a/Overlord-Server/test/e2e/file-transfer-api.e2e.ts b/Overlord-Server/test/e2e/file-transfer-api.e2e.ts index 91968fc..6effcd0 100644 --- a/Overlord-Server/test/e2e/file-transfer-api.e2e.ts +++ b/Overlord-Server/test/e2e/file-transfer-api.e2e.ts @@ -22,6 +22,7 @@ type AgentCommand = { class TransferTestAgent { private socket: WebSocket | null = null; private downloads = new Map(); + clientId = CLIENT_ID; setDownload(path: string, bytes: Uint8Array): void { this.downloads.set(path, bytes); @@ -76,6 +77,12 @@ class TransferTestAgent { return; } if (message.type === "hello_ack") { + if (typeof message.id !== "string" || !message.id) { + clearTimeout(timeout); + reject(new Error("Agent hello acknowledgement did not include a client ID")); + return; + } + this.clientId = message.id; clearTimeout(timeout); resolve(); return; @@ -163,7 +170,7 @@ test.describe("file transfer HTTP API runtime", () => { const requestUpload = await api.post("/api/file/upload/request", { data: { - clientId: CLIENT_ID, + clientId: agent.clientId, path: remotePath, fileName: "overlord-e2e-upload.bin", }, @@ -185,7 +192,7 @@ test.describe("file transfer HTTP API runtime", () => { const pullHeaders = { "x-agent-token": AGENT_TOKEN, - "x-overlord-client-id": CLIENT_ID, + "x-overlord-client-id": agent.clientId, }; const pull = await api.get(staged.pullUrl, { headers: pullHeaders }); expect(pull.ok()).toBeTruthy(); @@ -204,7 +211,7 @@ test.describe("file transfer HTTP API runtime", () => { agent.setDownload(remotePath, downloadBytes); const requestDownload = await api.post("/api/file/download/request", { - data: { clientId: CLIENT_ID, path: remotePath }, + data: { clientId: agent.clientId, path: remotePath }, }); expect(requestDownload.ok()).toBeTruthy(); const { downloadUrl } = await requestDownload.json(); diff --git a/Overlord-Server/test/e2e/global-setup.ts b/Overlord-Server/test/e2e/global-setup.ts index 9660cb6..b5b6245 100644 --- a/Overlord-Server/test/e2e/global-setup.ts +++ b/Overlord-Server/test/e2e/global-setup.ts @@ -113,6 +113,8 @@ export default async function globalSetup(_config: FullConfig) { HOST: "127.0.0.1", PORT: String(PORT), OVERLORD_TLS_OFFLOAD: "true", + OVERLORD_PUBLIC_ORIGIN: BASE_URL, + OVERLORD_WS_UPGRADE_RATE_MAX: "1000", OVERLORD_USER: "e2e-admin", OVERLORD_PASS: "E2ePassword!2026", JWT_SECRET: "e2e-jwt-secret-that-is-only-used-for-browser-tests", diff --git a/README.md b/README.md index 2ed446f..cd799ce 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- Overlord + Overlord

# Overlord @@ -8,6 +8,8 @@ Hello, I made this project for fun. +The canonical repository is [Gitea](https://overlord.kyun.li/vxaboveground/overlord); GitLab is maintained as a mirror and release-registry host. + The server is TypeScript on Node/Bun. The client is Go. Operators talk to the server through a web panel or the Electron desktop app, and agents connect over encrypted WebSockets. On Linux, Docker is the easiest way to run it. On Windows, a native @@ -103,7 +105,7 @@ docker compose version **2. Get the project** ```powershell -git clone https://gitlab.com/vxaboveground/overlord.git +git clone https://overlord.kyun.li/vxaboveground/overlord.git cd Overlord ``` @@ -190,14 +192,14 @@ Make a folder for it, drop in the file, and you're done: ```bash mkdir overlord && cd overlord -wget https://gitlab.com/vxaboveground/overlord/-/raw/main/docker-compose.yml +wget https://overlord.kyun.li/vxaboveground/overlord/raw/branch/main/docker-compose.yml ``` No `wget`? Use `curl`: ```bash mkdir overlord && cd overlord -curl -O https://gitlab.com/vxaboveground/overlord/-/raw/main/docker-compose.yml +curl -O https://overlord.kyun.li/vxaboveground/overlord/raw/branch/main/docker-compose.yml ``` **3. Start it** @@ -206,7 +208,8 @@ curl -O https://gitlab.com/vxaboveground/overlord/-/raw/main/docker-compose.yml docker compose up -d ``` -The image is pulled automatically from `registry.gitlab.com/vxaboveground/overlord:latest` on first run. +The image is currently pulled from the GitLab mirror's container registry at +`registry.gitlab.com/vxaboveground/overlord:latest` on first run. **4. Open the panel** @@ -266,7 +269,7 @@ docker compose version **2. Get the project** ```bash -git clone https://gitlab.com/vxaboveground/overlord.git +git clone https://overlord.kyun.li/vxaboveground/overlord.git cd Overlord ``` diff --git a/docker/agent-builder.Dockerfile b/docker/agent-builder.Dockerfile index 1305ee1..e2fffc2 100644 --- a/docker/agent-builder.Dockerfile +++ b/docker/agent-builder.Dockerfile @@ -1,6 +1,6 @@ # Build Overlord agent binaries for multiple OS/architectures FROM golang:1.22-bookworm AS builder -LABEL org.opencontainers.image.source="https://gitlab.com/vxaboveground/overlord" +LABEL org.opencontainers.image.source="https://overlord.kyun.li/vxaboveground/overlord" WORKDIR /src/Overlord-Client diff --git a/docs/GITEA_MIGRATION.md b/docs/GITEA_MIGRATION.md new file mode 100644 index 0000000..4af360f --- /dev/null +++ b/docs/GITEA_MIGRATION.md @@ -0,0 +1,183 @@ +# Make Gitea the primary repository + +The primary repository is +. These instructions preserve +all Git branches, tags, and commits reachable from them, make Gitea the default +remote for development, and configure Gitea to push-mirror to GitLab. + +This runbook targets Gitea 1.27.2. It intentionally does not use +`git push --mirror` from a working clone. A working clone contains local and +remote-tracking refs that are not part of the public branch/tag contract, and a +mirror push can also delete destination refs. + +## Canonical remotes + +The prepared working clone has these exact remotes: + +| Name | Role | Fetch and push URL | +| --- | --- | --- | +| `origin` | Primary Gitea repository and default push target | `ssh://git@overlord.kyun.li:222/vxaboveground/overlord.git` | +| `gitlab` | Former primary; retained for comparison while the Gitea push mirror is verified | `ssh://git@altssh.gitlab.com:443/vxaboveground/overlord.git` | +| `forgejo` | Legacy internal Forgejo remote | `ssh://git@10.0.22.220:22/KDOT/Overlord-Public.git` | + +`main` tracks `origin/main`, and `remote.pushDefault` is `origin`. Confirm the +local setup before the cutover: + +```bash +git remote -v +git config --get branch.main.remote +git config --get branch.main.merge +git config --get remote.pushDefault +``` + +The expected last three values are `origin`, `refs/heads/main`, and `origin`. +Do not push directly to `gitlab` after the server-side push mirror is enabled; +Gitea must be the sole write authority. + +## Copy Git history safely + +1. Announce a short write freeze on GitLab. Merge or close outstanding work and + wait for running pushes to finish. Commit the migration-preparation files in + this checkout and push that commit to `gitlab/main` before taking the final + bare clone, so the new Gitea workflows and canonical links are included in + the copied history. +2. Back up the GitLab project. Create the Gitea repository at the primary URL + as an **empty** repository: do not initialize a README, license, or + `.gitignore` in Gitea. +3. From a temporary directory outside this working clone, make a bare clone of + GitLab and inspect it: + + ```bash + migration_dir="$(mktemp -d)" + git clone --bare \ + ssh://git@altssh.gitlab.com:443/vxaboveground/overlord.git \ + "$migration_dir/overlord.git" + git -C "$migration_dir/overlord.git" fsck --full + git -C "$migration_dir/overlord.git" for-each-ref \ + --format='%(objectname) %(refname)' refs/heads refs/tags + ``` + +4. Add Gitea only to that bare migration clone, then push explicit branch and + tag namespaces. These refspecs do not include remote-tracking, CI, merge + request, or other implementation-specific refs, and they do not request + deletion of destination refs: + + ```bash + git -C "$migration_dir/overlord.git" remote add gitea \ + ssh://git@overlord.kyun.li:222/vxaboveground/overlord.git + git -C "$migration_dir/overlord.git" push --atomic gitea \ + 'refs/heads/*:refs/heads/*' \ + 'refs/tags/*:refs/tags/*' + ``` + + A non-fast-forward rejection means Gitea already contains divergent work. + Stop and reconcile that work; do not add `--force` just to make the command + pass. + +5. Compare the source and destination refs exactly: + + ```bash + git ls-remote --heads \ + ssh://git@altssh.gitlab.com:443/vxaboveground/overlord.git \ + | sort > "$migration_dir/gitlab-heads" + git ls-remote --heads \ + ssh://git@overlord.kyun.li:222/vxaboveground/overlord.git \ + | sort > "$migration_dir/gitea-heads" + git ls-remote --tags \ + ssh://git@altssh.gitlab.com:443/vxaboveground/overlord.git \ + | sort > "$migration_dir/gitlab-tags" + git ls-remote --tags \ + ssh://git@overlord.kyun.li:222/vxaboveground/overlord.git \ + | sort > "$migration_dir/gitea-tags" + diff -u "$migration_dir/gitlab-heads" "$migration_dir/gitea-heads" + diff -u "$migration_dir/gitlab-tags" "$migration_dir/gitea-tags" + ``` + + Both `diff` commands should produce no output. In Gitea, set `main` as the + default branch and recreate branch/tag protection, collaborators, deploy + keys, webhooks, Actions secrets, and other host-level settings. + +The explicit Git copy does not migrate GitLab issues, merge requests, comments, +release records, CI variables, job artifacts, package/container registries, or +other GitLab database content. Export/import those separately if they must be +retained. If Git LFS is enabled later, its objects also require an explicit LFS +fetch/push; ordinary ref pushes do not transfer LFS object content. + +## Make Gitea the default in other clones + +For an existing clone that still calls GitLab `origin`, preserve that remote +under the `gitlab` name and add Gitea as the new `origin`: + +```bash +git remote rename origin gitlab +git remote add origin \ + ssh://git@overlord.kyun.li:222/vxaboveground/overlord.git +git fetch origin --prune --tags +git branch --set-upstream-to=origin/main main +git config remote.pushDefault origin +``` + +If that clone already has a remote called `gitlab`, update URLs instead of +renaming over it: + +```bash +git remote set-url origin \ + ssh://git@overlord.kyun.li:222/vxaboveground/overlord.git +git remote set-url gitlab \ + ssh://git@altssh.gitlab.com:443/vxaboveground/overlord.git +git fetch origin --prune --tags +git branch --set-upstream-to=origin/main main +git config remote.pushDefault origin +``` + +Test the cutover with a normal branch push to `origin`. Avoid configuring a +client-side push URL that writes to both hosts: the Gitea server-side mirror is +the single replication mechanism and exposes failures in its UI. + +## Configure the Gitea-to-GitLab push mirror + +Gitea's push mirror force-updates the destination. Once enabled, changes made +directly on GitLab may be overwritten or deleted on the next sync. Keep the +GitLab project read-only for normal development and treat it as a replica. + +1. In GitLab, create a project access token or personal access token with the + `write_repository` scope. Use an account permitted to update the repository's + protected branches and tags. +2. In Gitea, open **Settings > Repository > Mirror Settings** for + `vxaboveground/overlord` and choose **Add Push Mirror**. +3. Enter these values: + + - Remote repository URL: `https://gitlab.com/vxaboveground/overlord.git` + - Authorization username: `oauth2` + - Authorization password: the GitLab token + +4. Enable **Sync when new commits are pushed**, add the mirror, and select + **Synchronize Now** for the initial replication. +5. Confirm that Gitea reports a successful sync, then compare heads and tags + again with the verification commands above. Make a small test branch in + Gitea, confirm it arrives in GitLab, and delete it from Gitea so the deletion + behavior is also understood before ending the write freeze. + +If a sync fails, inspect the error in Gitea's Mirror Settings. The usual causes +are an expired token, missing `write_repository` permission, or GitLab protected +branch/tag rules that reject the mirror account. Rotate the GitLab credential in +Gitea rather than embedding it in a Git remote URL or this repository. + +GitLab CI may run when mirrored commits arrive because this repository retains +`.gitlab-ci.yml`. Keep that behavior if GitLab remains a CI replica; otherwise +disable GitLab pipelines in the GitLab project settings after confirming Gitea +Actions covers the required jobs. + +## Final checks + +- `origin` fetches and pushes to Gitea over SSH port 222. +- `main` tracks `origin/main`, and `remote.pushDefault` is `origin`. +- All GitLab heads and tags match Gitea at the end of the write freeze. +- The Gitea push mirror reports a successful GitLab sync. +- Branch/tag protections, access controls, secrets, and webhooks exist in Gitea. +- The repository-scoped runner is online and a Gitea Actions workflow passes. +- Developers know Gitea is authoritative and GitLab is read-only. + +After an agreed observation period, remove the legacy `forgejo` remote from +developer clones if it is no longer needed. Keep backups according to the +project's retention policy.