Thank you for your interest in contributing! This guide explains everything you need to know to add a new script, fix a bug, or improve documentation.
- Getting Started
- Workflow
- Branch Naming
- Commit Messages
- Script Style Guide
- Testing Requirements
- Pull Request Process
- Fork the repository on GitHub.
- Clone your fork locally:
git clone https://github.com/<your-username>/bash-scripts.git cd bash-scripts
- Install dev tools:
# BATS test runner sudo apt-get install -y bats # Debian/Ubuntu brew install bats-core # macOS # ShellCheck linter sudo apt-get install -y shellcheck # Debian/Ubuntu brew install shellcheck # macOS
- Verify your setup:
make test # run the full test suite make lint # run ShellCheck on all scripts
main β feature/your-script-name
β fix/short-description
β docs/what-you-updated
β chore/tooling-change
- Create a branch from
main. - Make your changes.
- Run
make testandmake lintβ both must pass. - Open a pull request against
main.
| Type | Pattern | Example |
|---|---|---|
| New script | feature/<script-name> |
feature/disk-quota-monitor |
| Bug fix | fix/<short-description> |
fix/ssl-chain-check-date-parsing |
| Documentation | docs/<what> |
docs/update-readme-examples |
| Tooling / CI | chore/<what> |
chore/update-ci-actions |
Follow the Conventional Commits format:
<type>(<scope>): <short summary>
Types: feat, fix, docs, chore, test, refactor
Examples:
feat(scripts): add disk-quota-monitor.sh with threshold alerting
fix(ssl-chain-check): correct expiry date parsing on macOS
docs(readme): add usage example for api-latency-monitor
test(backup): add edge case tests for empty archive
- Use the imperative mood: "add" not "added", "fix" not "fixed"
- Keep the summary line under 72 characters
- Reference issues with
Closes #123orFixes #123in the body
Every script must follow this standard. Run shellcheck scripts/<name>.sh before opening a PR.
#!/bin/bash
# script-name.sh β one-line description of what this script does
# Usage: ./scripts/script-name.sh [OPTIONS] <required-arg>
set -euo pipefailshow_usage() {
echo "Usage: $(basename "$0") [OPTIONS] <required-arg>"
echo ""
echo "Description of what the script does."
echo ""
echo "Options:"
echo " -h, --help Show this help message"
echo ""
echo "Arguments:"
echo " <required-arg> Description of the argument"
echo ""
echo "Examples:"
echo " $(basename "$0") my-value"
echo " $(basename "$0") --help"
exit 0
}
[[ "${1:-}" =~ ^(-h|--help)$ ]] && show_usageValidate required arguments before doing any work:
if [[ $# -lt 1 ]]; then
echo "Error: <required-arg> is required."
show_usage
fi| Code | Meaning |
|---|---|
0 |
Success / check passed |
1 |
Alert condition met, check failed, or runtime error |
2 |
Missing argument or invalid input |
- Use
[[ ]]for all conditionals (not[ ]) - Always quote variables:
"$VAR"not$VAR - Use
$(command)not`command`for command substitution - Prefer
localvariables inside functions - Write descriptive
echooutput β the user should understand what happened without reading the script - Avoid hardcoded paths; use environment variables or flags
Every script must have a corresponding test file at tests/<script-name>.bats.
@test "script file exists" { ... }
@test "required variable or constant is defined" { ... }
@test "--help flag exits cleanly" { ... }
@test "missing required argument exits with error" { ... }Add more tests for functional behavior, edge cases, and error paths.
#!/usr/bin/env bats
load 'test_helper/bats-support/load'
load 'test_helper/bats-assert/load'
setup() {
SCRIPT_PATH="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)/scripts/your-script.sh"
export SCRIPT_PATH
chmod +x "$SCRIPT_PATH"
}
teardown() {
rm -f /tmp/test_your_script_*
}
@test "script file exists" {
[ -f "$SCRIPT_PATH" ]
}
@test "--help flag exits with status 0" {
run bash "$SCRIPT_PATH" --help
assert_success
assert_output --partial "Usage:"
}
@test "missing required argument exits with error" {
run bash "$SCRIPT_PATH"
assert_failure
}- Fill out the PR template completely.
- Ensure the CI checks (ShellCheck + BATS) pass β the PR will not be merged until they do.
- Keep each PR focused on one change. Large PRs are harder to review.
- Update
CHANGELOG.mdunder[Unreleased]with a brief summary of your change. - A maintainer will review and merge approved PRs.
Open a GitHub Discussion or file an issue using the feature request template.