rust.mts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #!/usr/bin/env zx
  2. // Script for working with Rust projects.
  3. import 'zx/globals';
  4. import {
  5. getCargo,
  6. getToolchainArgument,
  7. parseCliArguments,
  8. partitionArguments,
  9. popArgument,
  10. workingDirectory,
  11. } from './helpers/utils.mts';
  12. enum Command {
  13. BuildSbf = 'build-sbf',
  14. Format = 'format',
  15. LintClippy = 'lint-clippy',
  16. LintDocs = 'lint-docs',
  17. LintFeatures = 'lint-features',
  18. Lint = 'lint',
  19. Test = 'test',
  20. Wasm = 'wasm',
  21. Publish = 'publish',
  22. }
  23. const { command, libraryPath, args } = parseCliArguments();
  24. const manifestPath = path.join(libraryPath, 'Cargo.toml');
  25. async function cargo(
  26. toolchain: string,
  27. command: string | string[],
  28. defaultArgs?: string[],
  29. variables?: [string, string][],
  30. ) {
  31. const [cargoArgs, commandArgs] = partitionArguments(args, '--', defaultArgs);
  32. variables?.forEach(([k, v]) => $.env[k] = v);
  33. await $`cargo ${toolchain} ${command} --manifest-path ${manifestPath} ${cargoArgs} -- ${commandArgs}`;
  34. }
  35. async function buildSbf() {
  36. return cargo(
  37. 'build-sbf',
  38. ['--features', 'bpf-entrypoint'],
  39. );
  40. }
  41. async function format() {
  42. return cargo(
  43. getToolchainArgument('format'),
  44. 'fmt',
  45. popArgument(args, '--fix') ? [] : ['--', '--check'],
  46. );
  47. }
  48. async function lintClippy() {
  49. return cargo(
  50. getToolchainArgument('lint'),
  51. 'clippy',
  52. popArgument(args, '--fix') ? ['--fix'] : [],
  53. );
  54. }
  55. async function lintDocs() {
  56. return cargo(
  57. getToolchainArgument('lint'),
  58. 'doc',
  59. ['--all-features', '--no-deps'],
  60. [['RUSTDOCFLAGS', '--cfg docsrs -D warnings']],
  61. );
  62. }
  63. async function lintFeatures() {
  64. return cargo(
  65. getToolchainArgument('lint'),
  66. ['hack', 'check'],
  67. ['--feature-powerset', '--all-targets'],
  68. );
  69. }
  70. async function test() {
  71. return cargo(
  72. getToolchainArgument('test'),
  73. 'test',
  74. ['--all-features'],
  75. [['SBF_OUT_DIR', path.join(workingDirectory, 'target', 'deploy')]]
  76. );
  77. }
  78. async function wasm() {
  79. await $`wasm-pack build --target nodejs --dev ${path.dirname(manifestPath)} --features bincode ${args}`;
  80. }
  81. async function publish() {
  82. const dryRun = argv['dry-run'] ?? false;
  83. const [level] = args;
  84. if (!level) {
  85. throw new Error('A version level — e.g. "path" — must be provided.');
  86. }
  87. // Go to the client directory and install the dependencies.
  88. cd(path.dirname(manifestPath));
  89. // Publish the new version.
  90. const releaseArgs = dryRun
  91. ? []
  92. : ['--no-push', '--no-tag', '--no-confirm', '--execute'];
  93. await $`cargo release ${level} ${releaseArgs}`;
  94. // Stop here if this is a dry run.
  95. if (dryRun) {
  96. process.exit(0);
  97. }
  98. // Get the crate information.
  99. const toml = getCargo(path.dirname(manifestPath));
  100. const crateName = toml.package['name'];
  101. const newVersion = toml.package['version'];
  102. // Expose the new version to CI if needed.
  103. if (process.env.CI) {
  104. await $`echo "new_version=${newVersion}" >> $GITHUB_OUTPUT`;
  105. }
  106. // Soft reset the last commit so we can create our own commit and tag.
  107. await $`git reset --soft HEAD~1`;
  108. // Commit the new version.
  109. await $`git commit -am "Publish ${crateName} v${newVersion}"`;
  110. // Tag the new version.
  111. await $`git tag -a ${crateName}@v${newVersion} -m "${crateName} v${newVersion}"`;
  112. }
  113. switch (command) {
  114. case Command.BuildSbf:
  115. await buildSbf();
  116. break;
  117. case Command.Format:
  118. await format();
  119. break;
  120. case Command.LintClippy:
  121. await lintClippy();
  122. break;
  123. case Command.LintDocs:
  124. await lintDocs();
  125. break;
  126. case Command.LintFeatures:
  127. await lintFeatures();
  128. break;
  129. case Command.Lint:
  130. await Promise.all([lintClippy(), lintDocs(), lintFeatures()]);
  131. break;
  132. case Command.Test:
  133. await test();
  134. break;
  135. case Command.Wasm:
  136. await wasm();
  137. break;
  138. case Command.Publish:
  139. await publish();
  140. break;
  141. default:
  142. throw new Error(`Unknown command: ${command}`);
  143. }