git-stage-safe.ps1 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. param(
  2. [ValidateSet('ip', 'storage', 'billing', 'governance', 'all')]
  3. [string]$Group = 'all',
  4. [switch]$Apply
  5. )
  6. $ErrorActionPreference = 'Stop'
  7. function Write-Section([string]$Title) {
  8. Write-Host ""
  9. Write-Host "==== $Title ====" -ForegroundColor Cyan
  10. }
  11. function Invoke-GitAdd([string]$Name, [string[]]$Paths) {
  12. Write-Section "stage group: $Name"
  13. if (-not $Paths -or $Paths.Count -eq 0) {
  14. Write-Host "No paths configured. Skip."
  15. return
  16. }
  17. if (-not $Apply) {
  18. Write-Host "Dry run only. These paths would be staged:"
  19. $Paths | ForEach-Object { Write-Host " $_" }
  20. return
  21. }
  22. git add -- @Paths
  23. if ($LASTEXITCODE -ne 0) {
  24. throw "git add failed: $Name"
  25. }
  26. }
  27. function Test-ForbiddenStagedFiles {
  28. $forbiddenPatterns = @(
  29. '^docs/',
  30. '^data/',
  31. '^tmp/',
  32. '^test-results/',
  33. '^playwright-report/',
  34. '^blob-report/',
  35. '^coverage/',
  36. '^cloud-functions/deployable/',
  37. '^\.env($|\.)',
  38. '^deploy\.ps1$',
  39. '^src/video/',
  40. '\.xlsx$',
  41. '\.xls$'
  42. )
  43. $staged = git diff --cached --name-only
  44. $bad = @()
  45. foreach ($file in $staged) {
  46. foreach ($pattern in $forbiddenPatterns) {
  47. if ($file -match $pattern) {
  48. $bad += $file
  49. break
  50. }
  51. }
  52. }
  53. if ($bad.Count -gt 0) {
  54. Write-Section "forbidden staged files"
  55. $bad | Sort-Object -Unique | ForEach-Object { Write-Host " $_" -ForegroundColor Red }
  56. Write-Host ""
  57. Write-Host "Abort. Run: git restore --staged <path>" -ForegroundColor Yellow
  58. exit 1
  59. }
  60. }
  61. function Show-CredentialReminder {
  62. Write-Section "credential reminder"
  63. Write-Host "Before commit, manually verify there are no real tokens/API keys in:"
  64. Write-Host " cloud-functions/06-voiceManager.js"
  65. Write-Host " cloud-functions/11-jimengManager.js"
  66. Write-Host " cloud-functions/13-douyinInsightManager.js"
  67. Write-Host " cloud-functions/08-proxyHub.js"
  68. Write-Host " cloud-functions/12-douyinManager.js"
  69. }
  70. $groups = @{
  71. ip = @(
  72. 'src/app/pages/ip-operator',
  73. 'src/app/models/ip-operator.model.ts',
  74. 'src/app/services/ip-account-*',
  75. 'src/app/services/ip-operator-*',
  76. 'src/app/services/ip-content-production-flow*',
  77. 'src/app/services/ip-publish-*',
  78. 'src/app/services/ip-script-*',
  79. 'src/app/services/ip-topic-script-generator*',
  80. 'src/app/services/reference-video-prompt-planner*',
  81. 'src/app/services/retrospective.service*',
  82. 'src/app/services/viral-analysis.service*',
  83. 'e2e/ip-operator-*',
  84. 'src/app/app.ts',
  85. 'src/app/app.html',
  86. 'src/app/app.spec.ts',
  87. 'src/app/components/app-sidebar/app-sidebar.component.ts',
  88. 'src/app/models/app-tab.model.ts'
  89. )
  90. storage = @(
  91. 'cloud-functions/_session.js',
  92. 'cloud-functions/_session.spec.js',
  93. 'cloud-functions/_parseClassStore.js',
  94. 'cloud-functions/13-douyinInsightManager.js',
  95. 'cloud-functions/13-douyinInsightManager.spec.js',
  96. 'cloud-functions/14-systemStorageManager.js',
  97. 'cloud-functions/15-fileAssetManager.js',
  98. 'cloud-functions/09-uploadManager.js',
  99. 'scripts/build-cloud-functions.mjs',
  100. 'scripts/smoke-cloud-functions.mjs',
  101. 'scripts/validation/cloud-functions-readiness.mjs',
  102. 'scripts/validation/parse-storage-postdeploy.mjs',
  103. 'scripts/validation/storage-governance-postdeploy.mjs',
  104. 'scripts/validation/storage-sensitive-policy.mjs',
  105. 'src/app/services/cloud-session-storage*',
  106. 'src/app/services/file-asset*',
  107. 'src/app/services/storage-governance*',
  108. 'src/app/services/system-storage-migration*',
  109. 'src/app/services/douyin-insight*',
  110. 'src/app/services/douyin-api*'
  111. )
  112. billing = @(
  113. 'cloud-functions/10-authCreditManager.js',
  114. 'cloud-functions/11-jimengManager.js',
  115. 'cloud-functions/auth-credit-deploy.md',
  116. 'src/app/services/auth-credit*',
  117. 'src/app/services/jimeng*',
  118. 'src/app/services/cost-estimator*',
  119. 'src/app/pages/account/user-center.component*',
  120. 'src/app/pages/pipelines/image-to-video',
  121. 'src/app/pages/pipelines/image-generation/image-generation.component.ts',
  122. 'src/app/pages/pipelines/action-transfer/action-transfer.component.ts',
  123. 'src/app/pages/pipelines/asset-remix/asset-remix.component.ts',
  124. 'src/app/pages/pipelines/topic-to-video/topic-to-video.component.ts'
  125. )
  126. governance = @(
  127. 'AGENTS.md',
  128. '.githooks/pre-commit',
  129. '.gitignore',
  130. 'README.md',
  131. 'package.json',
  132. 'angular.json',
  133. 'cloud-functions/DEPLOY.md',
  134. 'scripts/git-stage-safe.ps1',
  135. 'scripts/validation/ip-operator-cleanup-dry-run.mjs',
  136. 'scripts/validation/ip-operator-cleanup-soft-delete.mjs',
  137. 'scripts/validation/ip-operator-cleanup-physical-delete.mjs',
  138. 'scripts/validation/videoworkflow-parse-cleanup.mjs',
  139. 'scripts/validation/ip-operator-scenario-seed.js',
  140. 'scripts/validation/jimeng-billing-policy.mjs'
  141. )
  142. }
  143. Write-Section "current git status"
  144. git status --short
  145. if ($Group -eq 'all') {
  146. Invoke-GitAdd 'ip' $groups.ip
  147. Invoke-GitAdd 'storage' $groups.storage
  148. Invoke-GitAdd 'billing' $groups.billing
  149. Invoke-GitAdd 'governance' $groups.governance
  150. } else {
  151. Invoke-GitAdd $Group $groups[$Group]
  152. }
  153. if ($Apply) {
  154. Test-ForbiddenStagedFiles
  155. Write-Section "staged files"
  156. git diff --cached --name-status
  157. } else {
  158. Write-Section "usage"
  159. Write-Host "Dry run group: powershell -ExecutionPolicy Bypass -File scripts/git-stage-safe.ps1 -Group ip"
  160. Write-Host "Stage group: powershell -ExecutionPolicy Bypass -File scripts/git-stage-safe.ps1 -Group ip -Apply"
  161. Write-Host "Stage all: powershell -ExecutionPolicy Bypass -File scripts/git-stage-safe.ps1 -Group all -Apply"
  162. }
  163. Show-CredentialReminder