Jelajahi Sumber

unified rust script

Joe Caulfield 11 bulan lalu
induk
melakukan
d6d3640cad

+ 15 - 15
package.json

@@ -12,21 +12,21 @@
     "js:lint": "tsx ./scripts/js/lint.mts",
     "js:publish": "tsx ./scripts/js/publish.mts",
     "js:test": "tsx ./scripts/js/test.mts",
-    "rust:format": "tsx ./scripts/rust/format.mts clients/rust",
-    "rust:lint": "tsx ./scripts/rust/lint.mts clients/rust",
-    "rust:lint:clippy": "tsx ./scripts/rust/lint-clippy.mts clients/rust",
-    "rust:lint:docs": "tsx ./scripts/rust/lint-docs.mts clients/rust",
-    "rust:lint:features": "tsx ./scripts/rust/lint-features.mts clients/rust",
-    "rust:publish": "tsx ./scripts/rust/publish.mts clients/rust",
-    "rust:test": "tsx ./scripts/rust/test.mts clients/rust",
-    "interface:format": "tsx ./scripts/rust/format.mts interface",
-    "interface:lint": "tsx ./scripts/rust/lint.mts interface",
-    "interface:lint:clippy": "tsx ./scripts/rust/lint-clippy.mts interface",
-    "interface:lint:docs": "tsx ./scripts/rust/lint-docs.mts interface",
-    "interface:lint:features": "tsx ./scripts/rust/lint-features.mts interface",
-    "interface:publish": "tsx ./scripts/rust/publish.mts interface",
-    "interface:test": "tsx ./scripts/rust/test.mts interface",
-    "interface:wasm": "tsx ./scripts/rust/wasm.mts interface",
+    "rust:format": "tsx ./scripts/rust.mts format clients/rust",
+    "rust:lint": "tsx ./scripts/rust.mts lint clients/rust",
+    "rust:lint:clippy": "tsx ./scripts/rust.mts lint-clippy clients/rust",
+    "rust:lint:docs": "tsx ./scripts/rust.mts lint-docs clients/rust",
+    "rust:lint:features": "tsx ./scripts/rust.mts lint-features clients/rust",
+    "rust:publish": "tsx ./scripts/rust.mts publish clients/rust",
+    "rust:test": "tsx ./scripts/rust.mts test clients/rust",
+    "interface:format": "tsx ./scripts/rust.mts format interface",
+    "interface:lint": "tsx ./scripts/rust.mts lint interface",
+    "interface:lint:clippy": "tsx ./scripts/rust.mts lint-clippy interface",
+    "interface:lint:docs": "tsx ./scripts/rust.mts lint-docs interface",
+    "interface:lint:features": "tsx ./scripts/rust.mts lint-features interface",
+    "interface:publish": "tsx ./scripts/rust.mts publish interface",
+    "interface:test": "tsx ./scripts/rust.mts test interface",
+    "interface:wasm": "tsx ./scripts/rust.mts wasm interface",
     "template:upgrade": "tsx ./scripts/helpers/upgrade-template.ts"
   },
   "devDependencies": {

+ 35 - 0
scripts/helpers/utils.mts

@@ -119,6 +119,22 @@ export function partitionArguments(
     : [args, []];
 }
 
+export function partitionArgumentsV2(
+  args: string[],
+  delimiter: string,
+  defaultArgs?: string[],
+): [string[], string[]] {
+  const [providedCargoArgs, providedCommandArgs] = partitionArguments(args, delimiter);
+  if (defaultArgs) {
+    const [defaultCargoArgs, defaultCommandArgs] = partitionArguments(defaultArgs, delimiter);
+    return [
+      [...defaultCargoArgs, ...providedCargoArgs],
+      [...defaultCommandArgs, ...providedCommandArgs],
+    ];
+  }
+  return [providedCargoArgs, providedCommandArgs];
+}
+
 export async function getInstalledSolanaVersion(): Promise<string | undefined> {
   try {
     const { stdout } = await $`solana --version`.quiet();
@@ -144,3 +160,22 @@ export function parseCliArguments(): { manifestPath: string; args: string[] } {
     args,
   };
 }
+
+export function parseCliArgumentsV2(): { command: string, manifestPath: string; args: string[] } {
+  const command = process.argv[2];
+  const args = process.argv.slice(3);
+  
+  // Extract the relative crate directory from the command-line arguments. This
+  // is the only required argument.
+  const relativePath = args.shift();
+
+  if (!relativePath) {
+    throw new Error('Missing relative manifest path');
+  }
+
+  return {
+    command,
+    manifestPath: path.join(workingDirectory, relativePath, 'Cargo.toml'),
+    args,
+  };
+}

+ 154 - 0
scripts/rust.mts

@@ -0,0 +1,154 @@
+#!/usr/bin/env zx
+
+// Script for working with Rust projects.
+
+import 'zx/globals';
+import {
+    getCargo,
+    getToolchainArgument,
+    parseCliArgumentsV2,
+    partitionArgumentsV2,
+    popArgument,
+    workingDirectory,
+} from './helpers/utils.mts';
+
+enum Command {
+    Format = 'format',
+    LintClippy = 'lint-clippy',
+    LintDocs = 'lint-docs',
+    LintFeatures = 'lint-features',
+    Lint = 'lint',
+    Test = 'test',
+    Wasm = 'wasm',
+    Publish = 'publish',
+}
+
+const { command, manifestPath, args } = parseCliArgumentsV2();
+
+async function cargo(
+    toolchain: string,
+    command: string | string[],
+    defaultArgs?: string[],
+    variables?: [string, string][],
+) {
+    const [cargoArgs, commandArgs] = partitionArgumentsV2(args, '--', defaultArgs);
+    variables?.forEach(([k, v]) => $.env[k] = v);
+    await $`cargo ${toolchain} ${command} --manifest-path ${manifestPath} ${cargoArgs} -- ${commandArgs}`;
+}
+
+async function format() {
+    return cargo(
+        getToolchainArgument('format'),
+        'fmt',
+        popArgument(args, '--fix') ? [] : ['--', '--check'],
+    );
+}
+
+async function lintClippy() {
+    return cargo(
+        getToolchainArgument('lint'),
+        'clippy',
+        popArgument(args, '--fix') ? ['--fix'] : [],
+    );
+}
+
+async function lintDocs() {
+    return cargo(
+        getToolchainArgument('lint'),
+        'doc',
+        ['--all-features', '--no-deps'],
+        [['RUSTDOCFLAGS', '--cfg docsrs -D warnings']],
+    );
+}
+
+async function lintFeatures() {
+    return cargo(
+        getToolchainArgument('lint'),
+        ['hack', 'check'],
+        ['--feature-powerset', '--all-targets'],
+    );
+}
+
+async function test() {
+    return cargo(
+        getToolchainArgument('test'),
+        'test',
+        ['--all-features'],
+        [['SBF_OUT_DIR', path.join(workingDirectory, 'target', 'deploy')]]
+    );
+}
+
+async function wasm() {
+    await $`wasm-pack build --target nodejs --dev ${path.dirname(manifestPath)} --features bincode ${args}`;
+}
+
+async function publish() {
+    const dryRun = argv['dry-run'] ?? false;
+    const [level] = args;
+    if (!level) {
+        throw new Error('A version level — e.g. "path" — must be provided.');
+    }
+
+    // Go to the client directory and install the dependencies.
+    cd(path.dirname(manifestPath));
+
+    // Publish the new version.
+    const releaseArgs = dryRun
+        ? []
+        : ['--no-push', '--no-tag', '--no-confirm', '--execute'];
+    await $`cargo release ${level} ${releaseArgs}`;
+
+    // Stop here if this is a dry run.
+    if (dryRun) {
+        process.exit(0);
+    }
+
+    // Get the crate information.
+    const toml = getCargo(path.dirname(manifestPath));
+    const crateName = toml.package['name'];
+    const newVersion = toml.package['version'];
+
+    // Expose the new version to CI if needed.
+    if (process.env.CI) {
+        await $`echo "new_version=${newVersion}" >> $GITHUB_OUTPUT`;
+    }
+    
+    // Soft reset the last commit so we can create our own commit and tag.
+    await $`git reset --soft HEAD~1`;
+    
+    // Commit the new version.
+    await $`git commit -am "Publish ${crateName} v${newVersion}"`;
+    
+    // Tag the new version.
+    await $`git tag -a ${crateName}@v${newVersion} -m "${crateName} v${newVersion}"`;
+}
+
+
+switch (command) {
+    case Command.Format:
+        await format();
+        break;
+    case Command.LintClippy:
+        await lintClippy();
+        break;
+    case Command.LintDocs:
+        await lintDocs();
+        break;
+    case Command.LintFeatures:
+        await lintFeatures();
+        break;
+    case Command.Lint:
+        await Promise.all([lintClippy(), lintDocs(), lintFeatures()]);
+        break;
+    case Command.Test:
+        await test();
+        break;
+    case Command.Wasm:
+        await wasm();
+        break;
+    case Command.Publish:
+        await publish();
+        break;
+    default:
+        throw new Error(`Unknown command: ${command}`);
+}

+ 0 - 20
scripts/rust/format.mts

@@ -1,20 +0,0 @@
-#!/usr/bin/env zx
-import 'zx/globals';
-import {
-  getToolchainArgument,
-  parseCliArguments,
-  partitionArguments,
-  popArgument,
-} from '../helpers/utils.mts';
-
-// Extract the crate directory from the command-line arguments.
-const { manifestPath, args } = parseCliArguments();
-// Configure additional arguments here, e.g.:
-// ['--arg1', '--arg2', ...args]
-const formatArgs = args;
-
-const fix = popArgument(args, '--fix');
-const [cargoArgs, fmtArgs] = partitionArguments(formatArgs, '--');
-const toolchain = getToolchainArgument('format');
-
-await $`cargo ${toolchain} fmt --manifest-path ${manifestPath} ${cargoArgs} -- ${fix ? '' : '--check'} ${fmtArgs}`;

+ 0 - 22
scripts/rust/lint-clippy.mts

@@ -1,22 +0,0 @@
-#!/usr/bin/env zx
-import 'zx/globals';
-import {
-  getToolchainArgument,
-  parseCliArguments,
-  popArgument,
-} from '../helpers/utils.mts';
-
-// Extract the crate directory from the command-line arguments.
-const { manifestPath, args } = parseCliArguments();
-// Configure additional arguments here, e.g.:
-// ['--arg1', '--arg2', ...args]
-const clippyArgs = args;
-// Note: need to use nightly clippy as frozen-abi proc-macro generates
-// a lot of code (frozen-abi is enabled only under nightly due to the
-// use of unstable rust feature). Likewise, frozen-abi(-macro) crates'
-// unit tests are only compiled under nightly.
-const toolchain = getToolchainArgument('lint');
-// Check if the `--fix` argument is present.
-const fix = popArgument(clippyArgs, '--fix');
-
-await $`cargo ${toolchain} clippy --manifest-path ${manifestPath} ${fix ? '--fix' : ''} ${clippyArgs}`;

+ 0 - 12
scripts/rust/lint-docs.mts

@@ -1,12 +0,0 @@
-#!/usr/bin/env zx
-import 'zx/globals';
-import { getToolchainArgument, parseCliArguments } from '../helpers/utils.mts';
-
-// Extract the crate directory from the command-line arguments.
-const { manifestPath, args } = parseCliArguments();
-// Configure additional arguments here, e.g.:
-// ['--arg1', '--arg2', ...args]
-const docArgs = args;
-const toolchain = getToolchainArgument('lint');
-
-await $`RUSTDOCFLAGS="--cfg docsrs -D warnings" cargo ${toolchain} doc --manifest-path ${manifestPath} --all-features --no-deps ${docArgs}`;

+ 0 - 13
scripts/rust/lint-features.mts

@@ -1,13 +0,0 @@
-#!/usr/bin/env zx
-import 'zx/globals';
-import { getToolchainArgument, parseCliArguments } from '../helpers/utils.mts';
-
-// Extract the crate directory from the command-line arguments.
-const { manifestPath, args } = parseCliArguments();
-// Configure additional arguments here, e.g.:
-// ['--arg1', '--arg2', ...args]
-const featuresArgs = ['--exclude-features', 'frozen-abi', ...args];
-const toolchain = getToolchainArgument('lint');
-
-// Check feature powerset.
-await $`cargo ${toolchain} hack check --manifest-path ${manifestPath} --feature-powerset --all-targets ${featuresArgs}`;

+ 0 - 17
scripts/rust/lint.mts

@@ -1,17 +0,0 @@
-// Script to lint a crate.
-//
-// This script runs the following sub-scripts:
-// - lint-clippy.mjs
-// - lint-docs.mjs
-// - lint-features.mjs
-
-import { cliArguments, workingDirectory } from '../helpers/utils.mts';
-
-const scripts = path.join(workingDirectory, 'scripts', 'rust');
-
-// clippy
-await $`tsx ${path.join(scripts, 'lint-clippy.mjs')} ${cliArguments()}`;
-// rustdoc
-await $`tsx ${path.join(scripts, 'lint-docs.mjs')} ${cliArguments()}`;
-// features
-await $`tsx ${path.join(scripts, 'lint-features.mjs')} ${cliArguments()}`;

+ 0 - 45
scripts/rust/publish.mts

@@ -1,45 +0,0 @@
-#!/usr/bin/env zx
-import 'zx/globals';
-import { getCargo, parseCliArguments } from '../helpers/utils.mts';
-
-// Extract the crate directory from the command-line arguments.
-const { manifestPath, args } = parseCliArguments();
-
-const dryRun = argv['dry-run'] ?? false;
-const [level] = args;
-if (!level) {
-  throw new Error('A version level — e.g. "path" — must be provided.');
-}
-
-// Go to the client directory and install the dependencies.
-cd(path.dirname(manifestPath));
-
-// Publish the new version.
-const releaseArgs = dryRun
-  ? []
-  : ['--no-push', '--no-tag', '--no-confirm', '--execute'];
-await $`cargo release ${level} ${releaseArgs}`;
-
-// Stop here if this is a dry run.
-if (dryRun) {
-  process.exit(0);
-}
-
-// Get the crate information.
-const toml = getCargo(path.dirname(manifestPath));
-const crateName = toml.package['name'];
-const newVersion = toml.package['version'];
-
-// Expose the new version to CI if needed.
-if (process.env.CI) {
-  await $`echo "new_version=${newVersion}" >> $GITHUB_OUTPUT`;
-}
-
-// Soft reset the last commit so we can create our own commit and tag.
-await $`git reset --soft HEAD~1`;
-
-// Commit the new version.
-await $`git commit -am "Publish ${crateName} v${newVersion}"`;
-
-// Tag the new version.
-await $`git tag -a ${crateName}@v${newVersion} -m "${crateName} v${newVersion}"`;

+ 0 - 25
scripts/rust/test.mts

@@ -1,25 +0,0 @@
-#!/usr/bin/env zx
-import 'zx/globals';
-import {
-  getToolchainArgument,
-  parseCliArguments,
-  workingDirectory,
-} from '../helpers/utils.mts';
-
-// Extract the crate directory from the command-line arguments.
-const { manifestPath, args } = parseCliArguments();
-// Configure additional arguments here, e.g.:
-// ['--arg1', '--arg2', ...args]
-const testArgs = args;
-
-const toolchain = getToolchainArgument('test');
-
-const hasSolfmt = await which('solfmt', { nothrow: true });
-const sbfOutDir = path.join(workingDirectory, 'target', 'deploy');
-
-// Run the tests.
-if (hasSolfmt) {
-  await $`SBF_OUT_DIR=${sbfOutDir} cargo ${toolchain} test --all-features --manifest-path ${manifestPath} ${testArgs} >&1 | solfmt`;
-} else {
-  await $`SBF_OUT_DIR=${sbfOutDir} cargo ${toolchain} test --all-features --manifest-path ${manifestPath} ${testArgs}`;
-}

+ 0 - 11
scripts/rust/wasm.mts

@@ -1,11 +0,0 @@
-#!/usr/bin/env zx
-import 'zx/globals';
-import { parseCliArguments } from '../helpers/utils.mts';
-
-// Extract the crate directory from the command-line arguments.
-const { manifestPath, args } = parseCliArguments();
-// Configure additional arguments here, e.g.:
-// ['--arg1', '--arg2', ...args]
-const wasmArgs = args;
-
-await $`wasm-pack build --target nodejs --dev ${path.dirname(manifestPath)} --features bincode ${wasmArgs}`;