Selaa lähdekoodia

script: Add features and rustdoc checks (#23)

* Add crate feature script

* Add rustdoc script

* Add script entrypoint

* Update CI

* Fix script name

* Review comments

* Fix frozen-abi dependencies

* Use test toolchain for cargo hack

* Switch to lint toolchain

* Refactor lint interface

* Fix script invocation

* Simplify step names

* Refactor rust client lint

* Move out format from lint

* Address review comments

* More review comments

* Fix cargo hack toolchain test
Fernando Otero 1 vuosi sitten
vanhempi
sitoutus
1cab018c8d

+ 5 - 0
.github/actions/setup/action.yml

@@ -70,6 +70,11 @@ runs:
         version: ${{ env.SOLANA_VERSION }}
         cache: true
 
+    - name: Install 'cargo-hack'
+      if: ${{ contains(inputs.toolchain, 'lint') }}
+      shell: bash
+      run: cargo install cargo-hack
+
     - name: Cache Cargo Dependencies
       if: ${{ inputs.cargo-cache-key && !inputs.cargo-cache-fallback-key }}
       uses: actions/cache@v4

+ 18 - 6
.github/workflows/main.yml

@@ -34,11 +34,17 @@ jobs:
         with:
           toolchain: format, lint
 
-      - name: Format Client Rust
+      - name: Format
         run: pnpm clients:rust:format
 
-      - name: Lint Client Rust
-        run: pnpm clients:rust:lint
+      - name: Lint / Clippy
+        run: pnpm zx ./scripts/client/lint-rust-clippy.mjs
+
+      - name: Lint / Features
+        run: pnpm zx ./scripts/client/lint-rust-features.mjs
+
+      - name: Lint / Docs
+        run: pnpm zx ./scripts/client/lint-rust-docs.mjs
 
   format_and_lint_interface:
     name: Format & Lint Interface
@@ -52,11 +58,17 @@ jobs:
         with:
           toolchain: format, lint
 
-      - name: Format Interface
+      - name: Format
         run: pnpm interface:format
 
-      - name: Lint Interface
-        run: pnpm interface:lint
+      - name: Lint / Clippy
+        run: pnpm zx ./scripts/interface/lint-clippy.mjs
+
+      - name: Lint / Features
+        run: pnpm zx ./scripts/interface/lint-features.mjs
+
+      - name: Lint / Docs
+        run: pnpm zx ./scripts/interface/lint-docs.mjs
 
   test_interface:
     name: Test Interface

+ 3 - 1
interface/Cargo.toml

@@ -36,6 +36,7 @@ solana-nonce = "^0.0.2"
 solana-program = { version = "^2.1", default-features = false }
 solana-program-entrypoint = "^2.1"
 solana-program-error = { version = "^2.1", features = ["borsh"] }
+solana-pubkey = { version = "^2.1", features = ["std"] }
 static_assertions = "1.1.0"
 strum = "0.24"
 strum_macros = "0.24"
@@ -45,5 +46,6 @@ frozen-abi = [
     "dep:solana-frozen-abi",
     "dep:solana-frozen-abi-macro",
     "dep:solana-logger",
-    "solana-pubkey/frozen-abi"
+    "solana-pubkey/frozen-abi",
+    "solana-pubkey/std"
 ]

+ 24 - 0
scripts/client/lint-rust-clippy.mjs

@@ -0,0 +1,24 @@
+#!/usr/bin/env zx
+import 'zx/globals';
+import {
+  cliArguments,
+  getToolchainArgument,
+  popArgument,
+  workingDirectory,
+} from '../utils.mjs';
+
+// Configure additional arguments here, e.g.:
+// ['--arg1', '--arg2', ...cliArguments()]
+const lintArgs = cliArguments();
+
+const fix = popArgument(lintArgs, '--fix');
+const toolchain = getToolchainArgument('lint');
+const manifestPath = path.join(
+  workingDirectory,
+  'clients',
+  'rust',
+  'Cargo.toml'
+);
+
+// Check the client using Clippy.
+await $`cargo ${toolchain} clippy --manifest-path ${manifestPath} ${fix ? '--fix' : ''} ${lintArgs}`;

+ 18 - 0
scripts/client/lint-rust-docs.mjs

@@ -0,0 +1,18 @@
+#!/usr/bin/env zx
+import 'zx/globals';
+import {
+  cliArguments,
+  getToolchainArgument,
+  workingDirectory,
+} from '../utils.mjs';
+
+const args = cliArguments();
+const toolchain = getToolchainArgument('lint');
+const manifestPath = path.join(
+  workingDirectory,
+  'clients',
+  'rust',
+  'Cargo.toml'
+);
+
+await $`RUSTDOCFLAGS="--cfg docsrs -D warnings" cargo ${toolchain} doc --manifest-path ${manifestPath} --all-features --no-deps ${args}`;

+ 19 - 0
scripts/client/lint-rust-features.mjs

@@ -0,0 +1,19 @@
+#!/usr/bin/env zx
+import 'zx/globals';
+import {
+  cliArguments,
+  getToolchainArgument,
+  workingDirectory,
+} from '../utils.mjs';
+
+const args = cliArguments();
+const toolchain = getToolchainArgument('lint');
+const manifestPath = path.join(
+  workingDirectory,
+  'clients',
+  'rust',
+  'Cargo.toml'
+);
+
+// Check feature powerset.
+await $`cargo ${toolchain} hack check --manifest-path ${manifestPath} --feature-powerset --all-targets ${args}`;

+ 14 - 25
scripts/client/lint-rust.mjs

@@ -1,28 +1,17 @@
-#!/usr/bin/env zx
-import 'zx/globals';
-import {
-  cliArguments,
-  getToolchainArgument,
-  popArgument,
-  workingDirectory,
-} from '../utils.mjs';
+// Script to lint the Rust client crate.
+//
+// This script runs the following sub-scripts:
+// - lint-rust-clippy.mjs
+// - lint-rust-features.mjs
+// - lint-rust-docs.mjs
 
-// Configure additional arguments here, e.g.:
-// ['--arg1', '--arg2', ...cliArguments()]
-const lintArgs = cliArguments();
+import { cliArguments, workingDirectory } from '../utils.mjs';
 
-const fix = popArgument(lintArgs, '--fix');
-const toolchain = getToolchainArgument('lint');
-const manifestPath = path.join(
-  workingDirectory,
-  'clients',
-  'rust',
-  'Cargo.toml'
-);
+const scripts = path.join(workingDirectory, 'scripts', 'client');
 
-// Check the client using Clippy.
-if (fix) {
-  await $`cargo ${toolchain} clippy --manifest-path ${manifestPath} --fix ${lintArgs}`;
-} else {
-  await $`cargo ${toolchain} clippy --manifest-path ${manifestPath} ${lintArgs}`;
-}
+// clippy
+await $`zx ${path.join(scripts, 'lint-rust-clippy.mjs')}`;
+// features
+await $`zx ${path.join(scripts, 'lint-rust-features.mjs')}`;
+// rustdoc
+await $`zx ${path.join(scripts, 'lint-rust-docs.mjs')}`;

+ 35 - 0
scripts/interface/lint-clippy.mjs

@@ -0,0 +1,35 @@
+#!/usr/bin/env zx
+import 'zx/globals';
+import {
+  cliArguments,
+  getToolchainArgument,
+  popArgument,
+  workingDirectory,
+} from '../utils.mjs';
+
+// Configure additional arguments here, e.g.:
+// ['--arg1', '--arg2', ...cliArguments()]
+const lintArgs = ['--all-targets', '--all-features', ...cliArguments()];
+// Check whether a '--' was already used.
+if (lintArgs.indexOf('--') === -1) {
+  lintArgs.push('--');
+}
+// Add additional arguments.
+lintArgs.push(
+  '--deny=warnings',
+  '--deny=clippy::default_trait_access',
+  '--deny=clippy::arithmetic_side_effects',
+  '--deny=clippy::manual_let_else',
+  '--deny=clippy::used_underscore_binding'
+);
+
+const fix = popArgument(lintArgs, '--fix');
+// 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');
+const manifestPath = path.join(workingDirectory, 'interface', 'Cargo.toml');
+
+// Lint the interface.
+await $`cargo ${toolchain} clippy --manifest-path ${manifestPath} ${fix ? '--fix' : ''} ${lintArgs}`;

+ 13 - 0
scripts/interface/lint-docs.mjs

@@ -0,0 +1,13 @@
+#!/usr/bin/env zx
+import 'zx/globals';
+import {
+  cliArguments,
+  getToolchainArgument,
+  workingDirectory,
+} from '../utils.mjs';
+
+const args = cliArguments();
+const toolchain = getToolchainArgument('lint');
+const manifestPath = path.join(workingDirectory, 'interface', 'Cargo.toml');
+
+await $`RUSTDOCFLAGS="--cfg docsrs -D warnings" cargo ${toolchain} doc --manifest-path ${manifestPath} --all-features --no-deps ${args}`;

+ 14 - 0
scripts/interface/lint-features.mjs

@@ -0,0 +1,14 @@
+#!/usr/bin/env zx
+import 'zx/globals';
+import {
+  cliArguments,
+  getToolchainArgument,
+  workingDirectory,
+} from '../utils.mjs';
+
+const args = ['--exclude-features', 'frozen-abi', ...cliArguments()];
+const toolchain = getToolchainArgument('lint');
+const manifestPath = path.join(workingDirectory, 'interface', 'Cargo.toml');
+
+// Check feature powerset.
+await $`cargo ${toolchain} hack check --manifest-path ${manifestPath} --feature-powerset --all-targets ${args}`;

+ 14 - 36
scripts/interface/lint.mjs

@@ -1,39 +1,17 @@
-#!/usr/bin/env zx
-import 'zx/globals';
-import {
-  cliArguments,
-  getToolchainArgument,
-  popArgument,
-  workingDirectory,
-} from '../utils.mjs';
+// Script to lint the interface crate.
+//
+// This script runs the following sub-scripts:
+// - lint-clippy.mjs
+// - lint-features.mjs
+// - lint-docs.mjs
 
-// Configure additional arguments here, e.g.:
-// ['--arg1', '--arg2', ...cliArguments()]
-const lintArgs = ['--all-targets', '--all-features', ...cliArguments()];
-// Check whether a '--' was already used.
-if (lintArgs.indexOf('--') === -1) {
-  lintArgs.push('--');
-}
-// Add additional arguments.
-lintArgs.push(
-  '--deny=warnings',
-  '--deny=clippy::default_trait_access',
-  '--deny=clippy::arithmetic_side_effects',
-  '--deny=clippy::manual_let_else',
-  '--deny=clippy::used_underscore_binding'
-);
+import { workingDirectory } from '../utils.mjs';
 
-const fix = popArgument(lintArgs, '--fix');
-// 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');
-const manifestPath = path.join(workingDirectory, 'interface', 'Cargo.toml');
+const scripts = path.join(workingDirectory, 'scripts', 'interface');
 
-// Lint the interface.
-if (fix) {
-  await $`cargo ${toolchain} clippy --manifest-path ${manifestPath} --fix ${lintArgs}`;
-} else {
-  await $`cargo ${toolchain} clippy --manifest-path ${manifestPath} ${lintArgs}`;
-}
+// clippy
+await $`zx ${path.join(scripts, 'lint-clippy.mjs')}`;
+// features
+await $`zx ${path.join(scripts, 'lint-features.mjs')}`;
+// rustdoc
+await $`zx ${path.join(scripts, 'lint-docs.mjs')}`;