publish.ts 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #!/usr/bin/env bun
  2. import { Script } from "@opencode-ai/script"
  3. import { $ } from "bun"
  4. import { Effect } from "effect"
  5. import { fileURLToPath } from "url"
  6. console.log("=== publishing ===\n")
  7. const tag = `v${Script.version}`
  8. const pkgjsons = await Array.fromAsync(
  9. new Bun.Glob("**/package.json").scan({
  10. absolute: true,
  11. }),
  12. ).then((arr) => arr.filter((x) => !x.includes("node_modules") && !x.includes("dist")))
  13. const extensionToml = fileURLToPath(new URL("../packages/extensions/zed/extension.toml", import.meta.url))
  14. const readText = (path: string) => Effect.promise(() => Bun.file(path).text())
  15. const writeText = (path: string, value: string) => Effect.promise(() => Bun.write(path, value))
  16. const shell = <A>(run: () => Promise<A>) => Effect.promise(run)
  17. const log = (message: string) => Effect.sync(() => console.log(message))
  18. const hasChanges = shell(() => $`git diff --quiet && git diff --cached --quiet`.nothrow()).pipe(
  19. Effect.map((result) => result.exitCode !== 0),
  20. )
  21. const releaseTagExists = shell(() => $`git rev-parse -q --verify refs/tags/${tag}`.nothrow()).pipe(
  22. Effect.map((result) => result.exitCode === 0),
  23. )
  24. const prepareReleaseFiles = Effect.gen(function* () {
  25. yield* Effect.forEach(pkgjsons, (file) =>
  26. Effect.gen(function* () {
  27. const next = (yield* readText(file)).replaceAll(/"version": "[^"]+"/g, `"version": "${Script.version}"`)
  28. yield* log(`updated: ${file}`)
  29. yield* writeText(file, next)
  30. }),
  31. )
  32. const nextToml = (yield* readText(extensionToml))
  33. .replace(/^version = "[^"]+"/m, `version = "${Script.version}"`)
  34. .replaceAll(/releases\/download\/v[^/]+\//g, `releases/download/v${Script.version}/`)
  35. yield* log(`updated: ${extensionToml}`)
  36. yield* writeText(extensionToml, nextToml)
  37. yield* shell(() => $`bun install`)
  38. yield* shell(() => $`./packages/sdk/js/script/build.ts`)
  39. })
  40. const program = Effect.gen(function* () {
  41. if (Script.release && !Script.preview) {
  42. yield* shell(() => $`git fetch origin --tags`)
  43. yield* shell(() => $`git switch --detach`)
  44. }
  45. yield* prepareReleaseFiles
  46. if (Script.release && !Script.preview) {
  47. if (yield* releaseTagExists) yield* log(`release tag ${tag} already exists, skipping tag creation`)
  48. else {
  49. yield* shell(() => $`git commit -am "release: ${tag}"`)
  50. yield* shell(() => $`git tag ${tag}`)
  51. yield* shell(() => $`git push origin refs/tags/${tag} --no-verify`)
  52. yield* shell(() => new Promise((resolve) => setTimeout(resolve, 5_000)))
  53. }
  54. }
  55. yield* log("\n=== cli ===\n")
  56. yield* shell(() => import(`../packages/opencode/script/publish.ts`))
  57. yield* log("\n=== sdk ===\n")
  58. yield* shell(() => import(`../packages/sdk/js/script/publish.ts`))
  59. yield* log("\n=== plugin ===\n")
  60. yield* shell(() => import(`../packages/plugin/script/publish.ts`))
  61. if (Script.release) {
  62. yield* shell(() => import(`../packages/desktop/scripts/finalize-latest-json.ts`))
  63. yield* shell(() => import(`../packages/desktop-electron/scripts/finalize-latest-yml.ts`))
  64. }
  65. if (Script.release && !Script.preview) {
  66. yield* shell(() => $`git fetch origin`)
  67. yield* shell(() => $`git checkout -B dev origin/dev`)
  68. yield* prepareReleaseFiles
  69. if (yield* hasChanges) {
  70. yield* shell(() => $`git commit -am "sync release versions for v${Script.version}"`)
  71. yield* shell(() => $`git push origin HEAD:dev --no-verify`)
  72. } else yield* log(`dev already synced for ${tag}`)
  73. }
  74. if (Script.release) yield* shell(() => $`gh release edit ${tag} --draft=false --repo ${process.env.GH_REPO}`)
  75. })
  76. await Effect.runPromise(program)
  77. const dir = fileURLToPath(new URL("..", import.meta.url))
  78. process.chdir(dir)