This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Framework Guides

Framework guides explaining main features and best practices

Articles in this section

TitleDescriptionUpdated
Configuration FilesUnderstanding configuration file management in Bash Tools Framework2026-03-01
Docker NamespaceUsing Docker functions in Bash Tools Framework2026-03-01
Best PracticesBash development best practices and recipes2026-03-01

General framework documentation explaining main framework features:

  • Configuration files loading management
  • Docker namespace usage
  • Best practices and recipes

For creating your first binary file, see the Commands documentation.

1 - Configuration Files

Understanding configuration file management in Bash Tools Framework

Inspired by Evan “Hippy” Slatis work

1. Config file format and loading rules

Configuration files loading is following these rules or best practices:

  • all env files are now loaded as properties file, it means bash arrays cannot be declared Eg: arrays should be converted to a string list separated by colon, and has to converted when needed.
  • All .env files have the ability to override value by env variable
  • all variables have to be written on one line, it is not possible to cut lines over multiple line
  • First variable set takes precedence, so writing following file would result to VAR1=value1
VAR1=value1
VAR1=value2

2. Config file overloading values

  • Best practice is to override variables only by
    • command argument –bash-framework-config to allow loading alternate env before other default files
    • command argument (–verbose, …) allows to override default displayed log level
    • in env files, always allow value to be overridden by prioritized variables
      • using bash variable default value mechanism, in following example, BASH_FRAMEWORK_LOG_LEVEL will be equal to 0 only if it hasn’t been set previously
BASH_FRAMEWORK_LOG_LEVEL="${BASH_FRAMEWORK_LOG_LEVEL:-0}"
  • Provide –config argument to see resulting config file + information about order of loaded config files for debugging purpose.

  • It is also possible to use environment variable, but highly discouraged to generalize this practice as it could lead to unwanted results if variables are not well scoped.

3. Config files loading order

The framework function Env::requireLoad loads the following files in this order if they are existing and are readable:

  • files provided in BASH_FRAMEWORK_ENV_FILES env variable array
  • ${FRAMEWORK_ROOT_DIR}/.framework-config if exists
  • .framework-config from current directory if exists
  • file from option –bash-framework-config

Options can override values provided by these env files:

  • if –verbose or -v argument is passed, set BASH_FRAMEWORK_DISPLAY_LEVEL to 3 (INFO)
  • if -vv argument is passed, set BASH_FRAMEWORK_DISPLAY_LEVEL to 4 (DEBUG)
  • later on, will manage other kind of arguments
  • additional files provided by this bash array variable, see below.
  • framework default values file, see below.

Eg: additional environment files

BASH_FRAMEWORK_ENV_FILES=("${HOME}/.bash-tools/.env" "${HOME}/.env")

Eg: framework default values file

BASH_FRAMEWORK_LOG_LEVEL="${BASH_FRAMEWORK_LOG_LEVEL:-0}"
BASH_FRAMEWORK_DISPLAY_LEVEL="${BASH_FRAMEWORK_DISPLAY_LEVEL:-${__LEVEL_WARNING}}"
BASH_FRAMEWORK_LOG_FILE="${BASH_FRAMEWORK_LOG_FILE:-"${FRAMEWORK_ROOT_DIR}/logs/${SCRIPT_NAME}.log"}"
BASH_FRAMEWORK_LOG_FILE_MAX_ROTATION="${BASH_FRAMEWORK_LOG_FILE_MAX_ROTATION:-5}"

Activity diagram to explain how Env::requireLoad is working:

how Env::requireLoad is working

activity diagram source code.

2 - Docker Namespace

Using Docker functions in Bash Tools Framework

Usage example: try to pull image from 3 tags in order (from more specific or recent to the less one)

# try to pull image from 3 tags in order (from more specific or recent to the less one)
args=(
  'id.dkr.ecr.eu-west-1.amazonaws.com/bash-tools:d93e03d5ab9e127647f575855f605bd189ca8a56'
  'id.dkr.ecr.eu-west-1.amazonaws.com/bash-tools:branchName'
  'id.dkr.ecr.eu-west-1.amazonaws.com/bash-tools:master'
)
digestPulled="$(Docker::pullImage "${args[@]}")"

# build the image using eventual image pulled as cache
# image will be tagged bash-tools:latest upon successful build
args=(
  "." ".docker/Dockerfile" "bash-tools"
  # it's important to not double quote following instruction
  $(Docker::getBuildCacheFromArg ${digestPulled})
  # you can add any additional docker build arg as needed
  --build-arg USER_ID="$(id -u)"
  --build-arg GROUP_ID="$(id -g)"
)
Docker::buildImage "${args[@]}"

# tag the image with a remote tag
args=(
  "id.dkr.ecr.eu-west-1.amazonaws.com/bash-tools"
  "bash-tools:latest"
  # tags list
  "branchName" "d93e03d5ab9e127647f575855f605bd189ca8a56"
)
Docker::tagImage "${args[@]}"

# finally push the image
args=(
  "id.dkr.ecr.eu-west-1.amazonaws.com/bash-tools"
  "bash-tools:latest"
  # tags list
  "branchName" "d93e03d5ab9e127647f575855f605bd189ca8a56"
)
Docker::pushImage "${args[@]}"

3 - Best Practices

Bash development best practices and recipes

DISCLAIMER: Some of the best practices mentioned are not fully applied in this project as they were written during development.

1. Framework-Specific Recommendations

1.1. Using @embed Keyword

The @embed keyword is really useful to inline configuration files. However, to run framework functions using sudo, it is recommended to call the same binary but passing options to change the behavior. This way the content of the script file does not seem to be obfuscated.

1.2. Function Organization

Follow the framework’s naming conventions:

  • Use Namespace::functionName pattern
  • Place functions in appropriate namespace directories
  • Include comprehensive documentation using shdoc annotations
  • Write unit tests for every function

1.3. Testing Strategy

  • Run tests on multiple Bash versions (4.4, 5.0, 5.3)
  • Test on both Ubuntu and Alpine environments
  • Use # bats test_tags=ubuntu_only for Ubuntu-specific tests
  • Leverage stub/mock capabilities for external dependencies