Thank you for your interest in contributing! This document provides guidelines and instructions for contributing to this project.
This project follows a Code of Conduct that all contributors are expected to adhere to:
- Be respectful and inclusive
- Welcome newcomers and help them learn
- Focus on what is best for the community
- Show empathy towards other community members
Before creating bug reports, please check existing issues to avoid duplicates. When creating a bug report, include:
- Clear title and description
- Steps to reproduce the behavior
- Expected behavior
- Actual behavior
- Environment details (OS, version, etc.)
- Log output if applicable
Enhancement suggestions are welcome! Please provide:
- Clear use case - why is this needed?
- Proposed solution - how should it work?
- Alternatives considered - what other approaches did you think about?
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Test thoroughly
- Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Bash 4.0+ or compatible shell
- Python 3.9+ (for Python scripts)
- ShellCheck (for linting)
- BATS (for testing)
# Clone your fork
git clone https://github.com/YOUR_USERNAME/sysadmin-shell-scripts.git
cd sysadmin-shell-scripts
# Install development dependencies
# For ShellCheck
sudo dnf install ShellCheck # RHEL/CentOS/Rocky/AlmaLinux
sudo apt install shellcheck # Debian/Ubuntu
# For BATS
git clone https://github.com/bats-core/bats-core.git
cd bats-core
sudo ./install.sh /usr/local
# For Python development
pip install -r python/requirements.txt
pip install pytest pytest-cov black flake8#!/usr/bin/env bash
#################################################
# #
# Script Name and Description #
# #
#################################################
# Version: 1.0.0
# Last Updated: YYYY-MM-DD
# Author: Your NameAlways use strict error handling:
set -euo pipefail
# Source common library
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/../lib/common.sh"
# Set up cleanup trap
trap cleanup_on_exit EXIT- Use descriptive function names
- Add comments explaining what the function does
- Validate inputs
- Use
localfor function variables
# Install package using detected package manager
# Usage: install_package <package_name>
install_package() {
local package="$1"
local pkg_mgr
if [ -z "$package" ]; then
print_error "Package name required"
return 1
fi
pkg_mgr=$(get_package_manager)
print_info "Installing $package using $pkg_mgr"
case "$pkg_mgr" in
dnf|yum)
$pkg_mgr install -y "$package"
;;
apt)
apt-get install -y "$package"
;;
*)
print_error "Unsupported package manager: $pkg_mgr"
return 1
;;
esac
}UPPERCASEfor constants and environment variableslowercasefor local variables- Meaningful names, not abbreviations
# Good
readonly BACKUP_DIR="/backups"
local source_directory="/etc"
# Bad
readonly BD="/backups"
local sd="/etc"Always quote variables unless you specifically need word splitting:
# Good
if [ -f "$config_file" ]; then
source "$config_file"
fi
# Bad
if [ -f $config_file ]; then
source $config_file
fiLeverage the common library instead of duplicating code:
# Good
require_root
validate_domain "$domain"
log_info "Starting installation"
# Bad
if [[ $EUID -ne 0 ]]; then
echo "Must be root"
exit 1
fiFollow PEP 8 and use type hints:
#!/usr/bin/env python3
"""
Module description.
"""
import argparse
from typing import Dict, List, Optional
def process_data(input_data: List[str], options: Optional[Dict] = None) -> List[str]:
"""
Process input data according to options.
Args:
input_data: List of strings to process
options: Optional configuration dictionary
Returns:
Processed list of strings
"""
if options is None:
options = {}
# Implementation
return processed_data- Python 3.9+ features
- Type hints everywhere
- Dataclasses for data structures
- f-strings for formatting
import sys
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
try:
result = risky_operation()
except SpecificException as e:
logger.error(f"Operation failed: {e}")
sys.exit(1)Create test files in tests/ directory:
#!/usr/bin/env bats
# tests/test_common.sh
load test_helper
@test "detect_os returns valid os family" {
source lib/common.sh
result=$(detect_os)
[[ "$result" =~ ^(rhel|debian|arch|unknown)$ ]]
}
@test "validate_ip accepts valid IP" {
source lib/common.sh
run validate_ip "192.168.1.1"
[ "$status" -eq 0 ]
}
@test "validate_ip rejects invalid IP" {
source lib/common.sh
run validate_ip "999.999.999.999"
[ "$status" -eq 1 ]
}Run tests:
bats tests/test_common.sh# tests/test_python.py
import pytest
from python.port_check import check_port
def test_check_port_valid():
result = check_port("localhost", 22, timeout=1)
assert isinstance(result, dict)
assert "open" in result
def test_check_port_invalid_port():
with pytest.raises(ValueError):
check_port("localhost", 99999)Run tests:
pytest tests/test_python.py -vFollow conventional commit format:
type(scope): subject
body
footer
Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Formatting changesrefactor: Code refactoringtest: Adding testschore: Maintenance tasks
Example:
feat(backup): add S3 support for remote backups
- Implement S3 upload functionality
- Add AWS credentials configuration
- Update backup.conf.example with S3 options
Closes #123
- Update documentation if adding features
- Add tests for new functionality
- Run linters:
shellcheck installation_scripts/*.sh black python/*.py flake8 python/*.py
- Run tests:
bats tests/*.sh pytest tests/ - Update CHANGELOG.md with your changes
- Request review from maintainers
All submissions require review. Reviewers will check:
- Code quality and style
- Test coverage
- Documentation completeness
- Security implications
- Backward compatibility
If you have questions:
- Check existing documentation
- Search existing issues
- Create a new issue with your question
- Join our community discussions
Thank you for contributing!