changelog-debug.ts 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #!/usr/bin/env bun
  2. import { $ } from "bun"
  3. import { parseArgs } from "util"
  4. import { getLatestRelease } from "./changelog"
  5. const paths = [
  6. "packages/opencode",
  7. "packages/sdk",
  8. "packages/plugin",
  9. "packages/desktop",
  10. "packages/app",
  11. "sdks/vscode",
  12. "packages/extensions",
  13. "github",
  14. ]
  15. const clean = (text: string) => text.split("\n").filter(Boolean)
  16. const ref = (value: string, head = false) => {
  17. if (head && value === "HEAD") return value
  18. if (value.startsWith("v")) return value
  19. return `v${value}`
  20. }
  21. const { values } = parseArgs({
  22. args: Bun.argv.slice(2),
  23. options: {
  24. from: { type: "string", short: "f" },
  25. to: { type: "string", short: "t", default: "HEAD" },
  26. base: { type: "string", short: "b", default: "origin/dev" },
  27. help: { type: "boolean", short: "h", default: false },
  28. },
  29. })
  30. if (values.help) {
  31. console.log(`
  32. Usage: bun script/changelog-debug.ts [options]
  33. Options:
  34. -f, --from <version> Starting version (default: latest GitHub release)
  35. -t, --to <ref> Ending ref (default: HEAD)
  36. -b, --base <ref> Compare base for ahead/behind (default: origin/dev)
  37. -h, --help Show this help message
  38. Examples:
  39. bun script/changelog-debug.ts
  40. bun script/changelog-debug.ts -f 1.0.200 -t dev
  41. bun script/changelog-debug.ts -f 1.0.200 -t HEAD -b origin/dev
  42. `)
  43. process.exit(0)
  44. }
  45. const to = values.to!
  46. const from = values.from ?? (await getLatestRelease())
  47. const fromRef = ref(from)
  48. const toRef = ref(to, true)
  49. console.log(`Debugging changelog range: ${fromRef} -> ${toRef}\n`)
  50. const [ahead, behind] = await $`git rev-list --left-right --count ${values.base}...HEAD`
  51. .text()
  52. .then((text) => text.trim().split("\t"))
  53. console.log(`Ahead/behind ${values.base}: ahead=${ahead ?? "0"} behind=${behind ?? "0"}`)
  54. const gh = await $`gh api "/repos/anomalyco/opencode/compare/${fromRef}...${toRef}" --jq '.commits[].sha'`
  55. .text()
  56. .then(clean)
  57. const localAll = await $`git log ${fromRef}..${toRef} --oneline --format="%H"`.text().then(clean)
  58. const localFiltered = await $`git log ${fromRef}..${toRef} --oneline --format="%H" -- ${paths}`.text().then(clean)
  59. const ghSet = new Set(gh)
  60. const missing = localFiltered.filter((hash) => !ghSet.has(hash))
  61. console.log(`GitHub compare commits: ${gh.length}`)
  62. console.log(`Local commits (all): ${localAll.length}`)
  63. console.log(`Local commits (filtered paths): ${localFiltered.length}`)
  64. console.log(`Filtered commits missing from GitHub compare: ${missing.length}`)
  65. if (missing.length > 0) {
  66. console.log("\nMissing hashes (first 10):")
  67. console.log(missing.slice(0, 10).join("\n"))
  68. }