From e97a1cf7875db90f9d769da78487bdb8fb995941 Mon Sep 17 00:00:00 2001 From: Brooke Hamilton <45323234+brooke-hamilton@users.noreply.github.com> Date: Sun, 9 Nov 2025 15:35:55 -0800 Subject: [PATCH] Shell scripting instructions for bash, sh, zsh, and other shells (#389) * shell scripting instructions Signed-off-by: Brooke Hamilton <45323234+brooke-hamilton@users.noreply.github.com> * parsing guidelines Signed-off-by: Brooke Hamilton <45323234+brooke-hamilton@users.noreply.github.com> --------- Signed-off-by: Brooke Hamilton <45323234+brooke-hamilton@users.noreply.github.com> --- docs/README.instructions.md | 1 + instructions/shell.instructions.md | 132 +++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 instructions/shell.instructions.md diff --git a/docs/README.instructions.md b/docs/README.instructions.md index 3b5416e..8e69ec1 100644 --- a/docs/README.instructions.md +++ b/docs/README.instructions.md @@ -106,6 +106,7 @@ Team and project-specific instructions to enhance GitHub Copilot's behavior for | [Rust MCP Server Development Best Practices](../instructions/rust-mcp-server.instructions.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Frust-mcp-server.instructions.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Frust-mcp-server.instructions.md) | Best practices for building Model Context Protocol servers in Rust using the official rmcp SDK with async/await patterns | | [Secure Coding and OWASP Guidelines](../instructions/security-and-owasp.instructions.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fsecurity-and-owasp.instructions.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fsecurity-and-owasp.instructions.md) | Comprehensive secure coding instructions for all languages and frameworks, based on OWASP Top 10 and industry best practices. | | [Self-explanatory Code Commenting Instructions](../instructions/self-explanatory-code-commenting.instructions.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fself-explanatory-code-commenting.instructions.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fself-explanatory-code-commenting.instructions.md) | Guidelines for GitHub Copilot to write comments to achieve self-explanatory code with less comments. Examples are in JavaScript but it should work on any language that has comments. | +| [Shell Scripting Guidelines](../instructions/shell.instructions.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fshell.instructions.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fshell.instructions.md) | Shell scripting best practices and conventions for bash, sh, zsh, and other shells | | [Spec Driven Workflow v1](../instructions/spec-driven-workflow-v1.instructions.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fspec-driven-workflow-v1.instructions.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fspec-driven-workflow-v1.instructions.md) | Specification-Driven Workflow v1 provides a structured approach to software development, ensuring that requirements are clearly defined, designs are meticulously planned, and implementations are thoroughly documented and validated. | | [Spring Boot Development](../instructions/springboot.instructions.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fspringboot.instructions.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fspringboot.instructions.md) | Guidelines for building Spring Boot base applications | | [SQL Development](../instructions/sql-sp-generation.instructions.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fsql-sp-generation.instructions.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fsql-sp-generation.instructions.md) | Guidelines for generating SQL statements and stored procedures | diff --git a/instructions/shell.instructions.md b/instructions/shell.instructions.md new file mode 100644 index 0000000..002d7ec --- /dev/null +++ b/instructions/shell.instructions.md @@ -0,0 +1,132 @@ +--- +description: 'Shell scripting best practices and conventions for bash, sh, zsh, and other shells' +applyTo: '**/*.sh' +--- + +# Shell Scripting Guidelines + +Instructions for writing clean, safe, and maintainable shell scripts for bash, sh, zsh, and other shells. + +## General Principles + +- Generate code that is clean, simple, and concise +- Ensure scripts are easily readable and understandable +- Add comments where helpful for understanding how the script works +- Generate concise and simple echo outputs to provide execution status +- Avoid unnecessary echo output and excessive logging +- Use shellcheck for static analysis when available +- Assume scripts are for automation and testing rather than production systems unless specified otherwise +- Prefer safe expansions: double-quote variable references (`"$var"`), use `${var}` for clarity, and avoid `eval` +- Use modern Bash features (`[[ ]]`, `local`, arrays) when portability requirements allow; fall back to POSIX constructs only when needed +- Choose reliable parsers for structured data instead of ad-hoc text processing + +## Error Handling & Safety + +- Always enable `set -euo pipefail` to fail fast on errors, catch unset variables, and surface pipeline failures +- Validate all required parameters before execution +- Provide clear error messages with context +- Use `trap` to clean up temporary resources or handle unexpected exits when the script terminates +- Declare immutable values with `readonly` (or `declare -r`) to prevent accidental reassignment +- Use `mktemp` to create temporary files or directories safely and ensure they are removed in your cleanup handler + +## Script Structure + +- Start with a clear shebang: `#!/bin/bash` unless specified otherwise +- Include a header comment explaining the script's purpose +- Define default values for all variables at the top +- Use functions for reusable code blocks +- Create reusable functions instead of repeating similar blocks of code +- Keep the main execution flow clean and readable + +## Working with JSON and YAML + +- Prefer dedicated parsers (`jq` for JSON, `yq` for YAML—or `jq` on JSON converted via `yq`) over ad-hoc text processing with `grep`, `awk`, or shell string splitting +- When `jq`/`yq` are unavailable or not appropriate, choose the next most reliable parser available in your environment, and be explicit about how it should be used safely +- Validate that required fields exist and handle missing/invalid data paths explicitly (e.g., by checking `jq` exit status or using `// empty`) +- Quote jq/yq filters to prevent shell expansion and prefer `--raw-output` when you need plain strings +- Treat parser errors as fatal: combine with `set -euo pipefail` or test command success before using results +- Document parser dependencies at the top of the script and fail fast with a helpful message if `jq`/`yq` (or alternative tools) are required but not installed + +```bash +#!/bin/bash + +# ============================================================================ +# Script Description Here +# ============================================================================ + +set -euo pipefail + +cleanup() { + # Remove temporary resources or perform other teardown steps as needed + if [[ -n "${TEMP_DIR:-}" && -d "$TEMP_DIR" ]]; then + rm -rf "$TEMP_DIR" + fi +} + +trap cleanup EXIT + +# Default values +RESOURCE_GROUP="" +REQUIRED_PARAM="" +OPTIONAL_PARAM="default-value" +readonly SCRIPT_NAME="$(basename "$0")" + +TEMP_DIR="" + +# Functions +usage() { + echo "Usage: $SCRIPT_NAME [OPTIONS]" + echo "Options:" + echo " -g, --resource-group Resource group (required)" + echo " -h, --help Show this help" + exit 0 +} + +validate_requirements() { + if [[ -z "$RESOURCE_GROUP" ]]; then + echo "Error: Resource group is required" + exit 1 + fi +} + +main() { + validate_requirements + + TEMP_DIR="$(mktemp -d)" + if [[ ! -d "$TEMP_DIR" ]]; then + echo "Error: failed to create temporary directory" >&2 + exit 1 + fi + + echo "============================================================================" + echo "Script Execution Started" + echo "============================================================================" + + # Main logic here + + echo "============================================================================" + echo "Script Execution Completed" + echo "============================================================================" +} + +# Parse arguments +while [[ $# -gt 0 ]]; do + case $1 in + -g|--resource-group) + RESOURCE_GROUP="$2" + shift 2 + ;; + -h|--help) + usage + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done + +# Execute main function +main "$@" + +```