rust.mts 3.9 KB

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