Commit e49a1b5
fix(scripts): eliminate phantom git changes from plugin generation (#1035)
## Description
Eliminated phantom git changes that `npm run plugin:generate` left in
the working tree after every run. The root cause was a
delete-and-recreate strategy that touched file timestamps and re-wrote
identical content, combined with a `--index-info` stdin call that broke
on Windows due to CRLF encoding.
### Plugin Generation — Conditional Writes
Introduced `Set-ContentIfChanged` in *CollectionHelpers.psm1* as the
single write choke point for all generated files. The function performs
an ordinal comparison of proposed content against the existing file and
skips the write when identical. Converted all five production write
sites in *PluginHelpers.psm1* — `Write-MarketplaceManifest`,
`New-PluginLink` fallback, *plugin.json*, *README.md*, and collection
YAML — to route through `Set-ContentIfChanged`.
Added a **GeneratedFiles** `HashSet` to `Write-PluginDirectory` that
tracks every output path and returns it in the result object, enabling
downstream orphan detection.
Rewrote `Repair-PluginSymlinkIndex` to parse `git ls-files --stage`
output, detect mode-120000 entries, skip already-correct symlinks, and
use per-entry `--cacheinfo` calls instead of piped `--index-info`. The
piped approach broke on Windows because PowerShell injected CRLF into
stdin, corrupting the index update.
### Plugin Generation — Orphan Cleanup
Replaced the delete-and-recreate Refresh strategy in
*Generate-Plugins.ps1* with orphan cleanup. After overwrite-in-place
generation completes, files not present in the `GeneratedFiles` set are
removed, followed by a bottom-up empty-directory sweep. All
`Remove-Item` calls gained `-ErrorAction Stop` for fail-fast behavior.
### Post-Processing Scope
Extracted post-processing into a `plugin:postprocess` script in
*package.json*, scoping *markdownlint-cli2* and
*markdown-table-formatter* to `plugins/**/*.md` and `collections/*.md`
only. This prevented post-processing from modifying unrelated files in
the working tree.
### Windows Test Compatibility
Separately fixed 14 pre-existing test failures in
*Invoke-PptxPipeline.Tests.ps1*. The tests created shell-script `.exe`
python stubs that are not valid PE executables on Windows. Replaced with
`.cmd` batch files that execute natively and correctly set
`$LASTEXITCODE`.
### Test Coverage
- Added a **Set-ContentIfChanged** test suite in
*CollectionHelpers.Tests.ps1* covering creation, skip-on-identical,
overwrite-on-diff, case-sensitivity, empty string, and UTF-8-without-BOM
behavior.
- Added 4 **Orphan Cleanup** tests in *Generate-Plugins.Tests.ps1*
validating orphan removal, generated file preservation, empty directory
pruning, and DryRun logging.
- Added 5 **Repair-PluginSymlinkIndex** tests in
*PluginHelpers.Tests.ps1* using a real git repo fixture — covers DryRun
counting, DryRun index immutability, mode-120000 re-indexing, and
skip-if-already-fixed logic.
## Related Issue(s)
Closes #1029
## Type of Change
Select all that apply:
**Code & Documentation:**
* [x] Bug fix (non-breaking change fixing an issue)
* [ ] New feature (non-breaking change adding functionality)
* [ ] Breaking change (fix or feature causing existing functionality to
change)
* [ ] Documentation update
**Infrastructure & Configuration:**
* [ ] GitHub Actions workflow
* [ ] Linting configuration (markdown, PowerShell, etc.)
* [ ] Security configuration
* [ ] DevContainer configuration
* [ ] Dependency update
**AI Artifacts:**
* [ ] Reviewed contribution with `prompt-builder` agent and addressed
all feedback
* [ ] Copilot instructions (`.github/instructions/*.instructions.md`)
* [ ] Copilot prompt (`.github/prompts/*.prompt.md`)
* [ ] Copilot agent (`.github/agents/*.agent.md`)
* [ ] Copilot skill (`.github/skills/*/SKILL.md`)
**Other:**
* [x] Script/automation (`.ps1`, `.sh`, `.py`)
* [ ] Other (please describe):
## Testing
Full test suite validated after both commits:
- **1707 passed**, 0 failed, 1 skipped
- PSScriptAnalyzer clean on all modified PowerShell files
- New tests cover `Set-ContentIfChanged`, orphan cleanup, and
`Repair-PluginSymlinkIndex` comprehensively
## Checklist
### Required Checks
* [ ] Documentation is updated (if applicable)
* [x] Files follow existing naming conventions
* [x] Changes are backwards compatible (if applicable)
* [x] Tests added for new functionality (if applicable)
### AI Artifact Contributions
<!-- Not applicable — no AI artifacts modified -->
### Required Automated Checks
The following validation commands must pass before merging:
* [x] Markdown linting: `npm run lint:md`
* [x] Spell checking: `npm run spell-check`
* [x] Frontmatter validation: `npm run lint:frontmatter`
* [x] Skill structure validation: `npm run validate:skills`
* [x] Link validation: `npm run lint:md-links` (pre-existing failures
only — no new broken links introduced)
* [x] PowerShell analysis: `npm run lint:ps`
* [x] Plugin freshness: `npm run plugin:generate`
## Security Considerations
* [x] This PR does not contain any sensitive or NDA information
* [x] Any new dependencies have been reviewed for security issues
* [x] Security-related scripts follow the principle of least privilege
## Additional Notes
- Two test files (*CollectionHelpers.Tests.ps1*,
*PluginHelpers.Tests.ps1*) gained UTF-8 BOM byte prefix — incidental
encoding change from editor saves on Windows, no functional impact.
- No new dependencies introduced. All changes are internal to existing
PowerShell modules and npm scripts.
---------
Co-authored-by: Bill Berry <wbery@microsoft.com>1 parent 52b0885 commit e49a1b5
File tree
7 files changed
+365
-52
lines changed- scripts
- collections/Modules
- plugins
- Modules
- tests
- collections
- plugins
7 files changed
+365
-52
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | | - | |
| 33 | + | |
| 34 | + | |
34 | 35 | | |
35 | 36 | | |
36 | 37 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
12 | 56 | | |
13 | 57 | | |
14 | 58 | | |
| |||
538 | 582 | | |
539 | 583 | | |
540 | 584 | | |
541 | | - | |
| 585 | + | |
542 | 586 | | |
543 | 587 | | |
544 | 588 | | |
| |||
557 | 601 | | |
558 | 602 | | |
559 | 603 | | |
| 604 | + | |
560 | 605 | | |
561 | 606 | | |
562 | 607 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
255 | 255 | | |
256 | 256 | | |
257 | 257 | | |
258 | | - | |
259 | | - | |
260 | | - | |
261 | | - | |
262 | | - | |
263 | | - | |
264 | | - | |
265 | | - | |
266 | | - | |
267 | | - | |
268 | | - | |
269 | | - | |
| 258 | + | |
270 | 259 | | |
271 | 260 | | |
272 | 261 | | |
| |||
277 | 266 | | |
278 | 267 | | |
279 | 268 | | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
280 | 310 | | |
281 | 311 | | |
282 | 312 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
399 | 399 | | |
400 | 400 | | |
401 | 401 | | |
402 | | - | |
| 402 | + | |
| 403 | + | |
403 | 404 | | |
404 | 405 | | |
405 | 406 | | |
| |||
525 | 526 | | |
526 | 527 | | |
527 | 528 | | |
528 | | - | |
| 529 | + | |
529 | 530 | | |
530 | 531 | | |
531 | 532 | | |
| |||
604 | 605 | | |
605 | 606 | | |
606 | 607 | | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
607 | 611 | | |
608 | 612 | | |
609 | 613 | | |
| |||
657 | 661 | | |
658 | 662 | | |
659 | 663 | | |
| 664 | + | |
| 665 | + | |
660 | 666 | | |
661 | 667 | | |
662 | 668 | | |
| |||
680 | 686 | | |
681 | 687 | | |
682 | 688 | | |
| 689 | + | |
| 690 | + | |
683 | 691 | | |
684 | 692 | | |
685 | 693 | | |
| |||
692 | 700 | | |
693 | 701 | | |
694 | 702 | | |
| 703 | + | |
695 | 704 | | |
696 | 705 | | |
697 | 706 | | |
| |||
700 | 709 | | |
701 | 710 | | |
702 | 711 | | |
703 | | - | |
| 712 | + | |
| 713 | + | |
704 | 714 | | |
705 | 715 | | |
706 | 716 | | |
| |||
710 | 720 | | |
711 | 721 | | |
712 | 722 | | |
| 723 | + | |
713 | 724 | | |
714 | 725 | | |
715 | 726 | | |
716 | 727 | | |
717 | 728 | | |
718 | | - | |
| 729 | + | |
719 | 730 | | |
720 | 731 | | |
721 | 732 | | |
| |||
724 | 735 | | |
725 | 736 | | |
726 | 737 | | |
| 738 | + | |
727 | 739 | | |
728 | 740 | | |
729 | 741 | | |
| |||
776 | 788 | | |
777 | 789 | | |
778 | 790 | | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
779 | 794 | | |
780 | | - | |
| 795 | + | |
781 | 796 | | |
782 | | - | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
783 | 805 | | |
784 | 806 | | |
785 | 807 | | |
786 | | - | |
787 | | - | |
788 | 808 | | |
789 | 809 | | |
790 | 810 | | |
| |||
805 | 825 | | |
806 | 826 | | |
807 | 827 | | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
808 | 832 | | |
809 | 833 | | |
810 | 834 | | |
| |||
824 | 848 | | |
825 | 849 | | |
826 | 850 | | |
827 | | - | |
828 | | - | |
829 | | - | |
830 | | - | |
831 | | - | |
832 | | - | |
833 | | - | |
834 | | - | |
835 | | - | |
836 | | - | |
837 | | - | |
838 | | - | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
839 | 856 | | |
840 | 857 | | |
841 | | - | |
842 | | - | |
843 | | - | |
844 | | - | |
845 | | - | |
846 | | - | |
847 | | - | |
848 | | - | |
849 | | - | |
850 | | - | |
851 | | - | |
852 | | - | |
| 858 | + | |
| 859 | + | |
853 | 860 | | |
| 861 | + | |
| 862 | + | |
854 | 863 | | |
855 | 864 | | |
856 | 865 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| |||
562 | 562 | | |
563 | 563 | | |
564 | 564 | | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
0 commit comments