insert_feature_flag_alpha_phase_0.mjs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import { scriptRunner } from './lib/ScriptRunner.mjs'
  2. import { db } from '../app/src/infrastructure/mongodb.mjs'
  3. import minimist from 'minimist'
  4. const argv = minimist(process.argv.slice(2))
  5. const commit = argv.commit !== undefined
  6. const splitTestName = argv._[0]
  7. if (!splitTestName) {
  8. console.error(
  9. 'Usage: node scripts/insert_feature_flag_alpha_phase_0.mjs <split-test-name> [--commit]'
  10. )
  11. console.error(
  12. '\nInserts a new version 1 (alpha phase, 0% rollout, active) and renumbers existing versions.'
  13. )
  14. console.error('Without --commit, runs in dry-run mode and shows a diff.')
  15. process.exit(1)
  16. }
  17. if (!commit) {
  18. console.log('DOING DRY RUN. TO SAVE CHANGES PASS --commit')
  19. }
  20. const RED = '\x1b[31m'
  21. const GREEN = '\x1b[32m'
  22. const RESET = '\x1b[0m'
  23. function formatDiff(before, after) {
  24. const aLines = before.split('\n')
  25. const bLines = after.split('\n')
  26. const m = aLines.length
  27. const n = bLines.length
  28. const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0))
  29. for (let i = 1; i <= m; i++) {
  30. for (let j = 1; j <= n; j++) {
  31. if (aLines[i - 1] === bLines[j - 1]) {
  32. dp[i][j] = dp[i - 1][j - 1] + 1
  33. } else {
  34. dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1])
  35. }
  36. }
  37. }
  38. const result = []
  39. let i = m
  40. let j = n
  41. while (i > 0 || j > 0) {
  42. if (i > 0 && j > 0 && aLines[i - 1] === bLines[j - 1]) {
  43. result.unshift(` ${aLines[i - 1]}`)
  44. i--
  45. j--
  46. } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
  47. result.unshift(`${GREEN}+ ${bLines[j - 1]}${RESET}`)
  48. j--
  49. } else {
  50. result.unshift(`${RED}- ${aLines[i - 1]}${RESET}`)
  51. i--
  52. }
  53. }
  54. return result.join('\n')
  55. }
  56. async function main() {
  57. const splitTest = await db.splittests.findOne({ name: splitTestName })
  58. if (!splitTest) {
  59. throw new Error(`Split test '${splitTestName}' not found`)
  60. }
  61. if (!splitTest.versions || splitTest.versions.length === 0) {
  62. throw new Error(`Split test '${splitTestName}' has no versions`)
  63. }
  64. const firstVersion = splitTest.versions[0]
  65. const newVersion = {
  66. ...firstVersion,
  67. versionNumber: 1,
  68. phase: 'alpha',
  69. active: true,
  70. variants: firstVersion.variants.map(v => ({
  71. ...v,
  72. rolloutPercent: 0,
  73. rolloutStripes: [],
  74. })),
  75. createdAt: new Date(firstVersion.createdAt.getTime() - 1000),
  76. comment: `Inserted alpha phase 0% rollout version (based on v${firstVersion.versionNumber})`,
  77. }
  78. const updatedVersions = [
  79. newVersion,
  80. ...splitTest.versions.map(v => ({
  81. ...v,
  82. versionNumber: v.versionNumber + 1,
  83. })),
  84. ]
  85. const beforeStr = JSON.stringify(splitTest.versions, null, 2)
  86. const afterStr = JSON.stringify(updatedVersions, null, 2)
  87. console.log(`\nSplit test: ${splitTestName}`)
  88. console.log(`Current versions: ${splitTest.versions.length}`)
  89. console.log(`After: ${updatedVersions.length} versions`)
  90. console.log('\n--- versions diff ---')
  91. console.log(formatDiff(beforeStr, afterStr))
  92. console.log('--- end diff ---\n')
  93. if (commit) {
  94. await db.splittests.updateOne(
  95. { name: splitTestName },
  96. { $set: { versions: updatedVersions } }
  97. )
  98. console.log(
  99. `Successfully inserted alpha phase 0% version for '${splitTestName}'`
  100. )
  101. } else {
  102. console.log('Dry run complete. Pass --commit to apply changes.')
  103. }
  104. }
  105. try {
  106. await scriptRunner(main)
  107. process.exit(0)
  108. } catch (error) {
  109. console.error(error)
  110. process.exit(1)
  111. }