detect-pr-changes.ts 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. #!/usr/bin/env bun
  2. import { appendFile } from 'node:fs/promises'
  3. export type ChangeFlags = {
  4. 'has-evals': boolean
  5. 'has-docs': boolean
  6. 'has-workflows': boolean
  7. 'has-packages': boolean
  8. }
  9. export function parseChangedPaths(input: string): string[] {
  10. return input.split('\0').filter((path) => path.length > 0)
  11. }
  12. export function classifyChangedPaths(paths: readonly string[]): ChangeFlags {
  13. const hasWorkspaceChange = paths.some((path) =>
  14. ['package.json', 'pnpm-lock.yaml', 'pnpm-workspace.yaml'].includes(path),
  15. )
  16. return {
  17. 'has-evals': hasWorkspaceChange || paths.some((path) => path.startsWith('evals/')),
  18. 'has-docs': paths.some((path) => path.startsWith('docs/')),
  19. 'has-workflows': paths.some((path) => path.startsWith('.github/workflows/')),
  20. 'has-packages': hasWorkspaceChange || paths.some((path) =>
  21. path.startsWith('packages/') ||
  22. path === '.github/dependabot.yml' ||
  23. path === '.github/workflows/packages-checks.yml' ||
  24. path === 'scripts/validation/detect-pr-changes.ts' ||
  25. path === 'scripts/validation/detect-pr-changes.test.ts',
  26. ),
  27. }
  28. }
  29. export function formatGitHubOutput(flags: ChangeFlags): string {
  30. return [
  31. `has-evals=${flags['has-evals']}`,
  32. `has-docs=${flags['has-docs']}`,
  33. `has-workflows=${flags['has-workflows']}`,
  34. `has-packages=${flags['has-packages']}`,
  35. ].join('\n') + '\n'
  36. }
  37. async function main(): Promise<void> {
  38. const outputPath = process.env.GITHUB_OUTPUT
  39. if (!outputPath) throw new Error('GITHUB_OUTPUT is required but was not set')
  40. const paths = parseChangedPaths(await Bun.stdin.text())
  41. const output = formatGitHubOutput(classifyChangedPaths(paths))
  42. await appendFile(outputPath, output, 'utf8').catch((error: unknown) => {
  43. const message = error instanceof Error ? error.message : String(error)
  44. throw new Error(`Unable to append change detection outputs to GITHUB_OUTPUT (${outputPath}): ${message}`)
  45. })
  46. }
  47. if (import.meta.main) {
  48. await main().catch((error: unknown) => {
  49. const message = error instanceof Error ? error.message : String(error)
  50. console.error(`detect-pr-changes: ${message}`)
  51. process.exitCode = 1
  52. })
  53. }