Compare commits

...

5 Commits

Author SHA1 Message Date
Arunavo Ray
b8965a9fd4 v3.4.0 2025-08-29 17:06:38 +05:30
Arunavo Ray
598e81ff45 updated package location 2025-08-29 17:04:48 +05:30
Arunavo Ray
fef6cbb60d toast showing full name now 2025-08-29 17:01:48 +05:30
Arunavo Ray
c793be5863 closed and merged pull requests will be created as closed issues 2025-08-29 16:58:48 +05:30
Arunavo Ray
d097ded6ee Updates to PR as issues 2025-08-29 16:54:21 +05:30
7 changed files with 62 additions and 36 deletions

View File

@@ -26,7 +26,7 @@ BETTER_AUTH_URL=http://localhost:4321
# Docker Registry Configuration # Docker Registry Configuration
DOCKER_REGISTRY=ghcr.io DOCKER_REGISTRY=ghcr.io
DOCKER_IMAGE=arunavo4/gitea-mirror DOCKER_IMAGE=raylabshq/gitea-mirror:
DOCKER_TAG=latest DOCKER_TAG=latest
# =========================================== # ===========================================

View File

@@ -31,7 +31,7 @@
"@tanstack/react-virtual": "^3.13.12", "@tanstack/react-virtual": "^3.13.12",
"@types/canvas-confetti": "^1.9.0", "@types/canvas-confetti": "^1.9.0",
"@types/react": "^19.1.12", "@types/react": "^19.1.12",
"@types/react-dom": "^19.1.8", "@types/react-dom": "^19.1.9",
"astro": "^5.13.4", "astro": "^5.13.4",
"bcryptjs": "^3.0.2", "bcryptjs": "^3.0.2",
"better-auth": "^1.3.7", "better-auth": "^1.3.7",
@@ -55,7 +55,7 @@
"typescript": "^5.9.2", "typescript": "^5.9.2",
"uuid": "^11.1.0", "uuid": "^11.1.0",
"vaul": "^1.1.2", "vaul": "^1.1.2",
"zod": "^4.1.4", "zod": "^4.1.5",
}, },
"devDependencies": { "devDependencies": {
"@testing-library/jest-dom": "^6.8.0", "@testing-library/jest-dom": "^6.8.0",
@@ -64,7 +64,7 @@
"@types/bun": "^1.2.21", "@types/bun": "^1.2.21",
"@types/jsonwebtoken": "^9.0.10", "@types/jsonwebtoken": "^9.0.10",
"@types/uuid": "^10.0.0", "@types/uuid": "^10.0.0",
"@vitejs/plugin-react": "^5.0.1", "@vitejs/plugin-react": "^5.0.2",
"drizzle-kit": "^0.31.4", "drizzle-kit": "^0.31.4",
"jsdom": "^26.1.0", "jsdom": "^26.1.0",
"tsx": "^4.20.5", "tsx": "^4.20.5",
@@ -439,7 +439,7 @@
"@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="], "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="],
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.32", "", {}, "sha512-QReCdvxiUZAPkvp1xpAg62IeNzykOFA6syH2CnClif4YmALN1XKpB39XneL80008UbtMShthSVDKmrx05N1q/g=="], "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.34", "", {}, "sha512-LyAREkZHP5pMom7c24meKmJCdhf2hEyvam2q0unr3or9ydwDL+DJ8chTF6Av/RFPb3rH8UFBdMzO5MxTZW97oA=="],
"@rollup/pluginutils": ["@rollup/pluginutils@5.1.4", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ=="], "@rollup/pluginutils": ["@rollup/pluginutils@5.1.4", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ=="],
@@ -587,7 +587,7 @@
"@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="], "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="],
"@types/react-dom": ["@types/react-dom@19.1.8", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-xG7xaBMJCpcK0RpN8jDbAACQo54ycO6h4dSSmgv8+fu6ZIAdANkx/WsawASUjVXYfy+J9AbUpRMNNEsXCDfDBQ=="], "@types/react-dom": ["@types/react-dom@19.1.9", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ=="],
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
@@ -595,7 +595,7 @@
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
"@vitejs/plugin-react": ["@vitejs/plugin-react@5.0.1", "", { "dependencies": { "@babel/core": "^7.28.3", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.32", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-DE4UNaBXwtVoDJ0ccBdLVjFTWL70NRuWNCxEieTI3lrq9ORB9aOCQEKstwDXBl87NvFdbqh/p7eINGyj0BthJA=="], "@vitejs/plugin-react": ["@vitejs/plugin-react@5.0.2", "", { "dependencies": { "@babel/core": "^7.28.3", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.34", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-tmyFgixPZCx2+e6VO9TNITWcCQl8+Nl/E8YbAyPVv85QCc7/A3JrdfG2A8gIzvVhWuzMOVrFW1aReaNxrI6tbw=="],
"@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="], "@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="],
@@ -1753,7 +1753,7 @@
"yoctocolors": ["yoctocolors@2.1.1", "", {}, "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ=="], "yoctocolors": ["yoctocolors@2.1.1", "", {}, "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ=="],
"zod": ["zod@4.1.4", "", {}, "sha512-2YqJuWkU6IIK9qcE4k1lLLhyZ6zFw7XVRdQGpV97jEIZwTrscUw+DY31Xczd8nwaoksyJUIxCojZXwckJovWxA=="], "zod": ["zod@4.1.5", "", {}, "sha512-rcUUZqlLJgBC33IT3PNMgsCq6TzLQEG/Ei/KTCU0PedSWRMAXoOUN+4t/0H+Q8bdnLPdqUYnvboJT0bn/229qg=="],
"zod-to-json-schema": ["zod-to-json-schema@3.24.5", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g=="], "zod-to-json-schema": ["zod-to-json-schema@3.24.5", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g=="],

View File

@@ -238,7 +238,7 @@ Settings specific to Docker deployments.
| Variable | Description | Default | Options | | Variable | Description | Default | Options |
|----------|-------------|---------|---------| |----------|-------------|---------|---------|
| `DOCKER_REGISTRY` | Docker registry URL | `ghcr.io` | Registry URL | | `DOCKER_REGISTRY` | Docker registry URL | `ghcr.io` | Registry URL |
| `DOCKER_IMAGE` | Docker image name | `arunavo4/gitea-mirror` | Image name | | `DOCKER_IMAGE` | Docker image name | `raylabshq/gitea-mirror:` | Image name |
| `DOCKER_TAG` | Docker image tag | `latest` | Tag name | | `DOCKER_TAG` | Docker image tag | `latest` | Tag name |
## Example Docker Compose Configuration ## Example Docker Compose Configuration

View File

@@ -1,7 +1,7 @@
{ {
"name": "gitea-mirror", "name": "gitea-mirror",
"type": "module", "type": "module",
"version": "3.3.0", "version": "3.4.0",
"engines": { "engines": {
"bun": ">=1.2.9" "bun": ">=1.2.9"
}, },
@@ -69,7 +69,7 @@
"@tanstack/react-virtual": "^3.13.12", "@tanstack/react-virtual": "^3.13.12",
"@types/canvas-confetti": "^1.9.0", "@types/canvas-confetti": "^1.9.0",
"@types/react": "^19.1.12", "@types/react": "^19.1.12",
"@types/react-dom": "^19.1.8", "@types/react-dom": "^19.1.9",
"astro": "^5.13.4", "astro": "^5.13.4",
"bcryptjs": "^3.0.2", "bcryptjs": "^3.0.2",
"better-auth": "^1.3.7", "better-auth": "^1.3.7",
@@ -93,7 +93,7 @@
"typescript": "^5.9.2", "typescript": "^5.9.2",
"uuid": "^11.1.0", "uuid": "^11.1.0",
"vaul": "^1.1.2", "vaul": "^1.1.2",
"zod": "^4.1.4" "zod": "^4.1.5"
}, },
"devDependencies": { "devDependencies": {
"@testing-library/jest-dom": "^6.8.0", "@testing-library/jest-dom": "^6.8.0",
@@ -102,7 +102,7 @@
"@types/bun": "^1.2.21", "@types/bun": "^1.2.21",
"@types/jsonwebtoken": "^9.0.10", "@types/jsonwebtoken": "^9.0.10",
"@types/uuid": "^10.0.0", "@types/uuid": "^10.0.0",
"@vitejs/plugin-react": "^5.0.1", "@vitejs/plugin-react": "^5.0.2",
"drizzle-kit": "^0.31.4", "drizzle-kit": "^0.31.4",
"jsdom": "^26.1.0", "jsdom": "^26.1.0",
"tsx": "^4.20.5", "tsx": "^4.20.5",

View File

@@ -57,7 +57,7 @@ http://<container-ip>:4321
```bash ```bash
git clone https://github.com/RayLabsHQ/gitea-mirror.git # if not already git clone https://github.com/RayLabsHQ/gitea-mirror.git # if not already
curl -fsSL https://raw.githubusercontent.com/arunavo4/gitea-mirror/main/scripts/gitea-mirror-lxc-local.sh -o gitea-mirror-lxc-local.sh curl -fsSL https://raw.githubusercontent.com/raylabshq/gitea-mirror:/main/scripts/gitea-mirror-lxc-local.sh -o gitea-mirror-lxc-local.sh
chmod +x gitea-mirror-lxc-local.sh chmod +x gitea-mirror-lxc-local.sh
sudo LOCAL_REPO_DIR=~/Development/gitea-mirror \ sudo LOCAL_REPO_DIR=~/Development/gitea-mirror \

View File

@@ -183,7 +183,9 @@ export default function Repository() {
); );
if (response.success) { if (response.success) {
toast.success(`Mirroring started for repository ID: ${repoId}`); const repo = repositories.find(r => r.id === repoId);
const repoName = repo?.fullName || `repository ${repoId}`;
toast.success(`Mirroring started for ${repoName}`);
setRepositories((prevRepos) => setRepositories((prevRepos) =>
prevRepos.map((repo) => { prevRepos.map((repo) => {
const updated = response.repositories.find((r) => r.id === repo.id); const updated = response.repositories.find((r) => r.id === repo.id);
@@ -496,7 +498,9 @@ export default function Repository() {
}); });
if (response.success) { if (response.success) {
toast.success(`Syncing started for repository ID: ${repoId}`); const repo = repositories.find(r => r.id === repoId);
const repoName = repo?.fullName || `repository ${repoId}`;
toast.success(`Syncing started for ${repoName}`);
setRepositories((prevRepos) => setRepositories((prevRepos) =>
prevRepos.map((repo) => { prevRepos.map((repo) => {
const updated = response.repositories.find((r) => r.id === repo.id); const updated = response.repositories.find((r) => r.id === repo.id);
@@ -588,7 +592,9 @@ export default function Repository() {
}); });
if (response.success) { if (response.success) {
toast.success(`Retrying job for repository ID: ${repoId}`); const repo = repositories.find(r => r.id === repoId);
const repoName = repo?.fullName || `repository ${repoId}`;
toast.success(`Retrying job for ${repoName}`);
setRepositories((prevRepos) => setRepositories((prevRepos) =>
prevRepos.map((repo) => { prevRepos.map((repo) => {
const updated = response.repositories.find((r) => r.id === repo.id); const updated = response.repositories.find((r) => r.id === repo.id);

View File

@@ -1583,9 +1583,26 @@ export async function mirrorGitRepoPullRequestsToGitea({
// Pull requests are typically created through Git operations // Pull requests are typically created through Git operations
// For now, we'll create them as issues with a special label // For now, we'll create them as issues with a special label
// Get or create a PR label // Get existing labels from Gitea and ensure "pull-request" label exists
const giteaLabelsRes = await httpGet(
`${config.giteaConfig.url}/api/v1/repos/${giteaOwner}/${repository.name}/labels`,
{
Authorization: `token ${decryptedConfig.giteaConfig.token}`,
}
);
const giteaLabels = giteaLabelsRes.data;
const labelMap = new Map<string, number>(
giteaLabels.map((label: any) => [label.name, label.id])
);
// Ensure "pull-request" label exists
let pullRequestLabelId: number | null = null;
if (labelMap.has("pull-request")) {
pullRequestLabelId = labelMap.get("pull-request")!;
} else {
try { try {
await httpPost( const created = await httpPost(
`${config.giteaConfig.url}/api/v1/repos/${giteaOwner}/${repository.name}/labels`, `${config.giteaConfig.url}/api/v1/repos/${giteaOwner}/${repository.name}/labels`,
{ {
name: "pull-request", name: "pull-request",
@@ -1596,8 +1613,11 @@ export async function mirrorGitRepoPullRequestsToGitea({
Authorization: `token ${decryptedConfig.giteaConfig.token}`, Authorization: `token ${decryptedConfig.giteaConfig.token}`,
} }
); );
pullRequestLabelId = created.data.id;
} catch (error) { } catch (error) {
// Label might already exist, continue console.error(`Failed to create "pull-request" label in Gitea: ${error}`);
// Continue without labels if creation fails
}
} }
const { processWithRetry } = await import("@/lib/utils/concurrency"); const { processWithRetry } = await import("@/lib/utils/concurrency");
@@ -1681,8 +1701,8 @@ export async function mirrorGitRepoPullRequestsToGitea({
const issueData = { const issueData = {
title: issueTitle, title: issueTitle,
body: richBody, body: richBody,
labels: [{ name: "pull-request" }], labels: pullRequestLabelId ? [pullRequestLabelId] : [],
state: pr.state === "closed" ? "closed" : "open", closed: pr.state === "closed" || pr.merged_at !== null,
}; };
console.log(`[Pull Requests] Creating enriched issue for PR #${pr.number}: ${pr.title}`); console.log(`[Pull Requests] Creating enriched issue for PR #${pr.number}: ${pr.title}`);
@@ -1701,8 +1721,8 @@ export async function mirrorGitRepoPullRequestsToGitea({
const basicIssueData = { const basicIssueData = {
title: `[PR #${pr.number}] ${pr.title}`, title: `[PR #${pr.number}] ${pr.title}`,
body: `**Original Pull Request:** ${pr.html_url}\n\n**State:** ${pr.state}\n**Merged:** ${pr.merged_at ? 'Yes' : 'No'}\n\n---\n\n${pr.body || 'No description provided'}`, body: `**Original Pull Request:** ${pr.html_url}\n\n**State:** ${pr.state}\n**Merged:** ${pr.merged_at ? 'Yes' : 'No'}\n\n---\n\n${pr.body || 'No description provided'}`,
labels: [{ name: "pull-request" }], labels: pullRequestLabelId ? [pullRequestLabelId] : [],
state: pr.state === "closed" ? "closed" : "open", closed: pr.state === "closed" || pr.merged_at !== null,
}; };
try { try {