get gitea ready
This commit is contained in:
+2
-1
@@ -39,7 +39,8 @@ Thumbs.db
|
|||||||
.gitignore
|
.gitignore
|
||||||
.gitattributes
|
.gitattributes
|
||||||
|
|
||||||
# GitLab CI metadata is not needed in container build contexts
|
# CI metadata is not needed in container build contexts
|
||||||
|
.gitea/
|
||||||
.gitlab/
|
.gitlab/
|
||||||
.gitlab-ci.yml
|
.gitlab-ci.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 ./...
|
||||||
@@ -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
|
||||||
@@ -32,6 +32,9 @@ config.json
|
|||||||
.env
|
.env
|
||||||
.docker-cache/
|
.docker-cache/
|
||||||
|
|
||||||
|
# Local Gitea Actions runner deployment
|
||||||
|
/deploy/gitea-runner/
|
||||||
|
|
||||||
# Go
|
# Go
|
||||||
bin/
|
bin/
|
||||||
*.exe
|
*.exe
|
||||||
|
|||||||
+1
-1
@@ -137,7 +137,7 @@ RUN test "$(wc -l < ./public/index.html)" -lt 20 \
|
|||||||
# Stage 2: runtime (slim)
|
# Stage 2: runtime (slim)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
FROM oven/bun:1-slim AS runtime
|
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
|
WORKDIR /app
|
||||||
|
|
||||||
# openssl/ca-certificates: TLS cert generation + HTTPS validation.
|
# openssl/ca-certificates: TLS cert generation + HTTPS validation.
|
||||||
|
|||||||
@@ -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.
|
The server is a separate component that you must deploy yourself.
|
||||||
|
|
||||||
2. Full setup instructions are in the README:
|
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
|
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.
|
server's IP address (or hostname) and port on the connection screen.
|
||||||
|
|||||||
@@ -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.
|
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<version>`.
|
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<version>`.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const TELEGRAM_URL = "https://t.me/Onimai";
|
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;
|
let mounted = false;
|
||||||
|
|
||||||
@@ -90,11 +90,11 @@ export function showOnboardingIfNeeded(user) {
|
|||||||
|
|
||||||
stepContent.innerHTML = `
|
stepContent.innerHTML = `
|
||||||
<div class="account-onboarding__card">
|
<div class="account-onboarding__card">
|
||||||
<h2><i class="fa-brands fa-gitlab" aria-hidden="true"></i> Found a bug? Use GitLab Issues</h2>
|
<h2><i class="fa-solid fa-code-branch" aria-hidden="true"></i> Found a bug? Use Gitea Issues</h2>
|
||||||
<p><strong>This is the official place to report bugs.</strong> Create a GitLab issue with what happened, what you expected, and any useful screenshots or logs so the problem can be tracked and fixed.</p>
|
<p><strong>This is the official place to report bugs.</strong> Create a Gitea issue with what happened, what you expected, and any useful screenshots or logs so the problem can be tracked and fixed.</p>
|
||||||
<div class="account-onboarding__url-label">Full bug report link</div>
|
<div class="account-onboarding__url-label">Full bug report link</div>
|
||||||
<a class="account-onboarding__url" href="${GITLAB_ISSUES_URL}" target="_blank" rel="noopener noreferrer">${GITLAB_ISSUES_URL}</a>
|
<a class="account-onboarding__url" href="${GITEA_ISSUES_URL}" target="_blank" rel="noopener noreferrer">${GITEA_ISSUES_URL}</a>
|
||||||
<a class="account-onboarding__open" href="${GITLAB_ISSUES_URL}" target="_blank" rel="noopener noreferrer"><i class="fa-brands fa-gitlab" aria-hidden="true"></i> Create a GitLab issue</a>
|
<a class="account-onboarding__open" href="${GITEA_ISSUES_URL}" target="_blank" rel="noopener noreferrer"><i class="fa-solid fa-code-branch" aria-hidden="true"></i> Create a Gitea issue</a>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
progressText.textContent = "Step 2 of 2";
|
progressText.textContent = "Step 2 of 2";
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ type AgentCommand = {
|
|||||||
class TransferTestAgent {
|
class TransferTestAgent {
|
||||||
private socket: WebSocket | null = null;
|
private socket: WebSocket | null = null;
|
||||||
private downloads = new Map<string, Uint8Array>();
|
private downloads = new Map<string, Uint8Array>();
|
||||||
|
clientId = CLIENT_ID;
|
||||||
|
|
||||||
setDownload(path: string, bytes: Uint8Array): void {
|
setDownload(path: string, bytes: Uint8Array): void {
|
||||||
this.downloads.set(path, bytes);
|
this.downloads.set(path, bytes);
|
||||||
@@ -76,6 +77,12 @@ class TransferTestAgent {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (message.type === "hello_ack") {
|
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);
|
clearTimeout(timeout);
|
||||||
resolve();
|
resolve();
|
||||||
return;
|
return;
|
||||||
@@ -163,7 +170,7 @@ test.describe("file transfer HTTP API runtime", () => {
|
|||||||
|
|
||||||
const requestUpload = await api.post("/api/file/upload/request", {
|
const requestUpload = await api.post("/api/file/upload/request", {
|
||||||
data: {
|
data: {
|
||||||
clientId: CLIENT_ID,
|
clientId: agent.clientId,
|
||||||
path: remotePath,
|
path: remotePath,
|
||||||
fileName: "overlord-e2e-upload.bin",
|
fileName: "overlord-e2e-upload.bin",
|
||||||
},
|
},
|
||||||
@@ -185,7 +192,7 @@ test.describe("file transfer HTTP API runtime", () => {
|
|||||||
|
|
||||||
const pullHeaders = {
|
const pullHeaders = {
|
||||||
"x-agent-token": AGENT_TOKEN,
|
"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 });
|
const pull = await api.get(staged.pullUrl, { headers: pullHeaders });
|
||||||
expect(pull.ok()).toBeTruthy();
|
expect(pull.ok()).toBeTruthy();
|
||||||
@@ -204,7 +211,7 @@ test.describe("file transfer HTTP API runtime", () => {
|
|||||||
agent.setDownload(remotePath, downloadBytes);
|
agent.setDownload(remotePath, downloadBytes);
|
||||||
|
|
||||||
const requestDownload = await api.post("/api/file/download/request", {
|
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();
|
expect(requestDownload.ok()).toBeTruthy();
|
||||||
const { downloadUrl } = await requestDownload.json();
|
const { downloadUrl } = await requestDownload.json();
|
||||||
|
|||||||
@@ -113,6 +113,8 @@ export default async function globalSetup(_config: FullConfig) {
|
|||||||
HOST: "127.0.0.1",
|
HOST: "127.0.0.1",
|
||||||
PORT: String(PORT),
|
PORT: String(PORT),
|
||||||
OVERLORD_TLS_OFFLOAD: "true",
|
OVERLORD_TLS_OFFLOAD: "true",
|
||||||
|
OVERLORD_PUBLIC_ORIGIN: BASE_URL,
|
||||||
|
OVERLORD_WS_UPGRADE_RATE_MAX: "1000",
|
||||||
OVERLORD_USER: "e2e-admin",
|
OVERLORD_USER: "e2e-admin",
|
||||||
OVERLORD_PASS: "E2ePassword!2026",
|
OVERLORD_PASS: "E2ePassword!2026",
|
||||||
JWT_SECRET: "e2e-jwt-secret-that-is-only-used-for-browser-tests",
|
JWT_SECRET: "e2e-jwt-secret-that-is-only-used-for-browser-tests",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://gitlab.com/vxaboveground/overlord/-/raw/main/Overlord-Server/public/assets/overlord.png" alt="Overlord" width="280" />
|
<img src="https://overlord.kyun.li/vxaboveground/overlord/raw/branch/main/Overlord-Server/public/assets/overlord.png" alt="Overlord" width="280" />
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
# Overlord
|
# Overlord
|
||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
Hello, I made this project for fun.
|
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.
|
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
|
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**
|
**2. Get the project**
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
git clone https://gitlab.com/vxaboveground/overlord.git
|
git clone https://overlord.kyun.li/vxaboveground/overlord.git
|
||||||
cd Overlord
|
cd Overlord
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -190,14 +192,14 @@ Make a folder for it, drop in the file, and you're done:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir overlord && cd overlord
|
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`:
|
No `wget`? Use `curl`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir overlord && cd overlord
|
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**
|
**3. Start it**
|
||||||
@@ -206,7 +208,8 @@ curl -O https://gitlab.com/vxaboveground/overlord/-/raw/main/docker-compose.yml
|
|||||||
docker compose up -d
|
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**
|
**4. Open the panel**
|
||||||
|
|
||||||
@@ -266,7 +269,7 @@ docker compose version
|
|||||||
**2. Get the project**
|
**2. Get the project**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://gitlab.com/vxaboveground/overlord.git
|
git clone https://overlord.kyun.li/vxaboveground/overlord.git
|
||||||
cd Overlord
|
cd Overlord
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Build Overlord agent binaries for multiple OS/architectures
|
# Build Overlord agent binaries for multiple OS/architectures
|
||||||
FROM golang:1.22-bookworm AS builder
|
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
|
WORKDIR /src/Overlord-Client
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,183 @@
|
|||||||
|
# Make Gitea the primary repository
|
||||||
|
|
||||||
|
The primary repository is
|
||||||
|
<https://overlord.kyun.li/vxaboveground/overlord>. 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.
|
||||||
Reference in New Issue
Block a user