mirror of
https://github.com/RayLabsHQ/gitea-mirror.git
synced 2026-03-14 22:43:02 +03:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1dd3dea231 | ||
|
|
db783c4225 | ||
|
|
8a4716bdbd | ||
|
|
9d37966c10 | ||
|
|
ac16ae56ea | ||
|
|
df3e665978 | ||
|
|
8a26764d2c | ||
|
|
ce365a706e | ||
|
|
be7daac5fb | ||
|
|
e32b7af5eb |
3
.github/workflows/README.md
vendored
3
.github/workflows/README.md
vendored
@@ -43,6 +43,9 @@ This workflow builds Docker images on pushes and pull requests, and pushes to Gi
|
||||
- Skips registry push for fork PRs (avoids package write permission failures)
|
||||
- Uses build caching to speed up builds
|
||||
- Creates multiple tags for each image (latest, semver, sha)
|
||||
- Auto-syncs `package.json` version from `v*` tags during release builds
|
||||
- Validates release tags use semver format before building
|
||||
- After tag builds succeed, writes the same version back to `main/package.json`
|
||||
|
||||
### Docker Security Scan (`docker-scan.yml`)
|
||||
|
||||
|
||||
4
.github/workflows/astro-build-test.yml
vendored
4
.github/workflows/astro-build-test.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
build-and-test:
|
||||
name: Build and Test Astro Project
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: '1.3.6'
|
||||
bun-version: '1.3.10'
|
||||
|
||||
- name: Check lockfile and install dependencies
|
||||
run: |
|
||||
|
||||
70
.github/workflows/docker-build.yml
vendored
70
.github/workflows/docker-build.yml
vendored
@@ -36,7 +36,7 @@ env:
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 25
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -77,13 +77,34 @@ jobs:
|
||||
id: tag_version
|
||||
run: |
|
||||
if [[ $GITHUB_REF == refs/tags/v* ]]; then
|
||||
echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
||||
echo "Using version tag: ${GITHUB_REF#refs/tags/}"
|
||||
TAG_VERSION="${GITHUB_REF#refs/tags/}"
|
||||
if [[ ! "$TAG_VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then
|
||||
echo "::error::Release tag '${TAG_VERSION}' is invalid. Expected semver tag format like v1.2.3 or v1.2.3-rc.1"
|
||||
exit 1
|
||||
fi
|
||||
APP_VERSION="${TAG_VERSION#v}"
|
||||
echo "VERSION=${TAG_VERSION}" >> $GITHUB_OUTPUT
|
||||
echo "APP_VERSION=${APP_VERSION}" >> $GITHUB_OUTPUT
|
||||
echo "Using version tag: ${TAG_VERSION}"
|
||||
else
|
||||
echo "VERSION=latest" >> $GITHUB_OUTPUT
|
||||
echo "APP_VERSION=dev" >> $GITHUB_OUTPUT
|
||||
echo "No version tag, using 'latest'"
|
||||
fi
|
||||
|
||||
# Keep version files aligned automatically for tag-based releases
|
||||
- name: Sync app version from release tag
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
run: |
|
||||
VERSION="${{ steps.tag_version.outputs.APP_VERSION }}"
|
||||
echo "Syncing package.json version to ${VERSION}"
|
||||
|
||||
jq --arg version "${VERSION}" '.version = $version' package.json > package.json.tmp
|
||||
mv package.json.tmp package.json
|
||||
|
||||
echo "Version sync diff (package.json):"
|
||||
git --no-pager diff -- package.json
|
||||
|
||||
# Extract metadata for Docker
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
@@ -232,8 +253,49 @@ jobs:
|
||||
|
||||
# Upload security scan results to GitHub Security tab
|
||||
- name: Upload Docker Scout scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
uses: github/codeql-action/upload-sarif@v4
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
with:
|
||||
sarif_file: scout-results.sarif
|
||||
|
||||
sync-version-main:
|
||||
name: Sync package.json version back to main
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
runs-on: ubuntu-latest
|
||||
needs: docker
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Checkout default branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.repository.default_branch }}
|
||||
|
||||
- name: Update package.json version on main
|
||||
env:
|
||||
TAG_VERSION: ${{ github.ref_name }}
|
||||
TARGET_BRANCH: ${{ github.event.repository.default_branch }}
|
||||
run: |
|
||||
if [[ ! "$TAG_VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then
|
||||
echo "::error::Release tag '${TAG_VERSION}' is invalid. Expected semver tag format like v1.2.3 or v1.2.3-rc.1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
APP_VERSION="${TAG_VERSION#v}"
|
||||
echo "Syncing ${TARGET_BRANCH}/package.json to ${APP_VERSION}"
|
||||
|
||||
jq --arg version "${APP_VERSION}" '.version = $version' package.json > package.json.tmp
|
||||
mv package.json.tmp package.json
|
||||
|
||||
if git diff --quiet -- package.json; then
|
||||
echo "package.json on ${TARGET_BRANCH} already at ${APP_VERSION}; nothing to commit."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git add package.json
|
||||
git commit -m "chore: sync version to ${APP_VERSION}"
|
||||
git push origin "HEAD:${TARGET_BRANCH}"
|
||||
|
||||
4
.github/workflows/e2e-tests.yml
vendored
4
.github/workflows/e2e-tests.yml
vendored
@@ -40,13 +40,13 @@ env:
|
||||
FAKE_GITHUB_PORT: 4580
|
||||
GIT_SERVER_PORT: 4590
|
||||
APP_PORT: 4321
|
||||
BUN_VERSION: "1.3.6"
|
||||
BUN_VERSION: "1.3.10"
|
||||
|
||||
jobs:
|
||||
e2e-tests:
|
||||
name: E2E Integration Tests
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
|
||||
4
.github/workflows/helm-test.yml
vendored
4
.github/workflows/helm-test.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
yamllint:
|
||||
name: Lint YAML
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
helm-template:
|
||||
name: Helm lint & template
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Helm
|
||||
|
||||
22
.github/workflows/nix-build.yml
vendored
22
.github/workflows/nix-build.yml
vendored
@@ -5,18 +5,18 @@ on:
|
||||
branches: [main, nix]
|
||||
tags:
|
||||
- 'v*'
|
||||
paths-ignore:
|
||||
- 'README.md'
|
||||
- 'docs/**'
|
||||
- 'www/**'
|
||||
- 'helm/**'
|
||||
paths:
|
||||
- 'flake.nix'
|
||||
- 'flake.lock'
|
||||
- 'bun.nix'
|
||||
- '.github/workflows/nix-build.yml'
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths-ignore:
|
||||
- 'README.md'
|
||||
- 'docs/**'
|
||||
- 'www/**'
|
||||
- 'helm/**'
|
||||
paths:
|
||||
- 'flake.nix'
|
||||
- 'flake.lock'
|
||||
- 'bun.nix'
|
||||
- '.github/workflows/nix-build.yml'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -24,7 +24,7 @@ permissions:
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 45
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1.4
|
||||
|
||||
FROM oven/bun:1.3.9-debian AS base
|
||||
FROM oven/bun:1.3.10-debian AS base
|
||||
WORKDIR /app
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
python3 make g++ gcc wget sqlite3 openssl ca-certificates \
|
||||
@@ -26,7 +26,7 @@ COPY bun.lock* ./
|
||||
RUN bun install --production --omit=peer --frozen-lockfile
|
||||
|
||||
# ----------------------------
|
||||
FROM oven/bun:1.3.9-debian AS runner
|
||||
FROM oven/bun:1.3.10-debian AS runner
|
||||
WORKDIR /app
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
git git-lfs wget sqlite3 openssl ca-certificates \
|
||||
|
||||
@@ -139,16 +139,29 @@ fi
|
||||
|
||||
# Initialize configuration from environment variables if provided
|
||||
echo "Checking for environment configuration..."
|
||||
if [ -f "dist/scripts/startup-env-config.js" ]; then
|
||||
echo "Loading configuration from environment variables..."
|
||||
bun dist/scripts/startup-env-config.js
|
||||
ENV_CONFIG_EXIT_CODE=$?
|
||||
elif [ -f "scripts/startup-env-config.ts" ]; then
|
||||
echo "Loading configuration from environment variables..."
|
||||
bun scripts/startup-env-config.ts
|
||||
ENV_CONFIG_EXIT_CODE=$?
|
||||
|
||||
# Only run the env config script if relevant env vars are set
|
||||
# This avoids spawning a heavy Bun process on memory-constrained systems
|
||||
HAS_ENV_CONFIG=false
|
||||
if [ -n "$GITHUB_USERNAME" ] || [ -n "$GITHUB_TOKEN" ] || [ -n "$GITEA_URL" ] || [ -n "$GITEA_USERNAME" ] || [ -n "$GITEA_TOKEN" ]; then
|
||||
HAS_ENV_CONFIG=true
|
||||
fi
|
||||
|
||||
if [ "$HAS_ENV_CONFIG" = "true" ]; then
|
||||
if [ -f "dist/scripts/startup-env-config.js" ]; then
|
||||
echo "Loading configuration from environment variables..."
|
||||
bun dist/scripts/startup-env-config.js || ENV_CONFIG_EXIT_CODE=$?
|
||||
ENV_CONFIG_EXIT_CODE=${ENV_CONFIG_EXIT_CODE:-0}
|
||||
elif [ -f "scripts/startup-env-config.ts" ]; then
|
||||
echo "Loading configuration from environment variables..."
|
||||
bun scripts/startup-env-config.ts || ENV_CONFIG_EXIT_CODE=$?
|
||||
ENV_CONFIG_EXIT_CODE=${ENV_CONFIG_EXIT_CODE:-0}
|
||||
else
|
||||
echo "Environment configuration script not found. Skipping."
|
||||
ENV_CONFIG_EXIT_CODE=0
|
||||
fi
|
||||
else
|
||||
echo "Environment configuration script not found. Skipping."
|
||||
echo "No GitHub/Gitea environment variables found, skipping env config initialization."
|
||||
ENV_CONFIG_EXIT_CODE=0
|
||||
fi
|
||||
|
||||
@@ -161,17 +174,15 @@ fi
|
||||
|
||||
# Run startup recovery to handle any interrupted jobs
|
||||
echo "Running startup recovery..."
|
||||
RECOVERY_EXIT_CODE=0
|
||||
if [ -f "dist/scripts/startup-recovery.js" ]; then
|
||||
echo "Running startup recovery using compiled script..."
|
||||
bun dist/scripts/startup-recovery.js --timeout=30000
|
||||
RECOVERY_EXIT_CODE=$?
|
||||
bun dist/scripts/startup-recovery.js --timeout=30000 || RECOVERY_EXIT_CODE=$?
|
||||
elif [ -f "scripts/startup-recovery.ts" ]; then
|
||||
echo "Running startup recovery using TypeScript script..."
|
||||
bun scripts/startup-recovery.ts --timeout=30000
|
||||
RECOVERY_EXIT_CODE=$?
|
||||
bun scripts/startup-recovery.ts --timeout=30000 || RECOVERY_EXIT_CODE=$?
|
||||
else
|
||||
echo "Warning: Startup recovery script not found. Skipping recovery."
|
||||
RECOVERY_EXIT_CODE=0
|
||||
fi
|
||||
|
||||
# Log recovery result
|
||||
@@ -185,17 +196,15 @@ fi
|
||||
|
||||
# Run repository status repair to fix any inconsistent mirroring states
|
||||
echo "Running repository status repair..."
|
||||
REPAIR_EXIT_CODE=0
|
||||
if [ -f "dist/scripts/repair-mirrored-repos.js" ]; then
|
||||
echo "Running repository repair using compiled script..."
|
||||
bun dist/scripts/repair-mirrored-repos.js --startup
|
||||
REPAIR_EXIT_CODE=$?
|
||||
bun dist/scripts/repair-mirrored-repos.js --startup || REPAIR_EXIT_CODE=$?
|
||||
elif [ -f "scripts/repair-mirrored-repos.ts" ]; then
|
||||
echo "Running repository repair using TypeScript script..."
|
||||
bun scripts/repair-mirrored-repos.ts --startup
|
||||
REPAIR_EXIT_CODE=$?
|
||||
bun scripts/repair-mirrored-repos.ts --startup || REPAIR_EXIT_CODE=$?
|
||||
else
|
||||
echo "Warning: Repository repair script not found. Skipping repair."
|
||||
REPAIR_EXIT_CODE=0
|
||||
fi
|
||||
|
||||
# Log repair result
|
||||
|
||||
@@ -310,26 +310,25 @@ bunx tsc --noEmit
|
||||
|
||||
## Release Process
|
||||
|
||||
1. **Update version**:
|
||||
```bash
|
||||
npm version patch # or minor/major
|
||||
```
|
||||
1. **Choose release version** (`X.Y.Z`) and update `CHANGELOG.md`
|
||||
|
||||
2. **Update CHANGELOG.md**
|
||||
|
||||
3. **Build and test**:
|
||||
2. **Build and test**:
|
||||
```bash
|
||||
bun run build
|
||||
bun test
|
||||
```
|
||||
|
||||
4. **Create release**:
|
||||
3. **Create release tag** (semver format required):
|
||||
```bash
|
||||
git tag vX.Y.Z
|
||||
git push origin vX.Y.Z
|
||||
```
|
||||
|
||||
5. **Create GitHub release**
|
||||
4. **Create GitHub release**
|
||||
|
||||
5. **CI version sync (automatic)**:
|
||||
- On `v*` tags, release CI updates `package.json` version in the build context from the tag (`vX.Y.Z` -> `X.Y.Z`), so Docker release images always report the correct app version.
|
||||
- After the release build succeeds, CI commits the same `package.json` version back to `main` automatically.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
14
flake.nix
14
flake.nix
@@ -49,6 +49,20 @@
|
||||
bunNix = ./bun.nix;
|
||||
};
|
||||
|
||||
# bun2nix defaults to isolated installs on Linux, which can be
|
||||
# very slow in CI for larger dependency trees and may appear stuck.
|
||||
# Use hoisted linker and fail fast on lockfile drift.
|
||||
bunInstallFlags = if pkgs.stdenv.hostPlatform.isDarwin then [
|
||||
"--linker=hoisted"
|
||||
"--backend=copyfile"
|
||||
"--frozen-lockfile"
|
||||
"--no-progress"
|
||||
] else [
|
||||
"--linker=hoisted"
|
||||
"--frozen-lockfile"
|
||||
"--no-progress"
|
||||
];
|
||||
|
||||
# Let the bun2nix hook handle dependency installation via the
|
||||
# pre-fetched cache, but skip its default build/check/install
|
||||
# phases since we have custom ones.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "gitea-mirror",
|
||||
"type": "module",
|
||||
"version": "3.10.1",
|
||||
"version": "3.12.3",
|
||||
"engines": {
|
||||
"bun": ">=1.2.9"
|
||||
},
|
||||
@@ -119,5 +119,5 @@
|
||||
"tsx": "^4.21.0",
|
||||
"vitest": "^4.0.18"
|
||||
},
|
||||
"packageManager": "bun@1.3.3"
|
||||
"packageManager": "bun@1.3.10"
|
||||
}
|
||||
|
||||
@@ -72,10 +72,21 @@ mock.module("./gitea", () => {
|
||||
const mirrorStrategy =
|
||||
config?.githubConfig?.mirrorStrategy ||
|
||||
(config?.giteaConfig?.preserveOrgStructure ? "preserve" : "flat-user");
|
||||
const configuredGitHubOwner =
|
||||
(config?.githubConfig?.owner || config?.githubConfig?.username || "")
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
const repoOwner = repository?.owner?.trim().toLowerCase();
|
||||
|
||||
switch (mirrorStrategy) {
|
||||
case "preserve":
|
||||
return repository?.organization || config?.giteaConfig?.defaultOwner || "giteauser";
|
||||
if (repository?.organization) {
|
||||
return repository.organization;
|
||||
}
|
||||
if (configuredGitHubOwner && repoOwner && repoOwner !== configuredGitHubOwner) {
|
||||
return repository.owner;
|
||||
}
|
||||
return config?.giteaConfig?.defaultOwner || "giteauser";
|
||||
case "single-org":
|
||||
return config?.giteaConfig?.organization || config?.giteaConfig?.defaultOwner || "giteauser";
|
||||
case "mixed":
|
||||
@@ -99,7 +110,7 @@ mock.module("./gitea", () => {
|
||||
return mockDbSelectResult[0].destinationOrg;
|
||||
}
|
||||
|
||||
return config?.giteaConfig?.defaultOwner || "giteauser";
|
||||
return mockGetGiteaRepoOwner({ config, repository });
|
||||
});
|
||||
return {
|
||||
isRepoPresentInGitea: mockIsRepoPresentInGitea,
|
||||
@@ -376,6 +387,7 @@ describe("Gitea Repository Mirroring", () => {
|
||||
describe("getGiteaRepoOwner - Organization Override Tests", () => {
|
||||
const baseConfig: Partial<Config> = {
|
||||
githubConfig: {
|
||||
owner: "testuser",
|
||||
username: "testuser",
|
||||
token: "token",
|
||||
preserveOrgStructure: false,
|
||||
@@ -484,6 +496,18 @@ describe("getGiteaRepoOwner - Organization Override Tests", () => {
|
||||
expect(result).toBe("giteauser");
|
||||
});
|
||||
|
||||
test("preserve strategy: personal repos owned by another user keep source owner namespace", () => {
|
||||
const repo = {
|
||||
...baseRepo,
|
||||
owner: "nice-user",
|
||||
fullName: "nice-user/test-repo",
|
||||
organization: undefined,
|
||||
isForked: true,
|
||||
};
|
||||
const result = getGiteaRepoOwner({ config: baseConfig, repository: repo });
|
||||
expect(result).toBe("nice-user");
|
||||
});
|
||||
|
||||
test("preserve strategy: org repos go to same org name", () => {
|
||||
const repo = { ...baseRepo, organization: "myorg" };
|
||||
const result = getGiteaRepoOwner({ config: baseConfig, repository: repo });
|
||||
@@ -589,4 +613,26 @@ describe("getGiteaRepoOwner - Organization Override Tests", () => {
|
||||
|
||||
expect(result).toBe("FOO");
|
||||
});
|
||||
|
||||
test("getGiteaRepoOwnerAsync preserves external personal owner for preserve strategy", async () => {
|
||||
const configWithUser: Partial<Config> = {
|
||||
...baseConfig,
|
||||
userId: "user-id",
|
||||
};
|
||||
|
||||
const repo = {
|
||||
...baseRepo,
|
||||
owner: "nice-user",
|
||||
fullName: "nice-user/test-repo",
|
||||
organization: undefined,
|
||||
isForked: true,
|
||||
};
|
||||
|
||||
const result = await getGiteaRepoOwnerAsync({
|
||||
config: configWithUser,
|
||||
repository: repo,
|
||||
});
|
||||
|
||||
expect(result).toBe("nice-user");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -138,14 +138,35 @@ export const getGiteaRepoOwner = ({
|
||||
// Get the mirror strategy - use preserveOrgStructure for backward compatibility
|
||||
const mirrorStrategy = config.githubConfig.mirrorStrategy ||
|
||||
(config.giteaConfig.preserveOrgStructure ? "preserve" : "flat-user");
|
||||
const configuredGitHubOwner =
|
||||
(
|
||||
config.githubConfig.owner ||
|
||||
(config.githubConfig as typeof config.githubConfig & { username?: string }).username ||
|
||||
""
|
||||
)
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
|
||||
switch (mirrorStrategy) {
|
||||
case "preserve":
|
||||
// Keep GitHub structure - org repos go to same org, personal repos to user (or override)
|
||||
// Keep GitHub structure:
|
||||
// - org repos stay in the same org
|
||||
// - personal repos owned by other users keep their source owner namespace
|
||||
// - personal repos owned by the configured account go to defaultOwner
|
||||
if (repository.organization) {
|
||||
return repository.organization;
|
||||
}
|
||||
// Use personal repos override if configured, otherwise use username
|
||||
|
||||
const normalizedRepoOwner = repository.owner.trim().toLowerCase();
|
||||
if (
|
||||
normalizedRepoOwner &&
|
||||
configuredGitHubOwner &&
|
||||
normalizedRepoOwner !== configuredGitHubOwner
|
||||
) {
|
||||
return repository.owner;
|
||||
}
|
||||
|
||||
// Personal repos from the configured GitHub account go to the configured default owner
|
||||
return config.giteaConfig.defaultOwner;
|
||||
|
||||
case "single-org":
|
||||
@@ -376,6 +397,23 @@ export const mirrorGithubRepoToGitea = async ({
|
||||
|
||||
// Get the correct owner based on the strategy (with organization overrides)
|
||||
let repoOwner = await getGiteaRepoOwnerAsync({ config, repository });
|
||||
const mirrorStrategy = config.githubConfig.mirrorStrategy ||
|
||||
(config.giteaConfig.preserveOrgStructure ? "preserve" : "flat-user");
|
||||
const configuredGitHubOwner = (
|
||||
config.githubConfig.owner ||
|
||||
(config.githubConfig as typeof config.githubConfig & { username?: string }).username ||
|
||||
""
|
||||
)
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
const normalizedRepoOwner = repository.owner.trim().toLowerCase();
|
||||
const isExternalPersonalRepoInPreserveMode =
|
||||
mirrorStrategy === "preserve" &&
|
||||
!repository.organization &&
|
||||
!repository.isStarred &&
|
||||
normalizedRepoOwner !== "" &&
|
||||
configuredGitHubOwner !== "" &&
|
||||
normalizedRepoOwner !== configuredGitHubOwner;
|
||||
|
||||
// Determine the actual repository name to use (handle duplicates for starred repos)
|
||||
let targetRepoName = repository.name;
|
||||
@@ -520,6 +558,13 @@ export const mirrorGithubRepoToGitea = async ({
|
||||
(orgError.message.includes('Permission denied') ||
|
||||
orgError.message.includes('Authentication failed') ||
|
||||
orgError.message.includes('does not have permission'))) {
|
||||
if (isExternalPersonalRepoInPreserveMode) {
|
||||
throw new Error(
|
||||
`Cannot create/access namespace "${repoOwner}" for ${repository.fullName}. ` +
|
||||
`Refusing fallback to "${config.giteaConfig.defaultOwner}" in preserve mode to avoid cross-owner overwrite.`
|
||||
);
|
||||
}
|
||||
|
||||
console.warn(`[Fallback] Organization creation/access failed. Attempting to mirror to user account instead.`);
|
||||
|
||||
// Update the repository owner to use the user account
|
||||
|
||||
16
www/pnpm-lock.yaml
generated
16
www/pnpm-lock.yaml
generated
@@ -1943,8 +1943,8 @@ packages:
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
|
||||
sax@1.4.4:
|
||||
resolution: {integrity: sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==}
|
||||
sax@1.5.0:
|
||||
resolution: {integrity: sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==}
|
||||
engines: {node: '>=11.0.0'}
|
||||
|
||||
scheduler@0.27.0:
|
||||
@@ -2012,8 +2012,8 @@ packages:
|
||||
style-to-object@1.0.14:
|
||||
resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==}
|
||||
|
||||
svgo@4.0.0:
|
||||
resolution: {integrity: sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==}
|
||||
svgo@4.0.1:
|
||||
resolution: {integrity: sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==}
|
||||
engines: {node: '>=16'}
|
||||
hasBin: true
|
||||
|
||||
@@ -3185,7 +3185,7 @@ snapshots:
|
||||
semver: 7.7.4
|
||||
shiki: 3.22.0
|
||||
smol-toml: 1.6.0
|
||||
svgo: 4.0.0
|
||||
svgo: 4.0.1
|
||||
tinyexec: 1.0.2
|
||||
tinyglobby: 0.2.15
|
||||
tsconfck: 3.1.6(typescript@5.8.3)
|
||||
@@ -4552,7 +4552,7 @@ snapshots:
|
||||
'@rollup/rollup-win32-x64-msvc': 4.59.0
|
||||
fsevents: 2.3.3
|
||||
|
||||
sax@1.4.4: {}
|
||||
sax@1.5.0: {}
|
||||
|
||||
scheduler@0.27.0: {}
|
||||
|
||||
@@ -4648,7 +4648,7 @@ snapshots:
|
||||
dependencies:
|
||||
inline-style-parser: 0.2.7
|
||||
|
||||
svgo@4.0.0:
|
||||
svgo@4.0.1:
|
||||
dependencies:
|
||||
commander: 11.1.0
|
||||
css-select: 5.2.2
|
||||
@@ -4656,7 +4656,7 @@ snapshots:
|
||||
css-what: 6.2.2
|
||||
csso: 5.0.5
|
||||
picocolors: 1.1.1
|
||||
sax: 1.4.4
|
||||
sax: 1.5.0
|
||||
|
||||
tailwind-merge@3.5.0: {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user