microsoft/hve-core

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
hve-core-v2.3.4

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

367lines · modecode

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