Browse Source

fix zombie spawning on polling

make announcement commits non-blocking on repo provision

Nostr-Signature: b0da119e7477b46f5d82be831693a92e117f25379476488f19351e2bac8f88b8 573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc b8ca18e8215a9f5b3fc877ce113936c582353d44f8d03cdccd9f9ee70fb3e6fdd64db7cc6a3ca15339fb21b9ca87ea8471a38b587721a594a189d97cc2964ad9
main
Silberengel 2 weeks ago
parent
commit
054aa9391e
  1. 6
      docker-entrypoint.sh
  2. 1
      nostr/commit-signatures.jsonl
  3. 21
      src/lib/services/git/announcement-manager.ts
  4. 66
      src/lib/services/git/repo-manager.ts

6
docker-entrypoint.sh

@ -59,6 +59,12 @@ if [ "$(id -u)" = "0" ]; then
echo "This may indicate a UID conflict. Consider using a different GITREPUBLIC_UID." echo "This may indicate a UID conflict. Consider using a different GITREPUBLIC_UID."
fi fi
# Configure git user.name and user.email for gitrepublic user
# This is required for git commits to work properly
echo "Configuring git identity for $ACTUAL_USER..."
su-exec $ACTUAL_USER git config --global user.name "GitRepublic" || true
su-exec $ACTUAL_USER git config --global user.email "gitrepublic@gitrepublic.web" || true
echo "Switching to user: $ACTUAL_USER (UID: $GITREPUBLIC_UID)..." echo "Switching to user: $ACTUAL_USER (UID: $GITREPUBLIC_UID)..."
exec su-exec $ACTUAL_USER "$@" exec su-exec $ACTUAL_USER "$@"
else else

1
nostr/commit-signatures.jsonl

@ -113,3 +113,4 @@
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772220851,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","bug-fixes"]],"content":"Signed commit: bug-fixes","id":"d98d2d6a6eb27ba36f19015f7d6969fe3925c40b23187d70ccc9b61141c6b4b7","sig":"8727e3015e38a78d7a6105c26e5b1469dc4d6d701e58d5d6c522ab529b4daa2d39d4353eb6d091f3c1fd28ad0289eae808494c9e2722bf9065dd2b2e9001664f"} {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772220851,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","bug-fixes"]],"content":"Signed commit: bug-fixes","id":"d98d2d6a6eb27ba36f19015f7d6969fe3925c40b23187d70ccc9b61141c6b4b7","sig":"8727e3015e38a78d7a6105c26e5b1469dc4d6d701e58d5d6c522ab529b4daa2d39d4353eb6d091f3c1fd28ad0289eae808494c9e2722bf9065dd2b2e9001664f"}
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772223624,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","bug-fixes"]],"content":"Signed commit: bug-fixes","id":"99cb543f1e821f1b7df4bbde2b3da3ab3a09cda7a1e9a537fe1b8df79b19e8e8","sig":"762a7ea92457ce81cc5aae9bc644fb9d80f90c7500035fbb506f2f76a5942333b828cc8a59f7656b0e714b15a59158be0a671f51476be2e8eabe9731ced74bcb"} {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772223624,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","bug-fixes"]],"content":"Signed commit: bug-fixes","id":"99cb543f1e821f1b7df4bbde2b3da3ab3a09cda7a1e9a537fe1b8df79b19e8e8","sig":"762a7ea92457ce81cc5aae9bc644fb9d80f90c7500035fbb506f2f76a5942333b828cc8a59f7656b0e714b15a59158be0a671f51476be2e8eabe9731ced74bcb"}
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772226191,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","bug-fixes"]],"content":"Signed commit: bug-fixes","id":"20be97351d2b05fa7ad9e161b2619e9babaaffc6a8090057c1a3ac50a0f08d6a","sig":"a174c7dd39f613dd88260ef5c111b943df381b0acae20d048596e11ef1a6b0e3c1bfb9a8858af3df0f8858c4c79d1e2d03ad248a0608ac5d5cded6a81e99af77"} {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772226191,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","bug-fixes"]],"content":"Signed commit: bug-fixes","id":"20be97351d2b05fa7ad9e161b2619e9babaaffc6a8090057c1a3ac50a0f08d6a","sig":"a174c7dd39f613dd88260ef5c111b943df381b0acae20d048596e11ef1a6b0e3c1bfb9a8858af3df0f8858c4c79d1e2d03ad248a0608ac5d5cded6a81e99af77"}
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772227102,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","bug-fix"]],"content":"Signed commit: bug-fix","id":"0f366a0cc7c003f74e375f40e7c322781746d12829943df1287bf67f36e1330a","sig":"167177ccfeb053cd645e50e7d00450b847ecd65c305165777bcfbe39fd3f48ccc86b57fdd183d2a4b138d94d27d11e4f1c121d702b295d94b9aee0a8dc81a744"}

21
src/lib/services/git/announcement-manager.ts

@ -266,6 +266,17 @@ export class AnnouncementManager {
logger.info({ repoPath, filesToAdd, isEmpty }, 'Adding files and committing announcement'); logger.info({ repoPath, filesToAdd, isEmpty }, 'Adding files and committing announcement');
await workGit.add(filesToAdd); await workGit.add(filesToAdd);
// Configure git user.name and user.email for this repository
// This is required for git commits to work (committer identity)
// We use a generic identity since the server is making the commit on behalf of the system
try {
await workGit.addConfig('user.name', 'GitRepublic', false, 'local');
await workGit.addConfig('user.email', 'gitrepublic@gitrepublic.web', false, 'local');
logger.debug({ repoPath }, 'Configured git user.name and user.email for repository');
} catch (configError) {
logger.warn({ repoPath, error: configError }, 'Failed to set git config, commit may fail');
}
// Use the event timestamp for commit date // Use the event timestamp for commit date
const commitDate = new Date(event.created_at * 1000).toISOString(); const commitDate = new Date(event.created_at * 1000).toISOString();
const commitMessage = selfTransferEvent const commitMessage = selfTransferEvent
@ -451,13 +462,9 @@ export class AnnouncementManager {
isEmpty isEmpty
}, 'Failed to ensure announcement in repo'); }, 'Failed to ensure announcement in repo');
// For empty repos, this is critical - we need the initial commit // Don't throw - this is now non-blocking
// For non-empty repos, it's less critical but still important // The announcement is available from relays, so this is just for offline papertrail
if (isEmpty) { // Even for empty repos, we don't throw since provisioning should succeed regardless
// Re-throw for empty repos so caller knows it failed
throw new Error(`Failed to commit announcement to empty repo: ${errorMessage}`);
}
// For non-empty repos, don't throw - announcement file creation is important but shouldn't block provisioning
} }
} }

66
src/lib/services/git/repo-manager.ts

@ -165,27 +165,34 @@ export class RepoManager {
} else { } else {
// Branches exist (from sync) - ensure announcement is committed to the default branch // Branches exist (from sync) - ensure announcement is committed to the default branch
// This must happen after syncing so we can commit it to the existing default branch // This must happen after syncing so we can commit it to the existing default branch
await this.announcementManager.ensureAnnouncementInRepo(repoPath.fullPath, event, selfTransferEvent); // Non-blocking: fire and forget - we have the announcement from relays, so this is just for offline papertrail
this.announcementManager.ensureAnnouncementInRepo(repoPath.fullPath, event, selfTransferEvent)
.catch((err) => {
logger.warn({ error: err, repoPath: repoPath.fullPath, eventId: event.id },
'Failed to save announcement to repo (non-blocking, announcement available from relays)');
});
} }
} else { } else {
// For existing repos, check if announcement exists in repo // For existing repos, check if announcement exists in repo
// If not, try to fetch from relays and save it // If not, try to fetch from relays and save it
// Note: We have the announcement from polling (event parameter), so we can use that
// Non-blocking: fire and forget - we have the announcement from relays, so this is just for offline papertrail
const hasAnnouncement = await this.announcementManager.hasAnnouncementInRepoFile(repoPath.fullPath); const hasAnnouncement = await this.announcementManager.hasAnnouncementInRepoFile(repoPath.fullPath);
if (!hasAnnouncement) { if (!hasAnnouncement) {
// Try to fetch from relays // We have the event from polling, so use it directly (no need to fetch from relays again)
const fetchedEvent = await this.announcementManager.fetchAnnouncementFromRelays(event.pubkey, repoPath.repoName); // Save announcement to repo asynchronously
if (fetchedEvent) { this.announcementManager.ensureAnnouncementInRepo(repoPath.fullPath, event, selfTransferEvent)
// Save fetched announcement to repo .catch((err) => {
await this.announcementManager.ensureAnnouncementInRepo(repoPath.fullPath, fetchedEvent, selfTransferEvent); logger.warn({ error: err, repoPath: repoPath.fullPath, eventId: event.id },
} else { 'Failed to save announcement to repo (non-blocking, announcement available from relays)');
// Announcement not found in repo or relays - this is a problem });
logger.warn({ repoPath: repoPath.fullPath }, 'Existing repo has no announcement in repo or on relays'); } else if (selfTransferEvent) {
} // Announcement exists but self-transfer might not - save it asynchronously
} this.announcementManager.ensureAnnouncementInRepo(repoPath.fullPath, event, selfTransferEvent)
.catch((err) => {
if (selfTransferEvent) { logger.warn({ error: err, repoPath: repoPath.fullPath, eventId: event.id },
// Ensure self-transfer event is also saved 'Failed to save self-transfer to repo (non-blocking)');
await this.announcementManager.ensureAnnouncementInRepo(repoPath.fullPath, event, selfTransferEvent); });
} }
} }
} }
@ -302,6 +309,18 @@ Your commits will all be signed by your Nostr keys and saved to the event files
} }
await workGit.add(filesToAdd); await workGit.add(filesToAdd);
// Configure git user.name and user.email for this repository
// This is required for git commits to work (committer identity)
// We use a generic identity since the server is making the commit on behalf of the system
// The --author flag sets the author, but we still need committer identity configured
try {
await workGit.addConfig('user.name', 'GitRepublic', false, 'local');
await workGit.addConfig('user.email', 'gitrepublic@gitrepublic.web', false, 'local');
logger.debug({ repoPath, npub, repoName }, 'Configured git user.name and user.email for repository');
} catch (configError) {
logger.warn({ repoPath, npub, repoName, error: configError }, 'Failed to set git config, commit may fail');
}
// Commit files together // Commit files together
await workGit.commit('Initial commit', filesToAdd, { await workGit.commit('Initial commit', filesToAdd, {
'--author': `${authorName} <${authorEmail}>` '--author': `${authorName} <${authorEmail}>`
@ -371,8 +390,13 @@ Your commits will all be signed by your Nostr keys and saved to the event files
} }
if (announcementToUse) { if (announcementToUse) {
// Save announcement to repo (this will create initial commit if repo is empty) // Save announcement to repo asynchronously (non-blocking)
await this.announcementManager.ensureAnnouncementInRepo(repoPath, announcementToUse); // We have the announcement from relays, so this is just for offline papertrail
this.announcementManager.ensureAnnouncementInRepo(repoPath, announcementToUse)
.catch((err) => {
logger.warn({ error: err, repoPath, eventId: announcementToUse?.id },
'Failed to save announcement to repo (non-blocking, announcement available from relays)');
});
return { success: true, announcement: announcementToUse }; return { success: true, announcement: announcementToUse };
} }
@ -616,12 +640,12 @@ Your commits will all be signed by your Nostr keys and saved to the event files
} }
// Ensure announcement is saved to nostr/repo-events.jsonl (non-blocking - repo is usable without it) // Ensure announcement is saved to nostr/repo-events.jsonl (non-blocking - repo is usable without it)
try { // Fire and forget - we have the announcement from relays, so this is just for offline papertrail
await this.announcementManager.ensureAnnouncementInRepo(repoPath, announcementEvent); this.announcementManager.ensureAnnouncementInRepo(repoPath, announcementEvent)
} catch (verifyError) { .catch((verifyError) => {
// Announcement file creation is optional - log but don't fail // Announcement file creation is optional - log but don't fail
logger.warn({ error: verifyError, npub, repoName }, 'Failed to ensure announcement in repo, but repository is usable'); logger.warn({ error: verifyError, npub, repoName }, 'Failed to ensure announcement in repo, but repository is usable');
} });
logger.info({ npub, repoName }, 'Successfully fetched repository on-demand'); logger.info({ npub, repoName }, 'Successfully fetched repository on-demand');
return { success: true, announcement: announcementEvent }; return { success: true, announcement: announcementEvent };

Loading…
Cancel
Save