From 67fde812ebd0f1177f84a9fa52023bc86ef11d64 Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Tue, 22 Jul 2025 12:51:32 -0400 Subject: [PATCH 1/4] Add shell script for spell check --- eng/common/spelling/README.md | 109 ++++++++++++++ eng/common/spelling/invoke-cspell.sh | 216 +++++++++++++++++++++++++++ 2 files changed, 325 insertions(+) create mode 100644 eng/common/spelling/README.md create mode 100644 eng/common/spelling/invoke-cspell.sh diff --git a/eng/common/spelling/README.md b/eng/common/spelling/README.md new file mode 100644 index 000000000000..38556e3e2399 --- /dev/null +++ b/eng/common/spelling/README.md @@ -0,0 +1,109 @@ +# Spelling Check Scripts + +This directory contains scripts to run cspell (Code Spell Checker) on the repository using the dependencies defined in the adjacent `package*.json` files. + +## Adding Legitimate Words + +If the spell checker flags legitimate words as misspelled, you can add them to the dictionary configuration file located at `.vscode/cspell.json`. + +### Where to Add Words + +There are two main places to add legitimate words. Maintain alphabetical order when adding words to keep the dictionary organized: + +1. **Root-level words array**: Add words to the `"words"` array at the root level of the configuration file. This is the preferred location for project-specific terms, technical vocabulary, and commonly used words. + +2. **Baseline dictionary**: Add words to the `"baseline"` dictionary under `"dictionaryDefinitions"`. This is typically used for words that were already present in the codebase when the spell checker was first introduced. + + +### Example + +To add new words, edit `.vscode/cspell.json` and add them to the `"words"` array: + +```json +{ + "words": [ + "myprojectname", + "customterm", + "technicalword" + ] +} +``` + +### Guidelines + +- Use lowercase for words +- Consider whether the word is truly legitimate or if it might be a typo + +## Available Scripts + +### PowerShell Version (Windows) +- **File**: `Invoke-Cspell.ps1` +- **Usage**: For Windows PowerShell environments + +### Bash Version (Linux/macOS) +- **File**: `invoke-cspell.sh` +- **Usage**: For Linux and macOS bash environments + +## Usage Examples + +### PowerShell +```powershell +# Check all files (default) +./eng/common/spelling/Invoke-Cspell.ps1 + +# Check specific files +./eng/common/spelling/Invoke-Cspell.ps1 -ScanGlobs 'sdk/*/*/PublicAPI/**/*.md' + +# Check multiple globs +./eng/common/spelling/Invoke-Cspell.ps1 -ScanGlobs @('sdk/storage/**', 'sdk/keyvault/**') + +# Check single file +./eng/common/spelling/Invoke-Cspell.ps1 -ScanGlobs './README.md' +``` + +### Bash +```bash +# Check all files (default) +./eng/common/spelling/invoke-cspell.sh + +# Check specific files +./eng/common/spelling/invoke-cspell.sh --scan-globs 'sdk/*/*/PublicAPI/**/*.md' + +# Check multiple globs +./eng/common/spelling/invoke-cspell.sh --scan-globs 'sdk/storage/**' 'sdk/keyvault/**' + +# Check single file +./eng/common/spelling/invoke-cspell.sh --scan-globs './README.md' + +# Get help +./eng/common/spelling/invoke-cspell.sh --help +``` + +## Parameters + +Both scripts support similar functionality: + +- **Job Type**: The cspell command to run (default: `lint`) +- **Scan Globs**: File patterns to check for spelling +- **Config Path**: Location of the cspell.json configuration file +- **Spell Check Root**: Root directory for relative paths +- **Package Cache**: Working directory for npm dependencies +- **Leave Cache**: Option to preserve the npm package cache + +## Requirements + +- Node.js and npm must be installed +- The `.vscode/cspell.json` configuration file must exist +- `jq` command-line JSON processor (for bash version) + +## How It Works + +1. Creates a temporary working directory for npm packages +2. Copies `package.json` and `package-lock.json` to the working directory +3. Installs npm dependencies using `npm ci` +4. Modifies the cspell configuration to include specified file globs +5. Runs cspell with the modified configuration +6. Restores the original configuration +7. Cleans up temporary files + +The scripts ensure that a LICENSE file (or temporary file) is always included in the scan to meet cspell's requirements for the "files" array. \ No newline at end of file diff --git a/eng/common/spelling/invoke-cspell.sh b/eng/common/spelling/invoke-cspell.sh new file mode 100644 index 000000000000..ad7c41b06ae7 --- /dev/null +++ b/eng/common/spelling/invoke-cspell.sh @@ -0,0 +1,216 @@ +#!/bin/bash + +# Bash version of Invoke-Cspell.ps1 +# +# SYNOPSIS +# Invokes cspell using dependencies defined in adjacent ./package*.json +# +# PARAMETERS +# --job-type Maps to cspell command (e.g. 'lint', 'trace', etc.). Default is 'lint' +# --scan-globs List of glob expressions to be scanned (space-separated) +# --config-path Location of cspell.json file to use when scanning +# --spell-check-root Location of root folder for generating readable relative file paths +# --package-cache Location of a working directory for npm packages +# --leave-cache If set, the package cache will not be deleted +# --help Display this help message +# +# EXAMPLES +# ./eng/common/spelling/invoke-cspell.sh --scan-globs 'sdk/*/*/PublicAPI/**/*.md' +# ./eng/common/spelling/invoke-cspell.sh --scan-globs 'sdk/storage/**' 'sdk/keyvault/**' +# ./eng/common/spelling/invoke-cspell.sh --scan-globs './README.md' + +set -euo pipefail + +# Default values +JOB_TYPE="lint" +SCAN_GLOBS=("**") +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CONFIG_PATH="$(realpath "${SCRIPT_DIR}/../../../.vscode/cspell.json")" +SPELL_CHECK_ROOT="$(realpath "${SCRIPT_DIR}/../../..")" +PACKAGE_CACHE="${TMPDIR:-/tmp}/cspell-tool-path" +LEAVE_CACHE=false + +# Logging functions +log_error() { + if [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then + echo "::error::$*" + elif [[ "${SYSTEM_TEAMFOUNDATIONCOLLECTIONURI:-}" != "" ]]; then + echo "##vso[task.LogIssue type=error;]$*" + else + echo "ERROR: $*" >&2 + fi +} + +log_info() { + echo "$*" +} + +# Function to display help +show_help() { + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Invokes cspell using dependencies defined in adjacent ./package*.json" + echo "" + echo "OPTIONS:" + echo " --job-type TYPE Maps to cspell command (default: lint)" + echo " --scan-globs GLOB... List of glob expressions to be scanned" + echo " --config-path PATH Location of cspell.json file" + echo " --spell-check-root PATH Root folder for relative file paths" + echo " --package-cache PATH Working directory for npm packages" + echo " --leave-cache Don't delete package cache" + echo " --help Display this help message" + echo "" + echo "EXAMPLES:" + echo " $0 --scan-globs 'sdk/*/*/PublicAPI/**/*.md'" + echo " $0 --scan-globs 'sdk/storage/**' 'sdk/keyvault/**'" + echo " $0 --scan-globs './README.md'" +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + --job-type) + JOB_TYPE="$2" + shift 2 + ;; + --scan-globs) + SCAN_GLOBS=() + shift + while [[ $# -gt 0 && ! "$1" =~ ^-- ]]; do + SCAN_GLOBS+=("$1") + shift + done + ;; + --config-path) + CONFIG_PATH="$2" + shift 2 + ;; + --spell-check-root) + SPELL_CHECK_ROOT="$2" + shift 2 + ;; + --package-cache) + PACKAGE_CACHE="$2" + shift 2 + ;; + --leave-cache) + LEAVE_CACHE=true + shift + ;; + --help) + show_help + exit 0 + ;; + *) + log_error "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +# Check if npm is available +if ! command -v npm &> /dev/null; then + log_error "Could not locate npm. Install NodeJS (includes npm) https://nodejs.org/en/download/" + exit 1 +fi + +# Check if config file exists +if [[ ! -f "$CONFIG_PATH" ]]; then + log_error "Could not locate config file $CONFIG_PATH" + exit 1 +fi + +# Prepare the working directory if it does not already have requirements in place +if [[ ! -d "$PACKAGE_CACHE" ]]; then + mkdir -p "$PACKAGE_CACHE" +fi + +if [[ ! -f "$PACKAGE_CACHE/package.json" ]]; then + cp "$SCRIPT_DIR/package.json" "$PACKAGE_CACHE/" +fi + +if [[ ! -f "$PACKAGE_CACHE/package-lock.json" ]]; then + cp "$SCRIPT_DIR/package-lock.json" "$PACKAGE_CACHE/" +fi + +# Handle LICENSE file requirement +DELETE_NOT_EXCLUDED_FILE=false +NOT_EXCLUDED_FILE="" + +if [[ -f "$SPELL_CHECK_ROOT/LICENSE" ]]; then + NOT_EXCLUDED_FILE="$SPELL_CHECK_ROOT/LICENSE" +elif [[ -f "$SPELL_CHECK_ROOT/LICENSE.txt" ]]; then + NOT_EXCLUDED_FILE="$SPELL_CHECK_ROOT/LICENSE.txt" +else + # If there is no LICENSE file, fall back to creating a temporary file + # The "files" list must always contain a file which exists, is not empty, and is + # not excluded in ignorePaths. In this case it will be a file with the contents + # "1" (no spelling errors will be detected) + NOT_EXCLUDED_FILE="$SPELL_CHECK_ROOT/$(uuidgen 2>/dev/null || echo "temp_$(date +%s)_$$")" + echo "1" > "$NOT_EXCLUDED_FILE" + DELETE_NOT_EXCLUDED_FILE=true +fi + +# Add the not excluded file to scan globs +SCAN_GLOBS+=("$NOT_EXCLUDED_FILE") + +# Read and parse the original cspell config +CSPELL_CONFIG_CONTENT=$(cat "$CONFIG_PATH") + +# Create a temporary modified config using jq +# Convert SCAN_GLOBS array to JSON array +SCAN_GLOBS_JSON=$(printf '%s\n' "${SCAN_GLOBS[@]}" | jq -R . | jq -s .) + +# Modify the config to include our scan globs +MODIFIED_CONFIG=$(echo "$CSPELL_CONFIG_CONTENT" | jq --argjson files "$SCAN_GLOBS_JSON" '. + {files: $files}') + +log_info "Setting config in: $CONFIG_PATH" + +# Backup original config and set the modified one +echo "$MODIFIED_CONFIG" > "$CONFIG_PATH" + +# Resolve absolute paths +CONFIG_PATH=$(realpath "$CONFIG_PATH") +SPELL_CHECK_ROOT=$(realpath "$SPELL_CHECK_ROOT") + +# Store original location +ORIGINAL_LOCATION=$(pwd) + +# Cleanup function +cleanup() { + local exit_code=$? + + # Restore original location + cd "$ORIGINAL_LOCATION" + + log_info "cspell run complete, restoring original configuration and removing temp file." + + # Restore original config + echo "$CSPELL_CONFIG_CONTENT" > "$CONFIG_PATH" + + # Remove temporary file if created + if [[ "$DELETE_NOT_EXCLUDED_FILE" == "true" && -f "$NOT_EXCLUDED_FILE" ]]; then + rm -f "$NOT_EXCLUDED_FILE" + fi + + # Remove package cache if not requested to leave it + if [[ "$LEAVE_CACHE" == "false" && -d "$PACKAGE_CACHE" ]]; then + rm -rf "$PACKAGE_CACHE" + fi + + exit $exit_code +} + +# Set up cleanup trap +trap cleanup EXIT INT TERM + +# Change to package cache directory and run npm ci +cd "$PACKAGE_CACHE" +npm ci + +# Run cspell with the modified configuration +COMMAND="npm exec --no -- cspell $JOB_TYPE --config $CONFIG_PATH --no-must-find-files --root $SPELL_CHECK_ROOT --relative" +log_info "$COMMAND" + +npm exec --no -- cspell "$JOB_TYPE" --config "$CONFIG_PATH" --no-must-find-files --root "$SPELL_CHECK_ROOT" --relative \ No newline at end of file From b9007c18c46cbeda5226faf6ce3e177edf27114c Mon Sep 17 00:00:00 2001 From: Ben Broderick Phillips Date: Thu, 24 Jul 2025 14:11:42 -0400 Subject: [PATCH 2/4] Add shebang and make cspell script executable for bash invocation --- eng/common/spelling/Invoke-Cspell.ps1 | 2 + eng/common/spelling/README.md | 31 +--- eng/common/spelling/invoke-cspell.sh | 216 -------------------------- 3 files changed, 5 insertions(+), 244 deletions(-) mode change 100644 => 100755 eng/common/spelling/Invoke-Cspell.ps1 delete mode 100644 eng/common/spelling/invoke-cspell.sh diff --git a/eng/common/spelling/Invoke-Cspell.ps1 b/eng/common/spelling/Invoke-Cspell.ps1 old mode 100644 new mode 100755 index 4e5baa0bdf33..93e3db4edf1c --- a/eng/common/spelling/Invoke-Cspell.ps1 +++ b/eng/common/spelling/Invoke-Cspell.ps1 @@ -1,3 +1,5 @@ +#! /bin/env pwsh + <# .SYNOPSIS Invokes cspell using dependencies defined in adjacent ./package*.json diff --git a/eng/common/spelling/README.md b/eng/common/spelling/README.md index 38556e3e2399..06e711c90a26 100644 --- a/eng/common/spelling/README.md +++ b/eng/common/spelling/README.md @@ -1,6 +1,6 @@ # Spelling Check Scripts -This directory contains scripts to run cspell (Code Spell Checker) on the repository using the dependencies defined in the adjacent `package*.json` files. +This directory contains a script to run cspell (Code Spell Checker) on the repository using the dependencies defined in the adjacent `package*.json` files. ## Adding Legitimate Words @@ -40,13 +40,8 @@ To add new words, edit `.vscode/cspell.json` and add them to the `"words"` array - **File**: `Invoke-Cspell.ps1` - **Usage**: For Windows PowerShell environments -### Bash Version (Linux/macOS) -- **File**: `invoke-cspell.sh` -- **Usage**: For Linux and macOS bash environments - ## Usage Examples -### PowerShell ```powershell # Check all files (default) ./eng/common/spelling/Invoke-Cspell.ps1 @@ -54,35 +49,15 @@ To add new words, edit `.vscode/cspell.json` and add them to the `"words"` array # Check specific files ./eng/common/spelling/Invoke-Cspell.ps1 -ScanGlobs 'sdk/*/*/PublicAPI/**/*.md' -# Check multiple globs +# Check multiple globs (powershell invocation only) ./eng/common/spelling/Invoke-Cspell.ps1 -ScanGlobs @('sdk/storage/**', 'sdk/keyvault/**') # Check single file ./eng/common/spelling/Invoke-Cspell.ps1 -ScanGlobs './README.md' ``` -### Bash -```bash -# Check all files (default) -./eng/common/spelling/invoke-cspell.sh - -# Check specific files -./eng/common/spelling/invoke-cspell.sh --scan-globs 'sdk/*/*/PublicAPI/**/*.md' - -# Check multiple globs -./eng/common/spelling/invoke-cspell.sh --scan-globs 'sdk/storage/**' 'sdk/keyvault/**' - -# Check single file -./eng/common/spelling/invoke-cspell.sh --scan-globs './README.md' - -# Get help -./eng/common/spelling/invoke-cspell.sh --help -``` - ## Parameters -Both scripts support similar functionality: - - **Job Type**: The cspell command to run (default: `lint`) - **Scan Globs**: File patterns to check for spelling - **Config Path**: Location of the cspell.json configuration file @@ -106,4 +81,4 @@ Both scripts support similar functionality: 6. Restores the original configuration 7. Cleans up temporary files -The scripts ensure that a LICENSE file (or temporary file) is always included in the scan to meet cspell's requirements for the "files" array. \ No newline at end of file +The scripts ensure that a LICENSE file (or temporary file) is always included in the scan to meet cspell's requirements for the "files" array. diff --git a/eng/common/spelling/invoke-cspell.sh b/eng/common/spelling/invoke-cspell.sh deleted file mode 100644 index ad7c41b06ae7..000000000000 --- a/eng/common/spelling/invoke-cspell.sh +++ /dev/null @@ -1,216 +0,0 @@ -#!/bin/bash - -# Bash version of Invoke-Cspell.ps1 -# -# SYNOPSIS -# Invokes cspell using dependencies defined in adjacent ./package*.json -# -# PARAMETERS -# --job-type Maps to cspell command (e.g. 'lint', 'trace', etc.). Default is 'lint' -# --scan-globs List of glob expressions to be scanned (space-separated) -# --config-path Location of cspell.json file to use when scanning -# --spell-check-root Location of root folder for generating readable relative file paths -# --package-cache Location of a working directory for npm packages -# --leave-cache If set, the package cache will not be deleted -# --help Display this help message -# -# EXAMPLES -# ./eng/common/spelling/invoke-cspell.sh --scan-globs 'sdk/*/*/PublicAPI/**/*.md' -# ./eng/common/spelling/invoke-cspell.sh --scan-globs 'sdk/storage/**' 'sdk/keyvault/**' -# ./eng/common/spelling/invoke-cspell.sh --scan-globs './README.md' - -set -euo pipefail - -# Default values -JOB_TYPE="lint" -SCAN_GLOBS=("**") -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -CONFIG_PATH="$(realpath "${SCRIPT_DIR}/../../../.vscode/cspell.json")" -SPELL_CHECK_ROOT="$(realpath "${SCRIPT_DIR}/../../..")" -PACKAGE_CACHE="${TMPDIR:-/tmp}/cspell-tool-path" -LEAVE_CACHE=false - -# Logging functions -log_error() { - if [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then - echo "::error::$*" - elif [[ "${SYSTEM_TEAMFOUNDATIONCOLLECTIONURI:-}" != "" ]]; then - echo "##vso[task.LogIssue type=error;]$*" - else - echo "ERROR: $*" >&2 - fi -} - -log_info() { - echo "$*" -} - -# Function to display help -show_help() { - echo "Usage: $0 [OPTIONS]" - echo "" - echo "Invokes cspell using dependencies defined in adjacent ./package*.json" - echo "" - echo "OPTIONS:" - echo " --job-type TYPE Maps to cspell command (default: lint)" - echo " --scan-globs GLOB... List of glob expressions to be scanned" - echo " --config-path PATH Location of cspell.json file" - echo " --spell-check-root PATH Root folder for relative file paths" - echo " --package-cache PATH Working directory for npm packages" - echo " --leave-cache Don't delete package cache" - echo " --help Display this help message" - echo "" - echo "EXAMPLES:" - echo " $0 --scan-globs 'sdk/*/*/PublicAPI/**/*.md'" - echo " $0 --scan-globs 'sdk/storage/**' 'sdk/keyvault/**'" - echo " $0 --scan-globs './README.md'" -} - -# Parse command line arguments -while [[ $# -gt 0 ]]; do - case $1 in - --job-type) - JOB_TYPE="$2" - shift 2 - ;; - --scan-globs) - SCAN_GLOBS=() - shift - while [[ $# -gt 0 && ! "$1" =~ ^-- ]]; do - SCAN_GLOBS+=("$1") - shift - done - ;; - --config-path) - CONFIG_PATH="$2" - shift 2 - ;; - --spell-check-root) - SPELL_CHECK_ROOT="$2" - shift 2 - ;; - --package-cache) - PACKAGE_CACHE="$2" - shift 2 - ;; - --leave-cache) - LEAVE_CACHE=true - shift - ;; - --help) - show_help - exit 0 - ;; - *) - log_error "Unknown option: $1" - show_help - exit 1 - ;; - esac -done - -# Check if npm is available -if ! command -v npm &> /dev/null; then - log_error "Could not locate npm. Install NodeJS (includes npm) https://nodejs.org/en/download/" - exit 1 -fi - -# Check if config file exists -if [[ ! -f "$CONFIG_PATH" ]]; then - log_error "Could not locate config file $CONFIG_PATH" - exit 1 -fi - -# Prepare the working directory if it does not already have requirements in place -if [[ ! -d "$PACKAGE_CACHE" ]]; then - mkdir -p "$PACKAGE_CACHE" -fi - -if [[ ! -f "$PACKAGE_CACHE/package.json" ]]; then - cp "$SCRIPT_DIR/package.json" "$PACKAGE_CACHE/" -fi - -if [[ ! -f "$PACKAGE_CACHE/package-lock.json" ]]; then - cp "$SCRIPT_DIR/package-lock.json" "$PACKAGE_CACHE/" -fi - -# Handle LICENSE file requirement -DELETE_NOT_EXCLUDED_FILE=false -NOT_EXCLUDED_FILE="" - -if [[ -f "$SPELL_CHECK_ROOT/LICENSE" ]]; then - NOT_EXCLUDED_FILE="$SPELL_CHECK_ROOT/LICENSE" -elif [[ -f "$SPELL_CHECK_ROOT/LICENSE.txt" ]]; then - NOT_EXCLUDED_FILE="$SPELL_CHECK_ROOT/LICENSE.txt" -else - # If there is no LICENSE file, fall back to creating a temporary file - # The "files" list must always contain a file which exists, is not empty, and is - # not excluded in ignorePaths. In this case it will be a file with the contents - # "1" (no spelling errors will be detected) - NOT_EXCLUDED_FILE="$SPELL_CHECK_ROOT/$(uuidgen 2>/dev/null || echo "temp_$(date +%s)_$$")" - echo "1" > "$NOT_EXCLUDED_FILE" - DELETE_NOT_EXCLUDED_FILE=true -fi - -# Add the not excluded file to scan globs -SCAN_GLOBS+=("$NOT_EXCLUDED_FILE") - -# Read and parse the original cspell config -CSPELL_CONFIG_CONTENT=$(cat "$CONFIG_PATH") - -# Create a temporary modified config using jq -# Convert SCAN_GLOBS array to JSON array -SCAN_GLOBS_JSON=$(printf '%s\n' "${SCAN_GLOBS[@]}" | jq -R . | jq -s .) - -# Modify the config to include our scan globs -MODIFIED_CONFIG=$(echo "$CSPELL_CONFIG_CONTENT" | jq --argjson files "$SCAN_GLOBS_JSON" '. + {files: $files}') - -log_info "Setting config in: $CONFIG_PATH" - -# Backup original config and set the modified one -echo "$MODIFIED_CONFIG" > "$CONFIG_PATH" - -# Resolve absolute paths -CONFIG_PATH=$(realpath "$CONFIG_PATH") -SPELL_CHECK_ROOT=$(realpath "$SPELL_CHECK_ROOT") - -# Store original location -ORIGINAL_LOCATION=$(pwd) - -# Cleanup function -cleanup() { - local exit_code=$? - - # Restore original location - cd "$ORIGINAL_LOCATION" - - log_info "cspell run complete, restoring original configuration and removing temp file." - - # Restore original config - echo "$CSPELL_CONFIG_CONTENT" > "$CONFIG_PATH" - - # Remove temporary file if created - if [[ "$DELETE_NOT_EXCLUDED_FILE" == "true" && -f "$NOT_EXCLUDED_FILE" ]]; then - rm -f "$NOT_EXCLUDED_FILE" - fi - - # Remove package cache if not requested to leave it - if [[ "$LEAVE_CACHE" == "false" && -d "$PACKAGE_CACHE" ]]; then - rm -rf "$PACKAGE_CACHE" - fi - - exit $exit_code -} - -# Set up cleanup trap -trap cleanup EXIT INT TERM - -# Change to package cache directory and run npm ci -cd "$PACKAGE_CACHE" -npm ci - -# Run cspell with the modified configuration -COMMAND="npm exec --no -- cspell $JOB_TYPE --config $CONFIG_PATH --no-must-find-files --root $SPELL_CHECK_ROOT --relative" -log_info "$COMMAND" - -npm exec --no -- cspell "$JOB_TYPE" --config "$CONFIG_PATH" --no-must-find-files --root "$SPELL_CHECK_ROOT" --relative \ No newline at end of file From 6614be719133ffd3d730febab99bbb7e01dbc1a3 Mon Sep 17 00:00:00 2001 From: Ben Broderick Phillips Date: Thu, 24 Jul 2025 14:14:16 -0400 Subject: [PATCH 3/4] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- eng/common/spelling/Invoke-Cspell.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/common/spelling/Invoke-Cspell.ps1 b/eng/common/spelling/Invoke-Cspell.ps1 index 93e3db4edf1c..fc5af4164a09 100755 --- a/eng/common/spelling/Invoke-Cspell.ps1 +++ b/eng/common/spelling/Invoke-Cspell.ps1 @@ -1,4 +1,4 @@ -#! /bin/env pwsh +#!/bin/env pwsh <# .SYNOPSIS From fb212214d08d0945cc911943b8530c09eba66115 Mon Sep 17 00:00:00 2001 From: Ben Broderick Phillips Date: Mon, 4 Aug 2025 18:13:14 -0400 Subject: [PATCH 4/4] Apply suggestion from @benbp --- eng/common/spelling/Invoke-Cspell.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/common/spelling/Invoke-Cspell.ps1 b/eng/common/spelling/Invoke-Cspell.ps1 index fc5af4164a09..df4d2e587348 100755 --- a/eng/common/spelling/Invoke-Cspell.ps1 +++ b/eng/common/spelling/Invoke-Cspell.ps1 @@ -1,4 +1,4 @@ -#!/bin/env pwsh +#!/usr/bin/env pwsh <# .SYNOPSIS