Skip to content

Authoring scripts

Requirements

Note

Please refer to RFC2119 for meaning of words MUST, SHOULD and MAY.

  1. MUST adhere to POSIX standard.
  2. MUST pass Shellcheck code analysis scan
  3. MUST start with:
     #!/usr/bin/env bash
     ##
     # Action description that the script performs.
     #
     # More description and usage information with a last empty
     # comment line.
     #
    
     set -eu
     [ "${DREVOPS_DEBUG-}" = "1" ] && set -x
    
  4. MUST list all variables with their default values and descriptions. i.e.:
    # Deployment reference, such as a git SHA.
    DREVOPS_NOTIFY_REF="${DREVOPS_NOTIFY_REF:-}"
    
  5. MUST include a delimiter between variables and the script body preceded and followed by an empty line (3 lines in total):
    # ------------------------------------------------------------------------------
    
  6. SHOULD include formatting helper functions:
    # @formatter:off
    note() { printf "       %s\n" "${1}"; }
    info() { [ "${TERM:-}" != "dumb" ] && tput colors >/dev/null 2>&1 && printf "\033[34m[INFO] %s\033[0m\n" "${1}" || printf "[INFO] %s\n" "${1}"; }
    pass() { [ "${TERM:-}" != "dumb" ] && tput colors >/dev/null 2>&1 && printf "\033[32m[ OK ] %s\033[0m\n" "${1}" || printf "[ OK ] %s\n" "${1}"; }
    fail() { [ "${TERM:-}" != "dumb" ] && tput colors >/dev/null 2>&1 && printf "\033[31m[FAIL] %s\033[0m\n" "${1}" || printf "[FAIL] %s\n" "${1}"; }
    # @formatter:on
    
  7. SHOULD include variable values checks with errors and early exist, i.e.:
    [ -z "${DREVOPS_NOTIFY_REF}" ] && fail "Missing required value for DREVOPS_NOTIFY_REF" && exit 1
    
  8. SHOULD include binaries checks if the script relies on them, i.e.:
    command -v curl > /dev/null || ( fail "curl command is not available." && exit 1 )
    
  9. MUST contain an info message about the start of the script body, e.g.:
    info "Started GitHub notification for operation ${DREVOPS_NOTIFY_EVENT}"
    
  10. MUST contain an pass message about the finish of the script body, e.g.:
    pass "Finished GitHub notification for operation ${DREVOPS_NOTIFY_EVENT}"
    
  11. MUST use uppercase global variables
  12. MUST use lowercase local variables.
  13. MUST use long options instead of short options for readability. I.e., drush cache:rebuild instead of drush cr.
  14. MUST use DREVOPS_ prefix for variables, unless it is a known 3-rd party variable like GITHUB_TOKEN or COMPOSER.
  15. MUST use script-specific prefix. I.e., for notify.sh, the variable to skip notifications should start with DREVOPS_NOTIFY_.
  16. MAY rely on variables from the external scripts (not prefixed with a script-specific prefix), but MUST declare such variables in the header of the file.
  17. MAY call other DrevOps scripts (discouraged), but MUST source them rather than creating a sub-process. This is to allow passing environment variables down the call stack.
  18. SHOULD use note messages for informing about the script progress.
  19. MUST use variables in the form of ${VAR}.

Variables

Follow these guidelines when creating or updating DrevOps variables.

  1. Local variables MUST be in lowercase, and global variables MUST be in uppercase.

  2. All DrevOps variables MUST start with DREVOPS_ to separate DrevOps from third-party variables.

  3. Global variables MAY be re-used as-is across scripts. For instance, the DREVOPS_WEBROOT variable is used in several scripts.

  4. DrevOps action-specific script variables MUST be scoped within their own script. For instance, the DREVOPS_PROVISION_OVERRIDE_DB variable in the provision.sh.

  5. Drupal-related variables SHOULD start with DRUPAL_ and SHOULD have a module name added as a second prefix. This is to separate DrevOps, third-party services variables, and Drupal variables. For instance, to set a user for Drupal's Shield module configuration, use DRUPAL_SHIELD_USER.

  6. Variables SHOULD NOT be exported into the global scope unless absolutely necessary. Thus, values in .env SHOULD have default values set, but SHOULD be commented out to provide visibility and avoid exposure to the global scope.

Scaffold script

Use the scaffold script below to kick-start your custom DrevOps script.

#!/usr/bin/env bash
##
# Action description that the script performs.
#
# More description and usage information with a last empty
# comment line.
#

set -eu
[ "${DREVOPS_DEBUG-}" = "1" ] && set -x

# Example scaffold variable with a default value.
DREVOPS_SCAFFOLD_EXAMPLE_URL="${DREVOPS_SCAFFOLD_EXAMPLE_URL:-http://example.com}"

# ------------------------------------------------------------------------------

# @formatter:off
note() { printf "       %s\n" "${1}"; }
info() { [ "${TERM:-}" != "dumb" ] && tput colors >/dev/null 2>&1 && printf "\033[34m[INFO] %s\033[0m\n" "${1}" || printf "[INFO] %s\n" "${1}"; }
pass() { [ "${TERM:-}" != "dumb" ] && tput colors >/dev/null 2>&1 && printf "\033[32m[ OK ] %s\033[0m\n" "${1}" || printf "[ OK ] %s\n" "${1}"; }
fail() { [ "${TERM:-}" != "dumb" ] && tput colors >/dev/null 2>&1 && printf "\033[31m[FAIL] %s\033[0m\n" "${1}" || printf "[FAIL] %s\n" "${1}"; }
# @formatter:on

info "Started scaffold operations."

[ -z "${DREVOPS_SCAFFOLD_EXAMPLE_URL}" ] && fail "Missing required value for DREVOPS_SCAFFOLD_EXAMPLE_URL" && exit 1
command -v curl >/dev/null || (fail "curl command is not available." && exit 1)

# Example of the script body.
curl -L -s -o /dev/null -w "%{http_code}" "${DREVOPS_SCAFFOLD_EXAMPLE_URL}" | grep -q '200\|403' && note "Requested example page"

pass "Finished scaffold operations."