summaryrefslogtreecommitdiff
path: root/internal/sync
AgeCommit message (Collapse)Author
2026-07-22fix(errcheck): handle all unchecked error returns without changing behaviormainPaul Buetow
errcheck ./... flagged unchecked HTTP response Close(), file Close(), os.RemoveAll(), fmt.Scanln(), and fmt.Fprintf() calls across codeberg, github, release, showcase, and sync. None of these were bugs causing incorrect behavior today, but leaving them unchecked hid real failure modes (e.g. a lagging NFS mount failing a file Close() after writes, which this codebase has hit before per commit 23ecaa2). - internal/codeberg/codeberg.go, internal/github/github.go, internal/release/release.go: added a small closeResponseBody(resp) helper per package and used it for all deferred resp.Body.Close() calls. The body is always fully read (or abandoned on an earlier error) by the time Close() runs, so the error is intentionally discarded - matching the explicit `_ = ...` discard convention already used elsewhere in this repo (e.g. showcase.go's os.RemoveAll on the worktree-add failure path). - internal/release/release.go: the two fmt.Scanln(&response) prompts now explicitly discard the return values; a Scanln error already leaves response == "", which the existing y/yes check already treats as a safe decline, so behavior is unchanged. - internal/showcase/code_extractor.go, images.go, language_detector.go: added a shared closeFile(*os.File) helper (package showcase) for the read-only file Close() calls, matching the same discard rationale. copyFile's destination Close() is the one write-side case where a close failure is real data-loss information, so it now uses a named return to surface it via err without masking any earlier error. - internal/showcase/showcase.go: the deferred os.RemoveAll(tempRoot) now explicitly discards its error, matching the sibling `_ =` call three lines above in the same function. - internal/sync/branch_analyzer.go: GenerateDeleteScript's per-repository fmt.Fprintf(file, ...) calls are now checked and wrapped with fmt.Errorf(...: %w), matching the error-wrapping convention already used by writeBranchDeletionBlock right below it in the same file (the repeated repo-header writes were pulled into a new writeDeleteScriptRepoHeader helper to keep this readable). The script file's defer file.Close() now uses a named return so a close failure is reported instead of silently discarded. Added focused tests for the two behavior-relevant paths: copyFile's missing-source/success paths after the named-return change, and PromptConfirmation's empty-input-declines/explicit-yes behavior after touching the Scanln call. Trivial defer-Close discards elsewhere are not additionally unit tested per the task's guidance against overengineering. Verified: go build ./..., go vet ./..., errcheck ./... (clean), and go test ./... all pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22fix(sync): make SSH backup repo creation survive non-root pushes and NFS lagPaul Buetow
Auditing a full bidirectional sync to the r0 git-server backup destination showed a stale/missing-repo pattern that cgit idle times alone did not explain: several public repos (rampage, ggaze, comicforge, fastforge, gonf, quicklog, shuriken.sh) were entirely absent from r0 even though they synced fine to GitHub/Codeberg. Root cause #1: createSSHBareRepository provisions missing backup repos by running `git init --bare` over a root SSH session directly on the r0 filesystem. That leaves the new repo directory at mode 0755 (root's session umask), owner-write only. Pushes into it later go through the git-server pod's own SSH endpoint as a different, non-root UID (1001, GID 33/www-data per the git-server helm chart's docker-image/Dockerfile), which then cannot write new objects into the 0755 tree ("unable to create temporary object directory"). Fixed by initializing with `git init --bare --shared=group` (mode 2775, matching the already-working repos on r0). Root cause #2: even with correct permissions, the push immediately following repository creation can still fail transiently (the git-server's own view of the newly created directory can lag behind, e.g. across an NFS mount). handlePushError treats any backup push failure as fatal for the remainder of that sync run and disables the backup destination entirely (disableBackupForSession) - so one transient failure early in a shuffled repo order silently skipped backup for every repo processed afterward in that pass, explaining the fuller set of stale repos. Fixed by retrying the post-creation push up to 3 times with a short backoff in the new createAndPushSSHBackupRepo helper, and by capturing/propagating the actual git stderr on failure (previously swallowed via cmd.Run()) so any future failure is diagnosable instead of a bare "exit status 128". Verified against the live r0 git-server (ssh://git@r0:30022/repos, /data/nfs/k3svolumes/git-server/repos): reinstalled gitsyncer and reran `sync bidirectional --force --backup --auto-create-releases` end to end with zero backup-disable events across both passes; all previously missing/broken repos (plus the pre-existing broken player.git and irregular.ninja.git, repaired directly via chmod) now match GitHub/Codeberg HEAD exactly and are browsable on c-git.f3s.buetow.org. Adds a regression test for the --shared=group init command. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22feat(sync): make backup fail-fast per-destination and add ↵Paul Buetow
forcePush/descriptionSync creation support Backup failures now disable retries only for the failing remote instead of the whole session, add an opt-in forcePush flag for backup organizations, and allow repository creation to go through descriptionSyncHost/Root when configured so the git remote endpoint can stay restricted. Also fixes the AI release-notes cache being bypassed by --force, which is meant to control sync scheduling, not cache invalidation. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-05-29fix(vq): restore version-prefix parsing and stash no-op handlingPaul Buetow
2026-05-29fix(vq): handle ignored stash/pop and parse errors explicitlyPaul Buetow
2026-05-29refactor(sync): move backup session state to Syncer instance (qq)Paul Buetow
2026-05-28refactor(sync): template delete script generation (eq)Paul Buetow
2026-05-28fix(sync): correct local tag peel syntax in getTagCommitHash (kp)Paul Buetow
2026-03-28feat(sync): auto-sync full backups and showcase cgit linksv0.17.0Paul Buetow
2026-03-12fix(sync): protect xerl hosts branch from auto-deletePaul Buetow
2026-03-11fix(sync): stop relying on process cwdPaul Buetow
2025-10-31feat: implement amp AI tool support and replace Taskfile with Magev0.10.0Paul Buetow
- Add amp as default AI tool for release notes and showcase generation - Fallback chain: amp → hexai → claude → aichat - Replace Taskfile.yaml with magefile.go for build automation - Update all documentation (README.md, AGENTS.md, doc/development.md) - Update version to 0.10.0 Amp-Thread-ID: https://ampcode.com/threads/T-735ba1e2-0255-4b43-8ed1-6c0d2f78301b Co-authored-by: Amp <amp@ampcode.com>
2025-07-19fix: switch branches before deletion in abandoned branch scriptv0.8.2Paul Buetow
- Add branch switching logic to prevent "refusing to delete current branch" error - Check if we're on the branch to be deleted and switch to main/master first - Skip deletion if no main/master branch exists to switch to - Bump version to 0.8.2 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-13fix: skip fetching from backup locations when --backup flag is not usedPaul Buetow
- Check all organizations (not just active ones) to identify backup locations - Skip fetching from backup remotes when backup is not enabled - Remove duplicate "Fetching" message from fetchRemote function - Prevents "Warning: Remote repository does not exist yet" for backup locations This ensures backup locations are truly opt-in and don't interfere with normal sync operations. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-12feat: add automatic release checking and creationPaul Buetow
- Add --check-releases flag for manual release checking - Enable automatic release checking after sync operations by default - Add --no-check-releases flag to disable automatic checking - Add --auto-create-releases flag for unattended release creation - Generate release notes from commit history - Support version tag formats: vX.Y.Z, vX.Y, vX, X.Y.Z, X.Y, X - Use tokens from gitsyncer config (with fallback to env vars and files) - Show release notes preview before creating releases - Group commits by type (features, fixes, other) in release notes
2025-07-08feat: add obsolete project notice for inactive projectsPaul Buetow
- Add warning notice for projects with avg commit age > 2 years AND last commit > 1 year - Display "⚠️ Notice: This project appears to be finished, obsolete, or no longer maintained" - Also update abandoned branch threshold from 1 to 3 years in branch analyzer - Helps users identify potentially outdated or unmaintained projects 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-07feat: add comprehensive showcase generation with metadata and imagesPaul Buetow
- Add --showcase flag to generate project showcases using Claude - Extract repository metadata (languages, commits, LOC, dates, license) - Support image extraction from README files (local and remote) - Add caching with --force flag to regenerate - Add exclude_from_showcase config option - Add standalone showcase mode (--showcase without sync) - Sort projects by recent activity (avg age of last 100 commits) - Output in Gemini Gemtext template format (.gmi.tpl) - Fix backup location fetching when --backup flag not set 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-03feat: add SSH backup locations with --backup flagv0.2.0Paul Buetow
- Add support for SSH backup locations (e.g., paul@server:git/) - Backup locations are one-way only (push only, never pull) - Automatic bare repository creation on SSH servers - Add --backup flag to opt-in to backup syncing - Backup locations are disabled by default for offline resilience - Update version to 0.2.0 This allows users to maintain private backups on home servers that may be offline without affecting regular sync operations. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-27fixPaul Buetow
2025-06-27feat: add detailed error message for tag conflictsPaul Buetow
2025-06-27feat: sync git tagsPaul Buetow
2025-06-24feat: add branch exclusion feature with regex patternsPaul Buetow
Users can now exclude branches from synchronization using regex patterns in the configuration file. This is useful for: - Excluding temporary or experimental branches - Skipping vendor or third-party branches - Ignoring deployment-specific branches Configuration example: ```json { "exclude_branches": [ "^codex/", // Exclude branches starting with "codex/" "^temp-", // Exclude branches starting with "temp-" "-wip$" // Exclude branches ending with "-wip" ] } ``` Features: - Regex pattern matching for flexible exclusion rules - Clear reporting of excluded branches during sync - Excluded branches are filtered from sync but still analyzed for abandonment - Invalid regex patterns are reported but don't stop sync The feature helps maintain cleaner synchronization by allowing users to ignore branches that shouldn't be synchronized across all repositories. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-24feat: add abandoned branch detection and reportingPaul Buetow
Automatically detects and reports abandoned branches during sync operations: - Branches are considered abandoned if they have no commits for 6+ months - Only reports on active repositories (main/master updated within last year) - Shows individual reports during sync of each repository - Displays comprehensive summary after sync-all operations - Provides helpful cleanup commands for removing old branches This helps maintain cleaner repositories by identifying stale branches that may no longer be needed. Example output: 🔍 Abandoned branches in dtail: Main branch last updated: 2025-04-17 Found 1 abandoned branches (no commits for 6+ months): - develop (last commit: 2023-10-05, No commits for 628 days) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-24fix: remove unused import in repository_setup.goPaul Buetow
Remove unused path/filepath import that was causing build errors. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-24refactor: break down large functions into smaller, focused onesPaul Buetow
Major refactoring to improve code maintainability: 1. Split main.go (481 lines → 72 lines) into internal/cli package: - flags.go: Command-line flag definitions and parsing - handlers.go: General command handlers (version, config, list operations) - sync_handlers.go: Sync-specific handlers for all sync operations 2. Refactored sync.go to extract logic into separate files: - git_operations.go: Git command helpers (merge, push, fetch, etc.) - repository_setup.go: Repository initialization and remote configuration - branch_sync.go: Branch synchronization helpers 3. Reduced function sizes to meet 30-line guideline: - syncBranch: 104 lines → 26 lines - SyncRepository: 97 lines → 44 lines - main(): 465 lines → 63 lines - getAllBranches: 32 lines → 9 lines All functionality remains the same, but the code is now more modular, testable, and easier to understand. Each function has a single, clear responsibility. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-23Add --full flag for bidirectional sync and update module namePaul Buetow
- Add --full flag that enables both --sync-codeberg-public and --sync-github-public - Also enables --create-github-repos and --create-codeberg-repos with --full - Update module name from github.com/paul/gitsyncer to codeberg.org/snonux/gitsyncer - Update all import statements to use new module name - Fix sync operations to work together when both are enabled - Add visual separator between sync operations in full mode - Update README with full sync documentation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-23Improve merge conflict error message with directory pathPaul Buetow
- Show full absolute path to the repository with conflicts - Provide clear instructions on how to resolve or delete the directory - Make error message more actionable for users 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-23Add debugging features and improve error handlingPaul Buetow
- Add --test-github-token flag to validate GitHub authentication - Improve error messages for 401 authentication failures - Add merge conflict detection before sync attempts - Stop sync on first error for easier debugging - Add GitHub repo creation support for --sync and --sync-all commands - Add detailed token loading debug output - Create test script for GitHub token validation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-23Add GitHub repository creation and improve error handlingPaul Buetow
- Add --create-github-repos flag to automatically create missing GitHub repositories - Implement GitHub API client with token support from config/env/file - Add Codeberg API integration to sync all public repositories - Make sync operations stop on first error for better debugging - Support GitHub repo creation for all sync commands (--sync, --sync-all, --sync-codeberg-public) - Add comprehensive error messages and debug logging 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-23Add support for multiple repository configuration and syncPaul Buetow
- Add optional 'repositories' array to configuration file - Add --list-repos flag to list configured repositories - Add --sync-all flag to sync all configured repositories at once - Show progress when syncing multiple repositories - Gracefully handle missing remote repositories with warnings - Improve error handling to continue syncing other repos on failure - Add comprehensive integration tests for all functionality - Add test for multiple repository sync feature Example usage: gitsyncer --sync-all # Sync all configured repos gitsyncer --list-repos # List configured repos gitsyncer --sync repo-name # Sync specific repo (still works) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-23Add repository synchronization functionalityPaul Buetow
- Create sync package to handle git repository synchronization - Implement multi-organization sync with branch tracking - Add merge conflict detection and error handling - Support cloning, fetching, merging, and pushing across all remotes - Add --sync flag to synchronize repositories - Add --work-dir flag for working directory specification - Create test infrastructure with setup and conflict test scripts - Update config validation to support file:// URLs - Add comprehensive .gitignore entries for test artifacts The sync package automatically: - Clones repositories if not present - Fetches updates from all configured organizations - Merges changes from all remotes for each branch - Pushes synchronized changes to all organizations - Detects and reports merge conflicts for manual resolution Test with: ./test/setup_test_repos.sh && ./gitsyncer --config test/test-config.json --sync test-repo 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>