mirror of
https://github.com/RayLabsHQ/gitea-mirror.git
synced 2025-12-08 20:46:44 +03:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0fb5f9e190 | ||
|
|
dacec93f55 |
35
CHANGELOG.md
35
CHANGELOG.md
@@ -7,6 +7,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [3.2.6] - 2025-08-09
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Added missing release asset mirroring functionality (APK, ZIP, Binary files)
|
||||||
|
- Release assets (attachments) are now properly downloaded from GitHub and uploaded to Gitea
|
||||||
|
- Fixed missing metadata component configuration checks
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Full support for mirroring release assets/attachments
|
||||||
|
- Debug logging for metadata component configuration to help troubleshoot mirroring issues
|
||||||
|
- Download and upload progress logging for release assets
|
||||||
|
|
||||||
|
### Improved
|
||||||
|
- Enhanced release mirroring to include all associated binary files and attachments
|
||||||
|
- Better visibility into which metadata components are enabled/disabled
|
||||||
|
- More detailed logging during the release asset transfer process
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
This patch adds the missing functionality to mirror release assets (APK, ZIP, Binary files, etc.) that was reported in Issue #68. Previously only release metadata was being mirrored, now all attachments are properly transferred to Gitea.
|
||||||
|
|
||||||
|
## [3.2.5] - 2025-08-09
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed critical authentication issue in releases mirroring that was still using encrypted tokens
|
||||||
|
- Added missing repository existence check for releases mirroring function
|
||||||
|
- Fixed "user does not exist [uid: 0]" error specifically affecting GitHub releases synchronization
|
||||||
|
|
||||||
|
### Improved
|
||||||
|
- Enhanced releases mirroring with duplicate detection to avoid errors on re-runs
|
||||||
|
- Better error handling and logging for release operations with [Releases] prefix
|
||||||
|
- Added individual release error handling to continue mirroring even if some releases fail
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
This patch completes the authentication fixes started in v3.2.4, specifically addressing the releases mirroring function that was accidentally missed in the previous update.
|
||||||
|
|
||||||
## [3.2.4] - 2025-08-09
|
## [3.2.4] - 2025-08-09
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "gitea-mirror",
|
"name": "gitea-mirror",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "3.2.4",
|
"version": "3.2.6",
|
||||||
"engines": {
|
"engines": {
|
||||||
"bun": ">=1.2.9"
|
"bun": ">=1.2.9"
|
||||||
},
|
},
|
||||||
|
|||||||
115
src/lib/gitea.ts
115
src/lib/gitea.ts
@@ -429,6 +429,7 @@ export const mirrorGithubRepoToGitea = async ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
//mirror releases
|
//mirror releases
|
||||||
|
console.log(`[Metadata] Release mirroring check: mirrorReleases=${config.giteaConfig?.mirrorReleases}`);
|
||||||
if (config.giteaConfig?.mirrorReleases) {
|
if (config.giteaConfig?.mirrorReleases) {
|
||||||
await mirrorGitHubReleasesToGitea({
|
await mirrorGitHubReleasesToGitea({
|
||||||
config,
|
config,
|
||||||
@@ -442,6 +443,8 @@ export const mirrorGithubRepoToGitea = async ({
|
|||||||
const shouldMirrorIssues = config.giteaConfig?.mirrorIssues &&
|
const shouldMirrorIssues = config.giteaConfig?.mirrorIssues &&
|
||||||
!(repository.isStarred && config.githubConfig?.skipStarredIssues);
|
!(repository.isStarred && config.githubConfig?.skipStarredIssues);
|
||||||
|
|
||||||
|
console.log(`[Metadata] Issue mirroring check: mirrorIssues=${config.giteaConfig?.mirrorIssues}, isStarred=${repository.isStarred}, skipStarredIssues=${config.githubConfig?.skipStarredIssues}, shouldMirrorIssues=${shouldMirrorIssues}`);
|
||||||
|
|
||||||
if (shouldMirrorIssues) {
|
if (shouldMirrorIssues) {
|
||||||
await mirrorGitRepoIssuesToGitea({
|
await mirrorGitRepoIssuesToGitea({
|
||||||
config,
|
config,
|
||||||
@@ -452,6 +455,7 @@ export const mirrorGithubRepoToGitea = async ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mirror pull requests if enabled
|
// Mirror pull requests if enabled
|
||||||
|
console.log(`[Metadata] Pull request mirroring check: mirrorPullRequests=${config.giteaConfig?.mirrorPullRequests}`);
|
||||||
if (config.giteaConfig?.mirrorPullRequests) {
|
if (config.giteaConfig?.mirrorPullRequests) {
|
||||||
await mirrorGitRepoPullRequestsToGitea({
|
await mirrorGitRepoPullRequestsToGitea({
|
||||||
config,
|
config,
|
||||||
@@ -462,6 +466,7 @@ export const mirrorGithubRepoToGitea = async ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mirror labels if enabled (and not already done via issues)
|
// Mirror labels if enabled (and not already done via issues)
|
||||||
|
console.log(`[Metadata] Label mirroring check: mirrorLabels=${config.giteaConfig?.mirrorLabels}, shouldMirrorIssues=${shouldMirrorIssues}`);
|
||||||
if (config.giteaConfig?.mirrorLabels && !shouldMirrorIssues) {
|
if (config.giteaConfig?.mirrorLabels && !shouldMirrorIssues) {
|
||||||
await mirrorGitRepoLabelsToGitea({
|
await mirrorGitRepoLabelsToGitea({
|
||||||
config,
|
config,
|
||||||
@@ -472,6 +477,7 @@ export const mirrorGithubRepoToGitea = async ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mirror milestones if enabled
|
// Mirror milestones if enabled
|
||||||
|
console.log(`[Metadata] Milestone mirroring check: mirrorMilestones=${config.giteaConfig?.mirrorMilestones}`);
|
||||||
if (config.giteaConfig?.mirrorMilestones) {
|
if (config.giteaConfig?.mirrorMilestones) {
|
||||||
await mirrorGitRepoMilestonesToGitea({
|
await mirrorGitRepoMilestonesToGitea({
|
||||||
config,
|
config,
|
||||||
@@ -683,6 +689,7 @@ export async function mirrorGitHubRepoToGiteaOrg({
|
|||||||
);
|
);
|
||||||
|
|
||||||
//mirror releases
|
//mirror releases
|
||||||
|
console.log(`[Metadata] Release mirroring check: mirrorReleases=${config.giteaConfig?.mirrorReleases}`);
|
||||||
if (config.giteaConfig?.mirrorReleases) {
|
if (config.giteaConfig?.mirrorReleases) {
|
||||||
await mirrorGitHubReleasesToGitea({
|
await mirrorGitHubReleasesToGitea({
|
||||||
config,
|
config,
|
||||||
@@ -706,6 +713,7 @@ export async function mirrorGitHubRepoToGiteaOrg({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mirror pull requests if enabled
|
// Mirror pull requests if enabled
|
||||||
|
console.log(`[Metadata] Pull request mirroring check: mirrorPullRequests=${config.giteaConfig?.mirrorPullRequests}`);
|
||||||
if (config.giteaConfig?.mirrorPullRequests) {
|
if (config.giteaConfig?.mirrorPullRequests) {
|
||||||
await mirrorGitRepoPullRequestsToGitea({
|
await mirrorGitRepoPullRequestsToGitea({
|
||||||
config,
|
config,
|
||||||
@@ -716,6 +724,7 @@ export async function mirrorGitHubRepoToGiteaOrg({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mirror labels if enabled (and not already done via issues)
|
// Mirror labels if enabled (and not already done via issues)
|
||||||
|
console.log(`[Metadata] Label mirroring check: mirrorLabels=${config.giteaConfig?.mirrorLabels}, shouldMirrorIssues=${shouldMirrorIssues}`);
|
||||||
if (config.giteaConfig?.mirrorLabels && !shouldMirrorIssues) {
|
if (config.giteaConfig?.mirrorLabels && !shouldMirrorIssues) {
|
||||||
await mirrorGitRepoLabelsToGitea({
|
await mirrorGitRepoLabelsToGitea({
|
||||||
config,
|
config,
|
||||||
@@ -726,6 +735,7 @@ export async function mirrorGitHubRepoToGiteaOrg({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mirror milestones if enabled
|
// Mirror milestones if enabled
|
||||||
|
console.log(`[Metadata] Milestone mirroring check: mirrorMilestones=${config.giteaConfig?.mirrorMilestones}`);
|
||||||
if (config.giteaConfig?.mirrorMilestones) {
|
if (config.giteaConfig?.mirrorMilestones) {
|
||||||
await mirrorGitRepoMilestonesToGitea({
|
await mirrorGitRepoMilestonesToGitea({
|
||||||
config,
|
config,
|
||||||
@@ -1298,21 +1308,61 @@ export async function mirrorGitHubReleasesToGitea({
|
|||||||
throw new Error("Gitea config is incomplete for mirroring releases.");
|
throw new Error("Gitea config is incomplete for mirroring releases.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decrypt config tokens for API usage
|
||||||
|
const decryptedConfig = decryptConfigTokens(config as Config);
|
||||||
|
|
||||||
const repoOwner = await getGiteaRepoOwnerAsync({
|
const repoOwner = await getGiteaRepoOwnerAsync({
|
||||||
config,
|
config,
|
||||||
repository,
|
repository,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { url, token } = config.giteaConfig;
|
// Verify the repository exists in Gitea before attempting to mirror releases
|
||||||
|
console.log(`[Releases] Verifying repository ${repository.name} exists at ${repoOwner}`);
|
||||||
|
const repoExists = await isRepoPresentInGitea({
|
||||||
|
config,
|
||||||
|
owner: repoOwner,
|
||||||
|
repoName: repository.name,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!repoExists) {
|
||||||
|
console.error(`[Releases] Repository ${repository.name} not found at ${repoOwner}. Cannot mirror releases.`);
|
||||||
|
throw new Error(`Repository ${repository.name} does not exist in Gitea at ${repoOwner}. Please ensure the repository is mirrored first.`);
|
||||||
|
}
|
||||||
|
|
||||||
const releases = await octokit.rest.repos.listReleases({
|
const releases = await octokit.rest.repos.listReleases({
|
||||||
owner: repository.owner,
|
owner: repository.owner,
|
||||||
repo: repository.name,
|
repo: repository.name,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(`[Releases] Found ${releases.data.length} releases to mirror for ${repository.fullName}`);
|
||||||
|
|
||||||
|
if (releases.data.length === 0) {
|
||||||
|
console.log(`[Releases] No releases to mirror for ${repository.fullName}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mirroredCount = 0;
|
||||||
|
let skippedCount = 0;
|
||||||
|
|
||||||
for (const release of releases.data) {
|
for (const release of releases.data) {
|
||||||
await httpPost(
|
try {
|
||||||
`${url}/api/v1/repos/${repoOwner}/${repository.name}/releases`,
|
// Check if release already exists
|
||||||
|
const existingReleasesResponse = await httpGet(
|
||||||
|
`${config.giteaConfig.url}/api/v1/repos/${repoOwner}/${repository.name}/releases/tags/${release.tag_name}`,
|
||||||
|
{
|
||||||
|
Authorization: `token ${decryptedConfig.giteaConfig.token}`,
|
||||||
|
}
|
||||||
|
).catch(() => null);
|
||||||
|
|
||||||
|
if (existingReleasesResponse) {
|
||||||
|
console.log(`[Releases] Release ${release.tag_name} already exists, skipping`);
|
||||||
|
skippedCount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the release
|
||||||
|
const createReleaseResponse = await httpPost(
|
||||||
|
`${config.giteaConfig.url}/api/v1/repos/${repoOwner}/${repository.name}/releases`,
|
||||||
{
|
{
|
||||||
tag_name: release.tag_name,
|
tag_name: release.tag_name,
|
||||||
target: release.target_commitish,
|
target: release.target_commitish,
|
||||||
@@ -1322,12 +1372,67 @@ export async function mirrorGitHubReleasesToGitea({
|
|||||||
prerelease: release.prerelease,
|
prerelease: release.prerelease,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Authorization: `token ${token}`,
|
Authorization: `token ${decryptedConfig.giteaConfig.token}`,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Mirror release assets if they exist
|
||||||
|
if (release.assets && release.assets.length > 0) {
|
||||||
|
console.log(`[Releases] Mirroring ${release.assets.length} assets for release ${release.tag_name}`);
|
||||||
|
|
||||||
|
for (const asset of release.assets) {
|
||||||
|
try {
|
||||||
|
// Download the asset from GitHub
|
||||||
|
console.log(`[Releases] Downloading asset: ${asset.name} (${asset.size} bytes)`);
|
||||||
|
const assetResponse = await fetch(asset.browser_download_url, {
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/octet-stream',
|
||||||
|
'Authorization': `token ${decryptedConfig.githubConfig.token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!assetResponse.ok) {
|
||||||
|
console.error(`[Releases] Failed to download asset ${asset.name}: ${assetResponse.statusText}`);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`✅ Mirrored ${releases.data.length} GitHub releases to Gitea`);
|
const assetData = await assetResponse.arrayBuffer();
|
||||||
|
|
||||||
|
// Upload the asset to Gitea release
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('attachment', new Blob([assetData]), asset.name);
|
||||||
|
|
||||||
|
const uploadResponse = await fetch(
|
||||||
|
`${config.giteaConfig.url}/api/v1/repos/${repoOwner}/${repository.name}/releases/${createReleaseResponse.data.id}/assets?name=${encodeURIComponent(asset.name)}`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `token ${decryptedConfig.giteaConfig.token}`,
|
||||||
|
},
|
||||||
|
body: formData,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (uploadResponse.ok) {
|
||||||
|
console.log(`[Releases] Successfully uploaded asset: ${asset.name}`);
|
||||||
|
} else {
|
||||||
|
const errorText = await uploadResponse.text();
|
||||||
|
console.error(`[Releases] Failed to upload asset ${asset.name}: ${errorText}`);
|
||||||
|
}
|
||||||
|
} catch (assetError) {
|
||||||
|
console.error(`[Releases] Error processing asset ${asset.name}: ${assetError instanceof Error ? assetError.message : String(assetError)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mirroredCount++;
|
||||||
|
console.log(`[Releases] Successfully mirrored release: ${release.tag_name}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`[Releases] Failed to mirror release ${release.tag_name}: ${error instanceof Error ? error.message : String(error)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`✅ Mirrored ${mirroredCount} new releases to Gitea (${skippedCount} already existed)`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function mirrorGitRepoPullRequestsToGitea({
|
export async function mirrorGitRepoPullRequestsToGitea({
|
||||||
|
|||||||
Reference in New Issue
Block a user