Repository navigation
fix: rename repos through their config file and never rename them back - #1136
TovaBecker wants to merge 1 commit into
Conversation
Renaming repos/old.yml to repos/new.yml did not rename the repo (github-community-projects#843), and a removed or replayed config file followed GitHub's rename redirect and renamed the repo back (github-community-projects#1123). Renaming from the file keeps the config the source of truth, and the PR dry run now shows the rename, its errors, and every other change in the file before merge.
16b46f9 to
ffd6b31
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved issues can apply settings to unrelated or renamed repositories, rename repositories back using stale identities, and bypass disabled repository management.
4 open issues
What changed in this PR
This PR adds config-file-driven repository renames and guards against stale names undoing renames during synchronization, addressing #843 and #1123.
Changes:
- Detects renames from push comparisons and paginated PR file lists.
- Adds rename validation, dry-run previews, and redirect checks before synchronization.
- Adds regression coverage and documents GitHub’s file-similarity-based rename detection.
| File | Description |
|---|---|
test/unit/lib/settings.test.js |
Tests app-installation deltas against the previous config path. |
test/unit/lib/settings-rename.test.js |
Covers renames, rejected operations, previews, and stale redirects. |
test/unit/index-rename.test.js |
Tests push comparisons, rename detection, and PR pagination. |
test/integration/plugins/repository.test.js |
Aligns repository mocks with live-name checks. |
test/integration/plugins/milestones.test.js |
Aligns milestone test mocks with live-name checks. |
README.md |
Explains rename-detection limitations and dry-run verification. |
lib/settings.js |
Coordinates renames, config mapping, and redirect protection. |
index.js |
Uses push comparisons and paginated PR files to identify changes. |
Review effort: Balanced
| const changedRepos = await settings.renameReposFromConfigFiles(changedFiles.repos) | ||
| await settings.loadConfigs() | ||
| for (const { repo, configName } of changedRepos) await settings.useConfigOfRenamedFile(repo, configName) |
| shouldUnarchive = state.shouldUnarchive | ||
| } | ||
|
|
||
| if (this.isRenamedAway(repo, repoConfig, archivePlugin.repository)) { |
| if (this.isRenamedAway(repo, null, archivePlugin.repository)) { | ||
| return | ||
| } | ||
| } |
| const params = { owner: repo.owner, repo: renamedFrom, name: repo.repo } | ||
| if (this.nop) { |
|
One case still renames the repo back with this PR: a full sync with #1142 is a smaller fix for #1123 only. It runs the same check inside the repository plugin, right after its own |


Why
repos/old.ymltorepos/new.ymldoesn't rename the repo (Can not rename repo #843).Approach
compareCommitsWithBasehead). A renamed repo file renames the repo once, before anything else syncs. If the diff can't be read, the push is skipped with an error.repository.name, or one of the names is restricted. A rename never creates a repo.repository.namechange with before and after values, together with every other change in the renamed file. It reads all PR files, not only the first 30. A taken name links to the repo that has it.Validation
standardfindings.BLOCK_REPO_RENAME_BY_HUMAN, a rename with other changes in the file, and the three error cases.Closes #843
Closes #1123
🤖 Generated with Claude Code