microsoft/hve-core

Public

mirrored fromhttps://github.com/microsoft/hve-coreAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
hve-core-v2.2.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

.github/instructions/bash/bash.instructions.md

368lines · modecode

1---
2applyTo: '**/*.sh'
3description: 'Instructions for bash script implementation - Brought to you by microsoft/edge-ai'
4maturity: stable
5---
6
7# Bash Script Instructions
8
9These instructions define conventions for authoring Bash scripts in this repository. Scripts follow Bash 5.x conventions with strict error handling and ShellCheck compliance.
10
11## Script Structure
12
13Scripts follow a consistent structure with shebang, header comment, strict mode, and a main function pattern.
14
15<!-- <template-script-structure> -->
16```bash
17#!/usr/bin/env bash
18#
19# script-name.sh
20# Brief description of what this script does
21
22set -euo pipefail
23
24main() {
25 # Script logic here
26 echo "Executing..."
27}
28
29main "$@"
30```
31<!-- </template-script-structure> -->
32
33### Shebang
34
35Use `#!/usr/bin/env bash` for portability across systems.
36
37### Strict Mode
38
39Enable strict error handling at the top of every script:
40
41```bash
42set -euo pipefail
43```
44
45This configuration:
46
47* `-e`: Exits immediately on command failure
48* `-u`: Treats unset variables as errors
49* `-o pipefail`: Propagates pipeline failures
50
51### Main Function Pattern
52
53Encapsulate script logic in a `main()` function called at the end. This pattern:
54
55* Ensures all functions are defined before use
56* Supports sourcing scripts for testing
57* Provides clear entry point
58
59## Formatting and Style
60
61### Indentation and Line Length
62
63* Use 2 spaces for indentation, never tabs
64* Limit lines to 80 characters when practical
65* Long commands use backslash continuation
66
67```bash
68az resource show \
69 --resource-group "$RESOURCE_GROUP_NAME" \
70 --name "$RESOURCE_NAME" \
71 --query id \
72 --output tsv
73```
74
75### Control Structures
76
77Place `then` and `do` on the same line as their control keyword:
78
79```bash
80if [[ -n "${VAR:-}" ]]; then
81 echo "Variable is set"
82fi
83
84for item in "${items[@]}"; do
85 process "$item"
86done
87```
88
89### Conditionals and Tests
90
91* Use `[[ ... ]]` instead of `[ ... ]` or `test`
92* Use `(( ... ))` for arithmetic operations
93
94```bash
95if [[ "${ENVIRONMENT}" == "prod" ]]; then
96 echo "Production environment"
97fi
98
99if (( count > 10 )); then
100 echo "Count exceeds threshold"
101fi
102```
103
104## Variables and Naming
105
106### Naming Conventions
107
108| Type | Convention | Example |
109| ---- | ---------- | ------- |
110| Environment variables | UPPER_SNAKE_CASE | `RESOURCE_GROUP_NAME` |
111| Constants | UPPER_SNAKE_CASE with `readonly` | `readonly MAX_RETRIES=3` |
112| Local variables | lower_snake_case | `local file_path` |
113| Function names | lower_snake_case | `validate_input()` |
114
115### Variable Expansion
116
117* Use braces for clarity: `"${var}"` over `"$var"`
118* Quote all variable expansions unless word splitting is intentional
119* Use command substitution with `$()`: never backticks
120
121```bash
122# Variable with default
123ENVIRONMENT="${ENVIRONMENT:-dev}"
124
125# Required variable check
126if [[ -z "${REQUIRED_VAR:-}" ]]; then
127 echo "ERROR: REQUIRED_VAR must be set" >&2
128 exit 1
129fi
130```
131
132### Arrays
133
134Use arrays for lists of elements:
135
136```bash
137declare -a files=("file1.txt" "file2.txt" "file3.txt")
138
139for file in "${files[@]}"; do
140 process "$file"
141done
142```
143
144## Functions
145
146Define functions before use. Use `local` for function-scoped variables.
147
148```bash
149log() {
150 local message="$1"
151 printf "========== %s ==========\n" "$message"
152}
153
154err() {
155 local message="$1"
156 printf "ERROR: %s\n" "$message" >&2
157 exit 1
158}
159
160validate_input() {
161 local input="$1"
162 if [[ -z "${input}" ]]; then
163 err "Input cannot be empty"
164 fi
165}
166```
167
168## Error Handling
169
170### Error Functions
171
172Implement consistent error reporting:
173
174```bash
175err() {
176 printf "ERROR: %s\n" "$1" >&2
177 exit 1
178}
179```
180
181### Command Validation
182
183Check for required commands before use:
184
185```bash
186if ! command -v "az" &>/dev/null; then
187 err "'az' command is required but not installed"
188fi
189```
190
191### Error Visibility
192
193Allow commands to fail naturally with their native error messages. Avoid redirecting stderr to `/dev/null` unless errors are genuinely irrelevant. Let tools display their built-in error information.
194
195## Comments
196
197Keep comments minimal. Add them only when logic requires explanation:
198
199* Complex regex patterns
200* Non-obvious conditionals
201* Workarounds with context
202
203```bash
204# Match semantic version pattern: major.minor.patch
205if [[ "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
206 echo "Valid version"
207fi
208```
209
210Document environment variables at the top of scripts that require them:
211
212```bash
213## Required Environment Variables:
214# ENVIRONMENT - Target environment (dev, prod)
215# RESOURCE_GROUP - Azure resource group name
216
217## Optional Environment Variables:
218# DEBUG - Enable verbose output when set
219```
220
221## Usage Functions
222
223Scripts with arguments include a usage function:
224
225```bash
226usage() {
227 echo "Usage: ${0##*/} [OPTIONS]"
228 echo ""
229 echo "Options:"
230 echo " --help, -h Show this help message"
231 echo " --verbose Enable verbose output"
232 exit 1
233}
234```
235
236## Argument Parsing
237
238Use `case` statements for argument handling:
239
240```bash
241while [[ $# -gt 0 ]]; do
242 case "$1" in
243 --verbose)
244 VERBOSE=true
245 shift
246 ;;
247 --output)
248 if [[ -z "${2:-}" || "$2" == --* ]]; then
249 echo "Error: --output requires an argument" >&2
250 usage
251 fi
252 OUTPUT_FILE="$2"
253 shift 2
254 ;;
255 --help|-h)
256 usage
257 ;;
258 *)
259 echo "Unknown option: $1" >&2
260 usage
261 ;;
262 esac
263done
264```
265
266## File Operations
267
268Create directories safely and handle paths properly:
269
270```bash
271mkdir -p "$(dirname "$OUTPUT_FILE")"
272
273if [[ -f "${config_file}" ]]; then
274 source "${config_file}"
275fi
276```
277
278## Security Practices
279
280### Variable Quoting
281
282Quote variables to prevent word splitting and command injection:
283
284```bash
285# Correct
286rm -f "${temp_file}"
287grep "${pattern}" "${file}"
288
289# Avoid
290rm -f $temp_file
291grep $pattern $file
292```
293
294### File Permissions
295
296Set appropriate permissions for sensitive files:
297
298```bash
299chmod 0600 "${HOME}/.kube/config"
300```
301
302### Checksum Verification
303
304Verify downloaded files before execution:
305
306```bash
307EXPECTED_SHA256="abc123..."
308if ! echo "${EXPECTED_SHA256} ${downloaded_file}" | sha256sum -c --quiet -; then
309 echo "ERROR: Checksum verification failed" >&2
310 rm "${downloaded_file}"
311 exit 1
312fi
313```
314
315## ShellCheck Compliance
316
317All scripts pass ShellCheck validation. Use the VS Code problems panel or run ShellCheck directly:
318
319```bash
320shellcheck script.sh
321```
322
323When a specific rule needs suppression, add a directive with justification:
324
325```bash
326# shellcheck disable=SC2034 # Variable used by sourced script
327EXPORTED_CONFIG="value"
328```
329
330## Azure CLI Patterns
331
332When working with Azure CLI commands:
333
334### Output Handling
335
336* Use `--output tsv` for single values in scripts
337* TSV output returns empty strings for null values (not the string "null")
338* Use `--query` with JMESPath for filtering results
339
340```bash
341resource_id=$(az resource show \
342 --resource-group "$RESOURCE_GROUP" \
343 --name "$RESOURCE_NAME" \
344 --resource-type "Microsoft.Storage/storageAccounts" \
345 --query id \
346 --output tsv)
347
348if [[ -z "${resource_id}" ]]; then
349 err "Resource not found"
350fi
351```
352
353### Conditional Command Arguments
354
355Build commands with arrays when arguments are conditional:
356
357```bash
358az_cmd=("az" "connectedk8s" "connect"
359 "--name" "$RESOURCE_NAME"
360 "--resource-group" "$RESOURCE_GROUP"
361)
362
363if [[ "${AUTO_UPGRADE:-true}" == "false" ]]; then
364 az_cmd+=("--disable-auto-upgrade")
365fi
366
367"${az_cmd[@]}"
368```
369