Validates shell scripts using ShellCheck for syntax errors, best practices, and potential bugs.
This reusable workflow module provides:
- Static Analysis: Comprehensive shell script linting with ShellCheck
- Automatic Detection: Finds shell scripts by extension and shebang
- Configurable Severity: Filter by error, warning, info, or style issues
- Multiple Dialect Support: Validate sh, bash, dash, or ksh scripts
- Flexible Exclusions: Ignore specific codes, patterns, or directories
name: Validate
on:
push:
branches: [main]
pull_request:
jobs:
shellcheck:
uses: bauer-group/automation-templates/.github/workflows/modules-validate-shellscript.yml@mainjobs:
shellcheck:
uses: bauer-group/automation-templates/.github/workflows/modules-validate-shellscript.yml@main
with:
scan-directory: 'scripts/'
severity: 'warning'
shell-dialect: 'bash'| Parameter | Description | Default |
|---|---|---|
scan-directory |
Directory to scan for shell scripts | '.' |
scan-paths |
Specific paths as JSON array | '' |
additional-files |
Extra file patterns as JSON array | '' |
| Parameter | Description | Default |
|---|---|---|
severity |
Minimum level: error, warning, info, style |
'warning' |
exclude-patterns |
Patterns to exclude as JSON array | '' |
exclude-codes |
ShellCheck codes to ignore as JSON array | '' |
| Parameter | Description | Default |
|---|---|---|
shell-dialect |
Shell to check: sh, bash, dash, ksh, auto |
'auto' |
external-sources |
Follow source statements | true |
enable-optional |
Optional checks as JSON array | '' |
| Parameter | Description | Default |
|---|---|---|
format |
Output format: tty, checkstyle, json, gcc, quiet |
'tty' |
fail-on-findings |
Fail workflow if issues found | true |
runs-on |
Runner OS | 'ubuntu-latest' |
| Output | Description |
|---|---|
passed |
Whether all scripts passed ('true'/'false') |
files-checked |
Number of files analyzed |
issues-found |
Total number of issues |
error-count |
Number of errors found |
warning-count |
Number of warnings found |
Scan entire repository for shell scripts:
name: CI
on: [push, pull_request]
jobs:
shellcheck:
uses: bauer-group/automation-templates/.github/workflows/modules-validate-shellscript.yml@mainScan only certain directories:
jobs:
shellcheck:
uses: bauer-group/automation-templates/.github/workflows/modules-validate-shellscript.yml@main
with:
scan-paths: '["scripts/", "bin/", "tools/"]'Skip third-party or generated scripts:
jobs:
shellcheck:
uses: bauer-group/automation-templates/.github/workflows/modules-validate-shellscript.yml@main
with:
exclude-patterns: '["vendor/*", "node_modules/*", "*.generated.sh"]'Suppress known acceptable warnings:
jobs:
shellcheck:
uses: bauer-group/automation-templates/.github/workflows/modules-validate-shellscript.yml@main
with:
exclude-codes: '["SC1091", "SC2034", "SC2155"]'Common codes to exclude:
SC1091- Not following sourced filesSC2034- Variable appears unusedSC2155- Declare and assign separately
Enable maximum strictness with optional checks:
jobs:
shellcheck:
uses: bauer-group/automation-templates/.github/workflows/modules-validate-shellscript.yml@main
with:
severity: 'style'
enable-optional: '["require-variable-braces", "check-unassigned-uppercase"]'
fail-on-findings: trueOptional checks include:
require-variable-braces- Require${var}instead of$varcheck-unassigned-uppercase- Warn on unassigned uppercase variablesavoid-nullary-conditions- Suggest explicit comparisons
Include template or config files with shell syntax:
jobs:
shellcheck:
uses: bauer-group/automation-templates/.github/workflows/modules-validate-shellscript.yml@main
with:
additional-files: '["*.sh.tpl", "*.sh.j2", "Makefile.include"]'Report issues without failing the build:
jobs:
shellcheck:
uses: bauer-group/automation-templates/.github/workflows/modules-validate-shellscript.yml@main
with:
severity: 'info'
fail-on-findings: falseComplete validation workflow for Docker Compose projects:
name: Release
on:
push:
branches: [main]
paths-ignore:
- '*.md'
- 'docs/**'
jobs:
validate-compose:
uses: bauer-group/automation-templates/.github/workflows/modules-validate-compose.yml@main
with:
compose-file: 'docker-compose.yml'
env-template: '{"DB_PASSWORD": "test", "API_KEY": "test"}'
validate-scripts:
uses: bauer-group/automation-templates/.github/workflows/modules-validate-shellscript.yml@main
with:
scan-directory: '.'
severity: 'warning'
exclude-patterns: '["vendor/*"]'
release:
needs: [validate-compose, validate-scripts]
uses: bauer-group/automation-templates/.github/workflows/modules-semantic-release.yml@main
with:
target-branch: 'main'
secrets: inheritjobs:
shellcheck:
uses: bauer-group/automation-templates/.github/workflows/modules-validate-shellscript.yml@main
report:
needs: shellcheck
runs-on: ubuntu-latest
if: always()
steps:
- name: Report Results
run: |
echo "Validation passed: ${{ needs.shellcheck.outputs.passed }}"
echo "Files checked: ${{ needs.shellcheck.outputs.files-checked }}"
echo "Issues found: ${{ needs.shellcheck.outputs.issues-found }}"
echo " Errors: ${{ needs.shellcheck.outputs.error-count }}"
echo " Warnings: ${{ needs.shellcheck.outputs.warning-count }}"
- name: Fail on Errors Only
if: needs.shellcheck.outputs.error-count != '0'
run: exit 1| Level | Description | Example |
|---|---|---|
error |
Definite bugs or syntax errors | Missing quotes around variables with spaces |
warning |
Likely issues or bad practices | Using deprecated syntax |
info |
Suggestions for improvement | Consider using [[ ]] instead of [ ] |
style |
Pure style suggestions | Prefer $(cmd) over backticks |
| Code | Description | Why Exclude |
|---|---|---|
SC1091 |
Not following sourced files | CI can't access all includes |
SC2034 |
Variable appears unused | May be used by sourced scripts |
SC2086 |
Quote to prevent splitting | Sometimes intentional |
SC2155 |
Declare and assign separately | Style preference |
| Code | Description | Impact |
|---|---|---|
SC2006 |
Use $() instead of backticks |
Deprecation |
SC2046 |
Quote to prevent word splitting | Security |
SC2068 |
Double quote array expansions | Correctness |
SC2129 |
Group commands for efficiency | Performance |
Begin with severity: warning and tighten over time:
severity: 'warning'When excluding codes, document why:
# SC1091: External config sourced at runtime
# SC2034: Variables used by deployment scripts
exclude-codes: '["SC1091", "SC2034"]'Always include a shebang for proper dialect detection:
#!/usr/bin/env bash
# or
#!/bin/bashAllow ShellCheck to follow sourced files when possible:
external-sources: trueFor new projects, enable strict mode:
severity: 'style'
enable-optional: '["require-variable-braces"]'If validation reports 0 files:
- Check
scan-directoryorscan-pathsare correct - Ensure scripts have
.shextension or proper shebang - Verify
exclude-patternsisn't too broad
If SC1091 errors on legitimate includes:
exclude-codes: '["SC1091"]'Or ensure sourced files are in the repository.
Ensure local ShellCheck version matches CI. The module uses the latest available version.
- modules-validate-compose.yml - Validate Docker Compose files
- modules-semantic-release.yml - Create semantic releases
- modules-pr-validation.yml - Validate pull requests
- Issues: Report problems in the automation-templates repository
- Documentation: See examples in this document
- Contributing: Follow repository contribution guidelines