Explorar o código

Add CLI versions to workspace Cargo.toml and Solana check scripts (#75)

Loris Leiva hai 1 ano
pai
achega
4adf466264

+ 5 - 0
.changeset/cuddly-cheetahs-kick.md

@@ -0,0 +1,5 @@
+---
+"create-solana-program": patch
+---
+
+Add CLI versions to workspace Cargo.toml and Solana check scripts

+ 10 - 13
template/base/.github/actions/setup/action.yml.njk

@@ -3,7 +3,7 @@ name: Setup environment
 inputs:
 {% if programFramework === 'anchor' %}
   anchor:
-    description: The Anchor version to install. Skips if not provided.
+    description: Install Anchor if `true`. Defaults to `false`.
     required: false
 {% endif %}
   cargo-cache-key:
@@ -18,14 +18,11 @@ inputs:
   clippy:
     description: Install Clippy if `true`. Defaults to `false`.
     required: false
-  node:
-    description: The Node.js version to install. Required.
-    required: true
   rustfmt:
     description: Install Rustfmt if `true`. Defaults to `false`.
     required: false
   solana:
-    description: The Solana version to install. Skips if not provided.
+    description: Install Solana if `true`. Defaults to `false`.
     required: false
 
 runs:
@@ -37,7 +34,7 @@ runs:
     - name: Setup Node.js
       uses: actions/setup-node@v4
       with:
-        node-version: {% raw %}${{ inputs.node }}{% endraw %}
+        node-version: 18
         cache: 'pnpm'
 
     - name: Install Dependencies
@@ -50,13 +47,13 @@ runs:
 
 {% if solanaVersion.withoutPatch === '2.0' %}
     - name: Install Protobuf Compiler (Temporary Workaround for Solana 2.0)
-      if: {% raw %}${{ inputs.solana || inputs.rustfmt == 'true' || inputs.clippy == 'true' }}{% endraw %}
+      if: {% raw %}${{ inputs.solana == 'true' || inputs.rustfmt == 'true' || inputs.clippy == 'true' }}{% endraw %}
       shell: bash
       run: |
         sudo apt-get update
         sudo apt-get install -y protobuf-compiler
-{% endif %}
 
+{% endif %}
     - name: Install Rustfmt
       if: {% raw %}${{ inputs.rustfmt == 'true' }}{% endraw %}
       uses: dtolnay/rust-toolchain@master
@@ -72,21 +69,21 @@ runs:
         components: clippy
 
     - name: Install Solana
-      if: {% raw %}${{ inputs.solana }}{% endraw %}
+      if: {% raw %}${{ inputs.solana == 'true' }}{% endraw %}
       uses: metaplex-foundation/actions/install-solana@v1
       with:
-        version: {% raw %}${{ inputs.solana }}{% endraw %}
+        version: {% raw %}${{ env.SOLANA_VERSION }}{% endraw %}
         cache: true
 
 {% if programFramework === 'anchor' %}
     - name: Install Anchor
-      if: {% raw %}${{ inputs.anchor != '' }}{% endraw %}
+      if: {% raw %}${{ inputs.anchor == 'true' }}{% endraw %}
       uses: metaplex-foundation/actions/install-anchor-cli@v1
       with:
-        version: {% raw %}${{ inputs.anchor }}{% endraw %}
+        version: {% raw %}${{ env.ANCHOR_VERSION }}{% endraw %}
         cache: true
-{% endif %}
 
+{% endif %}
     - name: Cache Cargo Dependencies
       if: {% raw %}${{ inputs.cargo-cache-key && !inputs.cargo-cache-fallback-key }}{% endraw %}
       uses: actions/cache@v4

+ 8 - 25
template/base/.github/workflows/main.yml.njk

@@ -6,13 +6,6 @@ on:
   pull_request:
     branches: [main]
 
-env:
-  NODE_VERSION: 18
-  SOLANA_VERSION: {{ solanaVersion.full }}
-{% if programFramework === 'anchor' %}
-  ANCHOR_VERSION: {{ anchorVersion.full }}
-{% endif %}
-
 jobs:
   format_and_lint_programs:
     name: Format & Lint Programs
@@ -25,7 +18,6 @@ jobs:
         uses: ./.github/actions/setup
         with:
           clippy: true
-          node: {% raw %}${{ env.NODE_VERSION }}{% endraw %}
           rustfmt: true
 
       - name: Format Programs
@@ -44,8 +36,6 @@ jobs:
 
       - name: Setup Environment
         uses: ./.github/actions/setup
-        with:
-          node: {% raw %}${{ env.NODE_VERSION }}{% endraw %}
 
       - name: Format Client JS
         run: pnpm clients:js:format
@@ -66,7 +56,6 @@ jobs:
         uses: ./.github/actions/setup
         with:
           clippy: true
-          node: {% raw %}${{ env.NODE_VERSION }}{% endraw %}
           rustfmt: true
 
       - name: Format Client Rust
@@ -88,10 +77,9 @@ jobs:
         uses: ./.github/actions/setup
         with:
           cargo-cache-key: cargo-programs
-          node: {% raw %}${{ env.NODE_VERSION }}{% endraw %}
-          solana: {% raw %}${{ env.SOLANA_VERSION }}{% endraw %}
+          solana: true
 {% if programFramework === 'anchor' %}
-          anchor: {% raw %}${{ env.ANCHOR_VERSION }}{% endraw %}
+          anchor: true
 {% endif %}
 
       - name: Build Programs
@@ -123,10 +111,9 @@ jobs:
         with:
           cargo-cache-key: cargo-program-tests
           cargo-cache-fallback-key: cargo-programs
-          node: {% raw %}${{ env.NODE_VERSION }}{% endraw %}
-          solana: {% raw %}${{ env.SOLANA_VERSION }}{% endraw %}
+          solana: true
 {% if programFramework === 'anchor' %}
-          anchor: {% raw %}${{ env.ANCHOR_VERSION }}{% endraw %}
+          anchor: true
 {% endif %}
 
       - name: Test Programs
@@ -145,10 +132,9 @@ jobs:
         with:
           cargo-cache-key: cargo-programs
           cargo-cache-local-key: cargo-local
-          node: {% raw %}${{ env.NODE_VERSION }}{% endraw %}
 {% if programFramework === 'anchor' %}
-          solana: {% raw %}${{ env.SOLANA_VERSION }}{% endraw %}
-          anchor: {% raw %}${{ env.ANCHOR_VERSION }}{% endraw %}
+          solana: true
+          anchor: true
 {% endif %}
 
       - name: Generate IDLs
@@ -171,7 +157,6 @@ jobs:
       - name: Setup Environment
         uses: ./.github/actions/setup
         with:
-          node: {% raw %}${{ env.NODE_VERSION }}{% endraw %}
           rustfmt: true
 
       - name: Generate Clients
@@ -195,8 +180,7 @@ jobs:
       - name: Setup Environment
         uses: ./.github/actions/setup
         with:
-          node: {% raw %}${{ env.NODE_VERSION }}{% endraw %}
-          solana: {% raw %}${{ env.SOLANA_VERSION }}{% endraw %}
+          solana: true
 
       - name: Restore Program Builds
         uses: actions/cache/restore@v4
@@ -221,8 +205,7 @@ jobs:
         uses: ./.github/actions/setup
         with:
           cargo-cache-key: cargo-rust-client
-          node: {% raw %}${{ env.NODE_VERSION }}{% endraw %}
-          solana: {% raw %}${{ env.SOLANA_VERSION }}{% endraw %}
+          solana: true
 
       - name: Restore Program Builds
         uses: actions/cache/restore@v4

+ 6 - 0
template/base/Cargo.toml.njk

@@ -11,6 +11,12 @@ members = ["program"]
 overflow-checks = true
 {% endif %}
 
+[workspace.metadata.cli]
+{% if programFramework === 'anchor' %}
+anchor = "{{ anchorVersion.full }}"
+{% endif %}
+solana = "{{ solanaVersion.full }}"
+
 # Specify Rust toolchains for rustfmt, clippy, and build.
 # Any unprovided toolchains default to stable.
 [workspace.metadata.toolchains]

+ 3 - 1
template/base/package.json

@@ -6,7 +6,9 @@
     "programs:clean": "zx ./scripts/program/clean.mjs",
     "programs:format": "zx ./scripts/program/format.mjs",
     "programs:lint": "zx ./scripts/program/lint.mjs",
-    "generate:idls": "zx ./scripts/generate-idls.mjs"
+    "generate:idls": "zx ./scripts/generate-idls.mjs",
+    "solana:check": "zx ./scripts/check-solana-version.mjs",
+    "solana:link": "zx ./scripts/link-solana-version.mjs"
   },
   "devDependencies": {
     "@iarna/toml": "^2.2.5",

+ 18 - 0
template/base/scripts/check-solana-version.mjs

@@ -0,0 +1,18 @@
+#!/usr/bin/env zx
+import 'zx/globals';
+import { getInstalledSolanaVersion, getSolanaVersion } from './utils.mjs';
+
+const expectedVersion = getSolanaVersion();
+const installedVersion = await getInstalledSolanaVersion();
+
+if (installedVersion !== expectedVersion) {
+  echo(
+    chalk.yellow('[ WARNING ]'),
+    `The installed Solana version ${installedVersion} does not match the expected version ${expectedVersion}.`
+  );
+} else {
+  echo(
+    chalk.green('[ SUCCESS ]'),
+    `The expected Solana version ${expectedVersion} is installed.`
+  );
+}

+ 0 - 5
template/base/scripts/ci/set-env.mjs

@@ -1,5 +0,0 @@
-#!/usr/bin/env zx
-import { getToolchain } from '../utils.mjs';
-
-await $`echo "TOOLCHAIN_FORMAT=${getToolchain('format')}" >> $GITHUB_ENV`;
-await $`echo "TOOLCHAIN_LINT=${getToolchain('lint')}" >> $GITHUB_ENV`;

+ 13 - 0
template/base/scripts/ci/set-env.mjs.njk

@@ -0,0 +1,13 @@
+#!/usr/bin/env zx
+{% if programFramework === 'anchor' %}
+import { getCargoMetadata, getSolanaVersion, getToolchain } from '../utils.mjs';
+{% else %}
+import { getSolanaVersion, getToolchain } from '../utils.mjs';
+{% endif %}
+
+{% if programFramework === 'anchor' %}
+await $`echo "ANCHOR_VERSION=${getCargoMetadata()?.cli?.anchor}" >> $GITHUB_ENV`;
+{% endif %}
+await $`echo "SOLANA_VERSION=${getSolanaVersion()}" >> $GITHUB_ENV`;
+await $`echo "TOOLCHAIN_FORMAT=${getToolchain('format')}" >> $GITHUB_ENV`;
+await $`echo "TOOLCHAIN_LINT=${getToolchain('lint')}" >> $GITHUB_ENV`;

+ 56 - 0
template/base/scripts/link-solana-version.mjs

@@ -0,0 +1,56 @@
+#!/usr/bin/env zx
+import 'zx/globals';
+import { getInstalledSolanaVersion, getSolanaVersion } from './utils.mjs';
+
+const installedVersion = await getInstalledSolanaVersion();
+const expectedVersion = getSolanaVersion();
+
+if (installedVersion === expectedVersion) {
+  echo(
+    chalk.green('[ SUCCESS ]'),
+    `The expected Solana version ${expectedVersion} is installed.`
+  );
+  process.exit(0);
+}
+
+const installPath = path.join(
+  os.homedir(),
+  '.local',
+  'share',
+  'solana',
+  'install'
+);
+const releasePath = path.join(
+  installPath,
+  'releases',
+  expectedVersion,
+  'solana-release'
+);
+const activeReleasePath = path.join(installPath, 'active_release');
+const hasRelease = await fs.exists(releasePath);
+
+if (hasRelease) {
+  await $`rm -f "${activeReleasePath}"`;
+  await $`ln -s "${releasePath}" "${activeReleasePath}"`;
+  echo(
+    chalk.green('[ SUCCESS ]'),
+    `Successfully switched from Solana version ${installedVersion} to ${expectedVersion} to match the project's requirements.`
+  );
+  process.exit(0);
+}
+
+echo(
+  chalk.yellow('[ WARNING ]'),
+  `Cannot switch from Solana version ${installedVersion} to ${expectedVersion} because it is not installed.`
+);
+
+const installRelease = await question('Should we install it now? [y/N] ');
+if (installRelease === 'y') {
+  echo(`Installing Solana ${expectedVersion}...`);
+  await $`sh -c "$(curl -sSfL https://release.solana.com/v${expectedVersion}/install)"`;
+}
+
+echo(
+  chalk.green('[ SUCCESS ]'),
+  `Successfully switched from Solana version ${installedVersion} to ${expectedVersion} to match the project's requirements.`
+);

+ 17 - 0
template/base/scripts/utils.mjs

@@ -84,6 +84,10 @@ export function getCargoMetadata(folder) {
   return folder ? cargo?.package?.metadata : cargo?.workspace?.metadata;
 }
 
+export function getSolanaVersion() {
+  return getCargoMetadata()?.cli?.solana;
+}
+
 export function getToolchain(operation) {
   return getCargoMetadata()?.toolchains?.[operation];
 }
@@ -111,3 +115,16 @@ export function partitionArguments(args, delimiter) {
     ? [args.slice(0, index), args.slice(index + 1)]
     : [args, []];
 }
+
+export async function getInstalledSolanaVersion() {
+  try {
+    const { stdout } = await $`solana --version`.quiet();
+    return stdout.match(/(\d+\.\d+\.\d+)/)?.[1];
+  } catch (error) {
+    echo(
+      chalk.red('[ ERROR ]'),
+      `No Solana installation found. Please install Solana ${getSolanaVersion()} before proceeding.`
+    );
+    process.exit(1);
+  }
+}

+ 3 - 0
template/clients/base/scripts/start-validator.mjs

@@ -10,6 +10,9 @@ import {
   getProgramFolders,
 } from './utils.mjs';
 
+// Check Solana version.
+await $`pnpm solana:check`;
+
 // Options and arguments.
 const restart = argv['restart'];
 

+ 3 - 1
template/clients/js/clients/js/package.json.njk

@@ -54,7 +54,9 @@
     "typescript": "^5.5.3"
   },
   "ava": {
-    "nodeArguments": ["--no-warnings"],
+    "nodeArguments": [
+      "--no-warnings"
+    ],
     "require": [
       "@solana/webcrypto-ed25519-polyfill"
     ],