diff --git a/.config/docs/start.sh b/.config/docs/start.sh
new file mode 100644
index 00000000..c380a48b
--- /dev/null
+++ b/.config/docs/start.sh
@@ -0,0 +1,334 @@
+#!/usr/bin/env bash
+
+# @file .config/scripts/start.sh
+# @brief Ensures Task is installed and up-to-date and then runs `task start`
+# @description
+# This script will ensure [Task](https://github.com/go-task/task) is up-to-date
+# and then run the `start` task which is generally a good entrypoint for any repository
+# that is using the Megabyte Labs templating/taskfile system. The `start` task will
+# ensure that the latest upstream changes are retrieved, that the project is
+# properly generated with them, and that all the development dependencies are installed.
+
+set -eo pipefail
+
+# @description Ensure .config/log is executable
+if [ -f .config/log ]; then
+ chmod +x .config/log
+fi
+
+# @description Installs package when user is root on Linux
+#
+# @example
+# ensureRootPackageInstalled "sudo"
+#
+# @arg $1 string The name of the package that must be present
+#
+# @exitcode 0 The package was successfully installed
+# @exitcode 1+ If there was an error, the package needs to be installed manually, or if the OS is unsupported
+function ensureRootPackageInstalled() {
+ if ! type "$1" &> /dev/null; then
+ if [[ "$OSTYPE" == 'linux'* ]]; then
+ if [ -f "/etc/redhat-release" ]; then
+ yum update
+ yum install -y "$1"
+ elif [ -f "/etc/lsb-release" ]; then
+ apt update
+ apt install -y "$1"
+ elif [ -f "/etc/arch-release" ]; then
+ pacman update
+ pacman -S "$1"
+ elif [ -f "/etc/alpine-release" ]; then
+ apk update
+ apk add -y "$1"
+ fi
+ fi
+ fi
+}
+
+# @description If the user is running this script as root, then create a new user named
+# megabyte and restart the script with that user. This is required because Homebrew
+# can only be invoked by non-root users.
+if [ "$EUID" -eq 0 ] && [ -z "$INIT_CWD" ] && type useradd &> /dev/null; then
+ # shellcheck disable=SC2016
+ echo 'INFO: Running as root - creating seperate user named `megabyte` to run script with'
+ echo "megabyte ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
+ useradd -m -s "$(which bash)" -c "Megabyte Labs Homebrew Account" megabyte
+ ensureRootPackageInstalled "sudo"
+ # shellcheck disable=SC2016
+ echo 'INFO: Reloading the script with the `megabyte` user'
+ exec su megabyte "$0" -- "$@"
+fi
+
+# @description Detect script paths
+BASH_SRC="$(dirname "${BASH_SOURCE[0]}")"
+SOURCE_PATH="$(
+ cd "$BASH_SRC"
+ pwd -P
+)"
+PROJECT_BASE_DIR="$SOURCE_PATH/../.."
+
+# @description Ensures ~/.local/bin is in the PATH variable on *nix machines and
+# exits with an error on unsupported OS types
+#
+# @example
+# ensureLocalPath
+#
+# @set PATH string The updated PATH with a reference to ~/.local/bin
+#
+# @noarg
+#
+# @exitcode 0 If the PATH was appropriately updated or did not need updating
+# @exitcode 1+ If the OS is unsupported
+function ensureLocalPath() {
+ if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux'* ]]; then
+ # shellcheck disable=SC2016
+ PATH_STRING='PATH="$HOME/.local/bin:$PATH"'
+ mkdir -p "$HOME/.local/bin"
+ if grep -L "$PATH_STRING" "$HOME/.profile" > /dev/null; then
+ echo -e "${PATH_STRING}\n" >> "$HOME/.profile"
+ echo "INFO: Updated the PATH variable to include ~/.local/bin in $HOME/.profile"
+ fi
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "FreeBSD support not added yet" && exit 1
+ else
+ echo "System type not recognized"
+ fi
+}
+
+# @description Ensures given package is installed on a system.
+#
+# @example
+# ensurePackageInstalled "curl"
+#
+# @arg $1 string The name of the package that must be present
+#
+# @exitcode 0 The package(s) were successfully installed
+# @exitcode 1+ If there was an error, the package needs to be installed manually, or if the OS is unsupported
+function ensurePackageInstalled() {
+ if ! type "$1" &> /dev/null; then
+ if [[ "$OSTYPE" == 'darwin'* ]]; then
+ brew install "$1"
+ elif [[ "$OSTYPE" == 'linux'* ]]; then
+ if [ -f "/etc/redhat-release" ]; then
+ sudo yum update
+ sudo yum install -y "$1"
+ elif [ -f "/etc/lsb-release" ]; then
+ sudo apt update
+ sudo apt install -y "$1"
+ elif [ -f "/etc/arch-release" ]; then
+ sudo pacman update
+ sudo pacman -S "$1"
+ elif [ -f "/etc/alpine-release" ]; then
+ apk update
+ apk add -y "$1"
+ else
+ echo "ERROR: $1 is missing. Please install $1 to continue." && exit 1
+ fi
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "ERROR: Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "ERROR: FreeBSD support not added yet" && exit 1
+ else
+ echo "ERROR: System type not recognized"
+ fi
+ fi
+}
+
+# @description Ensures the latest version of Task is installed to `/usr/local/bin` (or `~/.local/bin`, as
+# a fallback.
+#
+# @example
+# ensureTaskInstalled
+#
+# @noarg
+#
+# @exitcode 0 If the package is already present and up-to-date or if it was installed/updated
+# @exitcode 1+ If the OS is unsupported or if there was an error either installing the package or setting the PATH
+function ensureTaskInstalled() {
+ # @description Release API URL used to get the latest release's version
+ TASK_RELEASE_API="https://api.github.com/repos/go-task/task/releases/latest"
+ if ! type task &> /dev/null; then
+ if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl' ]]; then
+ installTask
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "ERROR: Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "ERROR: FreeBSD support not added yet" && exit 1
+ else
+ echo "ERROR: System type not recognized. You must install task manually." && exit 1
+ fi
+ else
+ echo "INFO: Checking for latest version of Task"
+ CURRENT_VERSION="$(task --version | cut -d' ' -f3 | cut -c 2-)"
+ LATEST_VERSION="$(curl -s "$TASK_RELEASE_API" | grep tag_name | cut -c 17- | sed 's/\",//')"
+ if printf '%s\n%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V -c &> /dev/null; then
+ echo "INFO: Task is already up-to-date"
+ else
+ echo "INFO: A new version of Task is available (version $LATEST_VERSION)"
+ echo "INFO: The current version of Task installed is $CURRENT_VERSION"
+ # Replace with rm "$(which task)" &> /dev/null when ready
+ if ! type task &> /dev/null; then
+ installTask
+ else
+ echo "WARNING: Unable to remove previous version of Task"
+ fi
+ fi
+ fi
+}
+
+# @description Helper function for ensureTaskInstalled that performs the installation of Task.
+#
+# @see ensureTaskInstalled
+#
+# @example
+# installTask
+#
+# @noarg
+#
+# @exitcode 0 If Task installs/updates properly
+# @exitcode 1+ If the installation fails
+function installTask() {
+ # @description Release URL to use when downloading [Task](https://github.com/go-task/task)
+ TASK_RELEASE_URL="https://github.com/go-task/task/releases/latest"
+ CHECKSUM_DESTINATION=/tmp/megabytelabs/task_checksums.txt
+ CHECKSUMS_URL="$TASK_RELEASE_URL/download/task_checksums.txt"
+ DOWNLOAD_DESTINATION=/tmp/megabytelabs/task.tar.gz
+ TMP_DIR=/tmp/megabytelabs
+ if [[ "$OSTYPE" == 'darwin'* ]]; then
+ DOWNLOAD_URL="$TASK_RELEASE_URL/download/task_darwin_amd64.tar.gz"
+ else
+ DOWNLOAD_URL="$TASK_RELEASE_URL/download/task_linux_amd64.tar.gz"
+ fi
+ mkdir -p "$(dirname "$DOWNLOAD_DESTINATION")"
+ echo "INFO: Downloading latest version of Task"
+ curl -sSL "$DOWNLOAD_URL" -o "$DOWNLOAD_DESTINATION"
+ curl -sSL "$CHECKSUMS_URL" -o "$CHECKSUM_DESTINATION"
+ DOWNLOAD_BASENAME="$(basename "$DOWNLOAD_URL")"
+ DOWNLOAD_SHA256="$(grep "$DOWNLOAD_BASENAME" < "$CHECKSUM_DESTINATION" | cut -d ' ' -f 1)"
+ sha256 "$DOWNLOAD_DESTINATION" "$DOWNLOAD_SHA256" > /dev/null
+ echo "SUCCESS: Validated checksum"
+ mkdir -p "$TMP_DIR/task"
+ tar -xzvf "$DOWNLOAD_DESTINATION" -C "$TMP_DIR/task" > /dev/null
+ if type task &> /dev/null && [ -w "$(which task)" ]; then
+ TARGET_DEST="$(which task)"
+ else
+ if [ -w /usr/local/bin ]; then
+ TARGET_BIN_DIR='/usr/local/bin'
+ else
+ TARGET_BIN_DIR="$HOME/.local/bin"
+ fi
+ TARGET_DEST="$TARGET_BIN_DIR/task"
+ mkdir -p "$TARGET_BIN_DIR"
+ fi
+ mv "$TMP_DIR/task/task" "$TARGET_DEST"
+ echo "SUCCESS: Installed Task to $TARGET_DEST"
+ rm "$CHECKSUM_DESTINATION"
+ rm "$DOWNLOAD_DESTINATION"
+}
+
+# @description Verifies the SHA256 checksum of a file
+#
+# @example
+# sha256 myfile.tar.gz 5b30f9c042553141791ec753d2f96786c60a4968fd809f75bb0e8db6c6b4529b
+#
+# @arg $1 string Path to the file
+# @arg $2 string The SHA256 signature
+#
+# @exitcode 0 The checksum is valid or the system is unrecognized
+# @exitcode 1+ The OS is unsupported or if the checksum is invalid
+function sha256() {
+ echo "$2"
+ echo "$1"
+ if [[ "$OSTYPE" == 'darwin'* ]]; then
+ if type brew &> /dev/null && ! type sha256sum &> /dev/null; then
+ brew install coreutils
+ else
+ echo "WARNING: Brew is not installed - this may cause issues"
+ fi
+ if type brew &> /dev/null; then
+ PATH="$(brew --prefix)/opt/coreutils/libexec/gnubin:$PATH"
+ fi
+ if type sha256sum &> /dev/null; then
+ echo "$2 $1" | sha256sum -c
+ else
+ echo "WARNING: Checksum validation is being skipped for $1 because the sha256sum program is not available"
+ fi
+ elif [[ "$OSTYPE" == 'linux-gnu'* ]]; then
+ if ! type shasum &> /dev/null; then
+ echo "WARNING: Checksum validation is being skipped for $1 because the shasum program is not installed"
+ else
+ echo "$2 $1" | shasum -s -a 256 -c
+ fi
+ elif [[ "$OSTYPE" == 'linux-musl' ]]; then
+ if ! type sha256sum &> /dev/null; then
+ echo "WARNING: Checksum validation is being skipped for $1 because the sha256sum program is not available"
+ else
+ echo "$2 $1" | sha256sum -c
+ fi
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "ERROR: Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "ERROR: FreeBSD support not added yet" && exit 1
+ else
+ echo "WARNING: System type not recognized. Skipping checksum validation."
+ fi
+}
+
+##### Main Logic #####
+
+if [ ! -f "$HOME/.profile" ]; then
+ touch "$HOME/.profile"
+fi
+
+# @description Ensures ~/.local/bin is in PATH
+ensureLocalPath
+
+# @description Ensures base dependencies are installed
+if [[ "$OSTYPE" == 'darwin'* ]]; then
+ if ! type curl &> /dev/null && type brew &> /dev/null; then
+ brew install curl
+ else
+ echo "ERROR: Neither curl nor brew are installed. Install one of them manually and try again."
+ fi
+ if ! type git &> /dev/null; then
+ # shellcheck disable=SC2016
+ echo 'INFO: Git is not present. A password may be required to run `sudo xcode-select --install`'
+ sudo xcode-select --install
+ fi
+elif [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl'* ]]; then
+ if ! type curl &> /dev/null || ! type git &> /dev/null; then
+ ensurePackageInstalled "curl"
+ ensurePackageInstalled "git"
+ fi
+fi
+
+# @description Ensures Homebrew and Poetry are installed
+if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl'* ]]; then
+ if ! type brew &> /dev/null && [ -z "$INIT_CWD" ]; then
+ echo "WARNING: Homebrew is not installed. The script will attempt to install Homebrew and you might be prompted for your password."
+ bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
+ fi
+fi
+
+# @description Attempts to pull the latest changes if the folder is a git repository
+cd "$PROJECT_BASE_DIR" || exit
+if [ -d .git ] && type git &> /dev/null; then
+ HTTPS_VERSION="$(git remote get-url origin | sed 's/git@gitlab.com:/https:\/\/gitlab.com\//')"
+ git pull "$HTTPS_VERSION" master --ff-only
+ git submodule update --init --recursive
+fi
+
+# @description Ensures Task is installed and properly configured
+ensureTaskInstalled
+
+# @description Run the start logic, if appropriate
+cd "$PROJECT_BASE_DIR" || exit
+if [ -z "$GITLAB_CI" ] && [ -z "$INIT_CWD" ]; then
+ # shellcheck disable=SC1091
+ . "$HOME/.profile"
+ task start
+ # shellcheck disable=SC2028
+ echo 'INFO: There may have been changes to your PATH variable. You may have to reload your terminal or run:\n\n`. '"$HOME/.profile"'`'
+fi
diff --git a/.config/docs/update-init.sh b/.config/docs/update-init.sh
new file mode 100644
index 00000000..c380a48b
--- /dev/null
+++ b/.config/docs/update-init.sh
@@ -0,0 +1,334 @@
+#!/usr/bin/env bash
+
+# @file .config/scripts/start.sh
+# @brief Ensures Task is installed and up-to-date and then runs `task start`
+# @description
+# This script will ensure [Task](https://github.com/go-task/task) is up-to-date
+# and then run the `start` task which is generally a good entrypoint for any repository
+# that is using the Megabyte Labs templating/taskfile system. The `start` task will
+# ensure that the latest upstream changes are retrieved, that the project is
+# properly generated with them, and that all the development dependencies are installed.
+
+set -eo pipefail
+
+# @description Ensure .config/log is executable
+if [ -f .config/log ]; then
+ chmod +x .config/log
+fi
+
+# @description Installs package when user is root on Linux
+#
+# @example
+# ensureRootPackageInstalled "sudo"
+#
+# @arg $1 string The name of the package that must be present
+#
+# @exitcode 0 The package was successfully installed
+# @exitcode 1+ If there was an error, the package needs to be installed manually, or if the OS is unsupported
+function ensureRootPackageInstalled() {
+ if ! type "$1" &> /dev/null; then
+ if [[ "$OSTYPE" == 'linux'* ]]; then
+ if [ -f "/etc/redhat-release" ]; then
+ yum update
+ yum install -y "$1"
+ elif [ -f "/etc/lsb-release" ]; then
+ apt update
+ apt install -y "$1"
+ elif [ -f "/etc/arch-release" ]; then
+ pacman update
+ pacman -S "$1"
+ elif [ -f "/etc/alpine-release" ]; then
+ apk update
+ apk add -y "$1"
+ fi
+ fi
+ fi
+}
+
+# @description If the user is running this script as root, then create a new user named
+# megabyte and restart the script with that user. This is required because Homebrew
+# can only be invoked by non-root users.
+if [ "$EUID" -eq 0 ] && [ -z "$INIT_CWD" ] && type useradd &> /dev/null; then
+ # shellcheck disable=SC2016
+ echo 'INFO: Running as root - creating seperate user named `megabyte` to run script with'
+ echo "megabyte ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
+ useradd -m -s "$(which bash)" -c "Megabyte Labs Homebrew Account" megabyte
+ ensureRootPackageInstalled "sudo"
+ # shellcheck disable=SC2016
+ echo 'INFO: Reloading the script with the `megabyte` user'
+ exec su megabyte "$0" -- "$@"
+fi
+
+# @description Detect script paths
+BASH_SRC="$(dirname "${BASH_SOURCE[0]}")"
+SOURCE_PATH="$(
+ cd "$BASH_SRC"
+ pwd -P
+)"
+PROJECT_BASE_DIR="$SOURCE_PATH/../.."
+
+# @description Ensures ~/.local/bin is in the PATH variable on *nix machines and
+# exits with an error on unsupported OS types
+#
+# @example
+# ensureLocalPath
+#
+# @set PATH string The updated PATH with a reference to ~/.local/bin
+#
+# @noarg
+#
+# @exitcode 0 If the PATH was appropriately updated or did not need updating
+# @exitcode 1+ If the OS is unsupported
+function ensureLocalPath() {
+ if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux'* ]]; then
+ # shellcheck disable=SC2016
+ PATH_STRING='PATH="$HOME/.local/bin:$PATH"'
+ mkdir -p "$HOME/.local/bin"
+ if grep -L "$PATH_STRING" "$HOME/.profile" > /dev/null; then
+ echo -e "${PATH_STRING}\n" >> "$HOME/.profile"
+ echo "INFO: Updated the PATH variable to include ~/.local/bin in $HOME/.profile"
+ fi
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "FreeBSD support not added yet" && exit 1
+ else
+ echo "System type not recognized"
+ fi
+}
+
+# @description Ensures given package is installed on a system.
+#
+# @example
+# ensurePackageInstalled "curl"
+#
+# @arg $1 string The name of the package that must be present
+#
+# @exitcode 0 The package(s) were successfully installed
+# @exitcode 1+ If there was an error, the package needs to be installed manually, or if the OS is unsupported
+function ensurePackageInstalled() {
+ if ! type "$1" &> /dev/null; then
+ if [[ "$OSTYPE" == 'darwin'* ]]; then
+ brew install "$1"
+ elif [[ "$OSTYPE" == 'linux'* ]]; then
+ if [ -f "/etc/redhat-release" ]; then
+ sudo yum update
+ sudo yum install -y "$1"
+ elif [ -f "/etc/lsb-release" ]; then
+ sudo apt update
+ sudo apt install -y "$1"
+ elif [ -f "/etc/arch-release" ]; then
+ sudo pacman update
+ sudo pacman -S "$1"
+ elif [ -f "/etc/alpine-release" ]; then
+ apk update
+ apk add -y "$1"
+ else
+ echo "ERROR: $1 is missing. Please install $1 to continue." && exit 1
+ fi
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "ERROR: Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "ERROR: FreeBSD support not added yet" && exit 1
+ else
+ echo "ERROR: System type not recognized"
+ fi
+ fi
+}
+
+# @description Ensures the latest version of Task is installed to `/usr/local/bin` (or `~/.local/bin`, as
+# a fallback.
+#
+# @example
+# ensureTaskInstalled
+#
+# @noarg
+#
+# @exitcode 0 If the package is already present and up-to-date or if it was installed/updated
+# @exitcode 1+ If the OS is unsupported or if there was an error either installing the package or setting the PATH
+function ensureTaskInstalled() {
+ # @description Release API URL used to get the latest release's version
+ TASK_RELEASE_API="https://api.github.com/repos/go-task/task/releases/latest"
+ if ! type task &> /dev/null; then
+ if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl' ]]; then
+ installTask
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "ERROR: Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "ERROR: FreeBSD support not added yet" && exit 1
+ else
+ echo "ERROR: System type not recognized. You must install task manually." && exit 1
+ fi
+ else
+ echo "INFO: Checking for latest version of Task"
+ CURRENT_VERSION="$(task --version | cut -d' ' -f3 | cut -c 2-)"
+ LATEST_VERSION="$(curl -s "$TASK_RELEASE_API" | grep tag_name | cut -c 17- | sed 's/\",//')"
+ if printf '%s\n%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V -c &> /dev/null; then
+ echo "INFO: Task is already up-to-date"
+ else
+ echo "INFO: A new version of Task is available (version $LATEST_VERSION)"
+ echo "INFO: The current version of Task installed is $CURRENT_VERSION"
+ # Replace with rm "$(which task)" &> /dev/null when ready
+ if ! type task &> /dev/null; then
+ installTask
+ else
+ echo "WARNING: Unable to remove previous version of Task"
+ fi
+ fi
+ fi
+}
+
+# @description Helper function for ensureTaskInstalled that performs the installation of Task.
+#
+# @see ensureTaskInstalled
+#
+# @example
+# installTask
+#
+# @noarg
+#
+# @exitcode 0 If Task installs/updates properly
+# @exitcode 1+ If the installation fails
+function installTask() {
+ # @description Release URL to use when downloading [Task](https://github.com/go-task/task)
+ TASK_RELEASE_URL="https://github.com/go-task/task/releases/latest"
+ CHECKSUM_DESTINATION=/tmp/megabytelabs/task_checksums.txt
+ CHECKSUMS_URL="$TASK_RELEASE_URL/download/task_checksums.txt"
+ DOWNLOAD_DESTINATION=/tmp/megabytelabs/task.tar.gz
+ TMP_DIR=/tmp/megabytelabs
+ if [[ "$OSTYPE" == 'darwin'* ]]; then
+ DOWNLOAD_URL="$TASK_RELEASE_URL/download/task_darwin_amd64.tar.gz"
+ else
+ DOWNLOAD_URL="$TASK_RELEASE_URL/download/task_linux_amd64.tar.gz"
+ fi
+ mkdir -p "$(dirname "$DOWNLOAD_DESTINATION")"
+ echo "INFO: Downloading latest version of Task"
+ curl -sSL "$DOWNLOAD_URL" -o "$DOWNLOAD_DESTINATION"
+ curl -sSL "$CHECKSUMS_URL" -o "$CHECKSUM_DESTINATION"
+ DOWNLOAD_BASENAME="$(basename "$DOWNLOAD_URL")"
+ DOWNLOAD_SHA256="$(grep "$DOWNLOAD_BASENAME" < "$CHECKSUM_DESTINATION" | cut -d ' ' -f 1)"
+ sha256 "$DOWNLOAD_DESTINATION" "$DOWNLOAD_SHA256" > /dev/null
+ echo "SUCCESS: Validated checksum"
+ mkdir -p "$TMP_DIR/task"
+ tar -xzvf "$DOWNLOAD_DESTINATION" -C "$TMP_DIR/task" > /dev/null
+ if type task &> /dev/null && [ -w "$(which task)" ]; then
+ TARGET_DEST="$(which task)"
+ else
+ if [ -w /usr/local/bin ]; then
+ TARGET_BIN_DIR='/usr/local/bin'
+ else
+ TARGET_BIN_DIR="$HOME/.local/bin"
+ fi
+ TARGET_DEST="$TARGET_BIN_DIR/task"
+ mkdir -p "$TARGET_BIN_DIR"
+ fi
+ mv "$TMP_DIR/task/task" "$TARGET_DEST"
+ echo "SUCCESS: Installed Task to $TARGET_DEST"
+ rm "$CHECKSUM_DESTINATION"
+ rm "$DOWNLOAD_DESTINATION"
+}
+
+# @description Verifies the SHA256 checksum of a file
+#
+# @example
+# sha256 myfile.tar.gz 5b30f9c042553141791ec753d2f96786c60a4968fd809f75bb0e8db6c6b4529b
+#
+# @arg $1 string Path to the file
+# @arg $2 string The SHA256 signature
+#
+# @exitcode 0 The checksum is valid or the system is unrecognized
+# @exitcode 1+ The OS is unsupported or if the checksum is invalid
+function sha256() {
+ echo "$2"
+ echo "$1"
+ if [[ "$OSTYPE" == 'darwin'* ]]; then
+ if type brew &> /dev/null && ! type sha256sum &> /dev/null; then
+ brew install coreutils
+ else
+ echo "WARNING: Brew is not installed - this may cause issues"
+ fi
+ if type brew &> /dev/null; then
+ PATH="$(brew --prefix)/opt/coreutils/libexec/gnubin:$PATH"
+ fi
+ if type sha256sum &> /dev/null; then
+ echo "$2 $1" | sha256sum -c
+ else
+ echo "WARNING: Checksum validation is being skipped for $1 because the sha256sum program is not available"
+ fi
+ elif [[ "$OSTYPE" == 'linux-gnu'* ]]; then
+ if ! type shasum &> /dev/null; then
+ echo "WARNING: Checksum validation is being skipped for $1 because the shasum program is not installed"
+ else
+ echo "$2 $1" | shasum -s -a 256 -c
+ fi
+ elif [[ "$OSTYPE" == 'linux-musl' ]]; then
+ if ! type sha256sum &> /dev/null; then
+ echo "WARNING: Checksum validation is being skipped for $1 because the sha256sum program is not available"
+ else
+ echo "$2 $1" | sha256sum -c
+ fi
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "ERROR: Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "ERROR: FreeBSD support not added yet" && exit 1
+ else
+ echo "WARNING: System type not recognized. Skipping checksum validation."
+ fi
+}
+
+##### Main Logic #####
+
+if [ ! -f "$HOME/.profile" ]; then
+ touch "$HOME/.profile"
+fi
+
+# @description Ensures ~/.local/bin is in PATH
+ensureLocalPath
+
+# @description Ensures base dependencies are installed
+if [[ "$OSTYPE" == 'darwin'* ]]; then
+ if ! type curl &> /dev/null && type brew &> /dev/null; then
+ brew install curl
+ else
+ echo "ERROR: Neither curl nor brew are installed. Install one of them manually and try again."
+ fi
+ if ! type git &> /dev/null; then
+ # shellcheck disable=SC2016
+ echo 'INFO: Git is not present. A password may be required to run `sudo xcode-select --install`'
+ sudo xcode-select --install
+ fi
+elif [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl'* ]]; then
+ if ! type curl &> /dev/null || ! type git &> /dev/null; then
+ ensurePackageInstalled "curl"
+ ensurePackageInstalled "git"
+ fi
+fi
+
+# @description Ensures Homebrew and Poetry are installed
+if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl'* ]]; then
+ if ! type brew &> /dev/null && [ -z "$INIT_CWD" ]; then
+ echo "WARNING: Homebrew is not installed. The script will attempt to install Homebrew and you might be prompted for your password."
+ bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
+ fi
+fi
+
+# @description Attempts to pull the latest changes if the folder is a git repository
+cd "$PROJECT_BASE_DIR" || exit
+if [ -d .git ] && type git &> /dev/null; then
+ HTTPS_VERSION="$(git remote get-url origin | sed 's/git@gitlab.com:/https:\/\/gitlab.com\//')"
+ git pull "$HTTPS_VERSION" master --ff-only
+ git submodule update --init --recursive
+fi
+
+# @description Ensures Task is installed and properly configured
+ensureTaskInstalled
+
+# @description Run the start logic, if appropriate
+cd "$PROJECT_BASE_DIR" || exit
+if [ -z "$GITLAB_CI" ] && [ -z "$INIT_CWD" ]; then
+ # shellcheck disable=SC1091
+ . "$HOME/.profile"
+ task start
+ # shellcheck disable=SC2028
+ echo 'INFO: There may have been changes to your PATH variable. You may have to reload your terminal or run:\n\n`. '"$HOME/.profile"'`'
+fi
diff --git a/.config/docs/variables.json b/.config/docs/variables.json
index 7b919cf9..5a4514d4 100644
--- a/.config/docs/variables.json
+++ b/.config/docs/variables.json
@@ -64,6 +64,11 @@
}
],
"group": "ansible",
+ "homebrew": {
+ "folder": "Formula",
+ "name": "homebrew-tap",
+ "owner": "installdoc"
+ },
"hostapp_var_chart": [
["App", "Description"],
["**[Authelia](https://www.authelia.com/)**", "An authentication portal that supports SSO and 2FA"],
@@ -96,6 +101,7 @@
["**[Tautulli](https://docs.linuxserver.io/images/docker-tautulli)**", "Metrics and monitoring for Plex"],
["**[Transmission](https://docs.linuxserver.io/images/docker-transmission)**", "BitTorrent client"]
],
+ "idPost": "megabyte.space",
"json_top_keys": "",
"license": "MIT",
"link": {
@@ -150,6 +156,7 @@
"overview": "[[ This is a new repository without the details filled in yet. Look for the section about blueprint data in the CONTRIBUTING.md to set up the project. ]]",
"playbook_path": "megabyte-labs/gas-station",
"profile": {
+ "dockerHubUser": "professormanhattan",
"dockerhub": "megabytelabs",
"galaxy": "professormanhattan",
"github": "ProfessorManhattan",
@@ -261,6 +268,52 @@
""
]
],
+ "releaseRules": [
+ {
+ "release": "patch",
+ "type": "build"
+ },
+ {
+ "release": "patch",
+ "type": "ci"
+ },
+ {
+ "release": false,
+ "type": "chore"
+ },
+ {
+ "release": false,
+ "type": "docs"
+ },
+ {
+ "release": "patch",
+ "type": "fix"
+ },
+ {
+ "release": "minor",
+ "type": "feat"
+ },
+ {
+ "release": "patch",
+ "type": "refactor"
+ },
+ {
+ "release": "patch",
+ "type": "revert"
+ },
+ {
+ "release": "patch",
+ "type": "perf"
+ },
+ {
+ "release": false,
+ "type": "style"
+ },
+ {
+ "release": false,
+ "type": "test"
+ }
+ ],
"repository": {
"github": "",
"gitlab": "",
diff --git a/.config/log b/.config/log
index aade526a..9abe2c39 100755
--- a/.config/log
+++ b/.config/log
@@ -14,7 +14,7 @@
if [ "${container:=}" != 'docker' ] && type node > /dev/null && [ -f './node_modules/chalk/package.json' ] \
&& [ -f './node_modules/string-break/package.json' ]; then
- ENHANCED_LOGGING=true
+ echo "Disabled enhanced logging temporarily"
fi
# @description Logs using Node.js
@@ -26,7 +26,7 @@ logger() {
# @description Logs an error message
# @example .config/log error "Something happened!"
error() {
- if [ "$ENHANCED_LOGGING" ]; then
+ if [ -n "$ENHANCED_LOGGING" ]; then
logger error "$1"
else
echo "ERROR: $1"
@@ -36,7 +36,7 @@ error() {
# @description Logs an info message
# @example .config/log info "Here is some information"
info() {
- if [ "$ENHANCED_LOGGING" ]; then
+ if [ -n "$ENHANCED_LOGGING" ]; then
logger info "$1"
else
echo "INFO: $1"
@@ -46,7 +46,7 @@ info() {
# @description Logs a message that starts with a star emoji
# @example .config/log star "Congratulations"
star() {
- if [ "$ENHANCED_LOGGING" ]; then
+ if [ -n "$ENHANCED_LOGGING" ]; then
logger star "$1"
else
echo "STAR: $1"
@@ -56,7 +56,7 @@ star() {
# @description Logs a success message
# @example .config/log success "Yay!"
success() {
- if [ "$ENHANCED_LOGGING" ]; then
+ if [ -n "$ENHANCED_LOGGING" ]; then
logger success "$1"
else
echo "SUCCESS: $1"
@@ -66,7 +66,7 @@ success() {
# @description Logs a warning message
# @example .config/log warn "Just so you know.."
warn() {
- if [ "$ENHANCED_LOGGING" ]; then
+ if [ -n "$ENHANCED_LOGGING" ]; then
logger warn "$1"
else
echo "WARNING: $1"
diff --git a/.config/nodemon.json b/.config/nodemon.json
new file mode 100644
index 00000000..d879e11a
--- /dev/null
+++ b/.config/nodemon.json
@@ -0,0 +1,4 @@
+{
+ "exec": "task project:livereload",
+ "ext": "py,yml"
+}
diff --git a/.config/scripts/prompts/environment.js b/.config/prompts/environment.js
similarity index 100%
rename from .config/scripts/prompts/environment.js
rename to .config/prompts/environment.js
diff --git a/.config/scripts/prompts/gitlab-group.js b/.config/prompts/gitlab-group.js
similarity index 100%
rename from .config/scripts/prompts/gitlab-group.js
rename to .config/prompts/gitlab-group.js
diff --git a/.config/scripts/prompts/lib/decorate-files.js b/.config/prompts/lib/decorate-files.js
similarity index 100%
rename from .config/scripts/prompts/lib/decorate-files.js
rename to .config/prompts/lib/decorate-files.js
diff --git a/.config/scripts/prompts/lib/decorate-system.js b/.config/prompts/lib/decorate-system.js
similarity index 100%
rename from .config/scripts/prompts/lib/decorate-system.js
rename to .config/prompts/lib/decorate-system.js
diff --git a/.config/scripts/prompts/lib/log.js b/.config/prompts/lib/log.js
similarity index 100%
rename from .config/scripts/prompts/lib/log.js
rename to .config/prompts/lib/log.js
diff --git a/.config/scripts/prompts/molecule/desktop.js b/.config/prompts/molecule/desktop.js
similarity index 100%
rename from .config/scripts/prompts/molecule/desktop.js
rename to .config/prompts/molecule/desktop.js
diff --git a/.config/scripts/prompts/molecule/docker.js b/.config/prompts/molecule/docker.js
similarity index 100%
rename from .config/scripts/prompts/molecule/docker.js
rename to .config/prompts/molecule/docker.js
diff --git a/.config/scripts/prompts/molecule/local.js b/.config/prompts/molecule/local.js
similarity index 100%
rename from .config/scripts/prompts/molecule/local.js
rename to .config/prompts/molecule/local.js
diff --git a/.config/scripts/prompts/molecule/molecule.js b/.config/prompts/molecule/molecule.js
similarity index 100%
rename from .config/scripts/prompts/molecule/molecule.js
rename to .config/prompts/molecule/molecule.js
diff --git a/.config/scripts/prompts/molecule/playbook.js b/.config/prompts/molecule/playbook.js
similarity index 100%
rename from .config/scripts/prompts/molecule/playbook.js
rename to .config/prompts/molecule/playbook.js
diff --git a/.config/scripts/prompts/molecule/ssh.js b/.config/prompts/molecule/ssh.js
similarity index 100%
rename from .config/scripts/prompts/molecule/ssh.js
rename to .config/prompts/molecule/ssh.js
diff --git a/.config/scripts/prompts/molecule/virtualbox.js b/.config/prompts/molecule/virtualbox.js
similarity index 100%
rename from .config/scripts/prompts/molecule/virtualbox.js
rename to .config/prompts/molecule/virtualbox.js
diff --git a/.config/scripts/prompts/package.js b/.config/prompts/package.js
similarity index 100%
rename from .config/scripts/prompts/package.js
rename to .config/prompts/package.js
diff --git a/.config/scripts/prompts/vagrant-up.js b/.config/prompts/vagrant-up.js
similarity index 100%
rename from .config/scripts/prompts/vagrant-up.js
rename to .config/prompts/vagrant-up.js
diff --git a/.config/requirements.txt b/.config/requirements.txt
index a225c817..93551b59 100644
--- a/.config/requirements.txt
+++ b/.config/requirements.txt
@@ -2,25 +2,24 @@ ansible-core==2.11.7; python_version >= "2.7" and python_full_version < "3.0.0"
ansible==4.10.0; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0")
certifi==2021.10.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
cffi==1.15.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
-charset-normalizer==2.0.9; python_full_version >= "3.6.0" and python_version >= "3.6"
+charset-normalizer==2.0.10; python_full_version >= "3.6.0" and python_version >= "3.6"
cryptography==36.0.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
docker==5.0.3; python_version >= "3.6"
idna==3.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
jinja2==3.0.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
-junit-xml==1.9
markupsafe==2.0.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
ntlm-auth==1.5.0; python_version >= "2.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0"
packaging==21.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
pycparser==2.21; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
-pyparsing==3.0.6; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
+pyparsing==3.0.7; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
python-vagrant==0.5.15
pywin32==227; sys_platform == "win32" and python_version >= "3.6"
pywinrm==0.4.2
pyyaml==5.4.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0"
requests-ntlm==1.1.0
-requests==2.26.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
+requests==2.27.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
resolvelib==0.5.5; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"
six==1.16.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0"
-urllib3==1.26.7; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.6"
+urllib3==1.26.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.6"
websocket-client==1.2.3; python_version >= "3.6"
xmltodict==0.12.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0"
diff --git a/.config/scripts/prompts/shell.js b/.config/scripts/prompts/shell.js
deleted file mode 100644
index fa9aa7a3..00000000
--- a/.config/scripts/prompts/shell.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import inquirer from 'inquirer'
-import { execSync } from 'node:child_process'
-import { decorateSystem } from './lib/decorate-system.js'
-import { logInstructions, LOG_DECORATOR_REGEX } from './lib/log.js'
-
-/**
- * Prompts the user for the operating system they wish to launch a shell session with.
- *
- * @returns {string} The selected operating system, lowercased, in the format the Taskfile is expecting
- */
-async function promptForShell() {
- const choices = [
- 'Archlinux',
- 'CentOS 7',
- 'CentOS 8',
- 'Debian 9',
- 'Debian 10',
- 'Fedora 33',
- 'Fedora 34',
- 'Ubuntu 18.04',
- 'Ubuntu 20.04',
- 'Ubuntu 21.04'
- ]
- const choicesDecorated = choices.map((choice) => decorateSystem(choice))
- const response = await inquirer.prompt([
- {
- choices: choicesDecorated,
- message: 'Which operating system would you like to open up a terminal session with?',
- name: 'operatingSystem',
- type: 'list'
- }
- ])
-
- const DECORATION_LENGTH = 2
-
- return response.operatingSystem
- .replace(LOG_DECORATOR_REGEX, '')
- .toLowerCase()
- .slice(DECORATION_LENGTH)
- .replace(' ', '-')
-}
-
-/**
- * Main script logic
- */
-async function run() {
- logInstructions(
- 'Launch a Docker Shell Environment',
- 'Open a shell session quickly, safely, and easily using Docker.' +
- 'Select an option from the prompt below to download and shell into a Docker environment.' +
- ' The environment will be automatically deleted after you exit the terminal session.'
- )
- const choice = await promptForShell()
- execSync(`task common:shell:cli -- ${choice}`, { stdio: 'inherit' })
-}
-
-run()
diff --git a/.config/scripts/semantic/prepare.sh b/.config/scripts/semantic/prepare.sh
deleted file mode 100644
index 48be93f6..00000000
--- a/.config/scripts/semantic/prepare.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# @file .config/scripts/semantic/prepare.sh
-# @brief Executes during the publish step of a `semantic-release` cycle
-# @description
-# This is a placeholder for now.
-
-.config/log info "Preparing release.."
diff --git a/.config/scripts/semantic/verify.sh b/.config/scripts/semantic/verify.sh
deleted file mode 100644
index 597f9f68..00000000
--- a/.config/scripts/semantic/verify.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# @file .config/scripts/semantic/verify.sh
-# @brief Executes code that runs during the `semantic-release` verify step
-# @description
-# This is a placeholder for now.
-
-.config/log info "Doing some verifying.."
diff --git a/.config/scripts/start.sh b/.config/scripts/start.sh
index 58d9390b..c380a48b 100644
--- a/.config/scripts/start.sh
+++ b/.config/scripts/start.sh
@@ -16,6 +16,49 @@ if [ -f .config/log ]; then
chmod +x .config/log
fi
+# @description Installs package when user is root on Linux
+#
+# @example
+# ensureRootPackageInstalled "sudo"
+#
+# @arg $1 string The name of the package that must be present
+#
+# @exitcode 0 The package was successfully installed
+# @exitcode 1+ If there was an error, the package needs to be installed manually, or if the OS is unsupported
+function ensureRootPackageInstalled() {
+ if ! type "$1" &> /dev/null; then
+ if [[ "$OSTYPE" == 'linux'* ]]; then
+ if [ -f "/etc/redhat-release" ]; then
+ yum update
+ yum install -y "$1"
+ elif [ -f "/etc/lsb-release" ]; then
+ apt update
+ apt install -y "$1"
+ elif [ -f "/etc/arch-release" ]; then
+ pacman update
+ pacman -S "$1"
+ elif [ -f "/etc/alpine-release" ]; then
+ apk update
+ apk add -y "$1"
+ fi
+ fi
+ fi
+}
+
+# @description If the user is running this script as root, then create a new user named
+# megabyte and restart the script with that user. This is required because Homebrew
+# can only be invoked by non-root users.
+if [ "$EUID" -eq 0 ] && [ -z "$INIT_CWD" ] && type useradd &> /dev/null; then
+ # shellcheck disable=SC2016
+ echo 'INFO: Running as root - creating seperate user named `megabyte` to run script with'
+ echo "megabyte ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
+ useradd -m -s "$(which bash)" -c "Megabyte Labs Homebrew Account" megabyte
+ ensureRootPackageInstalled "sudo"
+ # shellcheck disable=SC2016
+ echo 'INFO: Reloading the script with the `megabyte` user'
+ exec su megabyte "$0" -- "$@"
+fi
+
# @description Detect script paths
BASH_SRC="$(dirname "${BASH_SOURCE[0]}")"
SOURCE_PATH="$(
@@ -39,11 +82,11 @@ PROJECT_BASE_DIR="$SOURCE_PATH/../.."
function ensureLocalPath() {
if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux'* ]]; then
# shellcheck disable=SC2016
- local PATH_STRING='PATH="$HOME/.local/bin:$PATH"'
+ PATH_STRING='PATH="$HOME/.local/bin:$PATH"'
mkdir -p "$HOME/.local/bin"
if grep -L "$PATH_STRING" "$HOME/.profile" > /dev/null; then
echo -e "${PATH_STRING}\n" >> "$HOME/.profile"
- .config/log info "Updated the PATH variable to include ~/.local/bin in $HOME/.profile"
+ echo "INFO: Updated the PATH variable to include ~/.local/bin in $HOME/.profile"
fi
elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
echo "Windows is not directly supported. Use WSL or Docker." && exit 1
@@ -54,23 +97,23 @@ function ensureLocalPath() {
fi
}
-# @description Ensures given packages are installed on a system.
+# @description Ensures given package is installed on a system.
#
# @example
-# ensurePackagesInstalled "curl git"
+# ensurePackageInstalled "curl"
#
# @arg $1 string The name of the package that must be present
#
# @exitcode 0 The package(s) were successfully installed
# @exitcode 1+ If there was an error, the package needs to be installed manually, or if the OS is unsupported
-function ensurePackagesInstalled() {
+function ensurePackageInstalled() {
if ! type "$1" &> /dev/null; then
if [[ "$OSTYPE" == 'darwin'* ]]; then
brew install "$1"
elif [[ "$OSTYPE" == 'linux'* ]]; then
if [ -f "/etc/redhat-release" ]; then
sudo yum update
- sudo yum install "$1"
+ sudo yum install -y "$1"
elif [ -f "/etc/lsb-release" ]; then
sudo apt update
sudo apt install -y "$1"
@@ -79,16 +122,16 @@ function ensurePackagesInstalled() {
sudo pacman -S "$1"
elif [ -f "/etc/alpine-release" ]; then
apk update
- apk add "$1"
+ apk add -y "$1"
else
- .config/log error "$1 is missing. Please install $1 to continue." && exit 1
+ echo "ERROR: $1 is missing. Please install $1 to continue." && exit 1
fi
elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
- .config/log error "Windows is not directly supported. Use WSL or Docker." && exit 1
+ echo "ERROR: Windows is not directly supported. Use WSL or Docker." && exit 1
elif [[ "$OSTYPE" == 'freebsd'* ]]; then
- .config/log error "FreeBSD support not added yet" && exit 1
+ echo "ERROR: FreeBSD support not added yet" && exit 1
else
- .config/log error "System type not recognized"
+ echo "ERROR: System type not recognized"
fi
fi
}
@@ -110,27 +153,27 @@ function ensureTaskInstalled() {
if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl' ]]; then
installTask
elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
- .config/log error "Windows is not directly supported. Use WSL or Docker." && exit 1
+ echo "ERROR: Windows is not directly supported. Use WSL or Docker." && exit 1
elif [[ "$OSTYPE" == 'freebsd'* ]]; then
- .config/log error "FreeBSD support not added yet" && exit 1
+ echo "ERROR: FreeBSD support not added yet" && exit 1
else
- .config/log error "System type not recognized. You must install task manually." && exit 1
+ echo "ERROR: System type not recognized. You must install task manually." && exit 1
fi
else
+ echo "INFO: Checking for latest version of Task"
CURRENT_VERSION="$(task --version | cut -d' ' -f3 | cut -c 2-)"
LATEST_VERSION="$(curl -s "$TASK_RELEASE_API" | grep tag_name | cut -c 17- | sed 's/\",//')"
- if printf '%s\n%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V -C; then
- .config/log info "Task is already up-to-date"
+ if printf '%s\n%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V -c &> /dev/null; then
+ echo "INFO: Task is already up-to-date"
else
- .config/log info "A new version of Task is available (version $LATEST_VERSION)"
- if [ ! -w "$(which task)" ]; then
- local MSG_A
- MSG_A="ERROR: Task is currently installed in a location the current user does not have write permissions for."
- local MSG_B
- MSG_B="Manually remove Task from its current location ($(which task)) and then run this script again."
- .config/log error """$MSG_A"" ""$MSG_B""" && exit 1
+ echo "INFO: A new version of Task is available (version $LATEST_VERSION)"
+ echo "INFO: The current version of Task installed is $CURRENT_VERSION"
+ # Replace with rm "$(which task)" &> /dev/null when ready
+ if ! type task &> /dev/null; then
+ installTask
+ else
+ echo "WARNING: Unable to remove previous version of Task"
fi
- installTask
fi
fi
}
@@ -148,42 +191,39 @@ function ensureTaskInstalled() {
# @exitcode 1+ If the installation fails
function installTask() {
# @description Release URL to use when downloading [Task](https://github.com/go-task/task)
- local TASK_RELEASE_URL="https://github.com/go-task/task/releases/latest"
- local CHECKSUM_DESTINATION=/tmp/megabytelabs/task_checksums.txt
- local CHECKSUMS_URL="$TASK_RELEASE_URL/download/task_checksums.txt"
- local DOWNLOAD_DESTINATION=/tmp/megabytelabs/task.tar.gz
- local TMP_DIR=/tmp/megabytelabs
+ TASK_RELEASE_URL="https://github.com/go-task/task/releases/latest"
+ CHECKSUM_DESTINATION=/tmp/megabytelabs/task_checksums.txt
+ CHECKSUMS_URL="$TASK_RELEASE_URL/download/task_checksums.txt"
+ DOWNLOAD_DESTINATION=/tmp/megabytelabs/task.tar.gz
+ TMP_DIR=/tmp/megabytelabs
if [[ "$OSTYPE" == 'darwin'* ]]; then
- local DOWNLOAD_URL="$TASK_RELEASE_URL/download/task_darwin_amd64.tar.gz"
+ DOWNLOAD_URL="$TASK_RELEASE_URL/download/task_darwin_amd64.tar.gz"
else
- local DOWNLOAD_URL="$TASK_RELEASE_URL/download/task_linux_amd64.tar.gz"
+ DOWNLOAD_URL="$TASK_RELEASE_URL/download/task_linux_amd64.tar.gz"
fi
mkdir -p "$(dirname "$DOWNLOAD_DESTINATION")"
- .config/log info 'Downloading latest version of Task'
+ echo "INFO: Downloading latest version of Task"
curl -sSL "$DOWNLOAD_URL" -o "$DOWNLOAD_DESTINATION"
curl -sSL "$CHECKSUMS_URL" -o "$CHECKSUM_DESTINATION"
- local DOWNLOAD_BASENAME
DOWNLOAD_BASENAME="$(basename "$DOWNLOAD_URL")"
- local DOWNLOAD_SHA256
DOWNLOAD_SHA256="$(grep "$DOWNLOAD_BASENAME" < "$CHECKSUM_DESTINATION" | cut -d ' ' -f 1)"
- sha256 "$DOWNLOAD_DESTINATION" "$DOWNLOAD_SHA256"
- .config/log success 'Validated checksum'
+ sha256 "$DOWNLOAD_DESTINATION" "$DOWNLOAD_SHA256" > /dev/null
+ echo "SUCCESS: Validated checksum"
mkdir -p "$TMP_DIR/task"
- tar -xzvf "$DOWNLOAD_DESTINATION" -C "$TMP_DIR/task"
+ tar -xzvf "$DOWNLOAD_DESTINATION" -C "$TMP_DIR/task" > /dev/null
if type task &> /dev/null && [ -w "$(which task)" ]; then
- local TARGET_DEST
TARGET_DEST="$(which task)"
else
if [ -w /usr/local/bin ]; then
- local TARGET_BIN_DIR='/usr/local/bin'
+ TARGET_BIN_DIR='/usr/local/bin'
else
- local TARGET_BIN_DIR="$HOME/.local/bin"
+ TARGET_BIN_DIR="$HOME/.local/bin"
fi
- local TARGET_DEST="$TARGET_BIN_DIR/task"
+ TARGET_DEST="$TARGET_BIN_DIR/task"
+ mkdir -p "$TARGET_BIN_DIR"
fi
- mkdir -p "$TARGET_BIN_DIR"
- mv "$TMP_DIR/task/task" "$TARGET_BIN_DIR/"
- .config/log success "Successfully installed Task to $TARGET_DEST"
+ mv "$TMP_DIR/task/task" "$TARGET_DEST"
+ echo "SUCCESS: Installed Task to $TARGET_DEST"
rm "$CHECKSUM_DESTINATION"
rm "$DOWNLOAD_DESTINATION"
}
@@ -199,11 +239,13 @@ function installTask() {
# @exitcode 0 The checksum is valid or the system is unrecognized
# @exitcode 1+ The OS is unsupported or if the checksum is invalid
function sha256() {
+ echo "$2"
+ echo "$1"
if [[ "$OSTYPE" == 'darwin'* ]]; then
if type brew &> /dev/null && ! type sha256sum &> /dev/null; then
brew install coreutils
else
- .config/log warn "Brew is not installed - this may cause issues"
+ echo "WARNING: Brew is not installed - this may cause issues"
fi
if type brew &> /dev/null; then
PATH="$(brew --prefix)/opt/coreutils/libexec/gnubin:$PATH"
@@ -211,26 +253,26 @@ function sha256() {
if type sha256sum &> /dev/null; then
echo "$2 $1" | sha256sum -c
else
- .config/log warn "Checksum validation is being skipped for $1 because the sha256sum program is not available"
+ echo "WARNING: Checksum validation is being skipped for $1 because the sha256sum program is not available"
fi
elif [[ "$OSTYPE" == 'linux-gnu'* ]]; then
if ! type shasum &> /dev/null; then
- .config/log warn "Checksum validation is being skipped for $1 because the shasum program is not installed"
+ echo "WARNING: Checksum validation is being skipped for $1 because the shasum program is not installed"
else
echo "$2 $1" | shasum -s -a 256 -c
fi
elif [[ "$OSTYPE" == 'linux-musl' ]]; then
if ! type sha256sum &> /dev/null; then
- .config/log warn "Checksum validation is being skipped for $1 because the sha256sum program is not available"
+ echo "WARNING: Checksum validation is being skipped for $1 because the sha256sum program is not available"
else
- echo "$2 $1" | sha256sum -c
+ echo "$2 $1" | sha256sum -c
fi
elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
- .config/log error "Windows is not directly supported. Use WSL or Docker." && exit 1
+ echo "ERROR: Windows is not directly supported. Use WSL or Docker." && exit 1
elif [[ "$OSTYPE" == 'freebsd'* ]]; then
- .config/log error "FreeBSD support not added yet" && exit 1
+ echo "ERROR: FreeBSD support not added yet" && exit 1
else
- .config/log warn "System type not recognized. Skipping checksum validation."
+ echo "WARNING: System type not recognized. Skipping checksum validation."
fi
}
@@ -245,26 +287,27 @@ ensureLocalPath
# @description Ensures base dependencies are installed
if [[ "$OSTYPE" == 'darwin'* ]]; then
- if ! type curl > /dev/null && type brew > /dev/null; then
+ if ! type curl &> /dev/null && type brew &> /dev/null; then
brew install curl
else
- .config/log error 'Neither curl nor brew are installed. Install one of them manually and try again.'
+ echo "ERROR: Neither curl nor brew are installed. Install one of them manually and try again."
fi
- if ! type git > /dev/null; then
+ if ! type git &> /dev/null; then
# shellcheck disable=SC2016
- .config/log info 'Git is not present. A password may be required to run `sudo xcode-select --install`'
+ echo 'INFO: Git is not present. A password may be required to run `sudo xcode-select --install`'
sudo xcode-select --install
fi
elif [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl'* ]]; then
- if ! type curl > /dev/null || ! type git > /dev/null; then
- ensurePackagesInstalled "curl git"
+ if ! type curl &> /dev/null || ! type git &> /dev/null; then
+ ensurePackageInstalled "curl"
+ ensurePackageInstalled "git"
fi
fi
# @description Ensures Homebrew and Poetry are installed
if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl'* ]]; then
- if ! type brew > /dev/null; then
- .config/log warn 'Homebrew is not installed. The script will attempt to install Homebrew and you might be prompted for your password.'
+ if ! type brew &> /dev/null && [ -z "$INIT_CWD" ]; then
+ echo "WARNING: Homebrew is not installed. The script will attempt to install Homebrew and you might be prompted for your password."
bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
fi
@@ -282,9 +325,10 @@ ensureTaskInstalled
# @description Run the start logic, if appropriate
cd "$PROJECT_BASE_DIR" || exit
-if [ -z "$GITLAB_CI" ]; then
+if [ -z "$GITLAB_CI" ] && [ -z "$INIT_CWD" ]; then
# shellcheck disable=SC1091
. "$HOME/.profile"
task start
- .config/log info 'There may have been changes to your PATH variable. You may have to reload your terminal or run:\n\n`. '"$HOME/.profile"'`'
+ # shellcheck disable=SC2028
+ echo 'INFO: There may have been changes to your PATH variable. You may have to reload your terminal or run:\n\n`. '"$HOME/.profile"'`'
fi
diff --git a/.config/taskfiles/ansible/Taskfile-ansibler.yml b/.config/taskfiles/ansible/Taskfile-ansibler.yml
index 7a90b830..9c0f315e 100644
--- a/.config/taskfiles/ansible/Taskfile-ansibler.yml
+++ b/.config/taskfiles/ansible/Taskfile-ansibler.yml
@@ -20,6 +20,10 @@ tasks:
compatibility-chart:
deps:
- :install:software:jq
+ log:
+ error: Failed to generate operating system compatibility chart
+ start: Generating operating system compatibility chart
+ success: Successfully generated operating system compatibility chart
cmds:
- mkdir -p .cache
- if [ ! -f .cache/compatibility-chart.json ]; then echo "{}" > .cache/compatibility-chart.json; fi
@@ -29,10 +33,6 @@ tasks:
jq -s -S '.[0] + .[1]' '{{.VARIABLES_PATH}}' .cache/compatibility-chart.json > "$TMP"
mv "$TMP" '{{.VARIABLES_PATH}}'
- log:
- error: Failed to generate operating system compatibility chart
- start: Generating operating system compatibility chart
- success: Successfully generated operating system compatibility chart
compatibility-chart:generate:
deps:
- :install:python:requirements
@@ -48,12 +48,12 @@ tasks:
populate-platforms:
deps:
- :install:python:requirements
- cmds:
- - '{{.PYTHON_HANDLE}}ansibler --populate-platforms --json-file .cache/compatibility-chart.json'
log:
error: Failed to populate platforms in `meta/main.yml
start: Populating the supported platforms listed in `meta/main.yml` based on the compatibility chart data
success: Successfully populated `meta/main.yml` platforms
+ cmds:
+ - '{{.PYTHON_HANDLE}}ansibler --populate-platforms --json-file .cache/compatibility-chart.json'
sources:
- .cache/compatibility-chart.json
- meta/main.yml
@@ -61,6 +61,10 @@ tasks:
role-dependencies:
deps:
- :install:software:jq
+ log:
+ error: Failed to acquire role dependency information
+ start: Gathering information about role dependencies
+ success: Acquired role dependency information
cmds:
- mkdir -p .cache
- if [ ! -f .cache/role-dependencies.json ]; then echo "{}" > .cache/role-dependencies.json; fi
@@ -71,10 +75,6 @@ tasks:
jq -s -S '.[0] + .[1]' '{{.VARIABLES_PATH}}' .cache/role-dependencies.json > "$TMP"
mv "$TMP" '{{.VARIABLES_PATH}}'
- log:
- error: Failed to acquire role dependency information
- start: Gathering information about role dependencies
- success: Acquired role dependency information
role-dependencies:generate:
deps:
- :install:python:requirements
diff --git a/.config/taskfiles/ansible/Taskfile-playbook.yml b/.config/taskfiles/ansible/Taskfile-playbook.yml
index e93b86a0..7b8bc452 100644
--- a/.config/taskfiles/ansible/Taskfile-playbook.yml
+++ b/.config/taskfiles/ansible/Taskfile-playbook.yml
@@ -17,6 +17,10 @@ tasks:
```
vars:
DOC_IDS: '@binary,@brew,@cask,@chrome,@firefox,@gem,@helm,@npm,@pypi,@vscode'
+ log:
+ error: Failed to acquire package information from comments via `leasot`
+ start: Scanning and acquiring package information in comments via `leasot`
+ success: Acquired package information from comments
cmds:
- |
function populateChartVar() {
@@ -42,7 +46,6 @@ tasks:
for ID in {{replace "," " " .DOC_IDS}}; do
populateChartVar "$TMP" "$ID"
done
- .config/log success 'Finished scanning for documentation comments'
environment:
# @desc_when [ansible/Taskfile-playbook.yml] ansible/playbook
@@ -64,6 +67,12 @@ tasks:
- task: environment:{{if .CLI_ARGS}}cli{{else}}prompt{{end}}
environment:cli:
+ log:
+ error:
+ default: Encountered an error while switching environments to `{{.CLI_ARGS}}`
+ 69: A CLI argument must be passed in!
+ start: Switching environment to `{{.CLI_ARGS}}`
+ success: Successfully switched environment to `{{.CLI_ARGS}}`
cmds:
- |
{{if .CLI_ARGS}}
@@ -73,6 +82,8 @@ tasks:
ln -s "./environments/{{.CLI_ARGS}}/$ITEM" "$ITEM"
.config/log success "Successfully symlinked `$ITEM` from ./environments/{{.CLI_ARGS}}/$ITEM"
done
+ {{else}}
+ exit 69
{{end}}
environment:prompt:
@@ -81,7 +92,6 @@ tasks:
interactive: true
cmds:
- node .config/scripts/prompts/environment.js
-
preconditions:
- sh: test -d node_modules
msg: This task has dependencies in the `node_modules` folder which is missing.
@@ -100,6 +110,10 @@ tasks:
The example above will look through all the folders two levels deep (e.g. `./roles/tools/nmap`,
`./roles/system/snapd`) in the roles folder and display any roles that are missing the file.
+ log:
+ error: Failed to scan the `/roles/*` folders for roles missing `{{.CLI_ARGS}}`
+ start: Determining which roles in the `/roles/*` folders are missing `{{.CLI_ARGS}}`
+ success: Finished scanning for roles missing `{{.CLI_ARGS}}` (if there are any then they should be listed above)
cmds:
- |
FILES=$(find ./roles -mindepth 2 -maxdepth 2 -type d '!' -exec test -e "{}/{{.CLI_ARGS}}" ';' -print)
@@ -124,6 +138,10 @@ tasks:
It also adds a remote for a private submodule that is intended to store
files that are not meant to be shared. The remote is named `private`.
run: once
+ log:
+ error: Failed to set remotes for one or more of the roles in the `/roles/*` folders
+ start: Adding git remotes for all of the roles in the `/roles/*` folders
+ success: Successfully added git remotes for all of the roles in the `/roles/*` folders
cmds:
- git init -q
- |
@@ -141,7 +159,6 @@ tasks:
.config/log warn "${ROLE_RELATIVE_PATH}/package.json is missing!"
fi
done
- .config/log success 'Finished adding git remotes for the roles in the ./roles folder'
run:
cmds:
@@ -151,6 +168,10 @@ tasks:
deps:
- :install:python:requirements
- :symlink:playbook
+ log:
+ error: Error encounted while running `ansible-playbook -i inventories/{{.CLI_ARGS}} --ask-vault-pass main.yml`
+ start: Running `ansible-playbook -i inventories/{{.CLI_ARGS}} --ask-vault-pass main.yml`
+ success: Successfully ran `ansible-playbook -i inventories/{{.CLI_ARGS}} --ask-vault-pass main.yml`
cmds:
- ansible-playbook -i inventories/{{.CLI_ARGS}} --ask-vault-pass main.yml
diff --git a/.config/taskfiles/ansible/Taskfile-populate.yml b/.config/taskfiles/ansible/Taskfile-populate.yml
index 12937273..a2400749 100644
--- a/.config/taskfiles/ansible/Taskfile-populate.yml
+++ b/.config/taskfiles/ansible/Taskfile-populate.yml
@@ -9,6 +9,9 @@ tasks:
collection:
deps:
- :install:software:yq
+ log:
+ error: Failed to auto-populate the `{{.KEY}}` collection
+ start: Determining if the `{{.KEY}}` collection should be added to the `{{.REQUIREMENTS_PATH}}`
cmds:
- |
COLLECTIONS="$(yq eval '.collections' '{{.REQUIREMENTS_PATH}}')"
@@ -24,6 +27,9 @@ tasks:
collection:force:
deps:
- :install:software:yq
+ log:
+ error: Failed to forcefully auto-populate the `{{.KEY}}` collection
+ start: Determining if the `{{.KEY}}` collection should be added to the `{{.REQUIREMENTS_PATH}}` (forcefully)
cmds:
- |
COLLECTIONS="$(yq eval '.collections' '{{.REQUIREMENTS_PATH}}')"
@@ -56,6 +62,9 @@ tasks:
* community.general.gem
* community.general.npm
* community.general.snap
+ log:
+ start: Auto-populating the `{{.META_PATH}}` and `{{.REQUIREMENTS_PATH}}` with common dependencies (when appropriate)
+ success: Auto-populated the `{{.META_PATH}}` and `{{.REQUIREMENTS_PATH}}` with common dependencies
cmds:
- task: collection
vars:
@@ -116,6 +125,9 @@ tasks:
dependency:
deps:
- :install:software:yq
+ log:
+ error: Failed to auto-populate the `{{.KEY}}` role
+ start: Determining if the `{{.KEY}}` role should be added to the `{{.META_PATH}}`
cmds:
- |
DEPENDENCIES="$(yq eval '.dependencies' '{{.META_PATH}}')"
@@ -136,11 +148,16 @@ tasks:
deps:
- :install:npm:prettier
- :install:software:jq
+ - :install:software:yq
vars:
DESCRIPTION:
sh: yq eval '.galaxy_info.description' '{{.META_PATH}}'
REFERENCE_LINK: Take a look at an [example meta/main.yml
file](https://gitlab.com/megabyte-labs/ansible-roles/androidstudio/-/blob/master/{{.META_PATH}}).
+ log:
+ error: Failed to synchronize `package.json` with `{{.META_PATH}}`
+ start: Updating `package.json` blueprint description and slug using values present in `{{.META_PATH}}`
+ success: Ensured `package.json` is synchronized with `{{.META_PATH}}`
cmds:
- |
TMP="$(mktemp)"
diff --git a/.config/taskfiles/ansible/Taskfile-test.yml b/.config/taskfiles/ansible/Taskfile-test.yml
index cfc04eb5..1f0a5671 100644
--- a/.config/taskfiles/ansible/Taskfile-test.yml
+++ b/.config/taskfiles/ansible/Taskfile-test.yml
@@ -11,6 +11,10 @@ tasks:
allure:report:
deps:
- :install:software:allure
+ log:
+ error: Failed to generate and/or open the unit test report
+ start: Generating and opening unit test report
+ success: Successfully generated and opened unit test report
cmds:
- allure generate molecule/.results/junit --output allure-reports --clean
- mkdir -p molecule/.results/junit
@@ -33,8 +37,11 @@ tasks:
deps:
- :symlink:{{.REPOSITORY_SUBTYPE}}
- :install:python:requirements
+ log:
+ error: Encountered error while testing the Ansible playbook locally
+ start: Testing the Ansible playbook locally
+ success: Successfully tested the Ansible playbook locally
cmds:
- - .config/log info "Testing Ansible playbook locally"
- cp test/{{OS}}/inventory inventory
- if [ ! -f ansible.cfg.bak ]; then cp ansible.cfg ansible.cfg.bak; fi
- cp test/{{OS}}/ansible.cfg ansible.cfg
@@ -47,6 +54,10 @@ tasks:
molecule:dependencies:
deps:
- :install:python:requirements
+ log:
+ error: Encountered error while installing Ansible Galaxy requirements defined in `requirements.yml`
+ start: Installing Ansible Galaxy requirements defined in `requirements.yml`
+ success: Installed Ansible Galaxy requirements defined in `requirements.yml`
cmds:
- '{{.PYTHON_HANDLE}} ansible-galaxy install --ignore-errors -r requirements.yml'
- task: :symlink:{{.REPOSITORY_SUBTYPE}}
@@ -75,17 +86,13 @@ tasks:
- molecule:dependencies
- :install:software:docker
- :install:software:sshpass
+ log:
+ error: The `{{.CLI_ARGS}}` Docker Molecule test finished with errors
+ start: Running Docker Molecule test on containers in the `{{.CLI_ARGS}}` group
+ success: Successfully ran the `{{.CLI_ARGS}}` Docker Molecule test
cmds:
- |
- .config/log info 'Running Docker Molecule test on containers in the `{{.CLI_ARGS}}` group'
- EXIT_CODE=0
- {{.MOLECULE_TEST_OPTIONS}} MOLECULE_GROUP="{{.CLI_ARGS}}" {{.PYTHON_HANDLE}}molecule test -s docker -- --skip-tags skipdockertest || EXIT_CODE=$?
- if [ "$EXIT_CODE" != '0' ]; then
- .config/log error 'The `{{.CLI_ARGS}}` Docker Molecule test finished with errors'
- exit 1
- else
- .config/log success 'Successfully ran the `{{.CLI_ARGS}}` Docker Molecule test'
- fi
+ {{.MOLECULE_TEST_OPTIONS}} MOLECULE_GROUP="{{.CLI_ARGS}}" {{.PYTHON_HANDLE}}molecule test -s docker -- --skip-tags skipdockertest
molecule:docker:matrix:
deps:
@@ -95,6 +102,10 @@ tasks:
vars:
MOLECULE_DATE:
sh: date '+%Y-%m-%d'
+ log:
+ error: There were errors while running the test (results were logged to `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-$SCENARIO.txt`)
+ start: Running Docker Molecule test with results teed to `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-$SCENARIO.txt`
+ success: Finished running the test (results were logged to `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-$SCENARIO.txt`)
cmds:
- mkdir -p {{.MOLECULE_LOGS_PATH}}
- |
@@ -102,19 +113,9 @@ tasks:
if grep -Ril 'community.general.snap:' ./tasks; then
SCENARIO="Snap"
.config/log warn 'Running Docker Molecule tests on the Docker containers that are compatible with `snap` since the role has references to `snap`'
- else
- .config/log info 'Running full Docker Molecule test'
fi
- .config/log info 'Piping results to `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-$SCENARIO.txt` for compatibility chart data'
- EXIT_CODE=0
PY_COLORS=0 {{.MOLECULE_TEST_OPTIONS}} MOLECULE_GROUP="$SCENARIO" {{.PYTHON_HANDLE}}molecule test -s docker -- --skip-tags skipdockertest 2>&1 | \
- tee "{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-$SCENARIO.txt" || EXIT_CODE=$?
- if [ "$EXIT_CODE" != '0' ]; then
- .config/log error 'There were errors while running the test - results are available at `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-$SCENARIO.txt`'
- exit 1
- else
- .config/log success 'Finished running the test - results are available at `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-$SCENARIO.txt`'
- fi
+ tee "{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-$SCENARIO.txt"
molecule:docker:prompt:
interactive: true
@@ -128,18 +129,14 @@ tasks:
deps:
- molecule:dependencies
- :install:software:gcloud
+ log:
+ error: Encountered error(s) while running the Google Cloud Platform Molecule test
+ start: Running Google Cloud Platform Molecule test
+ success: Finished running Google Cloud Platform Molecule test
cmds:
- task: molecule:gcp:preconditions
- |
- .config/log info 'Running Google Cloud Platform Molecule test'
- EXIT_CODE=0
- {{.PYTHON_HANDLE}}molecule test -s gcp || EXIT_CODE=$?
- if [ "$EXIT_CODE" != '0' ]; then
- .config/log error 'Finished running the Google Cloud Platform Molecule test (with errors)'
- exit 1
- else
- .config/log success 'Finished running Google Cloud Platform Molecule test'
- fi
+ {{.PYTHON_HANDLE}}molecule test -s gcp
molecule:gcp:matrix:
deps:
@@ -149,18 +146,20 @@ tasks:
vars:
MOLECULE_DATE:
sh: date '+%Y-%m-%d'
+ log:
+ error: An error occurred while running the Google Cloud Platform Molecule test sequence
+ start: Running Docker Molecule test with results teed to `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-$SCENARIO.txt`
+ success: Finished running and formatting the results of the Google Cloud Platform molecule test
cmds:
- task: molecule:gcp:preconditions
- mkdir -p {{.MOLECULE_LOGS_PATH}}
- |
- .config/log info 'Piping results to `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-gcp.txt` for compatibility chart data'
EXIT_CODE=0
PY_COLORS=0 {{.PYTHON_HANDLE}}molecule test -s gcp 2>&1 | tee "{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-gcp.txt" || EXIT_CODE=$?
if [ "$EXIT_CODE" != '0' ]; then
- .config/log error 'Errors encountered while running the test - results are available at `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-gcp.txt`'
exit 1
else
- .config/log success 'Finished running the test - results are available at `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-gcp.txt`'
+ .config/log success 'Finished running the test (results were logged to `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-gcp.txt`)'
fi
- |
RESULTS="{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-gcp.txt"
@@ -210,18 +209,14 @@ tasks:
molecule:local:test:
deps:
- molecule:dependencies
+ log:
+ error: There was an error while running the Molecule test locally
+ start: Running the Molecule test locally
+ success: The local Molecule test was successfully run
cmds:
- |
- .config/log info 'Running Molecule test locally'
- EXIT_CODE=0
PATH="$(poetry env info | grep 'Python: /' | sed 's/Python: //' | sed 's/$/\/bin/'):$PATH" \
{{.MOLECULE_TEST_OPTIONS}} {{.PYTHON_HANDLE}}molecule test -s local || EXIT_CODE=$?
- if [ "$EXIT_CODE" != '0' ]; then
- .config/log error 'There was an error while running the Molecule test locally'
- exit 1
- else
- .config/log success 'The local Molecule test was successful!'
- fi
molecule:ssh:
desc: Runs a Molecule test over SSH
@@ -239,17 +234,12 @@ tasks:
molecule:ssh:cli:
deps:
- molecule:dependencies
+ log:
+ error: Errors encountered while running the SSH Molecule test
+ start: Running the Molecule test over SSH
+ success: Successfully ran the Molecule test over SSH
cmds:
- - |
- .config/log info 'Running Molecule test over SSH'
- EXIT_CODE=0
- {{.MOLECULE_TEST_OPTIONS}} {{.PYTHON_HANDLE}}molecule test -s remote || EXIT_CODE=$?
- if [ "$EXIT_CODE" != '0' ]; then
- .config/log error 'Errors encountered while running the remote Molecule test'
- exit 1
- else
- .config/log success 'Successfully ran the Molecule test on the SSH target'
- fi
+ - '{{.MOLECULE_TEST_OPTIONS}} {{.PYTHON_HANDLE}}molecule test -s remote'
molecule:ssh:prompt:
interactive: true
@@ -285,17 +275,12 @@ tasks:
env:
# yamllint disable-line rule:truthy
OBJC_DISABLE_INITIALIZE_FORK_SAFETY: YES
+ log:
+ error: Errors encountered while running the `{{.CLI_ARGS}}` VirtualBox Molecule test
+ start: Running a VirtualBox Molecule test on platforms in the `{{.CLI_ARGS}}` group
+ success: Finished running the `{{.CLI_ARGS}}` VirtualBox Molecule test
cmds:
- - |
- .config/log info 'Running VirtualBox Molecule test on platforms in the `{{.CLI_ARGS}}` group'
- EXIT_CODE=0
- {{.MOLECULE_TEST_OPTIONS}} MOLECULE_GROUP="{{.CLI_ARGS}}" {{.PYTHON_HANDLE}}molecule test || EXIT_CODE=$?
- if [ "$EXIT_CODE" != '0' ]; then
- .config/log error 'Errors encountered while running the `{{.CLI_ARGS}}` VirtualBox Molecule test'
- exit 1
- else
- .config/log success 'Finished running `{{.CLI_ARGS}}` VirtualBox Molecule test'
- fi
+ - '{{.MOLECULE_TEST_OPTIONS}} MOLECULE_GROUP="{{.CLI_ARGS}}" {{.PYTHON_HANDLE}}molecule test'
molecule:virtualbox:converge:
desc: Provisions a desktop VirtualBox VM and then runs a Molecule test
@@ -332,17 +317,12 @@ tasks:
env:
# yamllint disable-line rule:truthy
OBJC_DISABLE_INITIALIZE_FORK_SAFETY: YES
+ log:
+ error: Errors were encountered while running the `{{.CLI_ARGS}}` VirtualBox Molecule converge play
+ start: Running the `{{.CLI_ARGS}}` VirtualBox Molecule converge play (this will leave the VirtualBox instance open for inspection)
+ success: Finished running the `{{.CLI_ARGS}}` VirtualBox Molecule converge play (you are encouraged to inspect the VM)
cmds:
- - |
- .config/log info 'Running `{{.CLI_ARGS}}` VirtualBox Molecule converge play - this will leave the VirtualBox instance open for inspection'
- EXIT_CODE=0
- {{.MOLECULE_TEST_OPTIONS}} MOLECULE_GROUP={{.CLI_ARGS}} {{.PYTHON_HANDLE}}molecule converge -s desktop || EXIT_CODE=$?
- if [ "$EXIT_CODE" != '0' ]; then
- .config/log error 'Errors were encountered while running the `{{.CLI_ARGS}}` VirtualBox Molecule converge play'
- exit 1
- else
- .config/log success 'Finished running the `{{.CLI_ARGS}}` VirtualBox Molecule converge play - you are encouraged to inspect the VM'
- fi
+ - '{{.MOLECULE_TEST_OPTIONS}} MOLECULE_GROUP={{.CLI_ARGS}} {{.PYTHON_HANDLE}}molecule converge -s desktop'
molecule:virtualbox:converge:prompt:
interactive: true
@@ -363,18 +343,14 @@ tasks:
sh: date '+%Y-%m-%d'
# yamllint disable-line rule:truthy
OBJC_DISABLE_INITIALIZE_FORK_SAFETY: YES
+ log:
+ error: Errors were encountered while running the full E2E test (see `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-default.txt` for details)
+ start: Running a full E2E test with VirtualBox (results will be saved to `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-default.txt`)
+ success: Finished running the full E2E test (results are in `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-default.txt`)
cmds:
- mkdir -p {{.MOLECULE_LOGS_PATH}}
- |
- .config/log info 'Running full E2E test with VirtualBox - results will be saved to `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-default.txt`'
- EXIT_CODE=0
- PY_COLORS=0 {{.MOLECULE_TEST_OPTIONS}} {{.PYTHON_HANDLE}}molecule test | tee '{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-default.txt' || EXIT_CODE=$?
- if [ "$EXIT_CODE" != '0' ]; then
- .config/log error 'Errors were encountered while running the full E2E test - see `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-default.txt` for details'
- exit 1
- else
- .config/log success 'Finished running full E2E test - `{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-default.txt` contains the results'
- fi
+ PY_COLORS=0 {{.MOLECULE_TEST_OPTIONS}} {{.PYTHON_HANDLE}}molecule test | tee '{{.MOLECULE_LOGS_PATH}}/{{.MOLECULE_DATE}}-default.txt'
molecule:virtualbox:prompt:
interactive: true
@@ -431,10 +407,12 @@ tasks:
- :install:software:sshpass
- :install:software:vagrant
- :install:software:virtualbox
+ log:
+ error: Encountered error when running `vagrant up {{.CLI_ARGS}}`
+ start: Running `vagrant up {{.CLI_ARGS}}`
+ success: Successfully ran `vagrant up {{.CLI_ARGS}}`
cmds:
- - |
- .config/log info 'Running `vagrant up {{.CLI_ARGS}}`'
- vagrant up {{.CLI_ARGS}}
+ - vagrant up {{.CLI_ARGS}}
vagrant:prompt:
interactive: true
diff --git a/.config/taskfiles/ansible/Taskfile.yml b/.config/taskfiles/ansible/Taskfile.yml
index 21798485..09c0c112 100644
--- a/.config/taskfiles/ansible/Taskfile.yml
+++ b/.config/taskfiles/ansible/Taskfile.yml
@@ -25,6 +25,10 @@ tasks:
-r {{.VARIABLES_PATH}} | jq --raw-input --slurp 'split("\n") | .[0:((. | length) - 1)]'
TMP:
sh: mktemp
+ log:
+ error: Failed to generate documentation variable for collection dependencies
+ start: Generating documentation variable for collection dependencies
+ success: Generated documentation variable for collection dependencies
cmds:
- |
jq --arg collections "$COLLECTIONS" '.{{.COLLECTION_DEPS}} = ($collections | fromjson)' '{{.VARIABLES_PATH}}' > "$TMP"
@@ -42,6 +46,10 @@ tasks:
The collections along with a links to their source are listed below.\n\n{{\"{{\"}}{{.COLLECTION_DEPS}}{{\"}}\"}}"
SINGLE_COLLECTION_TEXT: "### Galaxy Collection\n\nThis role is dependent on the following Ansible Galaxy
collection:\n\n{{\"{{\"}}{{.COLLECTION_DEPS}}{{\"}}\"}}"
+ log:
+ error: Failed to generate documentation partial for collection dependencies
+ start: Generating documentation partial for collection dependencies
+ success: Generated documentation partial for collection dependencies
cmds:
- mkdir -p '{{dir .FILE_PATH}}'
- |
@@ -57,12 +65,16 @@ tasks:
- '{{.VARIABLES_PATH}}'
galaxy:import:
+ log:
+ error: Error occurred while importing Ansible Galaxy role
+ start: Triggering Ansible Galaxy import
+ success: Successfully imported role on Ansible Galaxy
cmds:
- |
- if [ -n "$ANSIBLE_GALAXY_TOKEN" ]; then
- GITHUB_ROLE_SLUG="$(jq -r '.blueprint.repository.github' package.json | sed 's/.*\///')"
- {{.PYTHON_HANDLE}} ansible-galaxy role import --token "$ANSIBLE_GALAXY_TOKEN" {{.GITHUB_ORG}} "$GITHUB_ROLE_SLUG"
- fi
+ GITHUB_ROLE_SLUG="$(jq -r '.blueprint.repository.github' package.json | sed 's/.*\///')"
+ {{.PYTHON_HANDLE}} ansible-galaxy role import --token "$ANSIBLE_GALAXY_TOKEN" {{.GITHUB_ORG}} "$GITHUB_ROLE_SLUG"
+ status:
+ - '[ -z "$ANSIBLE_GALAXY_TOKEN" ]'
galaxy:requirements:
run: once
@@ -75,6 +87,10 @@ tasks:
msg: The requirements.yml file is missing! It should be present even if it is empty (which should almost never be the case).
galaxy:requirements:install:
+ log:
+ error: Error encountered while installing the Ansible Galaxy requirements specified in `requirements.yml`
+ start: Installing the Ansible Galaxy requirements specified in `requirements.yml`
+ success: Installed the Ansible Galaxy requirements specified in `requirements.yml`
cmds:
- cmd: '{{.PYTHON_HANDLE}} ansible-galaxy install -r requirements.yml --ignore-errors'
ignore_error: true
@@ -96,9 +112,12 @@ tasks:
sh: jq -s --argjson galaxy "$(yq e -o=j '.galaxy_info.galaxy_tags' meta/main.yml)" '.[0].keywords + $galaxy | sort | unique' package.json
MERGED_TAGS_LENGTH:
sh: jq -s --argjson galaxy "$(yq e -o=j '.galaxy_info.galaxy_tags' meta/main.yml)" '.[0].keywords + $galaxy | sort | unique | length' package.json
+ log:
+ error: Error encountered while running the `package.json` / `meta/main.yml` synchronization logic
+ start: Synchronizing the keywords in `package.json` and `meta/main.yml`
+ success: Synchronized the keywords in `package.json` and `meta/main.yml`
cmds:
- |
- .config/log info 'Syncing the keywords in package.json with the keywords in meta/main.yml'
GALAXY_INFO="$(yq e -o=j meta/main.yml)"
OPTIONAL_TAGS="$(jq '.keywords' .config/common-keywords.json)"
TMP="$(mktemp)"
@@ -120,7 +139,9 @@ tasks:
jq -n --argjson result "$RESULT" --argjson gi "$GALAXY_INFO" '$gi | .galaxy_info.galaxy_tags = $result' > .cache/megabytelabs/galaxy-meta.json
yq eval -P .cache/megabytelabs/galaxy-meta.json > meta/main.yml
- '{{.NPX_HANDLE}}prettier --write meta/main.yml > /dev/null'
- - task fix:yaml:dashes -- meta/main.yml
+ - task: :fix:yaml:dashes
+ vars:
+ CLI_ARGS: meta/main.yml
mod-ansible-autodoc:
cmds:
@@ -152,16 +173,16 @@ tasks:
sh: jq -r '.autodoc_todo_description' '{{.VARIABLES_PATH}}'
VARIABLES_DESCRIPTION:
sh: jq -r '.autodoc_variables_description' '{{.VARIABLES_PATH}}'
+ log:
+ error: Error encountered while generating documentation partials with `mod-ansible-autodoc`
+ start: Compiling `mod-ansible-autodoc` documentation from comments in the play *.yml files
+ success: Successfully generated documentation partials with `mod-ansible-autodoc`
cmds:
- >
- .config/log info 'Compiling `mod-ansible-autodoc` documentation from comments in the play source files'
-
{{.PYTHON_HANDLE}}mod-ansible-autodoc --actions-title '## Features' --actions-description "$ACTIONS_DESCRIPTION"
--tags-title '### Tags' --tags-description "$TAGS_DESCRIPTION" --todo-title '### TODO'
--todo-description "$TODO_DESCRIPTION" --variables-title '## Variables' --variables-description
"$VARIABLES_DESCRIPTION" --variable-example-comment-prefix '#💬'
-
- .config/log success 'Successfully generated documentation partials with `mod-ansible-autodoc`'
- mkdir -p .autodoc
- mv ansible_actions.md ansible_tags.md ansible_todo.md ansible_variables.json ansible_variables.md .autodoc
sources:
@@ -173,6 +194,10 @@ tasks:
mod-ansible-autodoc:variables:
deps:
- :install:software:jq
+ log:
+ error: Failed to merge `.autodoc/ansible_variables.json` into `.variables.json`
+ start: Merging `.autodoc/ansible_variables.json` into `.variables.json`
+ success: Successfully merged `.autodoc/ansible_variables.json` into `.variables.json`
cmds:
- |
ROLE_VARIABLES="$(jq -r '.role_variables' .autodoc/ansible_variables.json)"
@@ -187,8 +212,11 @@ tasks:
vars:
INSTALLING:
sh: if test -f install_in_progress; then echo 'true'; else echo 'false'; fi
+ log:
+ error: Error occurred while running the Ansible play
+ start: Running the Ansible play locally
+ success: Successfully ran the Ansible play locally
cmds:
- - .config/log info "Running the Ansible play locally"
- cp test/{{OS}}/inventory inventory
- if [ ! -f ansible.cfg.bak ]; then cp ansible.cfg ansible.cfg.bak; fi
- cp test/{{OS}}/ansible.cfg ansible.cfg
@@ -203,6 +231,10 @@ tasks:
deps:
- :install:software:jq
- :install:software:yq
+ log:
+ error: Failed to synchronize role dependencies in `{{.META_PATH}}` to `{{.REQUIREMENTS_PATH}}`
+ start: Ensuring role dependencies in `{{.META_PATH}}` are also listed in `{{.REQUIREMENTS_PATH}}`
+ success: Successfully ensured role dependencies in `{{.META_PATH}}` are also listed in `{{.REQUIREMENTS_PATH}}`
cmds:
- |
ROLES="$(yq eval '.roles' '{{.REQUIREMENTS_PATH}}')"
@@ -216,6 +248,10 @@ tasks:
CLI_ARGS: '{{.REQUIREMENTS_PATH}}'
update:galaxy-id:
+ log:
+ error: Failed to look up or inject the Ansible Galaxy project ID into `package.json`
+ start: Adding Ansible Galaxy project ID to `package.json` (if available)
+ success: Successfully ensured Ansible Galaxy project ID is in `package.json` (if the project is on Ansible Galaxy)
cmds:
- |
TMP="$(mktemp)"
@@ -249,6 +285,10 @@ tasks:
SUBHEADER: '{{.SUBHEADER_PREFIX}} {{.DESCRIPTION_LOWER}}'
TMP:
sh: mktemp
+ log:
+ error: Failed to inject `.variables.json` with description variables
+ start: Injecting description variables into `.variables.json`
+ success: Successfully updated `.variables.json` with description variables
cmds:
- jq -S --arg alt "$ALT" --arg galaxyinfo "$GALAXY_INFO" --arg subheader "$SUBHEADER" '.alternative_description = $alt |
.galaxy_info = ($galaxyinfo | fromjson) | .subheader_description = $subheader' '{{.VARIABLES_PATH}}' > "$TMP"
@@ -278,11 +318,14 @@ tasks:
This task is leveraged by `lint-staged` to ensure that any file that matches `**/*vault.yml` is encrypted
with Ansible Vault.
+ log:
+ error: '`{{.CLI_ARGS}}` is not encrypted! All files matching `**/*vault.yml` must be encrypted by `ansible-vault`.'
+ start: Checking if `{{.CLI_ARGS}}` is encrypted with `ansible-vault`
+ success: Ensured `{{.CLI_ARGS}}` is encrypted
cmds:
- |
head -1 '{{.CLI_ARGS}}' | grep --quiet '^\$ANSIBLE_VAULT;' || {
if [ -s '{{.CLI_ARGS}}' ]; then
- .config/log error '`{{.CLI_ARGS}}` is not encrypted. All files matching `**/*vault.yml` should be encrypted by `ansible-vault`.'
exit 1
fi
}
diff --git a/.config/taskfiles/boilerplate/Taskfile.yml b/.config/taskfiles/boilerplate/Taskfile.yml
index ba551023..335e9ac4 100644
--- a/.config/taskfiles/boilerplate/Taskfile.yml
+++ b/.config/taskfiles/boilerplate/Taskfile.yml
@@ -9,6 +9,10 @@ tasks:
- :install:software:jq
vars:
BLUEPRINT_REQUIRED_FIELDS: title description group name overview slug subgroup
+ log:
+ error: Error occurred while validating/prompting for blueprint settings
+ start: Ensuring required fields in the blueprint section of `package.json` are present
+ succes: Successfully ensured `package.json` minimum blueprint requirements are present
cmds:
- |
if [ "$(jq -r '.type' package.json)" != 'module' ]; then
@@ -44,6 +48,10 @@ tasks:
clean:
deps:
- :install:software:jq
+ log:
+ error: Failed to clean `package.json`
+ start: Cleaning `package.json`
+ success: Cleaned `package.json`
cmds:
- |
TMP="$(mktemp)"
@@ -57,6 +65,10 @@ tasks:
prime:package:
deps:
- :install:software:jq
+ log:
+ error: Failed to merge shared `package.json` settings
+ start: Ensuring `package.json` has shared settings
+ success: Successfully merged shared `package.json` settings
cmds:
- curl -s https://gitlab.com/megabyte-labs/common/shared/-/raw/master/package.json > package-reference.json
- |
@@ -78,9 +90,12 @@ tasks:
update:taskfile:
deps:
- :install:software:yq
+ log:
+ error: Error encountered while ensuring `Taskfile.yml` has correct settings
+ start: Ensuring `Taskfile.yml` has correct settings
+ success: Successfully applied `Taskfile.yml` assurances
cmds:
- |
- .config/log info 'Ensuring Taskfile.yml has correct variables'
GROUP="$(jq -r '.blueprint.group' package.json)"
SUBGROUP="$(jq -r '.blueprint.subgroup' package.json)"
TASK_GROUP="$(yq eval '.vars.REPOSITORY_TYPE' Taskfile.yml)"
@@ -102,4 +117,3 @@ tasks:
UPSTREAM='upstream:docs'
fi
yq e -i ".tasks.start.cmds[0].task = \"$UPSTREAM\"" Taskfile.yml
- .config/log success 'Successfully ensured Taskfile.yml has correct variables'
diff --git a/.config/taskfiles/ci/Taskfile-github.yml b/.config/taskfiles/ci/Taskfile-github.yml
index 4492c34e..594f57fb 100644
--- a/.config/taskfiles/ci/Taskfile-github.yml
+++ b/.config/taskfiles/ci/Taskfile-github.yml
@@ -7,5 +7,9 @@ tasks:
- :install:software:act
- :install:software:docker
desc: Locally test the on-push GitHub Action event (only works for Linux containers)
+ log:
+ error: Error encountered while testing GitHub Actions locally with `act`
+ start: Testing GitHub Actions locally with `act`
+ success: Completed local GitHub Actions test
cmds:
- act
diff --git a/.config/taskfiles/ci/Taskfile.yml b/.config/taskfiles/ci/Taskfile.yml
index 92fb1c31..b1dcafca 100644
--- a/.config/taskfiles/ci/Taskfile.yml
+++ b/.config/taskfiles/ci/Taskfile.yml
@@ -12,11 +12,19 @@ tasks:
before:npm:
deps:
- - :install:software:node
+ - :install:npm:pnpm
+ log:
+ error: Error encountered while configuring pnpm to store its cache in `.pnpm-store`
+ start: Configuring pnpm to store its cache in `.pnpm-store`
+ success: Successfully updated pnpm to store its cache in `.pnpm-store`
cmds:
- pnpm config set store-dir .pnpm-store
checkout:
+ log:
+ error: Failed to pull latest changes
+ start: Pulling latest changes
+ success: Successfully pulled latest changes
cmds:
- |
if [[ "$CI_COMMIT_REF_NAME" == 'synchronize' ]]; then
@@ -30,7 +38,11 @@ tasks:
commit:
deps:
- :install:software:git
+ log:
+ error: Encountered error while pushing changes to master
+ start: Bypassing git hooks and pushing changes to master (if there are any changes)
cmds:
+ - task donothing
- task: commit:config
- git add --all
- git diff --cached "*"
@@ -60,12 +72,20 @@ tasks:
submodules:
deps:
- :install:software:git
+ log:
+ error: Encountered error while ensuring submodules are up-to-date
+ start: Ensuring submodules are configured and up-to-date with their master remote
+ success: Ensured submodules are up-to-date
cmds:
- >
git submodule foreach 'git config user.email "$GITLAB_CI_EMAIL"; git config user.name "$GITLAB_CI_NAME";
git checkout -q master; git pull -q origin master --ff-only'
synchronize:
+ log:
+ error: Failed to update the `synchronize` branch
+ start: Synchronizing the `synchronize` branch with the `master` branch
+ success: Successfully updated the `synchronize` branch
cmds:
- git checkout -b synchronize || git checkout synchronize
- git reset --hard HEAD
@@ -73,8 +93,10 @@ tasks:
- git push -q -o ci.skip origin synchronize --force
- |
if [ '{{.REPOSITORY_TYPE}}' == 'deprecated_common' ] && [ '{{.REPOSITORY_SUBTYPE}}' == 'shared' ]; then
- echo 'Not triggering any pipelines because this is the shared common repository'
+ .config/log info 'Bypassing the `master` branch pipeline trigger because the repository is not of the right type'
else
+ .config/log info 'Triggering the `master` branch pipeline'
curl -s --request POST --form "token=${CI_JOB_TOKEN}" --form ref=master --form "variables[PIPELINE_SOURCE]=$PIPELINE_SOURCE" \
"https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/trigger/pipeline"
fi
+ - git checkout master
diff --git a/.config/taskfiles/common/Taskfile-code.yml b/.config/taskfiles/common/Taskfile-code.yml
index 43bed0de..d7b58901 100644
--- a/.config/taskfiles/common/Taskfile-code.yml
+++ b/.config/taskfiles/common/Taskfile-code.yml
@@ -6,6 +6,9 @@ tasks:
deps:
- :install:software:tokei
desc: Display a chart detailing the lines of code for each language used
+ log:
+ error: Encountered error while running `tokei . --exclude .common .modules`
+ start: Analyzing project for code-language statistics
cmds:
- tokei . --exclude .common .modules
@@ -15,5 +18,8 @@ tasks:
desc: Scan code base for TODOs and FIXMEs
vars:
LEASOT_IGNORE: .common .modules .venv node_modules venv
+ log:
+ error: Encountered error while running `{{.NPX_HANDLE}}leasot --ignore {{.LEASOT_IGNORE}} {{.CLI_ARGS}}`
+ start: Scanning project for TODOs and FIXMEs
cmds:
- '{{.NPX_HANDLE}}leasot --ignore {{.LEASOT_IGNORE}} {{.CLI_ARGS}}'
diff --git a/.config/taskfiles/common/Taskfile-update.yml b/.config/taskfiles/common/Taskfile-update.yml
index e9ec5a86..79973cdc 100644
--- a/.config/taskfiles/common/Taskfile-update.yml
+++ b/.config/taskfiles/common/Taskfile-update.yml
@@ -19,10 +19,7 @@ tasks:
all:docs:
cmds:
- - |
- {{if eq .REPOSITORY_TYPE "common"}}{{else}}{{if eq .REPOSITORY_TYPE "documentation"}}{{else}}
- task common:update:all:docs:generate
- {{end}}{{end}}
+ - task: '{{if eq .REPOSITORY_TYPE "common"}}:donothing{{else}}{{if eq .REPOSITORY_TYPE "documentation"}}:donothing{{else}}all:docs:generate{{end}}{{end}}'
all:docs:generate:
deps:
@@ -41,9 +38,12 @@ tasks:
- :install:npm:readme
vars:
CONTRIB_TEMPLATE: .config/docs/blueprint-contributing.md
+ log:
+ error: Encountered error while generating `docs/CONTRIBUTING.md`
+ start: Generating `docs/CONTRIBUTING.md` using document partials
+ success: Successfully generated `docs/CONTRIBUTING.md`
cmds:
- mkdir -p docs
- - .config/log info 'Generating `docs/CONTRIBUTING.md` using document partials'
- >
{{.NPX_HANDLE}}readme generate --silent --headingPrefix '{}' --config .variables.json
--input "{{.CONTRIB_TEMPLATE}}" --output docs/CONTRIBUTING.md
@@ -51,7 +51,6 @@ tasks:
vars:
SCRUB_FILE: docs/CONTRIBUTING.md
- '{{.NPX_HANDLE}}prettier --write docs/CONTRIBUTING.md > /dev/null'
- - .config/log success 'Successfully generated `docs/CONTRIBUTING.md`'
sources:
- docs/CONTRIBUTING.md
- .config/docs/**/*
@@ -70,6 +69,10 @@ tasks:
sh: if [[ "${container:=}" == "docker" ]]; then echo "docker"; fi
FIRST_LINE:
sh: if [ -f Dockerfile ]; then head -n 1 Dockerfile; fi
+ log:
+ error: Encountered error while updating miscellaneous files
+ start: Updating miscellaneous files
+ success: Updated miscellaneous files
cmds:
- |
{{if eq .REPOSITORY_SUBTYPE "ci-pipeline"}}
@@ -82,6 +85,9 @@ tasks:
- task: :{{if eq .REPOSITORY_SUBTYPE "role"}}ansible:keywords:sync{{else}}donothing{{end}}
init:
+ log:
+ error: Encountered error while initializing project
+ start: Ensuring project is initialized
cmds:
- |
if ! test -f package.json; then
@@ -136,7 +142,6 @@ tasks:
modules:
deps:
- :install:software:git
- label: update:modules
summary: |
# Ensure all submodules in `.modules/` are updated
@@ -145,6 +150,10 @@ tasks:
might symlink files to one of the submodules stored in the `.modules/` folder.
If you are ok with the risk, you can use this task to update all the submodules
to the latest on the remote's master branch.
+ log:
+ error: Failed to ensure submodules in the `.modules/` folder are up-to-date
+ start: Ensuring submodules in the `.modules/` folder are up-to-date
+ success: Successfully ensured submodules in the `.modules/` folder are up-to-date
cmds:
- |
if ls .modules/*/ > /dev/null 2>&1; then
@@ -161,6 +170,8 @@ tasks:
- '! ls .modules/*/ > /dev/null 2>&1'
project:
+ log:
+ start: Pulling `master` if `origin` is defined
cmds:
- |
if [ -d .git ] && git branch -r | grep origin > /dev/null; then
@@ -175,6 +186,10 @@ tasks:
- :install:npm:readme
vars:
README_TEMPLATE: blueprint-readme-{{.REPOSITORY_SUBTYPE}}.md
+ log:
+ error: Error encountered while generating `README.md`
+ start: Generating `README.md`
+ success: Generated README.md successfully
cmds:
- >
{{.NPX_HANDLE}}readme generate --headingPrefix '{}' --silent --config .variables.json
@@ -184,7 +199,6 @@ tasks:
SCRUB_FILE: README.md
- task: ':{{if eq .REPOSITORY_TYPE "packer"}}packer:update:readme{{else}}donothing{{end}}'
- '{{.NPX_HANDLE}}prettier --write README.md > /dev/null'
- - .config/log success 'Generated README.md successfully'
sources:
- .autodoc/*
- .config/docs/**/*
@@ -222,7 +236,6 @@ tasks:
- ':{{if eq .REPOSITORY_TYPE "packer"}}packer:latestos{{else}}donothing{{end}}'
- init
- repositories
- label: update
summary: |
# Refresh project with latest upstream code and ensure project files are up-to-date
diff --git a/.config/taskfiles/common/Taskfile.yml b/.config/taskfiles/common/Taskfile.yml
index 1bb0bbaa..0a215192 100644
--- a/.config/taskfiles/common/Taskfile.yml
+++ b/.config/taskfiles/common/Taskfile.yml
@@ -17,6 +17,10 @@ tasks:
CLEAN_TARGETS: .autodoc .task .venv node_modules
RANDOM_STRING:
sh: openssl rand -hex 14
+ log:
+ error: Error removing `{{.CLEAN_TARGETS}}`
+ start: Removing `{{.CLEAN_TARGETS}}`
+ success: Removed `{{.CLEAN_TARGETS}}`
cmds:
- mkdir -p '/tmp/{{.RANDOM_STRING}}'
- mkdir -p '/tmp/{{.RANDOM_STRING}}-empty'
@@ -48,9 +52,10 @@ tasks:
It is very important that you use this task to commit rather than the conventional approach
using `git commit -m`. However, if you really need to, you can add the flag `--no-verify`
to your regular `git commit -m` command to bypass the pre-commit hook.
+ log:
+ start: Initiating commit dialog
cmds:
- . ./.config/husky/pre-commit
- - .config/log info "Initiating the commit dialog"
- exec < /dev/tty && git cz --hook || true
husky:
@@ -74,11 +79,14 @@ tasks:
husky:install:
deps:
- :install:npm:husky
+ log:
+ error: Error installing Husky git hooks
+ start: Installing Husky git hooks
cmds:
- |
if [ -d .git ] && [ "${container:=}" != 'docker' ]; then
{{.NPX_HANDLE}}husky install .config/husky > /dev/null
- .config/log success 'Installed husky git hooks'
+ .config/log success 'Installed Husky git hooks'
else
.config/log warn 'Cannot run `husky install` because there is no `.git/` folder (or this is a Docker container)'
fi
@@ -86,6 +94,10 @@ tasks:
- '[ ! -d .git ] || [[ "${container:=} == "docker" ]]'
husky:permissions:
+ log:
+ error: Encountered error while ensuring git hook scripts have the appropriate permissions
+ start: Ensuring git hook scripts are executable
+ success: Ensured git hook scripts are executable
cmds:
- |
chmod +x .config/log
@@ -154,6 +166,10 @@ tasks:
If using `task common:reset` does not fix your issues, you can run this task
to completely wipe out uncommitted work, clear all the caches, and sync
with the master branch of both this project and its upstream repositories.
+ log:
+ error: Failed to reset project back to its HEAD
+ start: Forcing project to reset aggressively
+ success: Successfully reset project back to its HEAD
cmds:
- task: clean
- git reset --hard HEAD
@@ -170,16 +186,52 @@ tasks:
shell:cli:
vars:
+ DC: '{{.CLI_ARGS}}'
WORKDIR:
sh: basename $PWD
+ log:
+ start: Starting a Docker container for `{{.DOCKER_CONTAINER}}` and attaching to `/bin/bash`
cmds:
- - cmd: docker run -it -v "$PWD:/{{.WORKDIR}}" -w /{{.WORKDIR}} --rm megabytelabs/ansible-molecule-{{.CLI_ARGS}}:latest /bin/bash
+ - .config/log info 'Running `docker run -it -v "$PWD:/{{.WORKDIR}}" -w /{{.WORKDIR}} --rm megabytelabs/ansible-molecule-{{.DC}}:latest /bin/bash`'
+ - cmd: docker run -it -v "$PWD:/{{.WORKDIR}}" -w /{{.WORKDIR}} --rm megabytelabs/ansible-molecule-{{.DC}}:latest /bin/bash
ignore_error: true
shell:prompt:
- deps:
- - :install:modules:local
+ vars:
+ HELP_MESSAGE: |
+ # Launch a Docker Shell Environment
+
+ Open a shell session quickly, safely, and easily using Docker. Select an option from the prompt below
+ to download and shell into a Docker environment. The environment will be automatically deleted after
+ you exit the terminal session.
+ cmds:
+ - task: log:markdown
+ vars:
+ HELP_MESSAGE: '{{.HELP_MESSAGE}}'
+ - task: shell:prompt:question
+
+ shell:prompt:question:
interactive: true
+ type: select
+ message: Which operating system would you like to open up a terminal session with?
+ options:
+ - Archlinux
+ - CentOS 7
+ - CentOS 8
+ - Debian 9
+ - Debian 10
+ - Fedora 33
+ - Fedora 34
+ - Ubuntu 18.04
+ - Ubuntu 20.04
+ - Ubuntu 21.04
+ answer:
+ cmds:
+ - task: shell:cli
+ env:
+ DC:
+ sh: echo '{{.ANSWER}}' | sed 's/ /-/g' | tr '[:upper:]' '[:lower:]'
+
env:
WORKDIR:
sh: basename $PWD
diff --git a/.config/taskfiles/docker/Taskfile-build.yml b/.config/taskfiles/docker/Taskfile-build.yml
index d9fc22b9..8cbde432 100644
--- a/.config/taskfiles/docker/Taskfile-build.yml
+++ b/.config/taskfiles/docker/Taskfile-build.yml
@@ -23,12 +23,13 @@ tasks:
sh: jq -r '.blueprint.slug' package.json
VERSION:
sh: jq -r '.version' package.json
+ log:
+ error: Error building `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:{{.VERSION}}`
+ start: Building Docker container `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:{{.VERSION}}` (also tagged as latest)
+ success: Successfully built Docker container named `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:{{.VERSION}}`
cmds:
- - |
- .config/log info 'Building Docker container `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:{{.VERSION}}` (also tagged as latest)'
- docker build --build-arg BUILD_DATE="{{.BUILD_DATE}}" --build-arg REVISION="{{.REVISION}}" --build-arg VERSION="{{.VERSION}}"
+ - docker build --build-arg BUILD_DATE="{{.BUILD_DATE}}" --build-arg REVISION="{{.REVISION}}" --build-arg VERSION="{{.VERSION}}"
--tag {{.DOCKERHUB_PROFILE}}/{{.SLUG}}:latest --tag {{.DOCKERHUB_PROFILE}}/{{.SLUG}}:{{.VERSION}} .
- .config/log success 'Successfully built Docker container named `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:{{.VERSION}}`'
sources:
- Dockerfile
- package.json
@@ -61,11 +62,12 @@ tasks:
sh: jq -r '.blueprint.dockerslim_command' package.json
SLUG:
sh: jq -r '.blueprint.slug' package.json
+ log:
+ error: Error building `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim` with `docker-slim`
+ start: Building Docker container named `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim`
+ success: Successfully built Docker container named `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim`
cmds:
- - |
- .config/log info 'Building Docker container named `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim`'
- docker-slim build --tag '{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim' {{.SLIM_COMMAND}} '{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:latest'
- .config/log success 'Successfully built Docker container named `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim`'
+ - docker-slim build --tag '{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim' {{.SLIM_COMMAND}} '{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:latest'
sources:
- Dockerfile
- package.json
@@ -78,6 +80,10 @@ tasks:
slim:prettier:
deps:
- :install:npm:prettier
+ log:
+ error: Failed to format `slim.report.json` with Prettier
+ start: Formatting `slim.report.json` with Prettier
+ success: Formatted `slim.report.json` with Prettier
cmds:
- '{{.NPX_HANDLE}}prettier --write slim.report.json > /dev/null'
sources:
@@ -96,6 +102,9 @@ tasks:
SLIM_SIZE:
sh: 'docker manifest inspect -v "{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim" | grep size | awk -F ":" "{sum+=$NF} END {print sum}"
| awk "{$1=$1/(1024^2); print $1,\"MB\";}"'
+ log:
+ error: Failed to acquire / inject `:slim` image file size information into `package.json` blueprint data
+ start: Injecting `:slim` image file size into `package.json` blueprint data
cmds:
- |
TMP="$(mktemp)"
diff --git a/.config/taskfiles/docker/Taskfile-test.yml b/.config/taskfiles/docker/Taskfile-test.yml
index 5d302c0d..55efe836 100644
--- a/.config/taskfiles/docker/Taskfile-test.yml
+++ b/.config/taskfiles/docker/Taskfile-test.yml
@@ -11,21 +11,23 @@ tasks:
container-structure-test:latest:
deps:
- :install:software:container-structure-test
+ log:
+ error: '`container-structure-test` reported error(s) when testing `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:latest`'
+ start: Testing the `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:latest` Docker image with `container-structure-test`
+ success: '`{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:latest` was successfully validated by `container-structure-test`'
cmds:
- - |
- if [[ "$(docker images -q {{.DOCKERHUB_PROFILE}}/{{.SLUG}}:latest 2>/dev/null)" != "" ]]; then
- .config/log info 'Testing the `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:latest` Docker image'
- container-structure-test test --image {{.DOCKERHUB_PROFILE}}/{{.SLUG}}:latest --config test.yml
- .config/log success 'Successfully tested Docker image named `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:latest`'
- fi
+ - container-structure-test test --image {{.DOCKERHUB_PROFILE}}/{{.SLUG}}:latest --config test.yml
+ status:
+ - '[[ "$(docker images -q {{.DOCKERHUB_PROFILE}}/{{.SLUG}}:latest 2>/dev/null)" == "" ]]'
container-structure-test:slim:
deps:
- :install:software:container-structure-test
+ log:
+ error: '`container-structure-test` reported error(s) when testing `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim`'
+ start: Testing the `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim` Docker image with `container-structure-test`
+ success: '`{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim` was successfully validated by `container-structure-test`'
cmds:
- - |
- if [[ "$(docker images -q {{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim 2> /dev/null)" != "" ]]; then
- .config/log info 'Testing the `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim` Docker image'
- container-structure-test test --image {{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim --config test.yml
- .config/log success 'Successfully tested Docker image named `{{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim`'
- fi
+ - container-structure-test test --image {{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim --config test.yml
+ status:
+ - '[[ "$(docker images -q {{.DOCKERHUB_PROFILE}}/{{.SLUG}}:slim 2> /dev/null)" == "" ]]'
diff --git a/.config/taskfiles/docker/Taskfile-update.yml b/.config/taskfiles/docker/Taskfile-update.yml
index ae79a9cf..1efeecc9 100644
--- a/.config/taskfiles/docker/Taskfile-update.yml
+++ b/.config/taskfiles/docker/Taskfile-update.yml
@@ -8,6 +8,9 @@ tasks:
vars:
GROUP_URL:
sh: jq -r '.repository.group.dockerfile' .variables.json
+ log:
+ start: Ensuring `Dockerfile` labels are up-to-date
+ success: '`Dockerfile` labels are up-to-date'
cmds:
- task: update:labels:add
- task: update:labels:{{OS}}
@@ -35,28 +38,29 @@ tasks:
sh: jq -r '.organization' .variables.json
URL:
sh: jq -r '.link.home' .variables.json
+ log:
+ error: Failed to add Dockerfile labels
+ start: Ensuring default Dockerfile labels are present (e.g. `org.opencontainers.image` tags)
+ success: Successfully injected `org.opencontainers.image` labels into Dockerfile
cmds:
- |
- if ! grep 'org.opencontainers.image.documentation' Dockerfile; then
- echo 'ARG BUILD_DATE' >> Dockerfile
- echo 'ARG REVISION' >> Dockerfile
- echo 'ARG VERSION' >> Dockerfile
- echo '' >> Dockerfile
- echo 'LABEL maintainer="{{.ORGANIZATION}} <{{.HELP_EMAIL}}>"' >> Dockerfile
- echo 'LABEL org.opencontainers.image.authors="{{.AUTHORS}}"' >> Dockerfile
- echo 'LABEL org.opencontainers.image.created=$BUILD_DATE' >> Dockerfile
- echo 'LABEL org.opencontainers.image.description="[[ Injected by running `task update` ]]"' >> Dockerfile
- echo 'LABEL org.opencontainers.image.documentation="[[ Injected by running `task update` ]]"' >> Dockerfile
- echo 'LABEL org.opencontainers.image.licenses="{{.LICENSE}}"' >> Dockerfile
- echo 'LABEL org.opencontainers.image.revision=$REVISION' >> Dockerfile
- echo 'LABEL org.opencontainers.image.source="[[ Injected by running `task update` ]]"' >> Dockerfile
- echo 'LABEL org.opencontainers.image.url="{{.URL}}"' >> Dockerfile
- echo 'LABEL org.opencontainers.image.vendor="{{.ORGANIZATION}}"' >> Dockerfile
- echo 'LABEL org.opencontainers.image.version=$VERSION' >> Dockerfile
- echo 'LABEL space.megabyte.type="{{.REPOSITORY_SUBTYPE}}"' >> Dockerfile
- echo '' >> Dockerfile
- .config/log success 'Successfully injected org.opencontainers labels into Dockerfile'
- fi
+ echo 'ARG BUILD_DATE' >> Dockerfile
+ echo 'ARG REVISION' >> Dockerfile
+ echo 'ARG VERSION' >> Dockerfile
+ echo '' >> Dockerfile
+ echo 'LABEL maintainer="{{.ORGANIZATION}} <{{.HELP_EMAIL}}>"' >> Dockerfile
+ echo 'LABEL org.opencontainers.image.authors="{{.AUTHORS}}"' >> Dockerfile
+ echo 'LABEL org.opencontainers.image.created=$BUILD_DATE' >> Dockerfile
+ echo 'LABEL org.opencontainers.image.description="[[ Injected by running `task update` ]]"' >> Dockerfile
+ echo 'LABEL org.opencontainers.image.documentation="[[ Injected by running `task update` ]]"' >> Dockerfile
+ echo 'LABEL org.opencontainers.image.licenses="{{.LICENSE}}"' >> Dockerfile
+ echo 'LABEL org.opencontainers.image.revision=$REVISION' >> Dockerfile
+ echo 'LABEL org.opencontainers.image.source="[[ Injected by running `task update` ]]"' >> Dockerfile
+ echo 'LABEL org.opencontainers.image.url="{{.URL}}"' >> Dockerfile
+ echo 'LABEL org.opencontainers.image.vendor="{{.ORGANIZATION}}"' >> Dockerfile
+ echo 'LABEL org.opencontainers.image.version=$VERSION' >> Dockerfile
+ echo 'LABEL space.megabyte.type="{{.REPOSITORY_SUBTYPE}}"' >> Dockerfile
+ echo '' >> Dockerfile
status:
- grep 'org.opencontainers.image.documentation' Dockerfile
@@ -64,6 +68,8 @@ tasks:
vars:
GROUP_URL:
sh: jq -r '.repository.group.dockerfile' .variables.json
+ log:
+ error: Encountered error while updating `Dockerfile` labels
cmds:
# yamllint disable rule:line-length
# eslint-disable max-len
@@ -81,6 +87,8 @@ tasks:
sh: jq -r '.repository.group.dockerfile' .variables.json
SLUG:
sh: jq -r '.blueprint.slug' package.json
+ log:
+ error: Encountered error while updating `Dockerfile` labels
cmds:
# yamllint disable rule:line-length
# eslint-disable max-len
diff --git a/.config/taskfiles/docker/Taskfile.yml b/.config/taskfiles/docker/Taskfile.yml
index 624b5a1d..4cb9bab5 100644
--- a/.config/taskfiles/docker/Taskfile.yml
+++ b/.config/taskfiles/docker/Taskfile.yml
@@ -1,6 +1,12 @@
---
version: '3'
+vars:
+ DOCKER_IMAGE:
+ sh: jq -r '.name' package.json | sed 's/^@//'
+ SLIM_ENABLED:
+ sh: jq -r '.blueprint.slimBuildEnabled' package.json | sed 's/null/false/'
+
tasks:
build:
desc: Build a regular Docker image and then generate a slim build from it
@@ -8,11 +14,78 @@ tasks:
- task: :docker:build:fat
- task: :docker:build:slim
- standard-version:prebump:
+ login:
+ deps:
+ - :install:software:docker
+ log:
+ error: Failed to authenticate `{{.DOCKERHUB_USER}}` with the DockerHub registry
+ start: Logging into DockerHub registry with `{{.DOCKERHUB_USER}}`
+ success: Authenticated to DockerHub registry with `{{.DOCKERHUB_USER}}`
+ cmds:
+ - echo "$DOCKERHUB_REGISTRY_PASSWORD" | docker login -u {{.DOCKERHUB_USER}} --password-stdin
+ preconditions:
+ - test -n "$DOCKERHUB_REGISTRY_PASSWORD"
+
+ prepare:
+ cmds:
+ - task: build
+
+ publish:
+ vars:
+ MAJOR_VERSION:
+ sh: '{{if .CLI_ARGS}}echo "{{.CLI_ARGS}}"{{else}}jq -r ".version" package.json{{end}} | sed "s/\..*\..*$//"'
+ VERSION:
+ sh: '{{if .CLI_ARGS}}echo "{{.CLI_ARGS}}"{{else}}jq -r ".version" package.json{{end}}'
+ log:
+ error: An error occurred while publishing the Docker images
+ start: Publishing Docker images
+ success: Finished uploading all Docker images
+ cmds:
+ - task: publish:image
+ vars:
+ SOURCE_TAG: latest
+ TARGET_TAG: '{{.VERSION}}'
+ - task: publish:image
+ vars:
+ SOURCE_TAG: latest
+ TARGET_TAG: '{{.MAJOR_VERSION}}-latest'
+ - task: publish:image
+ vars:
+ SOURCE_TAG: latest
+ TARGET_TAG: latest
+ - task: publish:image
+ vars:
+ SOURCE_TAG: slim
+ TARGET_TAG: '{{.VERSION}}-slim'
+ - task: publish:image
+ vars:
+ SOURCE_TAG: slim
+ TARGET_TAG: '{{.MAJOR_VERSION}}-slim'
+ - task: publish:image
+ vars:
+ SOURCE_TAG: slim
+ TARGET_TAG: slim
+
+ publish:image:
+ log:
+ error: Failed to tag / push `{{.DOCKER_IMAGE}}:{{.TARGET_TAG}}`
+ start: Tagging and pushing `{{.DOCKER_IMAGE}}:{{.TARGET_TAG}}`
+ success: Finished uploading `{{.DOCKER_IMAGE}}:{{.TARGET_TAG}}`
+ cmds:
+ - docker tag {{.DOCKER_IMAGE}}:{{.SOURCE_TAG}} {{.DOCKER_IMAGE}}:{{.TARGET_TAG}}
+ - docker push {{.DOCKER_IMAGE}}:{{.TARGET_TAG}}
+ status:
+ - if [[ '{{.SOURCE_TAG}}' == 'slim' ]]; then [[ '{{.SLIM_ENABLED}}' == 'false' ]]; fi
+
+ verify:
+ cmds:
+ - task: login
+
+ version:software:
cmds:
- |
if grep -q "CMD.\[\"--version\"\]" Dockerfile; then
- VERSION=$(docker run --cap-drop=ALL -e PY_COLORS=0 --rm megabytelabs/shellcheck:latest | perl \
+ VERSION=$(docker run --cap-drop=ALL -e PY_COLORS=0 --rm {{.DOCKER_IMAGE}}:latest | perl \
-pe 'if(($v)=/([0-9]+([.][0-9]+)+)/){print"$v";exit}$_=""')
if [[ $VERSION == *.*.* ]]; then
echo $VERSION
@@ -20,15 +93,3 @@ tasks:
echo $VERSION.0
fi
fi
-
- standard-version:prerelease: git add --all
-
- standard-version:pretag:
- vars:
- PACKAGE_VERSION:
- sh: grep version < package.json | head -1 | awk -F':' '{ print $2 }' | sed 's/[\",]//g' | tr -d '[[:space:]]'
- cmds:
- - |
- if git show-ref --tags 'v{{.PACKAGE_VERSION}}' --quiet; then
- git tag -d 'v{{.PACKAGE_VERSION}}'
- fi
diff --git a/.config/taskfiles/fix/Taskfile.yml b/.config/taskfiles/fix/Taskfile.yml
index 6054d4e9..df1a9c2f 100644
--- a/.config/taskfiles/fix/Taskfile.yml
+++ b/.config/taskfiles/fix/Taskfile.yml
@@ -14,6 +14,8 @@ tasks:
- '{{if .REPOSITORY_TYPE eq "python"}}python{{else}}:donothing{{end}}'
- toml
- xml
+ log:
+ start: Running all stable fixers in parallel
cmds:
- task: yaml:dashes
@@ -34,6 +36,10 @@ tasks:
**Example fixing all JS/TS files in a project:**
`task fix:js`
+ log:
+ error: ESLint found some issues that need to be fixed manually
+ start: Auto-fixing with ESLint
+ success: ESLint fixing appears to have corrected all the issues {{if .CLI_ARGS}}in `{{.CLI_ARGS}}`{{else}}in the project{{end}}
cmds:
- '{{.NPX_HANDLE}}eslint -c package.json --no-eslintrc --format pretty --cache --cache-location .cache/eslintcache
--fix {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}}'
@@ -58,6 +64,10 @@ tasks:
**Example looping through project:**
`task fix:json`
+ log:
+ error: '{{if .CLI_ARGS}}Manual fixing is still required for `{{.CLI_ARGS}}`{{else}}Failed to fix all project JSON issues with ESLint{{end}}'
+ start: Linting JSON with ESLint
+ success: ESLint has fixed all of the JSON issues {{if .CLI_ARGS}}in `{{.CLI_ARGS}}`{{else}}in the project{{end}}
cmds:
- '{{.NPX_HANDLE}}eslint -c package.json --no-eslintrc --cache --cache-location .cache/eslintcache --fix
--format pretty --ext .json {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}}'
@@ -80,6 +90,10 @@ tasks:
**Example applying fixes to single file:**
`task fix:misc -- singlefile.js`
+ log:
+ error: Encountered an error while performing miscellaneous fixes{{if .CLI_ARGS}} on `{{.CLI_ARGS}}`{{end}}
+ start: Performing miscellaneous fixes such as removing BOM and ensuring LF line endings
+ success: Finished performing miscellaneous fixes{{if .CLI_ARGS}} on `{{.CLI_ARGS}}`{{end}}
cmds:
- |
function misc() {
@@ -113,6 +127,10 @@ tasks:
`task fix:packer -- mytemplate.json`
For more information on `packer fix`, see [Packer's website](https://www.packer.io/docs/commands/fix).
+ log:
+ start: Attempting to fix Packer template{{if .CLI_ARGS}}{{else}}s{{end}}
+ stop: Error running `packer fix`
+ success: Successfully ran `packer fix` on the template(s)
cmds:
- |
function packerFix() {
@@ -152,6 +170,8 @@ tasks:
`task fix:formatting -- path/filename.ext`
For more information, see [Prettier's website](https://prettier.io/).
+ log:
+ start: Running Prettier on {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}project{{end}}
cmds:
- '{{.NPX_HANDLE}}prettier --ignore-path {{.PRETTIERIGNORE_CONFIG}} --write {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}}'
@@ -173,6 +193,10 @@ tasks:
`task fix:python -- myfile.py`
For more information, see [Black's GitHub page](https://github.com/psf/black).
+ log:
+ error: Error while running `black` auto-fixer
+ start: Fixing Python with `black`
+ success: Fixed {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}project{{end}} with `black`
cmds:
- |
{{if .CLI_ARGS}}
@@ -214,6 +238,10 @@ tasks:
`task fix:scripts -- myfile.sh`
For more information, see [Shellcheck's GitHub page](https://github.com/koalaman/shellcheck).
+ log:
+ error: Encountered an error while linting with `shellcheck` on {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}project{{end}}
+ start: Running `shellcheck` auto-fixer
+ success: Autofixed {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}project{{end}} with `shellcheck`
cmds:
- |
.config/log warn 'This is an experimental fix method - please manually inspect and test the scripts'
@@ -239,6 +267,10 @@ tasks:
**Example fixing specific `.xml` file(s):**
`task fix:xml -- 'file_name.xml'`
+ log:
+ error: Errors were reported by ESLint when auto-fixing XML
+ start: Attempting to auto-fix any XML files with ESLint
+ success: Any XML files present in the project were successfully fixed/validated by ESLint
cmds:
- '{{.NPX_HANDLE}}eslint -c package.json --no-eslintrc --cache --cache-location .cache/eslintcache --fix
--format pretty --ext .xml {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}}'
@@ -280,6 +312,10 @@ tasks:
**Example usage for one specific file:**
`task fix:yaml:dashes -- path/filename.yml`
+ log:
+ error: Error encountered while ensuring YML dashes
+ start: Ensuring {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}project{{end}} has YML files that start with `---`
+ success: Successfully ensured {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}project{{end}} has YML files that start with `---`
cmds:
- |
function yamlDashes() {
@@ -317,6 +353,10 @@ tasks:
**Example fixing specific `.yml` file(s):**
`task fix:yaml:order -- 'file_name.{yml,yaml}'`
+ log:
+ error: There are still some errors. Try running the command again.
+ start: Ensuring YML file(s) are in order specified in configuration
+ success: Successfully ensured YML file order
cmds:
- '{{.NPX_HANDLE}}eslint -c package.json --no-eslintrc --format pretty --fix --cache
--cache-location .cache/eslintcache --ext yml,yaml {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}}'
diff --git a/.config/taskfiles/git/Taskfile-github.yml b/.config/taskfiles/git/Taskfile-github.yml
index c8d917f9..6a7281fb 100644
--- a/.config/taskfiles/git/Taskfile-github.yml
+++ b/.config/taskfiles/git/Taskfile-github.yml
@@ -17,21 +17,19 @@ tasks:
PROJECT_TYPE:
sh: if [[ $(jq -r '.private' package.json) == 'true' ]]; then echo '--private'; else echo '--public'; fi
run: once
+ log:
+ error: Error while ensuring GitHub repository exists
+ start: Checking for presence of GitHub repository and creating one if it does not exist
+ success: Ensure GitHub repository is present
cmds:
- - cmd: |
- TMP="$(mktemp)"
- if [ ! -z "$GITHUB_TOKEN" ] && test -e .git && ! gh repo view {{.GITHUB_ORG}}/{{.GITHUB_SLUG}} > /dev/null; then
- gh repo create "{{.GITHUB_SLUG}}" --enable-wiki={{.GITHUB_WIKI}} -y --description "{{.EMOJI_START}}{{.DESCRIPTION}}{{.EMOJI_END}}" \
- --homepage "{{.HOMEPAGE}}" {{.PROJECT_TYPE}} > /dev/null
- .config/log success 'Created a GitHub repository - `https://github.com/{{.GITHUB_ORG}}/{{.GITHUB_SLUG}}`'
- git add --all
- git commit --quiet -m "🎂 Birth" -n
- git push --quiet -u --no-progress github master
- fi
+ - cmd: gh repo create "{{.GITHUB_SLUG}}" --enable-wiki={{.GITHUB_WIKI}} -y --description "{{.EMOJI_START}}{{.DESCRIPTION}}{{.EMOJI_END}}"
+ --homepage "{{.HOMEPAGE}}" {{.PROJECT_TYPE}} > /dev/null
ignore_error: true
- sources:
- - .variables.json
- - package.json
+ - git add --all
+ - git commit --quiet -m "🎂 Birth" -n
+ - git push --quiet -u --no-progress github master
+ status:
+ - '[ -z "$GITHUB_TOKEN" ] || ! test -e .git || gh repo view {{.GITHUB_ORG}}/{{.GITHUB_SLUG}} > /dev/null'
preconditions:
- sh: '[ "{{.DESCRIPTION}}" != "null" ]'
msg: The `.description` in `package.json` must be set.
@@ -45,12 +43,19 @@ tasks:
- :install:software:gh
- :install:software:jq
- create
+ vars:
+ CURRENT_PROJECT_ID:
+ sh: jq -r '.blueprint.github_id' package.json
+ PROJECT_ID:
+ sh: gh repo view --json id | jq -r '.id'
+ log:
+ error: Failed to add GitHub project ID to package.json
+ start: Saving GitHub project ID to package.json
+ success: Added GitHub project ID to package.json
cmds:
- - |
- PROJECT_ID="$(gh repo view --json id | jq -r '.id')"
- TMP="$(mktemp)" && jq --arg projectId "$PROJECT_ID" '.blueprint.github_id = $projectId' package.json > "$TMP"
- mv "$TMP" package.json
- .config/log success 'Added GitHub project ID to package.json'
+ - TMP="$(mktemp)" && jq --arg projectId "{{.PROJECT_ID}}" '.blueprint.github_id = $projectId' package.json > "$TMP" && mv "$TMP" package.json
+ status:
+ - '[[ "{{.CURRENT_PROJECT_ID}}" == "{{.PROJECT_ID}}" ]]'
update:
deps:
@@ -72,6 +77,10 @@ tasks:
sh: jq -r '.homepage' package.json
PRIVATE:
sh: jq -r '.private' package.json | sed 's/null/false/'
+ log:
+ error: Error while updating GitHub repository metadata
+ start: Updating GitHub project metadata
+ success: Updated GitHub repository metadata
cmds:
- |
OPTIONAL_TAGS="$(jq '.keywords' .config/common-keywords.json)"
@@ -115,11 +124,11 @@ tasks:
deps:
- :install:software:gh
- create
+ log:
+ error: Error setting GitHub Actions Ansible Galaxy token
+ start: Setting GitHub Actions Ansible Galaxy token
+ success: GitHub Actions Ansible Galaxy token set
cmds:
- - |
- if [ ! -z "$GITHUB_TOKEN" ] && [ ! -z "$ANSIBLE_GALAXY_TOKEN" ] && [ '{{.REPOSITORY_TYPE}}' == 'ansible' ]; then
- gh secret set ANSIBLE_GALAXY_TOKEN -b "$ANSIBLE_GALAXY_TOKEN"
- .config/log success 'Updated GitHub Actions `ANSIBLE_GALAXY_TOKEN` environment variable successfully'
- fi
+ - gh secret set ANSIBLE_GALAXY_TOKEN -b "$ANSIBLE_GALAXY_TOKEN"
status:
- '[ -z "$GITHUB_TOKEN" ] || [ -z "$ANSIBLE_GALAXY_TOKEN" ] || [ "{{.REPOSITORY_TYPE}}" != "ansible" ]'
diff --git a/.config/taskfiles/git/Taskfile-gitlab.yml b/.config/taskfiles/git/Taskfile-gitlab.yml
index d9ddf8d6..e5a9ed27 100644
--- a/.config/taskfiles/git/Taskfile-gitlab.yml
+++ b/.config/taskfiles/git/Taskfile-gitlab.yml
@@ -17,6 +17,10 @@ tasks:
TOKEN_STATUS:
sh: glab api projects/:fullpath/access_tokens | jq -r '.[] | select(.name=="PROJECT_CI_ACCESS_TOKENX") | .id'
run: once
+ log:
+ error: Failed to configure project-specific access token
+ start: Configuring project-specific access token
+ success: Configured project-specific access token
cmds:
- |
curl -sSL --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" --header \
@@ -33,6 +37,10 @@ tasks:
REPO_ID:
sh: glab api projects/:fullpath | jq '.id'
run: once
+ log:
+ error: Error encountered while setting up protected branches
+ start: Setting up protected branches
+ success: Set up protected branches
cmds:
- |
if [[ "$(glab api projects/:fullpath/protected_branches/master | jq '.code_owner_approval_required')" == 'false' ]]; then
@@ -54,11 +62,14 @@ tasks:
glab api projects/:fullpath/protected_branches -X POST -f name=main -f code_owner_approval_required=true > /dev/null &
glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=next -f ref=master > /dev/null &
glab api projects/:fullpath/protected_branches -X POST -f name=next -f code_owner_approval_required=true > /dev/null &
+ glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=alpha -f ref=master > /dev/null &
+ glab api projects/:fullpath/protected_branches -X POST -f name=alpha -f code_owner_approval_required=true > /dev/null &
+ glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=beta -f ref=master > /dev/null &
+ glab api projects/:fullpath/protected_branches -X POST -f name=beta -f code_owner_approval_required=true > /dev/null &
glab api projects/:fullpath/protected_branches -X POST -f name=protected/* -f code_owner_approval_required=true > /dev/null &
glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=synchronize -f ref=master > /dev/null &
glab api projects/:fullpath/protected_branches -X POST -f name=synchronize -f code_owner_approval_required=true -f allow_force_push=true > /dev/null &
wait
- .config/log success "Successfully set up GitLab protected branches"
create:
deps:
@@ -79,22 +90,21 @@ tasks:
TMP:
sh: mktemp
run: once
+ log:
+ error: Encountered error while creating GitLab repository
+ start: Ensuring GitLab repository has been created
+ success: Ensured GitLab repository exists
cmds:
- cmd: |
- KEYWORDS="$(jq -r '.keywords | tostring' package.json | sed 's/\[//' | sed 's/\]//')"
- if [ ! -z "$GITLAB_TOKEN" ] && test -e .git && ! glab repo view '{{.GITLAB_PATH}}' > /dev/null; then
- NO_PROMPT=1 glab repo create '{{.GITLAB_PATH}}' --group '{{.GITLAB_GROUP}}' \
- --description '{{.EMOJI_START}}{{.DESCRIPTION}}{{.EMOJI_END}}' --name '{{.NAME}}' \
- {{.PROJECT_TYPE}} --tag "$KEYWORDS"
- git add --all
- git commit --quiet -m "🎂 Birth" -n
- git push --quiet -u --no-progress gitlab master
- .config/log success 'Created new GitLab repository - `https://gitlab.com/{{.GITLAB_PATH}}`'
- fi
+ NO_PROMPT=1 glab repo create '{{.GITLAB_PATH}}' --group '{{.GITLAB_GROUP}}'
+ --description '{{.EMOJI_START}}{{.DESCRIPTION}}{{.EMOJI_END}}' --name '{{.NAME}}'
+ {{.PROJECT_TYPE}} --tag "$(jq -r '.keywords | tostring' package.json | sed 's/\[//' | sed 's/\]//')"
+ git commit --quiet -m "🎂 Birth" -n
+ git add --all
+ git push --quiet -u --no-progress gitlab master
ignore_error: true
- sources:
- - .variables.json
- - package.json
+ status:
+ - '[ -z "$GITLAB_TOKEN" ] || ! test -e .git && glab repo view "{{.GITLAB_PATH}}" > /dev/null'
preconditions:
- sh: '[ "{{.DESCRIPTION}}" != "null" ]'
msg: The `.description` in `package.json` must be set.
@@ -115,6 +125,10 @@ tasks:
- task: group:exec:{{if .CLI_ARGS}}cli{{else}}prompt{{end}}
group:exec:cli:
+ log:
+ error: Failed to run group:exec logic
+ start: Running group:exec logic
+ success: Successfully ran group:exec logic
cmds:
- task git:gitlab:group:repositories -- {{index (splitList " ---- " .CLI_ARGS) 0}}
- |
@@ -142,7 +156,7 @@ tasks:
}
cat {{.REPOSITORY_LIST}} | (while IFS= read -r REPO_DETAILS; do
.config/log info "Executing logic on $REPO_DETAILS"
- execRepo "$REPO_DETAILS" &
+ execRepo "$REPO_DETAILS"{{.CLI_ARGS}}
done
wait)
@@ -165,6 +179,10 @@ tasks:
**Example specifying a group and subgroup:**
`task {{.TASK}} -- megabyte-labs/ansible-roles`
+ log:
+ error: Encountered error while generating a list of repositories
+ start: Generating list of repositories
+ success: List of repositories generated
cmds:
- mkdir -p .cache
- rm -f {{.REPOSITORY_LIST}}
@@ -188,16 +206,20 @@ tasks:
- :install:software:glab
- :install:software:jq
- create
+ log:
+ error: Error acquiring GitLab project and group IDs
+ start: Acquiring GitLab project and group IDs
+ success: Saved GitLab project and group IDs to package.json
cmds:
- |
API_RES="$(glab api projects/:fullpath)"
PROJECT_ID="$(echo "$API_RES" | jq '.id')"
TMP="$(mktemp)" && jq --arg projectId "$PROJECT_ID" '.blueprint.gitlab_project_id = $projectId' package.json > "$TMP"
mv "$TMP" package.json
+ - |
GROUP_ID="$(echo "$API_RES" | jq '.namespace.id')"
TMP="$(mktemp)" && jq --arg groupId "$GROUP_ID" '.blueprint.gitlab_group_id = $groupId' package.json > "$TMP"
mv "$TMP" package.json
- .config/log success 'Added GitLab project ID to package.json'
integrations:
deps:
@@ -210,13 +232,15 @@ tasks:
deps:
- :install:software:glab
- :install:software:jq
+ log:
+ error: Error enabling GitLab's GitHub integration
+ start: Ensuring GitLab's GitHub integration is enabled
+ success: GitLab's GitHub integration is enabled
cmds:
- - |
- GITHUB_REPO="$(jq -r '.blueprint.repository.github' package.json)"
- if [ ! -z "$GITLAB_TOKEN" ] && [ ! -z "$GITHUB_TOKEN" ]; then
- glab api projects/:fullpath/integrations/github -X PUT -f token="$GITHUB_TOKEN" -f repository_url="$GITHUB_REPO" --silent
- .config/log success 'Ensured GitLab'\''s GitHub integration is activated'
- fi
+ - glab api projects/:fullpath/integrations/github -X PUT -f token="$GITHUB_TOKEN"
+ -f repository_url="$(jq -r '.blueprint.repository.github' package.json)" --silent
+ status:
+ - '[ -z "$GITLAB_TOKEN" ] || [ -z $GITHUB_TOKEN ]'
mirror:
deps:
@@ -231,22 +255,24 @@ tasks:
sh: glab api projects/:fullpath | jq -r '.id'
PUSH_MIRROR_COUNT:
sh: glab api projects/:fullpath/remote_mirrors | jq '. | length'
+ log:
+ error: Error ensuring push/pull mirroring is enabled between GitLab and GitHub
+ start: Ensuring push/pull mirroring from GitLab to GitHub is set up
+ success: Push and pull mirroring from GitLab to GitHub are enabled
cmds:
- - >
- if [ -n "$GITLAB_TOKEN" ] && [ -n "$GITHUB_TOKEN" ]; then
- if [[ "{{.PUSH_MIRROR_COUNT}}" == '0' ]]; then
- glab api projects/:fullpath/remote_mirrors --method POST --header "Content-Type: application/json" \
- -f "url=https://{{.GITHUB_USER}}:$GITHUB_TOKEN@github.com/{{.GITHUB_ORG}}/{{.GITHUB_SLUG}}.git" \
- -f 'enabled=true' > /dev/null
- .config/log success 'Successfully set up push mirroring from GitLab to GitHub'
- fi
- curl -s -H 'Content-Type: application/json' -H "Authorization: Bearer $GITLAB_TOKEN" -X PUT --data \
- "{\"mirror\": true, \"import_url\": \"https://{{.GITHUB_USER}}:$GITHUB_TOKEN@github.com/{{.GITHUB_ORG}}/{{.GITHUB_SLUG}}.git\"}" \
- 'https://gitlab.com/api/v4/projects/{{.GITLAB_REPO_ID}}' > /dev/null
- .config/log success 'Ensured pull mirroring from GitHub to GitLab is set up on GitLab'
+ - |
+ if [[ "{{.PUSH_MIRROR_COUNT}}" == '0' ]]; then
+ glab api projects/:fullpath/remote_mirrors --method POST --header "Content-Type: application/json" \
+ -f "url=https://{{.GITHUB_USER}}:$GITHUB_TOKEN@github.com/{{.GITHUB_ORG}}/{{.GITHUB_SLUG}}.git" \
+ -f 'enabled=true' > /dev/null
+ .config/log success 'Successfully set up push mirroring from GitLab to GitHub'
fi
- sources:
- - package.json
+ - >
+ curl -s -H 'Content-Type: application/json' -H "Authorization: Bearer $GITLAB_TOKEN" -X PUT --data
+ "{\"mirror\": true, \"import_url\": \"https://{{.GITHUB_USER}}:$GITHUB_TOKEN@github.com/{{.GITHUB_ORG}}/{{.GITHUB_SLUG}}.git\"}"
+ 'https://gitlab.com/api/v4/projects/{{.GITLAB_REPO_ID}}' > /dev/null
+ status:
+ - '[ -z "$GITLAB_TOKEN ] || [ -z "GITHUB_TOKEN ]'
pipelines:
deps:
@@ -256,35 +282,38 @@ tasks:
vars:
PIPELINE_COUNT:
sh: jq -r '.gitlab_pipelines | length' .variables.json
+ log:
+ error: Error setting up GitLab pipelines
+ start: Ensuring GitLab pipelines are set up according to the configuration
+ success: GitLab pipelines are set up
cmds:
- |
PIPELINES="$(jq -r '.gitlab_pipelines' .variables.json)"
PIPELINE_RES="$(glab api projects/:fullpath/pipeline_schedules)"
- if [ ! -z "$GITLAB_TOKEN" ]; then
- for INDEX in {1..{{.PIPELINE_COUNT}}}; do
- PIPELINE_INDEX="$((INDEX - 1))"
- ACTIVE="$(echo "$PIPELINES" | jq -r --arg i "$PIPELINE_INDEX" '.[$i | tonumber].active')"
- CRON="$(echo "$PIPELINES" | jq -r --arg i "$PIPELINE_INDEX" '.[$i | tonumber].cron' | sed 's/"//g')"
- DESC="$(echo "$PIPELINES" | jq -r --arg i "$PIPELINE_INDEX" '.[$i | tonumber].description')"
- REF="$(echo "$PIPELINES" | jq -r --arg i "$PIPELINE_INDEX" '.[$i | tonumber].ref')"
- if (! echo "$PIPELINE_RES" | grep "$DESC") > /dev/null; then
- glab api projects/:fullpath/pipeline_schedules -X POST -f active="$ACTIVE" -f description="$DESC" -f ref="$REF" \
- -f cron="$CRON" -f cron_timezone='{{.TIMEZONE}}' --silent
- if [ "$DESC" != 'null' ]; then .config/log success "Pipeline with description of '${DESC}' successfully added"; fi
- else
- if [ "$DESC" != 'null' ]; then .config/log info "Pipeline with description of '${DESC}' already added"; fi
- fi
- done
- else
- .config/log warn 'The `'"GITLAB_TOKEN"'` environment variable is not set so the GitLab pipelines cannot be updated via the API.'
- fi
- sources:
- - .variables.json
- - package.json
+ for INDEX in {1..{{.PIPELINE_COUNT}}}; do
+ PIPELINE_INDEX="$((INDEX - 1))"
+ ACTIVE="$(echo "$PIPELINES" | jq -r --arg i "$PIPELINE_INDEX" '.[$i | tonumber].active')"
+ CRON="$(echo "$PIPELINES" | jq -r --arg i "$PIPELINE_INDEX" '.[$i | tonumber].cron' | sed 's/"//g')"
+ DESC="$(echo "$PIPELINES" | jq -r --arg i "$PIPELINE_INDEX" '.[$i | tonumber].description')"
+ REF="$(echo "$PIPELINES" | jq -r --arg i "$PIPELINE_INDEX" '.[$i | tonumber].ref')"
+ if (! echo "$PIPELINE_RES" | grep "$DESC") > /dev/null; then
+ glab api projects/:fullpath/pipeline_schedules -X POST -f active="$ACTIVE" -f description="$DESC" -f ref="$REF" \
+ -f cron="$CRON" -f cron_timezone='{{.TIMEZONE}}' --silent
+ if [ "$DESC" != 'null' ]; then .config/log success "Pipeline with description of '${DESC}' successfully added"; fi
+ else
+ if [ "$DESC" != 'null' ]; then .config/log info "Pipeline with description of '${DESC}' already added"; fi
+ fi
+ done
+ status:
+ - '[ -z "$GITLAB_TOKEN" ]'
pipelines:clear:
deps:
- create
+ log:
+ error: Error clearing GitLab pipelines
+ start: Clearing GitLab pipelines
+ success: Cleared GitLab pipelines
cmds:
- |
TMP="$(mktemp)"
@@ -292,7 +321,6 @@ tasks:
for PIPELINE_ID in $(jq -r '.[].id' "$TMP"); do
glab api projects/:fullpath/pipeline_schedules/"$PIPELINE_ID" -X DELETE
done
- .config/log info 'Cleared pipeline schedules on GitLab'
preconditions:
- sh: '[ ! -z "$GITLAB_TOKEN" ]'
msg: The `GITLAB_TOKEN` environment variable must be set to run this task
@@ -332,22 +360,20 @@ tasks:
sh: if [[ $(jq -r '.private' package.json) == 'true' ]]; then echo 'private'; else echo 'public'; fi
TEST_COVERAGE_REGEX:
sh: jq -r '.build_coverage_regex' .variables.json | sed 's/^null$//'
+ log:
+ error: Error ensuring GitLab metadata is up-to-date
+ start: Ensuring GitLab metadata is up-to-date
+ success: GitLab metadata is up-to-date
cmds:
- |
KEYWORDS="$(jq -r '.keywords | tostring' package.json | sed 's/\[//' | sed 's/\]//' | sed 's/"//g')"
- if [ ! -z "$GITLAB_TOKEN" ]; then
- PROJECT_ID="$(glab api projects/:fullpath -X PUT -f build_coverage_regex="{{.TEST_COVERAGE_REGEX}}" \
- -f wiki_enabled={{.GITLAB_WIKI}} -f visibility="{{.PROJECT_TYPE}}" -f topics="$KEYWORDS" | jq '.id')"
- curl -s -H 'Content-Type: application/json' -H "Authorization: Bearer $GITLAB_TOKEN" -X PUT --data \
- '{"description": "{{.EMOJI_START}}{{.DESCRIPTION}}{{.EMOJI_END}}", "issues_template": "{{.ISSUES_TEMPLATE}}", "name": "{{.NAME}}"}' \
- "https://gitlab.com/api/v4/projects/$PROJECT_ID" > /dev/null
- .config/log success 'Ensured GitLab metadata is up-to-date'
- else
- .config/log warn 'The `GITLAB_TOKEN` environment variable is not set so the GitLab repository cannot be updated via the API.'
- fi
- sources:
- - .variables.json
- - package.json
+ PROJECT_ID="$(glab api projects/:fullpath -X PUT -f build_coverage_regex="{{.TEST_COVERAGE_REGEX}}" \
+ -f wiki_enabled={{.GITLAB_WIKI}} -f visibility="{{.PROJECT_TYPE}}" -f topics="$KEYWORDS" | jq '.id')"
+ curl -s -H 'Content-Type: application/json' -H "Authorization: Bearer $GITLAB_TOKEN" -X PUT --data \
+ '{"description": "{{.EMOJI_START}}{{.DESCRIPTION}}{{.EMOJI_END}}", "issues_template": "{{.ISSUES_TEMPLATE}}", "name": "{{.NAME}}"}' \
+ "https://gitlab.com/api/v4/projects/$PROJECT_ID" > /dev/null
+ status:
+ - '[ -z "$GITLAB_TOKEN" ]'
preconditions:
- sh: '[ "{{.DESCRIPTION}}" != "null" ]'
msg: The `.description` in `package.json` must be set.
@@ -363,16 +389,14 @@ tasks:
vars:
DOCS_URL:
sh: jq -r '.docs.link' .variables.json
+ log:
+ error: Failed to update GitLab wiki settings
+ start: Setting GitLab wiki settings
+ success: GitLab wiki settings are up-to-date
cmds:
- - |
- if [ ! -z "$GITLAB_TOKEN" ]; then
- glab api projects/:fullpath/services/external-wiki -X PUT -f external_wiki_url="{{.DOCS_URL}}" --silent
- .config/log success 'Ensured GitLab'\''s wiki settings are up-to-date'
- else
- .config/log warn 'The `GITLAB_TOKEN` environment variable is not set so the GitLab repository external wiki cannot be updated via the API.'
- fi
- sources:
- - .variables.json
+ - glab api projects/:fullpath/services/external-wiki -X PUT -f external_wiki_url="{{.DOCS_URL}}" --silent
+ status:
+ - '[ -z "$GITLAB_TOKEN" ]'
preconditions:
- sh: '[ "{{.DOCS_URL}}" != "null" ]'
msg: The `.docs.link` variable in `.variables.json` must be set.
diff --git a/.config/taskfiles/git/Taskfile-hook.yml b/.config/taskfiles/git/Taskfile-hook.yml
index ab12dfed..6f691f2e 100644
--- a/.config/taskfiles/git/Taskfile-hook.yml
+++ b/.config/taskfiles/git/Taskfile-hook.yml
@@ -8,21 +8,35 @@ tasks:
commit-msg:
deps:
- :lint:commit
+ log:
+ error: '`commit-msg` hook encountered an error!'
+ start: '`commit-msg` hook running..'
post-checkout:
deps:
- :install:npm:git-notify
- :install:npm:yarnhook
+ log:
+ error: '`post-checkout` hook encountered an error!'
+ start: '`post-checkout` hook running..'
cmds:
- git-notify checkout --prefix "@notify" --color "{{.GIT_NOTIFY_COLOR}}" "$GIT_PARAMS"
- yarnhook
- post-commit: 'true'
+ post-commit:
+ log:
+ error: '`post-commit` hook encountered an error!'
+ start: '`post-commit` hook running..'
+ cmds:
+ - 'true'
post-merge:
deps:
- :install:npm:git-notify
- :install:npm:yarnhook
+ log:
+ error: '`post-merge` hook encountered an error!'
+ start: '`post-merge` hook running..'
cmds:
- git-notify merge --prefix "@notify" --color "{{.GIT_NOTIFY_COLOR}}" "$GIT_PARAMS"
- yarnhook
@@ -31,6 +45,9 @@ tasks:
deps:
- :install:npm:git-notify
- :install:npm:yarnhook
+ log:
+ error: '`post-rewrite` hook encountered an error!'
+ start: '`post-rewrite` hook running..'
cmds:
- git-notify rewrite --prefix "@notify" --color "{{.GIT_NOTIFY_COLOR}}" "$GIT_PARAMS"
- yarnhook
@@ -41,5 +58,13 @@ tasks:
- :fix:misc
- :security:gitleaks
- :security:private-keys
+ log:
+ error: '`pre-commit` hook encountered an error!'
- pre-push: 'true'
+ start: '`pre-commit` hook running..'
+ pre-push:
+ log:
+ error: '`pre-push` hook encountered an error!'
+ start: '`pre-push` hook running..'
+ cmds:
+ - 'true'
diff --git a/.config/taskfiles/git/Taskfile.yml b/.config/taskfiles/git/Taskfile.yml
index 0621ad3f..eb9bdf4f 100644
--- a/.config/taskfiles/git/Taskfile.yml
+++ b/.config/taskfiles/git/Taskfile.yml
@@ -40,6 +40,8 @@ env:
tasks:
commit:automated:
+ log:
+ start: Running automated commit
cmds:
- cmd: |
if [[ "$FULLY_AUTOMATED_TASKS" == 'true' ]]; then
@@ -57,6 +59,10 @@ tasks:
sh: basename "$PWD"
GITLAB_REPO:
sh: jq -r '.blueprint.repository.gitlab' package.json
+ log:
+ error: Error converting `{{.BASENAME}}` to a submodule
+ start: Converting `{{.BASENAME}}` directory into a submodule
+ success: Converted the `{{.BASENAME}}` directory to a submodule
cmds:
- git init
- git remote add origin "{{.GITLAB_REPO}}"
@@ -72,7 +78,7 @@ tasks:
git add {{.BASENAME}}
git commit --quiet -m "refactor(convert-dir-to-submodule) Adding new submodule which was previously a directory."
git push --quiet -u --no-progress origin HEAD
- - .config/log success 'Converted the `{{.BASENAME}}` directory to a submodule'
+ - .config/log success ''
preconditions:
- sh: '[[ ! $(git rev-parse --git-dir) =~ ".git/modules" ]]'
msg: Cannot convert the directory to a submodule - the directory already appears to be a submodule.
@@ -85,6 +91,10 @@ tasks:
sh: basename "$PWD"
GITLAB_REPO:
sh: jq -r '.blueprint.repository.gitlab' package.json
+ log:
+ error: Error encountered while converting `{{.BASENAME}}` into a sub-repo
+ start: Converting `{{.BASENAME}}` into a sub-repo
+ success: Converted `{{.BASENAME}}` into a sub-repo
cmds:
- rm -rf .git
- |
@@ -95,6 +105,8 @@ tasks:
HUSKY=0 git subrepo clone {{.BASENAME}} "$RELATIVE_DIR" -b master
push:all:
+ log:
+ start: Running `git push all master`
cmds:
- |
if [[ "$FULLY_AUTOMATED_TASKS" == 'true' ]]; then
@@ -123,6 +135,10 @@ tasks:
GITLAB_REPO:
sh: jq -r '.blueprint.repository.gitlab' package.json | sed 's/^https:\/\//git@/' | sed 's/gitlab.com\//gitlab.com:/'
run: once
+ log:
+ error: Error setting git remotes
+ start: Setting up git remotes
+ success: Git remotes are set up
cmds:
- git init -q
- |
@@ -164,6 +180,16 @@ tasks:
- '[[ "$(git config remote.github.url)" == "${GITHUB_REPO}.git" ]] || [[ "${container:=}" == "docker" ]]'
- '[[ "$(git config remote.gitlab.url)" == "${GITLAB_REPO}.git" ]] || [[ "${container:=}" == "docker" ]]'
+ remove:history:cli:
+ deps:
+ - :install:software:git
+ log:
+ error: Failed to remove `{{.CLI_ARGS}}` from the git history
+ start: Removing `{{.CLI_ARGS}}` from the git history
+ success: Removed `{{.CLI_ARGS}}` from the git history
+ cmds:
+ - git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch {{.CLI_ARGS}}' HEAD
+
remove:submodules:
deps:
- :install:software:git
@@ -194,6 +220,10 @@ tasks:
# /home/hawkwood/Downloads/Backup/Code/docker/ci-pipeline/hadolint
TOP_LEVEL:
sh: git rev-parse --show-toplevel
+ log:
+ error: Error encountered while attempting to remove submodules
+ start: Attempting to remove submodules
+ success: Successfully removed submodules
cmds:
- |
if [ -f '.gitmodules' ]; then
diff --git a/.config/taskfiles/go/Taskfile-goreleaser.yml b/.config/taskfiles/go/Taskfile-goreleaser.yml
new file mode 100644
index 00000000..ed41e0ec
--- /dev/null
+++ b/.config/taskfiles/go/Taskfile-goreleaser.yml
@@ -0,0 +1,37 @@
+---
+version: '3'
+
+vars:
+ GORELEASER_CONFIG:
+ sh: if [ -f .goreleaser.yml ]; then echo ".goreleaser.yml"; else echo ".config/goreleaser.yml"; fi
+
+tasks:
+ build:
+ deps:
+ - :install:go:goreleaser
+ log:
+ error: GoReleaser encountered an error (config file -> `{{.GORELEASER_CONFIG}}`)
+ start: Building with project with GoReleaser
+ success: Completed building the project with GoReleaser
+ cmds:
+ - goreleaser build --config {{.GORELEASER_CONFIG}}
+
+ check:
+ deps:
+ - :install:go:goreleaser
+ log:
+ error: GoReleaser configuration appears to be invalid (config file -> `{{.GORELEASER_CONFIG}})
+ start: Validating the configuration file
+ success: GoReleaser configuration is valid!
+ cmds:
+ - goreleaser check --config {{.GORELEASER_CONFIG}}
+
+ release:
+ deps:
+ - :install:go:goreleaser
+ log:
+ error: Encountered error while releasing with GoReleaser (config file -> `{{.GORELEASER_CONFIG}})
+ start: Publishing compiled assets with GoReleaser
+ success: Successfully published assets with GoReleaser!
+ cmds:
+ - goreleaser release --skip-publish --config {{.GORELEASER_CONFIG}}
diff --git a/.config/taskfiles/go/Taskfile.yml b/.config/taskfiles/go/Taskfile.yml
index bd70bc83..91f57459 100644
--- a/.config/taskfiles/go/Taskfile.yml
+++ b/.config/taskfiles/go/Taskfile.yml
@@ -19,12 +19,12 @@ tasks:
build:bin:
deps:
- :install:software:go
- cmds:
- - '{{.BUILD_COMMAND}}'
log:
error: Failed to build binary
start: Running build command specified in `package.json` (defined under the `build_command` key in the `blueprint` section)
success: Successfully built the binary
+ cmds:
+ - '{{.BUILD_COMMAND}}'
sources:
- '**/*.go'
generates:
@@ -39,6 +39,10 @@ tasks:
sh: jq -r '.blueprint.build_command' package.json
BUILD_OUTPUT:
sh: jq -r '.blueprint.build_command_output' package.json
+ log:
+ error: Failed to query binary help menu output
+ start: Querying binary help menu output
+ success: Successfully injected binary help menu output into `.variables.json`
cmds:
- |
TMP_HELP="$(mktemp)"
@@ -46,9 +50,5 @@ tasks:
TMP_VARS="$(mktemp)"
jq --arg output "$(cat "$TMP_HELP")" '.help_menu_output = $output' .variables.json > "$TMP_VARS"
mv "$TMP_VARS" .variables.json
- log:
- error: Failed to query binary help menu output
- start: Querying binary help menu output
- success: Successfully injected binary help menu output into `.variables.json`
status:
- '[[ "{{.BUILD_COMMAND}}" == "null" ]] || [[ "{{.BUILD_OUTPUT}}" == "null" ]]'
diff --git a/.config/taskfiles/install/Taskfile-go.yml b/.config/taskfiles/install/Taskfile-go.yml
index 0ceb9e8c..2ad1e6f1 100644
--- a/.config/taskfiles/install/Taskfile-go.yml
+++ b/.config/taskfiles/install/Taskfile-go.yml
@@ -2,22 +2,46 @@
version: '3'
tasks:
- goget:
- deps:
- - :install:software:go
+ get:
run: when_changed
+ log:
+ error: Failed to acquire Go package named `{{.PACKAGE}}`
+ start: Getting Go package named `{{.PACKAGE}}`
+ success: Retrieved Go packaged named `{{.PACKAGE}}`
cmds:
- - |
- .config/log info 'Installing the `{{.PACKAGE}}` Go-lang package'
- go get {{.PACKAGE}}
- .config/log success 'Successfully installed the `{{.PACKAGE}}` Go-lang package'
+ - task: :install:software:go
+ - go get {{.PACKAGE}}
status:
- type {{.BIN}} &> /dev/null
+ goreleaser:
+ run: once
+ cmds:
+ - task: install
+ vars:
+ BIN: goreleaser
+ PACKAGE: github.com/goreleaser/goreleaser@latest
+ status:
+ - type goreleaser > /dev/null
+
gotestsum:
run: once
cmds:
- - task: goget
+ - task: get
vars:
BIN: gotestsum
PACKAGE: gotest.tools/gotestsum
+ status:
+ - type gotestsum > /dev/null
+
+ install:
+ run: when_changed
+ log:
+ error: Failed to install `{{.PACKAGE}}` with Go
+ start: Installing Go package named `{{.PACKAGE}}`
+ success: Successfully installed `{{.PACKAGE}}`
+ cmds:
+ - task: :install:software:go
+ - go install {{.PACKAGE}}
+ status:
+ - type {{.BIN}} &> /dev/null
diff --git a/.config/taskfiles/install/Taskfile-npm.yml b/.config/taskfiles/install/Taskfile-npm.yml
index 4d0a0dee..da039e2f 100644
--- a/.config/taskfiles/install/Taskfile-npm.yml
+++ b/.config/taskfiles/install/Taskfile-npm.yml
@@ -102,13 +102,12 @@ tasks:
vars:
PACKAGE_BIN: '{{if index . "NPM_PACKAGE_BIN"}}{{.NPM_PACKAGE_BIN}}{{else}}{{.NPM_PACKAGE}}{{end}}'
run: when_changed
+ log:
+ error: Failed to install NPM package `{{.NPM_PACKAGE}}` globally
+ start: Installing NPM package `{{.NPM_PACKAGE}}` globally
+ success: Installed NPM package `{{.NPM_PACKAGE}}` globally
cmds:
- - |
- if ! type {{.PACKAGE_BIN}} > /dev/null; then
- .config/log info 'Installing _NPM CLI_ package `{{.NPM_PACKAGE}}` globally'
- {{.NPM_PROGRAM}} install -g {{.NPM_PACKAGE}}
- .config/log success 'Successfully installed `{{.NPM_PACKAGE}}` globally'
- fi
+ - '{{.NPM_PROGRAM}} install -g {{.NPM_PACKAGE}}'
status:
- type {{.PACKAGE_BIN}} > /dev/null
@@ -125,27 +124,24 @@ tasks:
echo 'false'
fi
run: once
+ log:
+ error: Error installing `{{.NPM_PACKAGE}}` globally
+ start: Installing NPM global library `{{.NPM_PACKAGE}}` which does not have a CLI
+ success: '`{{.NPM_PACKAGE}}` has been installed globally'
cmds:
- - |
- if [[ "$PACKAGE_EXISTS" == 'false' ]]; then
- .config/log info "Installing _NPM library_ package `{{.NPM_PACKAGE}}` globally"
- {{.NPM_PROGRAM}} install -g {{.NPM_PACKAGE}}
- .config/log success 'Successfully installed `{{.NPM_PACKAGE}}` globally'
- fi
+ - '{{.NPM_PROGRAM}} install -g {{.NPM_PACKAGE}}'
status:
- '[[ "$PACKAGE_EXISTS" == "true" ]]'
global:package-manager:
- deps:
- - :install:software:node
run: once
+ log:
+ error: Failed to install `{{.NPM_PROGRAM}}`
+ start: Installing `{{.NPM_PROGRAM}}`
+ success: Successfully installed `{{.NPM_PROGRAM}}`
cmds:
- - |
- if ! type {{.NPM_PROGRAM}} > /dev/null; then
- .config/log info 'Installing `{{.NPM_PROGRAM}}'
- npm install -g {{.NPM_PROGRAM}}
- .config/log success 'Successfully installed `{{.NPM_PROGRAM}}`'
- fi
+ - task: :install:software:node
+ - npm install -g {{.NPM_PROGRAM}}
status:
- type {{.NPM_PROGRAM}} > /dev/null
@@ -280,10 +276,21 @@ tasks:
- task: global
vars:
NPM_PACKAGE: pnpm
- - if [ -f package-lock.json ] || [ -f yarn.lock ] || [ -f npm-shrinkwrap.json ]; then pnpm import; fi
+ - task: pnpm:import
status:
- type pnpm &> /dev/null
+ pnpm:import:
+ run: once
+ log:
+ error: Error running `pnpm import`
+ start: Running `pnpm import`
+ success: '`pnpm import` finished successfully!'
+ cmds:
+ - pnpm import
+ status:
+ - '[ ! -f package-lock.json ] && [ ! -f yarn.lock ] && [ ! -f npm-shrinkwrap.json ]'
+
prettier:
run: once
cmds:
@@ -307,6 +314,13 @@ tasks:
NPM_PACKAGE: remark-cli
NPM_PACKAGE_BIN: remark
+ semantic-release:
+ run: once
+ cmds:
+ - task: global
+ vars:
+ NPM_PACKAGE: semantic-release
+
sharp:
run: once
cmds:
diff --git a/.config/taskfiles/install/Taskfile-python.yml b/.config/taskfiles/install/Taskfile-python.yml
index b1b0cf11..ef3776f9 100644
--- a/.config/taskfiles/install/Taskfile-python.yml
+++ b/.config/taskfiles/install/Taskfile-python.yml
@@ -3,21 +3,23 @@ version: '3'
tasks:
pip:
- deps:
- - :install:software:python
run: when_changed
+ log:
+ error: Failed to install pip3 package `{{.PACKAGE}}`
+ start: Installing pip3 package `{{.PACKAGE}}`
+ success: Installed pip3 package `{{.PACKAGE}}`
cmds:
- - |
- .config/log info 'Installing `{{.PACKAGE}}` with pip3'
- pip3 install {{.PACKAGE}}
- .config/log success 'Successfully installed pip3 package named `{{.PACKAGE}}`'
+ - task: :install:software:python
+ - pip3 install {{.PACKAGE}}
status:
- type {{.PACKAGE}} > /dev/null
pipx:
- deps:
- - :install:software:python
run: when_changed
+ log:
+ error: Failed to install `{{.PACKAGE}}` with pipx
+ start: Installing `{{.PACKAGE}}` with pipx
+ success: Successfully installed `{{.PACKAGE}}` with pipx
cmds:
- task: :install:software:pipx
- |
@@ -42,10 +44,9 @@ tasks:
PACKAGE: pytest-cov
requirements:
- deps:
- - :install:software:python
run: once
cmds:
+ - task: :install:software:python
- task: requirements:poetry:prereqs
- task: requirements:poetry
- task: :{{if eq .REPOSITORY_TYPE "ansible"}}ansible:galaxy:requirements{{else}}donothing{{end}}
@@ -53,19 +54,17 @@ tasks:
- '[[ "$OPTIMIZED_IMAGE" == "true" ]]'
requirements:poetry:
- deps:
- - :install:software:poetry
run: once
+ log:
+ error: Failed to configure / install via `poetry`
+ start: Configuring Poetry and running `poetry install`
+ success: Successfully ran `poetry install`
cmds:
- - |
- .config/log info 'Running `poetry install`'
- if [ '{{.PYTHON_VIRTUALENV}}' != 'true' ]; then
- poetry config virtualenvs.create false
- else
- poetry config --local virtualenvs.in-project true
- fi
- poetry install
- .config/log success '`poetry install` completed successfully'
+ - task: :install:software:poetry
+ - poetry config virtualenvs.create {{.PYTHON_VIRTUALENV}}
+ - poetry config virtualenvs.in-project true
+ - poetry update {{.PYTHON_KEEP_UPDATED}}
+ - poetry install
sources:
- pyproject.toml
preconditions:
@@ -74,20 +73,43 @@ tasks:
requirements:poetry:prereqs:
vars:
- GCC5_MISSING_MESSAGE: 'It looks like your system is missing gcc-5 but gcc is available. You will be prompted
- for a password to run:'
+ GCC5_MISSING_MESSAGE: 'It looks like your system is missing gcc-5 but gcc is available. You might be prompted
+ for your sudo password to run the following command:'
+ log:
+ error: Error checking `gcc`
+ start: Checking if `gcc` should be symlinked to `gcc-5`
+ success: Checked `gcc`
cmds:
- |
- if ! which gcc-5 > /dev/null; then
- if which gcc; then
- if [ -w /usr/local/bin ]; then
- ln -s "$(which gcc)" /usr/local/bin/gcc-5
- else
- .config/log info '{{.GCC5_MISSING_MESSAGE}}'
- .config/log info '`sudo ln -s '"$(which gcc)"' /usr/local/bin/gcc-5`'
- sudo ln -s "$(which gcc)" /usr/local/bin/gcc-5
- fi
+ if which gcc; then
+ if [ -w /usr/local/bin ]; then
+ ln -s "$(which gcc)" /usr/local/bin/gcc-5
else
- .config/log warn '`gcc` is missing.'
+ .config/log info '{{.GCC5_MISSING_MESSAGE}}'
+ .config/log info '`sudo ln -s '"$(which gcc)"' /usr/local/bin/gcc-5`'
+ sudo ln -s "$(which gcc)" /usr/local/bin/gcc-5
fi
+ else
+ .config/log warn '`gcc` is missing.'
fi
+ status:
+ - which gcc-5
+
+ venv:node:
+ log:
+ error: Encountered error while setting up `.venv` environment.. Is Python 3 installed?
+ start: Setting up a Python 3 `.venv`
+ success: Finished setting up `.venv`. Run `. .venv/bin/activate` to load the environment into your shell.
+ cmds:
+ - task: :install:software:python
+ - |
+ REQUIREMENTS_PATH="$PWD/.config/requirements.txt"
+ cd "$INIT_CWD" || exit
+ if [ ! -f venv/bin/activate ]; then
+ python3 -m venv venv || exit 0
+ fi
+ . .venv/bin/activate || exit 0
+ pip3 install -U pip setuptools || exit 0
+ pip3 install -r "$REQUIREMENTS_PATH" || exit 0
+ sources:
+ - requirements.txt
diff --git a/.config/taskfiles/install/Taskfile-software.yml b/.config/taskfiles/install/Taskfile-software.yml
index 243c72a5..ceae4934 100644
--- a/.config/taskfiles/install/Taskfile-software.yml
+++ b/.config/taskfiles/install/Taskfile-software.yml
@@ -9,6 +9,8 @@ tasks:
- task: brew:formulae
vars:
FORMULAE: act
+ status:
+ - type act > /dev/null
allure:
run: once
@@ -16,28 +18,30 @@ tasks:
- task: brew:formulae
vars:
FORMULAE: allure
+ status:
+ - type allure > /dev/null
brew:
- deps:
- - common
run: once
- cmds:
- - task: brew:{{OS}}
-
log:
error: Failed to install or load Homebrew
start: Ensuring Homebrew is installed and available
success: Successfully ensured Homebrew is installed
+ cmds:
+ - task: common
+ - task: brew:{{OS}}
+ status:
+ - type brew > /dev/null
+
brew:cask:
- deps:
- - brew
run: when_changed
- cmds:
- - brew install --cask {{.CASK}}
log:
error: Failed to install `{{.CASK}}`
start: Ensuring the `{{.CASK}}` Homebrew cask is installed
success: Successfully installed `{{.CASK}}`
+ cmds:
+ - task: brew
+ - brew install --cask {{.CASK}}
status:
- type {{.CASK}} &> /dev/null
@@ -59,15 +63,14 @@ tasks:
- type brew &> /dev/null
brew:formulae:
- deps:
- - brew
run: when_changed
- cmds:
- - brew install {{.FORMULAE}}
log:
error: Failed to install `{{.FORMULAE}}`
start: Ensuring the `{{.FORMULAE}}` Homebrew formulae is installed
success: Successfully installed `{{.FORMULAE}}`
+ cmds:
+ - task: brew
+ - brew install {{.FORMULAE}}
status:
- type {{.FORMULAE}} &> /dev/null
@@ -97,6 +100,10 @@ tasks:
brew:utils:
run: once
+ log:
+ error: Failed to setup GNU-compatibility tools
+ start: Installing GNU-compatibility tools for macOS via Homebrew
+ success: Successfully installed GNU-compatibility tools
cmds:
- task: compatibility:coreutils
- task: compatibility:findutils
@@ -104,10 +111,6 @@ tasks:
- task: compatibility:grep
- task: compatibility:gnu-tar
- task: compatibility:gawk
- log:
- error: Failed to setup GNU-compatibility tools
- start: Installing GNU-compatibility tools for macOS via Homebrew
- success: Successfully installed GNU-compatibility tools
status:
- '[ "{{OS}}" != "darwin" ]'
@@ -125,13 +128,13 @@ tasks:
common:
run: once
- cmds:
- - task: common:{{OS}}
-
log:
error: There was an error ensuring common system tools are present
start: Ensuring common system tools are present
success: Ensured common system tools are present
+ cmds:
+ - task: common:{{OS}}
+
common:darwin:
cmds:
- task: common:darwin:xcode
@@ -140,12 +143,12 @@ tasks:
vars:
CLT_STATUS:
sh: brew config | grep CLT
- cmds:
- - sudo xcode-select --install
log:
error: Failed to run `sudo xcode-select --install`
start: Running `sudo xcode-select --install` to install macOS developer tools
success: Successfully ran `sudo xcode-select --install`
+ cmds:
+ - sudo xcode-select --install
status:
- '[ "{{.CLT_STATUS}}" != "CLT: N/A" ]'
@@ -162,6 +165,10 @@ tasks:
else
echo "unknown"
fi
+ log:
+ error: Failed to ensure basic system dependencies are installed
+ start: Ensuring basic system dependencies are installed
+ success: Basic system dependencies are installed!
cmds:
- task: common:linux:{{.LINUX_FAMILY}}
status:
@@ -172,7 +179,9 @@ tasks:
cmds:
- .config/log warn "Archlinux support for Homebrew is not very well documented.. if this does not work and you can get it working, please open a PR :)"
- |
+ .config/log info 'Attempting to run `sudo pacman update` (for Homebrew dependencies)'
sudo pacman update
+ .config/log info 'Attempting to run `sudo pacman -S base-devel curl file git procps-ng` (for Homebrew dependencies)'
sudo pacman -S base-devel curl file git procps-ng
status:
- type curl &> /dev/null
@@ -185,8 +194,9 @@ tasks:
interactive: true
cmds:
- |
- .config/log info 'Attempting to install Homebrew dependencies (sudo password required)'
+ .config/log info 'Attempting to run `sudo apt-get -y update` (for Homebrew dependencies)'
sudo apt-get -y update
+ .config/log info 'Attempting to run `sudo apt-get install -y build-essential curl file git procps` (Homebrew dependencies)'
sudo apt-get install -y build-essential curl file git procps
status:
- type curl &> /dev/null
@@ -204,35 +214,38 @@ tasks:
yum grouplist 'Development Tools' &> "$HOME/.config/bodega/yum-devtools-check-ran"
DEV_TOOLS_NOT_INSTALLED="$(grep 'No groups match' < "$HOME/.config/bodega/yum-devtools-check-ran" > /dev/null)"
if [[ "$DEV_TOOLS_NOT_INSTALLED" == '0' ]]; then
+ .config/log info 'Attempting to run `sudo yum groupinstall -y "Development Tools"`'
sudo yum groupinstall -y 'Development Tools'
fi
touch "$HOME/.config/bodega/yum-devtools-check-ran"
fi
if ! rpm --quiet --query curl file git procps-ng; then
- .config/log info 'Attempting to install Homebrew dependencies (sudo password required)'
+ .config/log info 'Attempting to run `sudo yum install -y curl file git procps-ng`'
sudo yum install -y curl file git procps-ng
fi
if [ -f '/etc/os-release' ]; then
source /etc/os-release
if [[ "$ID" == 'fedora' ]] && [ "$VERSION_ID" -gt "29" ]; then
if ! rpm --quiet --query libxcrypt-compat; then
- .config/log info 'Attempting to install Fedora-specific Homebrew dependency (sudo password required)'
+ .config/log info 'Attempting to run `sudo yum -y install libxcrypt-compat` (Homebrew dependencies)'
sudo yum -y install libxcrypt-compat
fi
fi
fi
common:linux:unknown:
+ log:
+ start: You are using an operating system that we do not directly support. Please make sure
+ the equivalent of `build-essential`, `curl`, `file`, `git`, and `procps` are installed.
cmds:
- - .config/log warn 'You are using an operating system that we do not directly support. Please make sure
- the equivalent of `build-essential`, `curl`, `file`, `git`, and `procps` are installed.'
+ - echo "*** Unknown OS is $OSTYPE ***"
common:windows:
+ log:
+ error: Windows is not supported. Try using a Windows WSL environment.
cmds:
- exit 1
- log:
- error: Windows is not supported. Try using a Windows WSL environment.
compatibility:findutils:
cmds:
- task: brew:formulae
@@ -246,6 +259,8 @@ tasks:
- task: brew:formulae
vars:
FORMULAE: gawk
+ status:
+ - type gawk > /dev/null
compatibility:gnu-sed:
cmds:
@@ -290,6 +305,8 @@ tasks:
run: once
cmds:
- task: docker:{{OS}}
+ status:
+ - type docker > /dev/null
docker:darwin:
run: once
@@ -330,6 +347,8 @@ tasks:
- task: brew:formulae
vars:
FORMULAE: exiftool
+ status:
+ - type exiftool > /dev/null
exit:notice:reload:
cmds:
@@ -355,6 +374,8 @@ tasks:
- task: brew:cask
vars:
CASK: google-cloud-sdk
+ status:
+ - type gcloud > /dev/null
gcloud:linux:
cmds:
@@ -372,11 +393,15 @@ tasks:
- task: brew:formulae
vars:
FORMULAE: gh
+ status:
+ - type gh > /dev/null
git:
- deps:
- - common
run: once
+ cmds:
+ - task: common
+ status:
+ - type git > /dev/null
gitleaks:
run: once
@@ -384,6 +409,8 @@ tasks:
- task: brew:formulae
vars:
FORMULAE: gitleaks
+ status:
+ - type gitleaks > /dev/null
glab:
run: once
@@ -391,6 +418,8 @@ tasks:
- task: brew:formulae
vars:
FORMULAE: glab
+ status:
+ - type glab > /dev/null
go:
run: once
@@ -398,6 +427,8 @@ tasks:
- task: brew:formulae
vars:
FORMULAE: go
+ status:
+ - type go > /dev/null
grype:
run: once
@@ -414,6 +445,8 @@ tasks:
- task: brew:formulae
vars:
FORMULAE: jq
+ status:
+ - type jq > /dev/null
node:
run: once
@@ -421,38 +454,38 @@ tasks:
- task: brew:formulae
vars:
FORMULAE: node
+ status:
+ - type node > /dev/null
pipx:
run: once
- cmds:
- - task: pipx:{{OS}}
log:
error: Failed to ensure `pipx` is installed
start: Ensuring `pipx` is installed
success: Successfully ensured `pipx` is installed
+ cmds:
+ - task: python
+ - task: pipx:{{OS}}
status:
- type pipx > /dev/null
pipx:darwin:
- deps:
- - brew
cmds:
+ - task: brew
- brew install pipx
- pipx ensurepath
pipx:linux:
- deps:
- - :install:software:python
cmds:
- python3 -m pip install --user pipx
- python3 -m pipx ensurepath
pipx:windows:
+ log:
+ error: These scripts are not currently compatible with Windows. Try using WSL.
cmds:
- exit 1
- log:
- error: These scripts are not currently compatible with Windows. Try using WSL.
poetry:
run: once
cmds:
@@ -476,17 +509,18 @@ tasks:
FORMULAE: poetry
poetry:windows:
+ log:
+ error: These scripts are not currently compatible with Windows. Try using WSL.
cmds:
- exit 1
- log:
- error: These scripts are not currently compatible with Windows. Try using WSL.
python:
- deps:
- - brew # bug fix
run: once
cmds:
+ - task: brew
- task: python:{{OS}}
+ status:
+ - type python3 > /dev/null
python:darwin:
run: once
@@ -505,17 +539,19 @@ tasks:
SOFTWARE: python
python:windows:
+ log:
+ error: These scripts are not currently compatible with Windows. Try using WSL.
cmds:
- exit 1
- log:
- error: These scripts are not currently compatible with Windows. Try using WSL.
rsync:
run: once
cmds:
- task: brew:formulae
vars:
FORMULAE: rsync
+ status:
+ - type rsync &> /dev/null
sshpass:
run: once
@@ -541,6 +577,8 @@ tasks:
- task: brew:formulae
vars:
FORMULAE: tokei
+ status:
+ - type tokei > /dev/null
trivy:
run: once
@@ -554,6 +592,8 @@ tasks:
vagrant:
cmds:
- task: vagrant:{{OS}}
+ status:
+ - type vagrant > /dev/null
vagrant:darwin:
run: once
@@ -617,3 +657,5 @@ tasks:
- task: brew:formulae
vars:
FORMULAE: yq
+ status:
+ - type yq > /dev/null
diff --git a/.config/taskfiles/install/Taskfile.yml b/.config/taskfiles/install/Taskfile.yml
index e9664a02..c50cca07 100644
--- a/.config/taskfiles/install/Taskfile.yml
+++ b/.config/taskfiles/install/Taskfile.yml
@@ -5,24 +5,26 @@ tasks:
brewfile:
deps:
- :install:software:brew
+ log:
+ error: Encountered error while installing Homebrew software bundle defined in `.config/Brewfile`
+ start: Installing Homebrew software bundle defined in `.config/Brewfile`
+ success: Successfully installed Homebrew software bundle defined in `.config/Brewfile`
cmds:
- |
- .config/log info 'Installing software bundle defined in `.config/Brewfile`'
brew tap Homebrew/bundle
cd .config
brew bundle
- .config/log success 'Successfully installed common dependencies defined in `.config/Brewfile`'
.config/log warn 'A reboot is recommended'
- .config/log info 'Some of the software you may have installed might require a reboot'
install-doctor:
+ log:
+ error: Error encountered while installing {{.SOFTWARE}} via https://install.doctor
+ start: Ensuring {{.SOFTWARE}} is installed using Install Doctor
+ success: Successfully installed `{{.SOFTWARE}}` via Install Doctor
cmds:
- |
- if ! type {{.SOFTWARE}} &> /dev/null; then
- .config/log info 'Installing `{{.SOFTWARE}}` via `curl -sS https://install.doctor/{{.SOFTWARE}} | bash`'
- curl -sS https://install.doctor/{{.SOFTWARE}} | bash
- .config/log success 'Successfully installed `{{.SOFTWARE}}`'
- fi
+ .config/log info 'Installing `{{.SOFTWARE}}` by running `curl -sS https://install.doctor/{{.SOFTWARE}} | bash`'
+ curl -sS https://install.doctor/{{.SOFTWARE}} | bash
status:
- type {{.SOFTWARE}} &> /dev/null || [[ "${container:=}" == "docker" ]]
@@ -31,6 +33,10 @@ tasks:
- :install:npm:{{.NPM_PROGRAM}}
- :install:software:yq
run: once
+ log:
+ error: Error pre-loading NPM global packages
+ start: Pre-loading NPM global packages
+ success: Finished pre-loading NPM global packages
cmds:
- |
PKGS="$(yq eval '.tasks[].cmds[0].vars.NPM_PACKAGE' .config/taskfiles/install/Taskfile-npm.yml | tr '\n' ' ')"
@@ -43,7 +49,6 @@ tasks:
.config/log info "Installing the following NPM packages globally - $LIST"
npm install -g $LIST
fi
- .config/log success 'Finished preloading global NPM packages'
status:
- '[[ "${container:=}" == "docker" ]]'
@@ -52,16 +57,22 @@ tasks:
- :install:npm:{{.NPM_PROGRAM_LOCAL}}
- :install:npm:cz-emoji
run: once
+ log:
+ error: Encountered error while installing local NPM dependencies
+ start: Installing local NPM dependencies
+ success: Successfully installed local NPM dependencies
cmds:
- - .config/log info 'Installing local NPM dependencies'
- cmd: '{{.NPM_PROGRAM_LOCAL}} i --shamefully-hoist --no-frozen-lockfile'
ignore_error: true
- task: modules:local:sync
- - .config/log success 'Successfully installed local NPM dependencies'
sources:
- package.json
modules:local:sync:
+ log:
+ error: Error while synchronizing `NPM_KEEP_UPDATED` packages with the latest version(s)
+ start: Ensuring `NPM_KEEP_UPDATED` NPM packages are the latest version
+ success: '`NPM_KEEP_UPDATED` packages are all the latest version'
cmds:
- |
TMP_REFRESH="$(mktemp)"
@@ -69,7 +80,7 @@ tasks:
function updateAvailable() {
LATEST="$(npm view $1 version)"
LOCAL="$(jq -r '.version' ./node_modules/$1/package.json)"
- if ! printf '%s\n%s\n' "$LATEST" "$LOCAL" | sort -V -c; then
+ if ! printf '%s\n%s\n' "$LATEST" "$LOCAL" | sort -V -c > /dev/null; then
.config/log info "Version $LATEST is available for $1 (currently version $LOCAL)"
echo "true" > "$TMP_REFRESH"
fi
@@ -113,6 +124,9 @@ tasks:
vars:
UNAME:
sh: uname
+ log:
+ error: Failed to modify PATH
+ start: Adding `$HOME/{{.PATH_STRING}}` to the PATH in $HOME/.profile
cmds:
- |
if [[ '{{.UNAME}}' == 'Darwin' ]] || [[ '{{.UNAME}}' == 'Linux' ]]; then
@@ -127,7 +141,7 @@ tasks:
elif [[ "$OSTYPE" == 'freebsd'* ]]; then
.config/log error "FreeBSD support not added yet" && exit 1
else
- .config/log error "System type not recognized"
+ .config/log error "System type not recognized ($OSTYPE)"
fi
pipx:global:
@@ -138,6 +152,10 @@ tasks:
PIPX_PACKAGES: ansible-base ansible-lint ansibler black blocklint docker flake8
mod-ansible-autodoc molecule molecule-docker molecule-vagrant pre-commit-hooks
proselint python-vagrant pywinrm
+ log:
+ error: Error encountered while pre-loading common pipx packages
+ start: Pre-loading common pipx packages
+ success: Finished pre-loading common pipx packages
cmds:
- |
for PKG in {{.PIPX_PACKAGES}}; do
@@ -149,9 +167,12 @@ tasks:
fi
done
wait
- .config/log success 'Successfully preloaded commonly used Python packages'
profile:add:
+ log:
+ error: Error modifying $HOME/.profile
+ start: Adding `{{.PROFILE_STRING}}` to $HOME/.profile
+ success: Successfully modified $HOME/.profile
cmds:
- |
if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux-gnu'* ]]; then
@@ -175,21 +196,21 @@ tasks:
in tsconfig.json to `true`. After importHelpers is set to true, the taskfiles will automatically
install tslib.
run: once
+ log:
+ error: Failed to probe `tslib`
+ start: Checking if `tslib` is being used
cmds:
- |
- if [ -f 'tsconfig.json' ]; then
- if [[ "$(jq -r '.dependencies.tslib' package.json)" == 'null' ]]; then
- if [ "$(jq -r '.compilerOptions.importHelpers')" != 'true' ]; then
- .config/log info '{{.TSLIB_MSG}}'
- else
- .config/log info 'Automatically installing `tslib` since `importHelpers` is set to true in tsconfig.json'
- {{.NPM_PROGRAM}} install --save tslib@latest
- .config/log success 'Successfully installed `tslib`'
- fi
+ if [[ "$(jq -r '.dependencies.tslib' package.json)" == 'null' ]]; then
+ if [ "$(jq -r '.compilerOptions.importHelpers')" != 'true' ]; then
+ .config/log info '{{.TSLIB_MSG}}'
else
- task install:modules:local:sync -- "tslib"
+ .config/log info 'Automatically installing `tslib` since `importHelpers` is set to true in tsconfig.json'
+ {{.NPM_PROGRAM}} install --save tslib@latest
+ .config/log success 'Successfully installed `tslib`'
fi
+ else
+ task install:modules:local:sync -- "tslib"
fi
- sources:
- - package.json
- - tsconfig.json
+ status:
+ - '[ ! -f tsconfig.json ]'
diff --git a/.config/taskfiles/lint/Taskfile-esprint.yml b/.config/taskfiles/lint/Taskfile-esprint.yml
index 7f62951e..6bb5b3ea 100644
--- a/.config/taskfiles/lint/Taskfile-esprint.yml
+++ b/.config/taskfiles/lint/Taskfile-esprint.yml
@@ -6,10 +6,11 @@ tasks:
deps:
- :install:modules:local
- :install:npm:esprint
- desc: Lint with `eslint` across multiple threads
summary: |
# Lint with `eslint` across multiple threads
+ DEVELOPER NOTE: This feature might not work. I was unable to get this working.
+
This task will lint the project using `esprint`. Using `esprint` allows you to run `eslint`
across multiple threads which improves performance in most cases (especially for larger
projects). It is capable of linting JSON, YML, JS, TS, and HTML as long as the correct
diff --git a/.config/taskfiles/lint/Taskfile-markdown.yml b/.config/taskfiles/lint/Taskfile-markdown.yml
index 798e907c..9455f784 100644
--- a/.config/taskfiles/lint/Taskfile-markdown.yml
+++ b/.config/taskfiles/lint/Taskfile-markdown.yml
@@ -21,6 +21,10 @@ tasks:
For more information on `remark`, see the [GitHub page](https://github.com/remarkjs/remark).
For more information on `remark-lint`, see the [GitHub page](https://github.com/remarkjs/remark-lint).
+ log:
+ error: Error running `remark`
+ start: Filtering markdown files with `remark`
+ success: Successfully filtered markdown files with `remark`
cmds:
- |
{{if .CLI_ARGS}}
@@ -49,6 +53,10 @@ tasks:
`task lint:markdown-broken-links -- filename.md`
For more information on `markdown-link-check`, see their [GitHub page](https://github.com/tcort/markdown-link-check).
+ log:
+ error: Errors reported by `markdown-link-check`
+ start: Checking for broken links in markdown files with `markdown-link-check`
+ success: Successfully passed `markdown-link-check`
cmds:
- |
{{if .CLI_ARGS}}
diff --git a/.config/taskfiles/lint/Taskfile-prose.yml b/.config/taskfiles/lint/Taskfile-prose.yml
index 9ac04447..cbd5877a 100644
--- a/.config/taskfiles/lint/Taskfile-prose.yml
+++ b/.config/taskfiles/lint/Taskfile-prose.yml
@@ -19,6 +19,10 @@ tasks:
`task lint:prose -- myfile.js`
For more information, see [Proselint's GitHub page](https://github.com/amperser/proselint).
+ log:
+ error: Error encountered while validating {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}the project{{end}} with Proselint
+ start: Linting {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}the project{{end}} prose with Proselint
+ success: Successfully validated {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}the project{{end}} with Proselint
cmds:
- task: prose:config
- |
@@ -30,6 +34,10 @@ tasks:
- task: prose:config:restore
prose:config:
+ log:
+ error: Error encountered while ensuring Proselint configuration is in proper location
+ start: Moving Proselint configuration to proper location
+ success: Ensured Proselint configuration is in proper location
cmds:
- |
if [ -f ~/.config/proselint/config.json ]; then
@@ -40,9 +48,10 @@ tasks:
- cp .config/proselint.json ~/.config/proselint/config.json
prose:config:restore:
+ log:
+ error: Error restoring original Proselint configuration
+ start: Restoring original Proselint configuration
cmds:
- - |
- if [ -f ~/.config/proselint/config.json.backup ]; then
- .config/log info "Restoring original Proselint configuration"
- mv ~/.config/proselint/config.json.backup ~/.config/proselint/config
- fi
+ - mv ~/.config/proselint/config.json.backup ~/.config/proselint/config
+ status:
+ - '[ ! -f ~/.config/proselint/config.json.backup ]'
diff --git a/.config/taskfiles/lint/Taskfile.yml b/.config/taskfiles/lint/Taskfile.yml
index 7fdc9cf2..e2fb94db 100644
--- a/.config/taskfiles/lint/Taskfile.yml
+++ b/.config/taskfiles/lint/Taskfile.yml
@@ -36,6 +36,10 @@ tasks:
[syntax described in this link](https://ansible-lint.readthedocs.io/en/latest/rules.html#false-positives-skipping-rules).
For more information, see [Ansible Lint's GitHub page](https://github.com/ansible-community/ansible-lint).
+ log:
+ error: Ansible Lint has detected possible errors!
+ start: Linting project with Ansible Lint
+ success: Validated project with Ansible Lint
cmds:
- |
.config/log info 'Linting the project with ansible-lint'
@@ -45,6 +49,9 @@ tasks:
deps:
- :install:python:requirements
desc: Generic linting of files for things like destroyed-symlinks, merge conflicts, etc.
+ log:
+ error: Errors were reported by the global linters for `{{.CLI_ARGS}}`
+ start: Linting `{{.CLI_ARGS}}` with global linters
cmds:
- '{{.PYTHON_HANDLE}}blocklint --wordlist blacklist,slave,whitelist {{.CLI_ARGS}}'
- '{{.PYTHON_HANDLE}}check-merge-conflict {{.CLI_ARGS}}'
@@ -55,6 +62,10 @@ tasks:
codeclimate:
deps:
- :install:software:codeclimate
+ log:
+ error: '`codeclimate` has detected errors'
+ start: Running `codeclimate`
+ success: Successfully validated the project by running `codeclimate`
cmds:
- codeclimate
@@ -70,6 +81,8 @@ tasks:
**Example:**
`task lint:commit -- 'My commit message'`
+ log:
+ error: Encountered error while linting commit message ({{.CLI_ARGS}})
cmds:
- |
if [ ! -z '{{.CLI_ARGS}}' ] && [ '{{.CLI_ARGS}}' != '.git/MERGE_MSG' ] && [ "$(head -c12 < .git/MERGE_MSG)" != 'Merge branch' ]; then
@@ -118,6 +131,10 @@ tasks:
`task lint:docker -- CustomDockerfile`
For more information, see [Hadolint's GitHub page](https://github.com/hadolint/hadolint).
+ log:
+ error: Hadolint reported errors
+ start: Linting {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}the project{{end}} with Hadolint
+ success: Hadolint reported no errors
cmds:
- |
.config/log info 'Linting {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}all Dockerfiles{{end}} with a Hadolint Docker image'
@@ -153,21 +170,56 @@ tasks:
**Example linting specific pattern of files:**
`task lint:eslint -- '**/*.js'`
+ log:
+ error: ESLint has detected errors that need to be addressed
+ start: Linting {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}the project{{end}} with ESLint
+ success: Successfully passed the ESLint test (please still address warnings)
cmds:
- >
- .config/log info 'Linting {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}the project{{end}} with ESLint'
-
- {{.NPX_HANDLE}}eslint -c package.json --no-eslintrc --format pretty --cache
+ {{.NPX_HANDLE}}eslint -c package.json --no-eslintrc --format {{.ESLINT_FORMATTER}} --cache
--cache-location .cache/eslintcache {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}}
- js:
+ eslint:warn-all:
deps:
- :install:modules:local
- :install:npm:eslint
+ desc: Convert ESLint errors into warnings in `package.json`
+ summary: |
+ # Convert ESLint Errors into Warnings
+
+ This task will run ESLint against the project and then automatically inline
+ all reported errors as warnings in `package.json`.
+ log:
+ error: Encountered error while converting `eslint` errors to warnings
+ start: Overriding all errors reported from `eslint` as `warnings` in `package.json`
+ success: Successfully overrode `eslint` errors as warnings
cmds:
- >
- .config/log info 'Linting {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}JavaScript/TypeScript files{{end}} with ESLint'
+ ESLINT_TMP="$(mktemp)"
+
+ {{.NPX_HANDLE}}eslint -c package.json --no-eslintrc --format summary --cache
+ --cache-location .cache/eslintcache {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}} |
+ tee "$ESLINT_TMP"
+
+ while read LINE; do
+ TMP="$(mktemp)";
+ ESLINT_RULE="$(echo "$LINE" | grep 'errors ' | sed 's/.*rule:\ //')";
+ if [ -n "$ESLINT_RULE" ]; then
+ jq --arg rule "$ESLINT_RULE" '.eslintConfig.rules[$rule] - "warn"' package.json > "$TMP";
+ mv "$TMP" package.json;
+ fi;
+ done < "$ESLINT_TMP"
+ js:
+ deps:
+ - :install:modules:local
+ - :install:npm:eslint
+ log:
+ error: Errors were reported by ESLint for {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}JavaScript/TypeScript files{{end}}
+ start: Linting {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}JavaScript/TypeScript files{{end}} with ESLint
+ success: Successfully passed ESLint checks for {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}JavaScript/TypeScript files{{end}}
+ cmds:
+ - >
{{.NPX_HANDLE}}eslint -c package.json --no-eslintrc --format pretty --ext .js,.jsx,.ts,.tsx --cache
--cache-location .cache/eslintcache {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}}
@@ -176,10 +228,12 @@ tasks:
- :install:modules:global
- :install:modules:local
- :install:python:requirements
+ log:
+ error: Errors were encountered when validating the staged files
+ start: Linting staged files
+ success: The staged files appear to be good!
cmds:
- - |
- .config/log info 'Linting changed files'
- {{.NPX_HANDLE}}lint-staged
+ - '{{.NPX_HANDLE}}lint-staged'
packer:
deps:
@@ -199,6 +253,10 @@ tasks:
`task lint:packer -- filename.json`
For more information on `packer validate`, see the [Packer website](https://www.packer.io/docs/commands/validate).
+ log:
+ error: Error while running `packer validate`
+ start: Running {{if .CLI_ARGS}}`packer validate {{.CLI_ARGS}}`{{else}}`packer validate` on all files ending with `template.json`{{end}}
+ success: '`packer validate` reported no issues'
cmds:
- |
{{if .CLI_ARGS}}
@@ -228,10 +286,12 @@ tasks:
file.
For more information, see [Prettier's website](https://prettier.io/).
+ log:
+ error: Errors were encountered by Prettier
+ start: Linting {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}the project{{end}} with Prettier
+ success: Prettier successfully finished
cmds:
- - |
- .config/log info 'Linting {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}the project{{end}} with Prettier'
- {{.NPX_HANDLE}}prettier --ignore-path {{.PRETTIERIGNORE_CONFIG}} --list-different {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}}
+ - '{{.NPX_HANDLE}}prettier --ignore-path {{.PRETTIERIGNORE_CONFIG}} --list-different {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}}'
python:
deps:
@@ -260,6 +320,10 @@ tasks:
`task lint:python -- myfile.py`
For more information, see [Flake8's GitHub page](https://github.com/PyCQA/flake8).
+ log:
+ error: flake8 detected some issues
+ start: Linting {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}the project{{end}} with flake8
+ success: flake8 validation was successful
cmds:
- |
{{if .CLI_ARGS}}
@@ -297,6 +361,10 @@ tasks:
`task lint:scripts -- myfile.sh`
For more information, see [Shellcheck's GitHub page](https://github.com/koalaman/shellcheck).
+ log:
+ error: Shellcheck reported errors for {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}the project{{end}}
+ start: Linting {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}the project{{end}} with Shellcheck
+ success: Linted {{if .CLI_ARGS}}`{{.CLI_ARGS}}`{{else}}the project{{end}} with no errors from Shellcheck
cmds:
- |
.config/log info 'Linting with Shellcheck'
@@ -332,11 +400,12 @@ tasks:
- task: spelling:{{if .CLI_ARGS}}cli{{else}}staged{{end}}
spelling:cli:
+ log:
+ start: Running a spell-check with `cspell`
cmds:
- cmd: |
set -e
EXIT_CODE=0
- .config/log info 'Running a spell-check with `cspell`'
{{.NPX_HANDLE}}cspell --no-progress --show-context --no-must-find-files --config {{.CSPELL_CONFIG}} {{.CLI_ARGS}} || EXIT_CODE=$?
if [ "$EXIT_CODE" != '0' ]; then
.config/log warn 'Possible spelling errors were detected. Take appropriate action before merging changes.'
@@ -347,6 +416,8 @@ tasks:
deps:
- :install:npm:cspell
- :install:software:git
+ log:
+ start: Detecting possible spelling errors in staged files
cmds:
- cmd: |
STAGED_FILES="$(git diff --cached --name-only)"
@@ -377,10 +448,12 @@ tasks:
**Example scanning specific file:**
`task lint:toml -- myfile.toml`
+ log:
+ error: Possible TOML errors were detected
+ start: Ensuring {{if .CLI_ARGS}}`{{.CLI_ARGS}}` is valid TOML{{else}}the project'\''s TOML files are valid{{end}}
+ success: The TOML appears to be valid!
cmds:
- - |
- .config/log info 'Ensuring {{if .CLI_ARGS}}{{.CLI_ARGS}} is valid TOML{{else}}the project'\''s TOML files are valid{{end}}'
- {{.PYTHON_HANDLE}}check-toml {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}}
+ - '{{.PYTHON_HANDLE}}check-toml {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}}'
vagrant:
deps:
@@ -394,10 +467,12 @@ tasks:
is using valid syntax.
For more information on `vagrant validate`, see the [Vagrant website](https://www.vagrantup.com/docs/cli/validate).
+ log:
+ error: '`vagrant validate` detected one or more issues with the Vagrantfile'
+ start: Validating the Vagrantfile
+ success: The Vagrantfile passed `vagrant validate`
cmds:
- - |
- .config/log info 'Validating the Vagrantfile'
- vagrant validate
+ - vagrant validate
xml:
deps:
@@ -414,10 +489,12 @@ tasks:
**Example scanning specific file:**
`task lint:xml -- myfile.xml`
+ log:
+ error: Possible issues were detected with the XML{{if .CLI_ARGS}}(`{{.CLI_ARGS}}`){{end}}
+ start: Ensuring {{if .CLI_ARGS}}{{.CLI_ARGS}} is valid XML{{else}}the project contains only valid XML{{end}}
+ success: The XML appears to be valid
cmds:
- - |
- .config/log info 'Ensuring {{if .CLI_ARGS}}{{.CLI_ARGS}} is valid XML{{else}}the project contains only valid XML{{end}}'
- {{.PYTHON_HANDLE}}check-xml {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}}
+ - '{{.PYTHON_HANDLE}}check-xml {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}}'
yaml:
deps:
@@ -443,7 +520,9 @@ tasks:
`task lint:yaml -- myfile.sh`
For more information, see the [YAML Lint GitHub page](https://github.com/adrienverge/yamllint).
+ log:
+ error: Possible issues were detected by `yamllint`
+ start: Linting {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}the project{{end}} with `yamllint`
+ success: No issues were detected by `yamllint`
cmds:
- - |
- .config/log info 'Linting {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}the project{{end}} with `yamllint`'
- {{.PYTHON_HANDLE}}yamllint -c {{.YAMLLINT_CONFIG}} -s {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}}
+ - '{{.PYTHON_HANDLE}}yamllint -c {{.YAMLLINT_CONFIG}} -s {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.{{end}}'
diff --git a/.config/taskfiles/nest/Taskfile.yml b/.config/taskfiles/nest/Taskfile.yml
index 9189ea59..093c0f2e 100644
--- a/.config/taskfiles/nest/Taskfile.yml
+++ b/.config/taskfiles/nest/Taskfile.yml
@@ -19,7 +19,7 @@ tasks:
**Example with custom endpoint:**
`task npm:benchmark -- /custom/endpoint`
+ log:
+ start: Running clinic with autocannon on dist/main.js
cmds:
- - |
- .config/log info 'Running clinic with autocannon on dist/main.js'
- {{.NPX_HANDLE}}clinic doctor --autocannon [ {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}/{{end}} --method POST ] -- node ./dist/main.js
+ - '{{.NPX_HANDLE}}clinic doctor --autocannon [ {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}/{{end}} --method POST ] -- node ./dist/main.js'
diff --git a/.config/taskfiles/npm/Taskfile-cov.yml b/.config/taskfiles/npm/Taskfile-cov.yml
index f86e3936..ff6e3157 100644
--- a/.config/taskfiles/npm/Taskfile-cov.yml
+++ b/.config/taskfiles/npm/Taskfile-cov.yml
@@ -12,28 +12,34 @@ tasks:
deps:
- :install:modules:local
- :install:npm:nyc
+ log:
+ error: Errors encountered while running `nyc report` and `nyc check-coverage`
+ start: Running `nyc report` and `nyc check-coverage`
+ success: Finished running `nyc`
cmds:
- - |
- .config/log info 'Running `nyc report`'
- {{.NPX_HANDLE}}nyc report
- - |
- .config/log info 'Checking coverage with `nyc`'
- {{.NPX_HANDLE}}nyc check-coverage --lines 100 --functions 100 --branches 100
+ - '{{.NPX_HANDLE}}nyc report'
+ - '{{.NPX_HANDLE}}nyc check-coverage --lines 100 --functions 100 --branches 100'
html:
deps:
- :install:modules:local
- :install:npm:nyc
+ log:
+ error: Error while generating HTML report with `nyc`
+ start: Reporting with `nyc` in HTML format
+ success: Report generated by `nyc` in HTML format
cmds:
- - .config/log info 'Reporting with nyc in html format'
- '{{.NPX_HANDLE}}nyc report --reporter=html'
lcov:
deps:
- :install:modules:local
- :install:npm:nyc
+ log:
+ error: Encountered error generating `lcov` report with `nyc`
+ start: Reporting with `nyc` in `lcov` format
+ success: Finished `lcov` report with `nyc`
cmds:
- - .config/log info 'Reporting with nyc in lcov format'
- '{{.NPX_HANDLE}}nyc report --reporter=lcov'
open:
@@ -41,8 +47,9 @@ tasks:
- html
- :npm:install:open-cli
desc: Ensures the code coverage report is generated and opens it in a browser
+ log:
+ start: Opening `coverage/index.html` with the default browser
cmds:
- - .config/log info 'Opening coverage/index.html in the default browser'
- '{{.NPX_HANDLE}}open-cli coverage/index.html'
report:
@@ -55,6 +62,9 @@ tasks:
- lcov
- :install:npm:codecov
desc: Uploads code coverage report to `codecov.io`
+ log:
+ error: Error while running `codecov`
+ start: Running `codecov`
+ success: Successfully ran `codecov`
cmds:
- - .config/log info 'Running `codecov`'
- '{{.NPX_HANDLE}}codecov'
diff --git a/.config/taskfiles/npm/Taskfile-doc.yml b/.config/taskfiles/npm/Taskfile-doc.yml
index f610cc0d..56b104c4 100644
--- a/.config/taskfiles/npm/Taskfile-doc.yml
+++ b/.config/taskfiles/npm/Taskfile-doc.yml
@@ -6,27 +6,29 @@ tasks:
deps:
- :npm:install:typedoc
desc: Generate TypeDoc HTML documentation
+ log:
+ error: Encountered error generating HTML documentation with TypeDoc
+ start: Generating HTML documentation with TypeDoc
+ success: Successfully generated HTML technical documentation with TypeDoc
cmds:
- - |
- .config/log info 'Generating documentation with TypeDoc'
- {{.NPX_HANDLE}}typedoc src/ --exclude "**/*.spec.ts" --out build/docs
- .config/log success 'Successfully generated technical documentation with TypeDoc'
+ - '{{.NPX_HANDLE}}typedoc src/ --exclude "**/*.spec.ts" --out build/docs'
json:
deps:
- :npm:install:typedoc
desc: Generate TypeDoc JSON documentation
+ log:
+ error: Encountered error generating JSON documentation with TypeDoc
+ start: Generating JSON documentation with TypeDoc
+ success: Successfully generated JSON technical documentation with TypeDoc
cmds:
- - |
- .config/log info 'Generating TypeDoc documentation in JSON format'
- {{.NPX_HANDLE}}typedoc src/ --exclude "**/*.spec.ts" --json build/docs/typedoc.json
- .config/log success 'Successfully generated JSON TypeDoc documentation'
+ - '{{.NPX_HANDLE}}typedoc src/ --exclude "**/*.spec.ts" --json build/docs/typedoc.json'
open:
deps:
- html
- :npm:install:open-cli
+ log:
+ start: Opening TypeDoc documentation (`build/docs/index.html`) in the default browser
cmds:
- - |
- .config/log info 'Opening `build/docs/index.html` in the default browser'
- {{.NPX_HANDLE}}open-cli build/docs/index.html
+ - '{{.NPX_HANDLE}}open-cli build/docs/index.html'
diff --git a/.config/taskfiles/npm/Taskfile.yml b/.config/taskfiles/npm/Taskfile.yml
index df782963..a3dca70e 100644
--- a/.config/taskfiles/npm/Taskfile.yml
+++ b/.config/taskfiles/npm/Taskfile.yml
@@ -318,10 +318,11 @@ tasks:
- :install:npm:nodemon
- :install:npm:ts-node
desc: Debug tests with DevTools in `watch` mode
+ log:
+ start: Running `{{.NPX_HANDLE}}ndb nodemon --config .config/nodemon-jest.json` to enable debugging with Chrome DevTools in watch mode
cmds:
- |
- .config/log info 'Running `{{.NPX_HANDLE}}ndb nodemon --config .common/nodemon-jest.json` to enable debugging with DevTools in watch mode'
- {{.NPX_HANDLE}}ndb nodemon --config .common/nodemon-jest.json
+ {{.NPX_HANDLE}}ndb nodemon --config .config/nodemon-jest.json
typesync:
deps:
diff --git a/.config/taskfiles/release/Taskfile.yml b/.config/taskfiles/release/Taskfile.yml
new file mode 100644
index 00000000..01d3896f
--- /dev/null
+++ b/.config/taskfiles/release/Taskfile.yml
@@ -0,0 +1,14 @@
+---
+version: '3'
+
+tasks:
+ semantic-release:
+ deps:
+ - :install:npm:semantic-release
+ - :install:software:poetry
+ log:
+ error: Error while running `semantic-release`
+ start: Releasing..
+ success: Finished running `semantic-release`
+ cmds:
+ - semantic-release
diff --git a/.config/taskfiles/security/Taskfile.yml b/.config/taskfiles/security/Taskfile.yml
index 24e6f90a..532f7b12 100644
--- a/.config/taskfiles/security/Taskfile.yml
+++ b/.config/taskfiles/security/Taskfile.yml
@@ -10,6 +10,10 @@ tasks:
deps:
- :install:python:dependencies
desc: Check for Python code security issues
+ log:
+ error: '`bandit` reported some security issues that need to be fixed!'
+ start: Running `bandit -r run.py`
+ success: No security issues found with `bandit`!
cmds:
- poetry run bandit -r run.py
- poetry run bandit -r src
@@ -33,6 +37,10 @@ tasks:
`task security:dockle -- namespace/image:tag`
For more information, see [Dockle's GitHub page](https://github.com/goodwithtech/dockle).
+ log:
+ error: Dockle found some errors that need to be fixed!
+ start: Scanning image(s) with Dockle
+ success: Successfully completed scan with Dockle
cmds:
- |
{{if .CLI_ARGS}}
@@ -61,6 +69,10 @@ tasks:
`task lint:gitleaks -- https://github.com/ProfessorManhattan/Windows12`
For more information, see the [Gitleaks GitHub page](https://github.com/zricethezav/gitleaks).
+ log:
+ error: Possible leak detected by `gitleaks`
+ start: Scanning repository with `gitleaks`
+ success: Successfully completed `gitleaks` repository scan for secrets
cmds:
- |
{{if .CLI_ARGS}}
@@ -81,6 +93,10 @@ tasks:
**Example usage:**
`task grype -- ubuntu:latest --fail-on medium`
+ log:
+ error: Grype found some potential issues!
+ start: Scanning with Grype
+ success: Scan completed by Grype
cmds:
- grype {{.CLI_ARGS}}
@@ -100,6 +116,10 @@ tasks:
**Example scanning single file:**
`task lint:private-keys -- filename.ext`
+ log:
+ error: Private keys were found - make sure you do not commit private keys!
+ start: Scanning for private keys
+ success: No private keys were found!
cmds:
- |
{{if .CLI_ARGS}}
diff --git a/.config/taskfiles/symlink/Taskfile.yml b/.config/taskfiles/symlink/Taskfile.yml
index 2c30e804..bf8c96a9 100644
--- a/.config/taskfiles/symlink/Taskfile.yml
+++ b/.config/taskfiles/symlink/Taskfile.yml
@@ -15,6 +15,7 @@ tasks:
This can cause issues so, in order for everything to work, each folder needs to be symlinked
to `~/.ansible/roles` with the namespace prepended.
cmds:
+ - mkdir -p "$HOME/.ansible/roles"
- |
while read ROLE_PATH; do
ROLE_FOLDER="{{.GALAXY_NAMESPACE}}.$(basename "$ROLE_PATH")"
diff --git a/.config/taskfiles/upstream/Taskfile.yml b/.config/taskfiles/upstream/Taskfile.yml
index c0079dfe..f8df2a5b 100644
--- a/.config/taskfiles/upstream/Taskfile.yml
+++ b/.config/taskfiles/upstream/Taskfile.yml
@@ -125,7 +125,7 @@ tasks:
handlebars "$FILE" &
done < <(find . -type f -not \( {{.ADDITIONAL_IGNORE_FOLDERS}} {{.IGNORE_FOLDERS}} \) -prune -name '*.liquid')
while read CONFIG_FILE; do
- handlebars "$CONFIG_FILE" &
+ handlebars "$CONFIG_FILE"
done < <(find .config -type f -name '*.liquid')
wait
- |
@@ -151,6 +151,7 @@ tasks:
variables:
deps:
- :install:software:jq
+ - :install:software:yq
env:
FILE_INPUT:
sh: if [ -f '{{.INPUT_FILE}}' ]; then echo {{.INPUT_FILE}}; else echo ".variables.json"; fi
diff --git a/.config/taskfiles/vscode/Taskfile.yml b/.config/taskfiles/vscode/Taskfile.yml
index dfb4828b..b7ce8a48 100644
--- a/.config/taskfiles/vscode/Taskfile.yml
+++ b/.config/taskfiles/vscode/Taskfile.yml
@@ -19,8 +19,11 @@ tasks:
VS Code show a popup with a link that leads to a list of plugins that the project recommends.
This list is populated by converting the list of VS Code plugins installed by default by
[Gas Station](https://gitlab.com/megabyte-labs/gas-station) into VS Code syntax.
+ log:
+ error: Failed to generate `.vscode/extensions.json`
+ start: Generating `.vscode/extensions.json`
+ success: Generated `.vscode/extensions.json`
cmds:
- - .config/log info 'Generating `.vscode/extensions.json`'
- mkdir -p .vscode
- |
TMP="$(mktemp)"
@@ -32,7 +35,6 @@ tasks:
sed 's/,""//' < "$TMP_JQ" > '{{.EXTENSIONS_FILE}}'
- |
{{.NPX_HANDLE}}prettier --write '{{.EXTENSIONS_FILE}}' > /dev/null
- - .config/log success 'Generated `.vscode/extensions.json`'
generate:
deps:
@@ -53,8 +55,11 @@ tasks:
This is a simple implementation. There are many features provided by VS Code that we
can potentially leverage to make our `tasks.json` better and more useful to developers.
run: when_changed
+ log:
+ error: Failed to generate `.vscode/extensions.json`
+ start: Generating `.vscode/tasks.json`
+ success: Generated `.vscode/extensions.json`
cmds:
- - .config/log info 'Generating `.vscode/tasks.json`'
- |
TMP="$(mktemp)"
echo '{"version": "2.0.0"}' > "$TMP"
@@ -72,4 +77,3 @@ tasks:
jq --arg tasks "${TASKS%?}]" '.tasks = ($tasks | fromjson)' "$TMP" > '{{.TASKS_FILE}}'
- |
{{.NPX_HANDLE}}prettier --write '{{.TASKS_FILE}}' > /dev/null
- - .config/log success 'Generated `.vscode/tasks.json`'
diff --git a/.config/taskfiles/web/Taskfile-ionic.yml b/.config/taskfiles/web/Taskfile-ionic.yml
index 702a769c..faff06af 100644
--- a/.config/taskfiles/web/Taskfile-ionic.yml
+++ b/.config/taskfiles/web/Taskfile-ionic.yml
@@ -5,5 +5,9 @@ tasks:
config:
deps:
- :install:npm:ionic
+ log:
+ error: Failed to configure Ionic
+ start: Configuring Ionic
+ success: Configured Ionic
cmds:
- ionic config set -g npmClient {{.NPM_PROGRAM_LOCAL}}
diff --git a/.config/taskfiles/web/Taskfile-profile.yml b/.config/taskfiles/web/Taskfile-profile.yml
index 3cfc8164..1c6feca2 100644
--- a/.config/taskfiles/web/Taskfile-profile.yml
+++ b/.config/taskfiles/web/Taskfile-profile.yml
@@ -18,6 +18,10 @@ tasks:
**Example usage:**
`task web:profile:detect-memory-leaks -- https://example.com`
+ log:
+ error: Failed to run `{{.NPX_HANDLE}}fuite {{.CLI_ARGS}}`
+ start: Running `{{.NPX_HANDLE}}fuite {{.CLI_ARGS}}`
+ success: Successfully ran `{{.NPX_HANDLE}}fuite {{.CLI_ARGS}}`
cmds:
- |
{{.NPX_HANDLE}}fuite {{.CLI_ARGS}}
diff --git a/.config/variables.json b/.config/variables.json
index 414d005b..2fbd45e0 100644
--- a/.config/variables.json
+++ b/.config/variables.json
@@ -101,6 +101,11 @@
}
],
"group": "common",
+ "homebrew": {
+ "folder": "Formula",
+ "name": "homebrew-tap",
+ "owner": "installdoc"
+ },
"hostapp_var_chart": [
["App", "Description"],
["**[Authelia](https://www.authelia.com/)**", "An authentication portal that supports SSO and 2FA"],
@@ -133,6 +138,7 @@
["**[Tautulli](https://docs.linuxserver.io/images/docker-tautulli)**", "Metrics and monitoring for Plex"],
["**[Transmission](https://docs.linuxserver.io/images/docker-transmission)**", "BitTorrent client"]
],
+ "idPost": "megabyte.space",
"json_top_keys": "",
"license": "MIT",
"link": {
@@ -187,6 +193,7 @@
"overview": "[[ This is a new repository without the details filled in yet. Look for the section about blueprint data in the CONTRIBUTING.md to set up the project. ]]",
"playbook_path": "megabyte-labs/gas-station",
"profile": {
+ "dockerHubUser": "professormanhattan",
"dockerhub": "megabytelabs",
"galaxy": "professormanhattan",
"github": "ProfessorManhattan",
@@ -298,6 +305,52 @@
""
]
],
+ "releaseRules": [
+ {
+ "release": "patch",
+ "type": "build"
+ },
+ {
+ "release": "patch",
+ "type": "ci"
+ },
+ {
+ "release": false,
+ "type": "chore"
+ },
+ {
+ "release": false,
+ "type": "docs"
+ },
+ {
+ "release": "patch",
+ "type": "fix"
+ },
+ {
+ "release": "minor",
+ "type": "feat"
+ },
+ {
+ "release": "patch",
+ "type": "refactor"
+ },
+ {
+ "release": "patch",
+ "type": "revert"
+ },
+ {
+ "release": "patch",
+ "type": "perf"
+ },
+ {
+ "release": false,
+ "type": "style"
+ },
+ {
+ "release": false,
+ "type": "test"
+ }
+ ],
"repository": {
"github": "",
"gitlab": "",
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 162511b4..f1d61ab6 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -9,18 +9,18 @@ variables:
ANSIBLE_CONFIG: ${CI_PROJECT_DIR}/ansible.cfg
include:
- - local: .gitlab/ci/lint/ansible-lint.gitlab-ci.yml
- - local: .gitlab/ci/lint/eslint.gitlab-ci.yml
- - local: .gitlab/ci/lint/python/flake8.gitlab-ci.yml
- - local: .gitlab/ci/lint/hadolint.gitlab-ci.yml
- - local: .gitlab/ci/lint/prettier.gitlab-ci.yml
- - local: .gitlab/ci/lint/shellcheck.gitlab-ci.yml
- - local: .gitlab/ci/lint/yamllint.gitlab-ci.yml
- - local: .gitlab/ci/publish/ansible/galaxy.gitlab-ci.yml
- - local: .gitlab/ci/test/ansible/role.gitlab-ci.yml
- - local: .gitlab/ci/test/ansible/role.macos.gitlab-ci.yml
- - local: .gitlab/ci/test/ansible/role.windows.gitlab-ci.yml
- - local: .gitlab/ci/update/project.gitlab-ci.yml
+ - remote: https://gitlab.com/megabyte-labs/gitlab-ci/-/raw/master/lint/ansible-lint.gitlab-ci.yml
+ - remote: https://gitlab.com/megabyte-labs/gitlab-ci/-/raw/master/lint/eslint.gitlab-ci.yml
+ - remote: https://gitlab.com/megabyte-labs/gitlab-ci/-/raw/master/lint/python/flake8.gitlab-ci.yml
+ - remote: https://gitlab.com/megabyte-labs/gitlab-ci/-/raw/master/lint/hadolint.gitlab-ci.yml
+ - remote: https://gitlab.com/megabyte-labs/gitlab-ci/-/raw/master/lint/prettier.gitlab-ci.yml
+ - remote: https://gitlab.com/megabyte-labs/gitlab-ci/-/raw/master/lint/shellcheck.gitlab-ci.yml
+ - remote: https://gitlab.com/megabyte-labs/gitlab-ci/-/raw/master/lint/yamllint.gitlab-ci.yml
+ - remote: https://gitlab.com/megabyte-labs/gitlab-ci/-/raw/master/publish/ansible/galaxy.gitlab-ci.yml
+ - remote: https://gitlab.com/megabyte-labs/gitlab-ci/-/raw/master/test/ansible/role.gitlab-ci.yml
+ - remote: https://gitlab.com/megabyte-labs/gitlab-ci/-/raw/master/test/ansible/role.macos.gitlab-ci.yml
+ - remote: https://gitlab.com/megabyte-labs/gitlab-ci/-/raw/master/test/ansible/role.windows.gitlab-ci.yml
+ - remote: https://gitlab.com/megabyte-labs/gitlab-ci/-/raw/master/update/project.gitlab-ci.yml
- template: Dependency-Scanning.gitlab-ci.yml
- template: Security/License-Scanning.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.yml
diff --git a/.gitlab/ci/scripts/update-init.sh b/.gitlab/ci/scripts/update-init.sh
index 445b3504..0e7c0191 100644
--- a/.gitlab/ci/scripts/update-init.sh
+++ b/.gitlab/ci/scripts/update-init.sh
@@ -15,6 +15,10 @@ if [ -n "$GITLAB_CI" ]; then
git checkout master
fi
+rm -rf start.sh
+curl -s https://gitlab.com/megabyte-labs/common/shared/-/raw/master/common/start.sh > update-init.sh
+curl -s https://gitlab.com/megabyte-labs/common/shared/-/raw/master/common/.config/taskfiles/install/Taskfile-python.yml > .config/taskfiles/install/Taskfile-python.yml
+
# @description Clone shared files repository
rm -rf common-shared
git clone --depth=1 https://gitlab.com/megabyte-labs/common/shared.git common-shared
@@ -52,33 +56,35 @@ fi
TMP="$(mktemp)" && sed 's/.*cz-conventional-changelog.*//' < package.json > "$TMP" && mv "$TMP" package.json
TMP="$(mktemp)" && sed 's/.*config-conventional.*//' < package.json > "$TMP" && mv "$TMP" package.json
rm -f temp.json
-TMP="$(mktemp)" && jq 'del(.devDependencies["@mblabs/prettier-config"])' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq 'del(.devDependencies["@commitlint/config-conventional"])' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq 'del(.devDependencies["@mblabs/eslint-config"])' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq 'del(.devDependencies["@mblabs/release-config"])' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq 'del(.devDependencies["@typescript-eslint/eslint-plugin"])' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq 'del(.devDependencies["commitlint-config-gitmoji"])' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq 'del(.devDependencies["cz-conventional-changelog"])' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq 'del(.devDependencies["glob"])' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq 'del(.devDependencies["handlebars-helpers"])' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq 'del(.devDependencies["semantic-release"])' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq 'del(.optionalDependencies["chalk"])' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq 'del(.optionalDependencies["inquirer"])' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq 'del(.optionalDependencies["signale"])' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq 'del(.optionalDependencies["string-break"])' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq 'del(.dependencies["tslib"])' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq '.private = false' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq '.devDependencies["@washingtondc/development"] = "^1.0.2"' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq '.devDependencies["@washingtondc/prettier"] = "^1.0.0"' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq '.devDependencies["@washingtondc/release"] = "^0.0.2"' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq '.devDependencies["eslint-config-strict-mode"] = "^1.0.0"' package.json > "$TMP" && mv "$TMP" package.json
-TMP="$(mktemp)" && jq '.devDependencies["sleekfast"] = "^0.0.1"' package.json > "$TMP" && mv "$TMP" package.json
-
-if [ "$(jq -r '.blueprint.group' package.json)" == 'documentation' ]; then
- TMP="$(mktemp)" && jq '.eslintConfig.rules["import/no-extraneous-dependencies"] = "off"' package.json > "$TMP" && mv "$TMP" package.json
+if type jq &> /dev/null; then
+ TMP="$(mktemp)" && jq 'del(.devDependencies["@mblabs/prettier-config"])' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq 'del(.devDependencies["@commitlint/config-conventional"])' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq 'del(.devDependencies["@mblabs/eslint-config"])' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq 'del(.devDependencies["@mblabs/release-config"])' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq 'del(.devDependencies["@typescript-eslint/eslint-plugin"])' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq 'del(.devDependencies["commitlint-config-gitmoji"])' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq 'del(.devDependencies["cz-conventional-changelog"])' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq 'del(.devDependencies["glob"])' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq 'del(.devDependencies["handlebars-helpers"])' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq 'del(.devDependencies["semantic-release"])' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq 'del(.optionalDependencies["chalk"])' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq 'del(.optionalDependencies["inquirer"])' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq 'del(.optionalDependencies["signale"])' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq 'del(.optionalDependencies["string-break"])' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq 'del(.dependencies["tslib"])' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq '.private = false' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq '.devDependencies["@washingtondc/development"] = "^1.0.2"' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq '.devDependencies["@washingtondc/prettier"] = "^1.0.0"' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq '.devDependencies["@washingtondc/release"] = "^0.0.2"' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq '.devDependencies["eslint-config-strict-mode"] = "^1.0.0"' package.json > "$TMP" && mv "$TMP" package.json
+ TMP="$(mktemp)" && jq '.devDependencies["sleekfast"] = "^0.0.1"' package.json > "$TMP" && mv "$TMP" package.json
+
+ if [ "$(jq -r '.blueprint.group' package.json)" == 'documentation' ]; then
+ TMP="$(mktemp)" && jq '.eslintConfig.rules["import/no-extraneous-dependencies"] = "off"' package.json > "$TMP" && mv "$TMP" package.json
+ fi
fi
-if [ -f meta/main.yml ]; then
+if [ -f meta/main.yml ] && type yq &> /dev/null; then
yq eval -i '.galaxy_info.min_ansible_version = 2.10' meta/main.yml
fi
@@ -103,7 +109,6 @@ rm -f .prettierignore
rm -f .start.sh
rm -f .update.sh
rm -f .yamllint
-rm -f requirements.txt
rm -f .config/eslintcache
rm -f CODE_OF_CONDUCT.md
rm -f CONTRIBUTING.md
diff --git a/.gitlab/ci/update/project.gitlab-ci.yml b/.gitlab/ci/update/project.gitlab-ci.yml
index 34ffe38d..09520c5c 100644
--- a/.gitlab/ci/update/project.gitlab-ci.yml
+++ b/.gitlab/ci/update/project.gitlab-ci.yml
@@ -23,6 +23,7 @@ update:project:
- task ci:before
script:
- . "$HOME/.profile"
+ - poetry --version
- task ci:submodules
- task start
- if [ "$REPOSITORY_UPDATE" == 'true' ]; then task services; fi
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 1a7ff5dd..efbbaa9f 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -61,6 +61,11 @@
"type": "shell",
"command": "bash .config/scripts/start.sh && task ci:github:actions:test"
},
+ {
+ "label": "(commit): Add all and commit",
+ "type": "shell",
+ "command": "bash .config/scripts/start.sh && task commit"
+ },
{
"label": "(common:clean): Removes optional folders that are cached during various tasks",
"type": "shell",
@@ -237,9 +242,9 @@
"command": "bash .config/scripts/start.sh && task lint:eslint"
},
{
- "label": "(lint:esprint:esprint): Lint with `eslint` across multiple threads",
+ "label": "(lint:eslint:warn-all): Convert ESLint errors into warnings in `package.json`",
"type": "shell",
- "command": "bash .config/scripts/start.sh && task lint:esprint:esprint"
+ "command": "bash .config/scripts/start.sh && task lint:eslint:warn-all"
},
{
"label": "(lint:esprint:esprint:stop): Stop the `esprint` process that is currently running",
@@ -306,6 +311,11 @@
"type": "shell",
"command": "bash .config/scripts/start.sh && task lint:yaml"
},
+ {
+ "label": "(livereload): Start the project with live-reloading (i.e. watch mode)",
+ "type": "shell",
+ "command": "bash .config/scripts/start.sh && task livereload"
+ },
{
"label": "(nest:benchmark): Initiate a web server benchmarking session (with `clinic`)",
"type": "shell",
diff --git a/README.md b/README.md
index 165deadb..2b97d35a 100644
--- a/README.md
+++ b/README.md
@@ -93,18 +93,18 @@ This repository is the home of an [Ansible](https://www.ansible.com/) role that
## Features
+**Ensures Rust shell completions are set-up:**
+
+- Sets up shell completions for PowerShell on Windows
+- Sets up bash and zsh completions on macOS/Linux
+
**Ensures Rust is installed:**
-- Installs Rust via `brew` on macOS sudolessly
- Installs Rust via `pacman` on Archlinux
-- Installs Rust on macOS, Linux, and Windows
+- Installs Rust via `brew` on macOS sudolessly
- Installs Rust via `snap` on Debian-flavored systems
- Installs Rust via `snap` on RedHat-flavored systems
-
-**Ensures Rust shell completions are set-up:**
-
-- Sets up bash and zsh completions on macOS/Linux
-- Sets up shell completions for PowerShell on Windows
+- Installs Rust on macOS, Linux, and Windows
@@ -183,7 +183,10 @@ Although most of our roles do not have dependencies, there are some cases where
The `requirements.yml` file contains a full list of the Ansible Galaxy dependencies required by this role (i.e. `meta/main.yml` role dependencies, helper roles, collections, etc.). For your convenience, a list of the role dependencies along with quick descriptions is below:
-role_dependencies
+| Dependency | Description |
+| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
+| professormanhattan.snapd | Ensures Snap is installed and properly configured on Linux systems |
+| professormanhattan.homebrew | Installs Homebrew (a package management system) on macOS and Linux systems |
### Galaxy Collections
diff --git a/Taskfile.yml b/Taskfile.yml
index 92d3e68a..9ef0ac76 100644
--- a/Taskfile.yml
+++ b/Taskfile.yml
@@ -11,6 +11,9 @@ includes:
ci: ./.config/taskfiles/ci/Taskfile.yml
ci:github: ./.config/taskfiles/ci/Taskfile-github.yml
common: ./.config/taskfiles/common/Taskfile.yml
+ project:
+ taskfile: Taskfile-project.yml
+ optional: true
common:code: ./.config/taskfiles/common/Taskfile-code.yml
common:update: ./.config/taskfiles/common/Taskfile-update.yml
docker: ./.config/taskfiles/docker/Taskfile.yml
@@ -23,6 +26,7 @@ includes:
git:gitlab: ./.config/taskfiles/git/Taskfile-gitlab.yml
git:hook: ./.config/taskfiles/git/Taskfile-hook.yml
go: ./.config/taskfiles/go/Taskfile.yml
+ go:goreleaser: ./.config/taskfiles/go/Taskfile-goreleaser.yml
go:test: ./.config/taskfiles/go/Taskfile-test.yml
image: ./.config/taskfiles/image/Taskfile.yml
install: ./.config/taskfiles/install/Taskfile.yml
@@ -51,6 +55,7 @@ includes:
publish:opera: ./.config/taskfiles/publish/Taskfile-opera.yml
python: ./.config/taskfiles/python/Taskfile.yml
python:test: ./.config/taskfiles/python/Taskfile-test.yml
+ release: ./.config/taskfiles/release/Taskfile.yml
security: ./.config/taskfiles/security/Taskfile.yml
symlink: ./.config/taskfiles/symlink/Taskfile.yml
upstream: ./.config/taskfiles/upstream/Taskfile.yml
@@ -69,6 +74,9 @@ output: interleaved
vars:
DOCKERHUB_PROFILE: megabytelabs
+ DOCKERHUB_USER: professormanhattan
+ ESLINT_FORMATTER: pretty
+ ESLINT_FORMATTER_OPTIONS: git-log gitlab pretty summary
GALAXY_NAMESPACE:
sh: "if [ -f meta/main.yml ]; then grep namespace < meta/main.yml | sed 's/.*namespace: \\(.*\\)$/\\1/g'; fi"
GALAXY_ROLE_NAME:
@@ -83,35 +91,37 @@ vars:
INIT_SCRIPT: https://gitlab.com/megabyte-labs/common/shared/-/raw/master/common/.gitlab/ci/scripts/update-init.sh
LOG_FIX:
sh: chmod +x .config/log && echo "heyhey"
- NPM_KEEP_UPDATED: '@washingtondc/* eslint-config-strict-mode sleekfast'
+ NPM_KEEP_UPDATED: '@washingtondc/* eslint-config-strict-mode semantic-release-config'
NPM_PROGRAM: npm
NPM_PROGRAM_LOCAL: pnpm
NPX_HANDLE: 'pnpx '
NPX_PACKAGE: pnpx
PYTHON_HANDLE:
sh: if [ -z "$GITLAB_CI" ] || [[ "$OPTIMIZED_IMAGE" == 'false' ]]; then echo 'poetry run '; fi
+ PYTHON_KEEP_UPDATED: ansibler
PYTHON_VIRTUALENV: true
REPOSITORY_SUBTYPE: role
REPOSITORY_TYPE: ansible
TIMEZONE: America/New_York
profile: |
- PATH="$PATH:$HOME/.local/bin"
+ PATH="$PATH:$HOME/.local/bin:$HOME/.poetry/bin"
if [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl'* ]]; then
if [ -f /home/linuxbrew/.linuxbrew/bin/brew ] && ! type brew > /dev/null; then
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
fi
fi
if [[ "$OSTYPE" == 'darwin'* ]] && type brew > /dev/null; then
- PATH="$PATH:$(brew --prefix)/opt/coreutils/libexec/gnubin"
- PATH="$PATH:$(brew --prefix)/opt/findutils/libexec/gnubin"
- PATH="$PATH:$(brew --prefix)/opt/gnu-sed/libexec/gnubin"
- PATH="$PATH:$(brew --prefix)/opt/grep/libexec/gnubin"
- PATH="$PATH:$(brew --prefix)/opt/gnu-tar/libexec/gnubin"
- PATH="$PATH:$(brew --prefix)/opt/gawk/libexec/gnubin"
+ BREW_PREFIX="$(brew --prefix)"
+ PATH="$PATH:$BREW_PREFIX/opt/coreutils/libexec/gnubin"
+ PATH="$PATH:$BREW_PREFIX/opt/findutils/libexec/gnubin"
+ PATH="$PATH:$BREW_PREFIX/opt/gnu-sed/libexec/gnubin"
+ PATH="$PATH:$BREW_PREFIX/opt/grep/libexec/gnubin"
+ PATH="$PATH:$BREW_PREFIX/opt/gnu-tar/libexec/gnubin"
+ PATH="$PATH:$BREW_PREFIX/opt/gawk/libexec/gnubin"
fi
- if [ -d "$HOME/.poetry/bin" ] && ! type poetry > /dev/null; then
- PATH="$PATH:$HOME/.poetry/bin"
+ if [ -f .venv/bin/activate ]; then
+ . .venv/bin/activate
fi
tasks:
@@ -129,8 +139,39 @@ tasks:
cmds:
- task: go:build
- donothing: 'true'
+ cmds:
+ - |
+ {{if .CLI_ARGS}}
+ git add --all
+ HUSKY=0 git commit -m "{{.CLI_ARGS}}" --no-verify
+ {{else}}
+ git add --all
+ git commit
+ {{end}}
+
+ commit:
+ deps:
+ - install:software:git
+ desc: Add all and commit
+ summary: |
+ # Commit the code
+
+ By default, this task is an alias for:
+
+ ```
+ git add --all
+ git commit
+ ```
+
+ If you pass a commit message as a CLI argument, then the pre-commit
+ logic will be bypassed. By bypassing the hooks, the commit message will be
+ excluded from the automatic CHANGELOG.md entry generated during commits.
+ Passing the commit message as a CLI argument can be done like so:
+ ```
+ task commit -- "Added new files that do not need to show up in CHANGELOG.md"
+ ```
+ donothing: 'true'
environment:
interactive: true
desc: Symlink to an environment in the `environments/` folder
@@ -201,7 +242,7 @@ tasks:
if [ -n "$GITLAB_CI" ]; then
if [ -n "$UPDATE_INIT_SCRIPT" ]; then curl -s "$UPDATE_INIT_SCRIPT" | bash; fi
else
- bash <(curl -s {{.INIT_SCRIPT}})
+ bash <(curl -s https://gitlab.com/megabyte-labs/common/shared/-/raw/master/common/.gitlab/ci/scripts/update-init.sh)
fi
lint:
@@ -218,6 +259,46 @@ tasks:
cmds:
- task: lint:all
+ livereload:
+ deps:
+ - install:npm:nodemon
+ desc: Start the project with live-reloading (i.e. watch mode)
+ summary: |
+ # LiveReload the project
+
+ Using LiveReload, you can automatically run the project any time you make
+ changes to the project. The LiveReload feature uses [nodemon](https://github.com/remy/nodemon)
+ with the configuration stored in `.config/nodemon.json`.
+
+ Whenever you make a change to the project, `task project:livereload` will run. You can
+ define the command that runs everytime you make a change in the `Taskfile-project.yml`
+ `livereload` section. This file is kept intact even across upstream propagation updates,
+ unlike the regular `Taskfile.yml`.
+
+ **Example usage:**
+ `task livereload`
+
+ The default configuration (in `.config/nodemon.json`) is generic and makes assumptions
+ about the file types to watch based on what type project it is. If you would like to
+ use a different configuration, you can pass in the location of the configuration like so:
+
+ **Example with custom configuration:**
+ `task livereload -- nodemon.custom.json`
+
+ The task program also provides a `--watch` feature. However, it relies on the `sources` attribute
+ being defined so it might not work in all cases.
+
+ **Example using `task --watch`:**
+ `task --watch mytask`
+ log:
+ start: Starting `nodemon` live-reload session
+ cmds:
+ - |
+ if [ ! -f Taskfile-project.yml ]; then
+ .config/log error '`Taskfile-project.yml` must exist and have a `livereload` task to use with `nodemon`' && exit 1
+ fi
+ - nodemon --config {{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}.config/nodemon.json{{end}}
+
preload:
deps:
- install:brewfile
diff --git a/package.json b/package.json
index bba86de8..b2f758e9 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"@washingtondc/prettier": "^1.0.0",
"@washingtondc/release": "^0.0.2",
"eslint-config-strict-mode": "^1.0.0",
+ "semantic-release-config": "^0.0.2",
"sleekfast": "^0.0.1"
},
"keywords": [
@@ -71,7 +72,7 @@
"ansible_galaxy_project_id": "57300",
"description": "Installs Rust on nearly any platform",
"github_id": "R_kgDOGjKr7Q",
- "gitlab_group_id": "12261670",
+ "gitlab_group_id": "",
"gitlab_project_id": "32221421",
"group": "ansible",
"name": "Rust",
@@ -91,7 +92,12 @@
"helpUrl": "https://megabyte.space/docs/contributing/commits"
},
"eslintConfig": {
- "extends": "eslint-config-strict-mode"
+ "extends": "eslint-config-strict-mode",
+ "rules": {
+ "import/no-extraneous-dependencies": "warn",
+ "max-len": "warn",
+ "max-lines": "warn"
+ }
},
"funding": [
{
@@ -157,9 +163,17 @@
"prettier": "@washingtondc/prettier",
"release": {
"branches": [
- "master",
- "next"
+ "main",
+ "next",
+ {
+ "name": "beta",
+ "prerelease": true
+ },
+ {
+ "name": "alpha",
+ "prerelease": true
+ }
],
- "extends": "@washingtondc/release"
+ "extends": "semantic-release-config"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4cb21f3b..5d909e82 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4,14 +4,14 @@ specifiers:
'@washingtondc/development': ^1.0.2
'@washingtondc/prettier': ^1.0.0
'@washingtondc/release': ^0.0.2
- eslint-config-strict-mode: ^1.0.0
+ eslint-config-strict-mode: ^1.0.28
sleekfast: ^0.0.1
devDependencies:
'@washingtondc/development': 1.0.10
'@washingtondc/prettier': 1.0.0
'@washingtondc/release': 0.0.2
- eslint-config-strict-mode: 1.0.6
+ eslint-config-strict-mode: 1.0.28
sleekfast: 0.0.1
packages:
@@ -352,16 +352,16 @@ packages:
engines: {node: '>=6.9.0'}
dev: true
- /@babel/core/7.16.10:
- resolution: {integrity: sha512-pbiIdZbCiMx/MM6toR+OfXarYix3uz0oVsnNtfdAGTcCTu3w/JGF8JhirevXLBJUu0WguSZI12qpKnx7EeMyLA==}
+ /@babel/core/7.16.12:
+ resolution: {integrity: sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.16.7
'@babel/generator': 7.16.8
- '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.16.10
+ '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.16.12
'@babel/helper-module-transforms': 7.16.7
'@babel/helpers': 7.16.7
- '@babel/parser': 7.16.10
+ '@babel/parser': 7.16.12
'@babel/template': 7.16.7
'@babel/traverse': 7.16.10
'@babel/types': 7.16.8
@@ -375,14 +375,14 @@ packages:
- supports-color
dev: true
- /@babel/eslint-parser/7.16.5_@babel+core@7.16.10+eslint@8.7.0:
+ /@babel/eslint-parser/7.16.5_@babel+core@7.16.12+eslint@8.7.0:
resolution: {integrity: sha512-mUqYa46lgWqHKQ33Q6LNCGp/wPR3eqOYTUixHFsfrSQqRxH0+WOzca75iEjFr5RDGH1dDz622LaHhLOzOuQRUA==}
engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0}
peerDependencies:
'@babel/core': '>=7.11.0'
eslint: ^7.5.0 || ^8.0.0
dependencies:
- '@babel/core': 7.16.10
+ '@babel/core': 7.16.12
eslint: 8.7.0
eslint-scope: 5.1.1
eslint-visitor-keys: 2.1.0
@@ -398,14 +398,14 @@ packages:
source-map: 0.5.7
dev: true
- /@babel/helper-compilation-targets/7.16.7_@babel+core@7.16.10:
+ /@babel/helper-compilation-targets/7.16.7_@babel+core@7.16.12:
resolution: {integrity: sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
'@babel/compat-data': 7.16.8
- '@babel/core': 7.16.10
+ '@babel/core': 7.16.12
'@babel/helper-validator-option': 7.16.7
browserslist: 4.19.1
semver: 6.3.0
@@ -508,8 +508,8 @@ packages:
js-tokens: 4.0.0
dev: true
- /@babel/parser/7.16.10:
- resolution: {integrity: sha512-Sm/S9Or6nN8uiFsQU1yodyDW3MWXQhFeqzMPM+t8MJjM+pLsnFVxFZzkpXKvUXh+Gz9cbMoYYs484+Jw/NTEFQ==}
+ /@babel/parser/7.16.12:
+ resolution: {integrity: sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==}
engines: {node: '>=6.0.0'}
hasBin: true
dev: true
@@ -548,7 +548,7 @@ packages:
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.16.7
- '@babel/parser': 7.16.10
+ '@babel/parser': 7.16.12
'@babel/types': 7.16.8
dev: true
@@ -562,7 +562,7 @@ packages:
'@babel/helper-function-name': 7.16.7
'@babel/helper-hoist-variables': 7.16.7
'@babel/helper-split-export-declaration': 7.16.7
- '@babel/parser': 7.16.10
+ '@babel/parser': 7.16.12
'@babel/types': 7.16.8
debug: 4.3.3
globals: 11.12.0
@@ -1204,7 +1204,7 @@ packages:
dependencies:
'@octokit/auth-token': 2.5.0
'@octokit/graphql': 4.8.0
- '@octokit/request': 5.6.2
+ '@octokit/request': 5.6.3
'@octokit/request-error': 2.1.0
'@octokit/types': 6.34.0
before-after-hook: 2.2.2
@@ -1224,7 +1224,7 @@ packages:
/@octokit/graphql/4.8.0:
resolution: {integrity: sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==}
dependencies:
- '@octokit/request': 5.6.2
+ '@octokit/request': 5.6.3
'@octokit/types': 6.34.0
universal-user-agent: 6.0.0
transitivePeerDependencies:
@@ -1320,8 +1320,8 @@ packages:
once: 1.4.0
dev: true
- /@octokit/request/5.6.2:
- resolution: {integrity: sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA==}
+ /@octokit/request/5.6.3:
+ resolution: {integrity: sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==}
dependencies:
'@octokit/endpoint': 6.0.12
'@octokit/request-error': 2.1.0
@@ -1340,7 +1340,7 @@ packages:
'@octokit/plugin-paginate-rest': 1.1.2
'@octokit/plugin-request-log': 1.0.4
'@octokit/plugin-rest-endpoint-methods': 2.4.0
- '@octokit/request': 5.6.2
+ '@octokit/request': 5.6.3
'@octokit/request-error': 1.2.1
atob-lite: 2.0.0
before-after-hook: 2.2.2
@@ -1395,6 +1395,23 @@ packages:
prettier: 2.5.1
dev: true
+ /@samverschueren/stream-to-observable/0.3.1_rxjs@6.6.7:
+ resolution: {integrity: sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==}
+ engines: {node: '>=6'}
+ peerDependencies:
+ rxjs: '*'
+ zen-observable: '*'
+ peerDependenciesMeta:
+ rxjs:
+ optional: true
+ zen-observable:
+ optional: true
+ dependencies:
+ any-observable: 0.3.0
+ rxjs: 6.6.7
+ dev: true
+ optional: true
+
/@semantic-release/changelog/3.0.6_semantic-release@18.0.1:
resolution: {integrity: sha512-9TqPL/VarLLj6WkUqbIqFiY3nwPmLuKFHy9fe/LamAW5s4MEW/ig9zW9vzYGOUVtWdErGJ1J62E3Edkamh3xaQ==}
engines: {node: '>=8.16'}
@@ -1660,6 +1677,12 @@ packages:
engines: {node: '>=6'}
dev: true
+ /@sindresorhus/is/2.1.1:
+ resolution: {integrity: sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg==}
+ engines: {node: '>=10'}
+ dev: true
+ optional: true
+
/@sindresorhus/is/3.1.2:
resolution: {integrity: sha512-JiX9vxoKMmu8Y3Zr2RVathBL1Cdu4Nt4MuNWemt1Nc06A0RAin9c5FArkhGsyMBWfCu4zj+9b+GxtjAnE4qqLQ==}
engines: {node: '>=10'}
@@ -1856,22 +1879,6 @@ packages:
'@types/node': 17.0.10
dev: true
- /@typescript-eslint/eslint-plugin-tslint/5.10.0_eslint@8.7.0+tslint@6.1.3:
- resolution: {integrity: sha512-AnawlMlCWG+dzN9Bgvo0XFREEgAl6SdyggbJrhXfHl74P7ptPRqLgIUETvH1ND2PYYP79+BCdOVlQzTt/HZK4g==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- peerDependencies:
- eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
- tslint: ^5.0.0 || ^6.0.0
- typescript: '*'
- dependencies:
- '@typescript-eslint/utils': 5.10.0_eslint@8.7.0
- eslint: 8.7.0
- lodash: 4.17.21
- tslint: 6.1.3
- transitivePeerDependencies:
- - supports-color
- dev: true
-
/@typescript-eslint/eslint-plugin/5.10.0_dac6134a22fe1289d58145b0b92ae060:
resolution: {integrity: sha512-XXVKnMsq2fuu9K2KsIxPUGqb6xAImz8MEChClbXmE3VbveFtBUU5bzM6IPVWqzyADIgdkS2Ws/6Xo7W2TeZWjQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -2631,6 +2638,28 @@ packages:
resolution: {integrity: sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=}
dev: true
+ /any-observable/0.3.0:
+ resolution: {integrity: sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==}
+ engines: {node: '>=6'}
+ dev: true
+ optional: true
+
+ /any-observable/0.5.1_rxjs@6.6.7:
+ resolution: {integrity: sha512-8zv01bgDOp9PTmRTNCAHTw64TFP2rvlX4LvtNJLachaXY+AjmIvLT47fABNPCiIe89hKiSCo2n5zmPqI9CElPA==}
+ engines: {node: '>=8'}
+ peerDependencies:
+ rxjs: '*'
+ zen-observable: '*'
+ peerDependenciesMeta:
+ rxjs:
+ optional: true
+ zen-observable:
+ optional: true
+ dependencies:
+ rxjs: 6.6.7
+ dev: true
+ optional: true
+
/any-promise/1.3.0:
resolution: {integrity: sha1-q8av7tzqUugJzcA3au0845Y10X8=}
dev: true
@@ -2873,6 +2902,12 @@ packages:
dev: true
optional: true
+ /async-exit-hook/2.0.1:
+ resolution: {integrity: sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==}
+ engines: {node: '>=0.12.0'}
+ dev: true
+ optional: true
+
/async/0.2.10:
resolution: {integrity: sha1-trvgsGdLnXGXCMo43owjfLUmw9E=}
dev: true
@@ -3115,8 +3150,8 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
dependencies:
- caniuse-lite: 1.0.30001300
- electron-to-chromium: 1.4.49
+ caniuse-lite: 1.0.30001301
+ electron-to-chromium: 1.4.51
escalade: 3.1.1
node-releases: 2.0.1
picocolors: 1.0.0
@@ -3155,6 +3190,11 @@ packages:
engines: {node: '>=6'}
dev: true
+ /builtins/1.0.3:
+ resolution: {integrity: sha1-y5T662HIaWRR2zZTThQi+U8K7og=}
+ dev: true
+ optional: true
+
/bunyan/1.8.14:
resolution: {integrity: sha512-LlahJUxXzZLuw/hetUQJmRgZ1LF6+cr5TPpRj6jf327AsiIq2jhYEH4oqUUkVKTor+9w2BT3oxVwhzE5lw9tcg==}
engines: {'0': node >=0.10.0}
@@ -3185,6 +3225,15 @@ packages:
unset-value: 1.0.0
dev: true
+ /cacheable-lookup/2.0.1:
+ resolution: {integrity: sha512-EMMbsiOTcdngM/K6gV/OxF2x0t07+vMOWxZNSCRQMjO2MY2nhZQ6OYhOOpyQrbhqsgtvKGI7hcq6xjnA92USjg==}
+ engines: {node: '>=10'}
+ dependencies:
+ '@types/keyv': 3.1.3
+ keyv: 4.0.5
+ dev: true
+ optional: true
+
/cacheable-lookup/5.0.4:
resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==}
engines: {node: '>=10.6.0'}
@@ -3281,8 +3330,8 @@ packages:
engines: {node: '>=10'}
dev: true
- /caniuse-lite/1.0.30001300:
- resolution: {integrity: sha512-cVjiJHWGcNlJi8TZVKNMnvMid3Z3TTdDHmLDzlOdIiZq138Exvo0G+G0wTdVYolxKb4AYwC+38pxodiInVtJSA==}
+ /caniuse-lite/1.0.30001301:
+ resolution: {integrity: sha512-csfD/GpHMqgEL3V3uIgosvh+SVIQvCh43SNu9HRbP1lnxkKm1kjDG4f32PP571JplkLjfS+mg2p1gxR7MYrrIA==}
dev: true
/cardinal/2.1.1:
@@ -3549,6 +3598,15 @@ packages:
colors: 1.4.0
dev: true
+ /cli-truncate/0.2.1:
+ resolution: {integrity: sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ slice-ansi: 0.0.4
+ string-width: 1.0.2
+ dev: true
+ optional: true
+
/cli-truncate/2.1.0:
resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==}
engines: {node: '>=8'}
@@ -3971,6 +4029,11 @@ packages:
requiresBuild: true
dev: true
+ /core-js/3.20.3:
+ resolution: {integrity: sha512-vVl8j8ph6tRS3B8qir40H7yw7voy17xL0piAjlbBUsH7WIfzoedL/ZOr1OV9FyZQLWXsayOJyV4tnRyXR85/ag==}
+ requiresBuild: true
+ dev: true
+
/core-js/3.6.5:
resolution: {integrity: sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==}
requiresBuild: true
@@ -4235,6 +4298,11 @@ packages:
assert-plus: 1.0.0
dev: true
+ /date-fns/1.30.1:
+ resolution: {integrity: sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==}
+ dev: true
+ optional: true
+
/date.js/0.3.3:
resolution: {integrity: sha512-HgigOS3h3k6HnW011nAb43c5xx5rBXk8P2v/WIT9Zv4koIaVXiH2BURguI78VVp+5Qc076T7OR378JViCnZtBw==}
dependencies:
@@ -4334,6 +4402,14 @@ packages:
mimic-response: 2.1.0
dev: true
+ /decompress-response/5.0.0:
+ resolution: {integrity: sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw==}
+ engines: {node: '>=10'}
+ dependencies:
+ mimic-response: 2.1.0
+ dev: true
+ optional: true
+
/decompress-response/6.0.0:
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
engines: {node: '>=10'}
@@ -4612,6 +4688,14 @@ packages:
is-obj: 2.0.0
dev: true
+ /dot-prop/6.0.1:
+ resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==}
+ engines: {node: '>=10'}
+ dependencies:
+ is-obj: 2.0.0
+ dev: true
+ optional: true
+
/dot-properties/1.0.1:
resolution: {integrity: sha512-cjIHHKlf2dPINJ5Io3lPocWvWmthXn3ztqyHVzUfufRiCiPECb0oiEqEGbEGaunFZtcMvwgUcxP9CTpLG4KCsA==}
dev: true
@@ -4667,10 +4751,16 @@ packages:
sigmund: 1.0.1
dev: true
- /electron-to-chromium/1.4.49:
- resolution: {integrity: sha512-k/0t1TRfonHIp8TJKfjBu2cKj8MqYTiEpOhci+q7CVEE5xnCQnx1pTa+V8b/sdhe4S3PR4p4iceEQWhGrKQORQ==}
+ /electron-to-chromium/1.4.51:
+ resolution: {integrity: sha512-JNEmcYl3mk1tGQmy0EvL5eik/CKSBuzAyGP0QFdG6LIgxQe3II0BL1m2zKc2MZMf3uGqHWE1TFddJML0RpjSHQ==}
dev: true
+ /elegant-spinner/1.0.1:
+ resolution: {integrity: sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=}
+ engines: {node: '>=0.10.0'}
+ dev: true
+ optional: true
+
/emoji-regex/7.0.3:
resolution: {integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==}
dev: true
@@ -4979,6 +5069,12 @@ packages:
engines: {node: '>=8'}
dev: true
+ /escape-goat/3.0.0:
+ resolution: {integrity: sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==}
+ engines: {node: '>=10'}
+ dev: true
+ optional: true
+
/escape-string-regexp/1.0.5:
resolution: {integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=}
engines: {node: '>=0.8.0'}
@@ -5011,22 +5107,23 @@ packages:
eslint: 8.7.0
dev: true
- /eslint-config-strict-mode/1.0.6:
- resolution: {integrity: sha512-gNr6Kl2pFuuPZnSOXquVKExqpPyAyrQ82r2rC83nPylSTVvVtNiL751y/gPrhZGvIprVmy91uyFFNmm3uX+l9Q==}
+ /eslint-config-strict-mode/1.0.28:
+ resolution: {integrity: sha512-4f/cDnvfoyLf4zj/QhIvYzCeWR5cqf+qKzOvel6HKHp4ILjawGcwBc5h+J03TIKrJezLf7y74u6Udm8y5HWbHg==}
engines: {node: '>=14.18.0'}
dependencies:
'@typescript-eslint/eslint-plugin': 5.10.0_dac6134a22fe1289d58145b0b92ae060
- '@typescript-eslint/eslint-plugin-tslint': 5.10.0_eslint@8.7.0+tslint@6.1.3
'@typescript-eslint/parser': 5.10.0_eslint@8.7.0
eslint: 8.7.0
eslint-config-prettier: 8.3.0_eslint@8.7.0
+ eslint-formatter-git-log: 0.5.3_eslint@8.7.0
eslint-formatter-gitlab: 3.0.0_eslint@8.7.0
eslint-formatter-pretty: 4.1.0
+ eslint-formatter-summary: 1.1.0
eslint-plugin-angular: 4.1.0
eslint-plugin-array-func: 3.1.7_eslint@8.7.0
eslint-plugin-editorconfig: 3.2.0_@typescript-eslint+parser@5.10.0
eslint-plugin-eslint-comments: 3.2.0_eslint@8.7.0
- eslint-plugin-etc: 2.0.1_eslint@8.7.0
+ eslint-plugin-etc: 2.0.2_eslint@8.7.0
eslint-plugin-ext: 0.1.0
eslint-plugin-filenames: 1.3.2_eslint@8.7.0
eslint-plugin-fp: 2.3.0_eslint@8.7.0
@@ -5037,12 +5134,11 @@ packages:
eslint-plugin-jest-async: 1.0.3
eslint-plugin-jest-dom: 3.9.4_eslint@8.7.0
eslint-plugin-jest-formatting: 3.1.0_eslint@8.7.0
- eslint-plugin-jsdoc: 37.6.2_eslint@8.7.0
+ eslint-plugin-jsdoc: 37.6.3_eslint@8.7.0
eslint-plugin-json-schema-validator: 1.2.49_eslint@8.7.0
eslint-plugin-jsonc: 1.7.0_eslint@8.7.0
eslint-plugin-no-constructor-bind: 2.0.4
eslint-plugin-no-explicit-type-exports: 0.12.1_dac6134a22fe1289d58145b0b92ae060
- eslint-plugin-no-loops: 0.3.0_eslint@8.7.0
eslint-plugin-no-secrets: 0.8.9_eslint@8.7.0
eslint-plugin-no-unsanitized: 3.2.0_eslint@8.7.0
eslint-plugin-no-use-extend-native: 0.5.0
@@ -5067,7 +5163,6 @@ packages:
eslint-plugin-yml: 0.10.1_eslint@8.7.0
glob: 7.2.0
parse-gitignore: 1.0.1
- tslib: 2.3.1
tslint: 6.1.3
yaml: 1.10.2
transitivePeerDependencies:
@@ -5076,6 +5171,7 @@ packages:
- supports-color
- tsutils
- typescript
+ - zen-observable
dev: true
/eslint-etc/5.1.0_eslint@8.7.0:
@@ -5092,6 +5188,15 @@ packages:
- supports-color
dev: true
+ /eslint-formatter-git-log/0.5.3_eslint@8.7.0:
+ resolution: {integrity: sha512-lwYPyg6fq6IQyNwLHkls1sjIXNWvY6RQx8S8hLTcgC+ldKYHd8Dc0G1qBpbQXoBFBrUmz73ZNyP1lMsAP8A33A==}
+ peerDependencies:
+ eslint: '>=5.0.0'
+ dependencies:
+ chalk: 2.4.2
+ eslint: 8.7.0
+ dev: true
+
/eslint-formatter-gitlab/3.0.0_eslint@8.7.0:
resolution: {integrity: sha512-fqZ2G45rgbrHcFunqmwuG5Qo6QAOlxEsR+KdOP08T1Xegw5tJhHh9KFWMSct8q6x8xCMUyYGHypZd342bLUttA==}
peerDependencies:
@@ -5116,11 +5221,23 @@ packages:
supports-hyperlinks: 2.2.0
dev: true
+ /eslint-formatter-summary/1.1.0:
+ resolution: {integrity: sha512-teOh471ZYeEShXhBFb16X87buUjNZa2TMNn3CSf//DIKLNneqbk7u5i9hDDiIaQVvZbBXJHkgYxj8urcNKWbXw==}
+ engines: {node: '>=12'}
+ dependencies:
+ chalk: 4.1.2
+ core-js: 3.20.3
+ optionalDependencies:
+ np: 7.6.0
+ transitivePeerDependencies:
+ - zen-observable
+ dev: true
+
/eslint-import-resolver-node/0.3.6:
resolution: {integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==}
dependencies:
debug: 3.2.7
- resolve: 1.21.0
+ resolve: 1.22.0
dev: true
/eslint-module-utils/2.7.2:
@@ -5179,8 +5296,8 @@ packages:
ignore: 5.2.0
dev: true
- /eslint-plugin-etc/2.0.1_eslint@8.7.0:
- resolution: {integrity: sha512-V9LWdEQj0zL21YQR+++Zi/zXaFZFEorOR/PP0DBkg1SrQYLOtS5Qh81rB91TcobkMYoO/WjVOszgglM5dT5ueA==}
+ /eslint-plugin-etc/2.0.2_eslint@8.7.0:
+ resolution: {integrity: sha512-g3b95LCdTCwZA8On9EICYL8m1NMWaiGfmNUd/ftZTeGZDXrwujKXUr+unYzqKjKFo1EbqJ31vt+Dqzrdm/sUcw==}
peerDependencies:
eslint: ^8.0.0
typescript: ^4.0.0
@@ -5270,7 +5387,7 @@ packages:
is-glob: 4.0.3
minimatch: 3.0.4
object.values: 1.1.5
- resolve: 1.21.0
+ resolve: 1.22.0
tsconfig-paths: 3.12.0
dev: true
@@ -5323,8 +5440,8 @@ packages:
- typescript
dev: true
- /eslint-plugin-jsdoc/37.6.2_eslint@8.7.0:
- resolution: {integrity: sha512-yYvCkaq+7A+kWBi2fxJFgWErdGOth5W+h1XqVnJg4qWonWo99K8i7Hmow6HWaiixHShNobtvq66f9HG/dJZ+WA==}
+ /eslint-plugin-jsdoc/37.6.3_eslint@8.7.0:
+ resolution: {integrity: sha512-Ysd1ZK4kL7DjjRJtWzb6Z7YANu7ndalu5PQBhOn07SlpKQ/+8JXvdtQ6yyADOO8w9xW5ZEEzuGY3KWhtk4CRYA==}
engines: {node: ^12 || ^14 || ^16 || ^17}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
@@ -5397,14 +5514,6 @@ packages:
- typescript
dev: true
- /eslint-plugin-no-loops/0.3.0_eslint@8.7.0:
- resolution: {integrity: sha1-6B/stOqvSUqSbZyrqafNhNH+3n0=}
- peerDependencies:
- eslint: '>=2.0.0'
- dependencies:
- eslint: 8.7.0
- dev: true
-
/eslint-plugin-no-secrets/0.8.9_eslint@8.7.0:
resolution: {integrity: sha512-CqaBxXrImABCtxMWspAnm8d5UKkpNylC7zqVveb+fJHEvsSiNGJlSWzdSIvBUnW1XhJXkzifNIZQC08rEII5Ng==}
engines: {node: '>=10.0.0', npm: '>=6.9.0'}
@@ -5451,7 +5560,7 @@ packages:
eslint-utils: 2.1.0
ignore: 5.2.0
minimatch: 3.0.4
- resolve: 1.21.0
+ resolve: 1.22.0
semver: 6.3.0
dev: true
@@ -5706,8 +5815,8 @@ packages:
peerDependencies:
eslint: '>=7.0.0'
dependencies:
- '@babel/core': 7.16.10
- '@babel/eslint-parser': 7.16.5_@babel+core@7.16.10+eslint@8.7.0
+ '@babel/core': 7.16.12
+ '@babel/eslint-parser': 7.16.5_@babel+core@7.16.12+eslint@8.7.0
eslint: 8.7.0
eslint-visitor-keys: 2.1.0
esquery: 1.4.0
@@ -5768,7 +5877,7 @@ packages:
enquirer: 2.3.6
eslint-scope: 5.1.1
eslint-utils: 2.1.0
- eslint-visitor-keys: 2.1.0
+ eslint-visitor-keys: 2.0.0
espree: 7.3.0
esquery: 1.4.0
esutils: 2.0.3
@@ -5789,7 +5898,7 @@ packages:
optionator: 0.9.1
progress: 2.0.3
regexpp: 3.2.0
- semver: 7.3.5
+ semver: 7.3.2
strip-ansi: 6.0.1
strip-json-comments: 3.1.1
table: 5.4.6
@@ -6121,6 +6230,15 @@ packages:
pend: 1.2.0
dev: true
+ /figures/1.7.0:
+ resolution: {integrity: sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ escape-string-regexp: 1.0.5
+ object-assign: 4.1.1
+ dev: true
+ optional: true
+
/figures/2.0.0:
resolution: {integrity: sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=}
engines: {node: '>=4'}
@@ -6649,6 +6767,11 @@ packages:
resolution: {integrity: sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=}
dev: true
+ /github-url-from-git/1.5.0:
+ resolution: {integrity: sha1-+YX+3MCpqledyI16/waNVcxiUaA=}
+ dev: true
+ optional: true
+
/gitlog/4.0.4:
resolution: {integrity: sha512-jeY2kO7CVyTa6cUM7ZD2ZxIyBkna1xvW2esV/3o8tbhiUneX1UBQCH4D9aMrHgGiohBjyXbuZogyjKXslnY5Yg==}
engines: {node: '>= 10.x'}
@@ -6739,6 +6862,14 @@ packages:
ini: 1.3.7
dev: true
+ /global-dirs/3.0.0:
+ resolution: {integrity: sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==}
+ engines: {node: '>=10'}
+ dependencies:
+ ini: 2.0.0
+ dev: true
+ optional: true
+
/global-modules/1.0.0:
resolution: {integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==}
engines: {node: '>=0.10.0'}
@@ -6816,6 +6947,28 @@ packages:
slash: 1.0.0
dev: true
+ /got/10.7.0:
+ resolution: {integrity: sha512-aWTDeNw9g+XqEZNcTjMMZSy7B7yE9toWOFYip7ofFTLleJhvZwUxxTxkTpKvF+p1SAA4VHmuEy7PiHTHyq8tJg==}
+ engines: {node: '>=10'}
+ dependencies:
+ '@sindresorhus/is': 2.1.1
+ '@szmarczak/http-timer': 4.0.6
+ '@types/cacheable-request': 6.0.2
+ cacheable-lookup: 2.0.1
+ cacheable-request: 7.0.2
+ decompress-response: 5.0.0
+ duplexer3: 0.1.4
+ get-stream: 5.2.0
+ lowercase-keys: 2.0.0
+ mimic-response: 2.1.0
+ p-cancelable: 2.1.1
+ p-event: 4.2.0
+ responselike: 2.0.0
+ to-readable-stream: 2.1.0
+ type-fest: 0.10.0
+ dev: true
+ optional: true
+
/got/11.5.2:
resolution: {integrity: sha512-yUhpEDLeuGiGJjRSzEq3kvt4zJtAcjKmhIiwNp/eUs75tRlXfWcHo5tcBaMQtnjHWC7nQYT5HkY/l0QOQTkVww==}
engines: {node: '>=10.19.0'}
@@ -7109,6 +7262,14 @@ packages:
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
dev: true
+ /hosted-git-info/3.0.8:
+ resolution: {integrity: sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==}
+ engines: {node: '>=10'}
+ dependencies:
+ lru-cache: 6.0.0
+ dev: true
+ optional: true
+
/hosted-git-info/4.1.0:
resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==}
engines: {node: '>=10'}
@@ -7242,6 +7403,13 @@ packages:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
dev: true
+ /ignore-walk/3.0.4:
+ resolution: {integrity: sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==}
+ dependencies:
+ minimatch: 3.0.4
+ dev: true
+ optional: true
+
/ignore/3.3.10:
resolution: {integrity: sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==}
dev: true
@@ -7288,6 +7456,16 @@ packages:
engines: {node: '>=4'}
dev: true
+ /import-local/3.1.0:
+ resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==}
+ engines: {node: '>=8'}
+ hasBin: true
+ dependencies:
+ pkg-dir: 4.2.0
+ resolve-cwd: 3.0.0
+ dev: true
+ optional: true
+
/imurmurhash/0.1.4:
resolution: {integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o=}
engines: {node: '>=0.8.19'}
@@ -7332,6 +7510,21 @@ packages:
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
dev: true
+ /ini/2.0.0:
+ resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==}
+ engines: {node: '>=10'}
+ dev: true
+ optional: true
+
+ /inquirer-autosubmit-prompt/0.2.0:
+ resolution: {integrity: sha512-mzNrusCk5L6kSzlN0Ioddn8yzrhYNLli+Sn2ZxMuLechMYAzakiFCIULxsxlQb5YKzthLGfrFACcWoAvM7p04Q==}
+ dependencies:
+ chalk: 2.4.2
+ inquirer: 6.5.2
+ rxjs: 6.6.7
+ dev: true
+ optional: true
+
/inquirer/6.5.2:
resolution: {integrity: sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==}
engines: {node: '>=6.0.0'}
@@ -7646,6 +7839,15 @@ packages:
is-path-inside: 3.0.3
dev: true
+ /is-installed-globally/0.4.0:
+ resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ global-dirs: 3.0.0
+ is-path-inside: 3.0.3
+ dev: true
+ optional: true
+
/is-interactive/1.0.0:
resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==}
engines: {node: '>=8'}
@@ -7714,6 +7916,14 @@ packages:
engines: {node: '>=8'}
dev: true
+ /is-observable/1.1.0:
+ resolution: {integrity: sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==}
+ engines: {node: '>=4'}
+ dependencies:
+ symbol-observable: 1.2.0
+ dev: true
+ optional: true
+
/is-odd/0.1.2:
resolution: {integrity: sha1-vFc7XONx7yqtbm9JeZtyvvE5eKc=}
engines: {node: '>=0.10.0'}
@@ -7748,6 +7958,11 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
+ /is-promise/2.2.2:
+ resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==}
+ dev: true
+ optional: true
+
/is-proto-prop/2.0.0:
resolution: {integrity: sha512-jl3NbQ/fGLv5Jhan4uX+Ge9ohnemqyblWVVCpAvtTQzNFvV2xhJq+esnkIbYQ9F1nITXoLfDDQLp7LBw/zzncg==}
dependencies:
@@ -7768,6 +7983,14 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
+ /is-scoped/2.1.0:
+ resolution: {integrity: sha512-Cv4OpPTHAK9kHYzkzCrof3VJh7H/PrG2MBUMvvJebaaUMbqhm0YAtXnvh0I3Hnj2tMZWwrRROWLSgfJrKqWmlQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ scoped-regex: 2.1.0
+ dev: true
+ optional: true
+
/is-self-closing/1.0.1:
resolution: {integrity: sha512-E+60FomW7Blv5GXTlYee2KDrnG6srxF7Xt1SjrhWUGUEsTFIqY/nq2y3DaftCsgUMdh89V07IVfhY9KIJhLezg==}
engines: {node: '>=0.12.0'}
@@ -7825,6 +8048,12 @@ packages:
engines: {node: '>=10'}
dev: true
+ /is-url-superb/4.0.0:
+ resolution: {integrity: sha512-GI+WjezhPPcbM+tqE9LnmsY5qqjwHzTvjJ36wxYX5ujNXefSUJ/T17r5bqDV8yLhcgB59KTPNOc9O9cmHTPWsA==}
+ engines: {node: '>=10'}
+ dev: true
+ optional: true
+
/is-utf8/0.2.1:
resolution: {integrity: sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=}
dev: true
@@ -7906,6 +8135,12 @@ packages:
lodash.uniqby: 4.7.0
dev: true
+ /issue-regex/3.1.0:
+ resolution: {integrity: sha512-0RHjbtw9QXeSYnIEY5Yrp2QZrdtz21xBDV9C/GIlY2POmgoS6a7qjkYS5siRKXScnuAj5/SPv1C3YForNCHTJA==}
+ engines: {node: '>=10'}
+ dev: true
+ optional: true
+
/java-properties/1.0.2:
resolution: {integrity: sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==}
engines: {node: '>= 0.6.0'}
@@ -8306,6 +8541,70 @@ packages:
hasBin: true
dev: true
+ /listr-input/0.2.1:
+ resolution: {integrity: sha512-oa8iVG870qJq+OuuMK3DjGqFcwsK1SDu+kULp9kEq09TY231aideIZenr3lFOQdASpAr6asuyJBbX62/a3IIhg==}
+ engines: {node: '>=6'}
+ dependencies:
+ inquirer: 7.3.3
+ inquirer-autosubmit-prompt: 0.2.0
+ rxjs: 6.6.7
+ through: 2.3.8
+ dev: true
+ optional: true
+
+ /listr-silent-renderer/1.1.1:
+ resolution: {integrity: sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=}
+ engines: {node: '>=4'}
+ dev: true
+ optional: true
+
+ /listr-update-renderer/0.5.0_listr@0.14.3:
+ resolution: {integrity: sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==}
+ engines: {node: '>=6'}
+ peerDependencies:
+ listr: ^0.14.2
+ dependencies:
+ chalk: 1.1.3
+ cli-truncate: 0.2.1
+ elegant-spinner: 1.0.1
+ figures: 1.7.0
+ indent-string: 3.2.0
+ listr: 0.14.3
+ log-symbols: 1.0.2
+ log-update: 2.3.0
+ strip-ansi: 3.0.1
+ dev: true
+ optional: true
+
+ /listr-verbose-renderer/0.5.0:
+ resolution: {integrity: sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==}
+ engines: {node: '>=4'}
+ dependencies:
+ chalk: 2.4.2
+ cli-cursor: 2.1.0
+ date-fns: 1.30.1
+ figures: 2.0.0
+ dev: true
+ optional: true
+
+ /listr/0.14.3:
+ resolution: {integrity: sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==}
+ engines: {node: '>=6'}
+ dependencies:
+ '@samverschueren/stream-to-observable': 0.3.1_rxjs@6.6.7
+ is-observable: 1.1.0
+ is-promise: 2.2.2
+ is-stream: 1.1.0
+ listr-silent-renderer: 1.1.1
+ listr-update-renderer: 0.5.0_listr@0.14.3
+ listr-verbose-renderer: 0.5.0
+ p-map: 2.1.0
+ rxjs: 6.6.7
+ transitivePeerDependencies:
+ - zen-observable
+ dev: true
+ optional: true
+
/listr2/3.13.5_enquirer@2.3.6:
resolution: {integrity: sha512-3n8heFQDSk+NcwBn3CgxEibZGaRzx+pC64n3YjpMD1qguV4nWus3Al+Oo3KooqFKTQEJ1v7MmnbnyyNspgx3NA==}
engines: {node: '>=10.0.0'}
@@ -8402,6 +8701,11 @@ packages:
resolution: {integrity: sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=}
dev: true
+ /lodash.isequal/4.5.0:
+ resolution: {integrity: sha1-QVxEePK8wwEgwizhDtMib30+GOA=}
+ dev: true
+ optional: true
+
/lodash.isinteger/4.0.4:
resolution: {integrity: sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=}
dev: true
@@ -8503,6 +8807,14 @@ packages:
success-symbol: 0.1.0
dev: true
+ /log-symbols/1.0.2:
+ resolution: {integrity: sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ chalk: 1.1.3
+ dev: true
+ optional: true
+
/log-symbols/4.1.0:
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
engines: {node: '>=10'}
@@ -8511,6 +8823,16 @@ packages:
is-unicode-supported: 0.1.0
dev: true
+ /log-update/2.3.0:
+ resolution: {integrity: sha1-iDKP19HOeTiykoN0bwsbwSayRwg=}
+ engines: {node: '>=4'}
+ dependencies:
+ ansi-escapes: 3.2.0
+ cli-cursor: 2.1.0
+ wrap-ansi: 3.0.1
+ dev: true
+ optional: true
+
/log-update/4.0.0:
resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==}
engines: {node: '>=10'}
@@ -8834,6 +9156,12 @@ packages:
engines: {node: '>=6'}
dev: true
+ /mimic-fn/3.1.0:
+ resolution: {integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==}
+ engines: {node: '>=8'}
+ dev: true
+ optional: true
+
/mimic-response/1.0.1:
resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==}
engines: {node: '>=4'}
@@ -9035,6 +9363,14 @@ packages:
resolution: {integrity: sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==}
dev: true
+ /new-github-release-url/1.0.0:
+ resolution: {integrity: sha512-dle7yf655IMjyFUqn6Nxkb18r4AOAkzRcgcZv6WZ0IqrOH4QCEZ8Sm6I7XX21zvHdBeeMeTkhR9qT2Z0EJDx6A==}
+ engines: {node: '>=10'}
+ dependencies:
+ type-fest: 0.4.1
+ dev: true
+ optional: true
+
/next-tick/1.1.0:
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
dev: true
@@ -9138,6 +9474,72 @@ packages:
engines: {node: '>=10'}
dev: true
+ /np/7.6.0:
+ resolution: {integrity: sha512-WWGZtfNkE6MEkI7LE8NtG7poTqzTHj/tssBzcPnBAdMVPXkXDtX2wk0ptrj8YZ3u4TFmGSqioSohdud86aJxSg==}
+ engines: {git: '>=2.11.0', node: '>=10', npm: '>=6.8.0', yarn: '>=1.7.0'}
+ hasBin: true
+ requiresBuild: true
+ dependencies:
+ '@samverschueren/stream-to-observable': 0.3.1_rxjs@6.6.7
+ any-observable: 0.5.1_rxjs@6.6.7
+ async-exit-hook: 2.0.1
+ chalk: 4.1.2
+ cosmiconfig: 7.0.1
+ del: 6.0.0
+ escape-goat: 3.0.0
+ escape-string-regexp: 4.0.0
+ execa: 5.1.1
+ github-url-from-git: 1.5.0
+ has-yarn: 2.1.0
+ hosted-git-info: 3.0.8
+ ignore-walk: 3.0.4
+ import-local: 3.1.0
+ inquirer: 7.3.3
+ is-installed-globally: 0.3.2
+ is-interactive: 1.0.0
+ is-scoped: 2.1.0
+ issue-regex: 3.1.0
+ listr: 0.14.3
+ listr-input: 0.2.1
+ log-symbols: 4.1.0
+ meow: 8.1.2
+ minimatch: 3.0.4
+ new-github-release-url: 1.0.0
+ npm-name: 6.0.1
+ onetime: 5.1.2
+ open: 7.4.2
+ ow: 0.21.0
+ p-memoize: 4.0.4
+ p-timeout: 4.1.0
+ pkg-dir: 5.0.0
+ read-pkg-up: 7.0.1
+ rxjs: 6.6.7
+ semver: 7.3.5
+ split: 1.0.1
+ symbol-observable: 3.0.0
+ terminal-link: 2.1.1
+ update-notifier: 5.1.0
+ transitivePeerDependencies:
+ - zen-observable
+ dev: true
+ optional: true
+
+ /npm-name/6.0.1:
+ resolution: {integrity: sha512-fhKRvUAxaYzMEUZim4mXWyfFbVS+M1CbrCLdAo3txWzrctxKka/h+KaBW0O9Cz5uOM00Nldn2JLWhuwnyW3SUw==}
+ engines: {node: '>=10'}
+ dependencies:
+ got: 10.7.0
+ is-scoped: 2.1.0
+ is-url-superb: 4.0.0
+ lodash.zip: 4.2.0
+ org-regex: 1.0.0
+ p-map: 3.0.0
+ registry-auth-token: 4.2.1
+ registry-url: 5.1.0
+ validate-npm-package-name: 3.0.0
+ dev: true
+ optional: true
+
/npm-run-path/2.0.2:
resolution: {integrity: sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=}
engines: {node: '>=4'}
@@ -9523,6 +9925,15 @@ packages:
is-wsl: 2.2.0
dev: true
+ /open/7.4.2:
+ resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==}
+ engines: {node: '>=8'}
+ dependencies:
+ is-docker: 2.2.1
+ is-wsl: 2.2.0
+ dev: true
+ optional: true
+
/open/8.4.0:
resolution: {integrity: sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==}
engines: {node: '>=12'}
@@ -9569,6 +9980,12 @@ packages:
wcwidth: 1.0.1
dev: true
+ /org-regex/1.0.0:
+ resolution: {integrity: sha512-7bqkxkEJwzJQUAlyYniqEZ3Ilzjh0yoa62c7gL6Ijxj5bEpPL+8IE1Z0PFj0ywjjXQcdrwR51g9MIcLezR0hKQ==}
+ engines: {node: '>=8'}
+ dev: true
+ optional: true
+
/os-homedir/1.0.2:
resolution: {integrity: sha1-/7xJiDNuDoM94MFox+8VISGqf7M=}
engines: {node: '>=0.10.0'}
@@ -9608,6 +10025,19 @@ packages:
os-tmpdir: 1.0.2
dev: true
+ /ow/0.21.0:
+ resolution: {integrity: sha512-dlsoDe39g7mhdsdrC1R/YwjT7yjVqE3svWwOlMGvN690waBkgEZBmKBdkmKvSt5/wZ6E0Jn/nIesPqMZOpPKqw==}
+ engines: {node: '>=10'}
+ dependencies:
+ '@sindresorhus/is': 4.3.0
+ callsites: 3.1.0
+ dot-prop: 6.0.1
+ lodash.isequal: 4.5.0
+ type-fest: 0.20.2
+ vali-date: 1.0.0
+ dev: true
+ optional: true
+
/p-cancelable/1.1.0:
resolution: {integrity: sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==}
engines: {node: '>=6'}
@@ -9628,6 +10058,14 @@ packages:
engines: {node: '>=8'}
dev: true
+ /p-event/4.2.0:
+ resolution: {integrity: sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ p-timeout: 3.2.0
+ dev: true
+ optional: true
+
/p-filter/2.1.0:
resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==}
engines: {node: '>=8'}
@@ -9702,6 +10140,14 @@ packages:
engines: {node: '>=6'}
dev: true
+ /p-map/3.0.0:
+ resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ aggregate-error: 3.1.0
+ dev: true
+ optional: true
+
/p-map/4.0.0:
resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
engines: {node: '>=10'}
@@ -9709,11 +10155,27 @@ packages:
aggregate-error: 3.1.0
dev: true
+ /p-memoize/4.0.4:
+ resolution: {integrity: sha512-ijdh0DP4Mk6J4FXlOM6vPPoCjPytcEseW8p/k5SDTSSfGV3E9bpt9Yzfifvzp6iohIieoLTkXRb32OWV0fB2Lw==}
+ engines: {node: '>=10'}
+ dependencies:
+ map-age-cleaner: 0.1.3
+ mimic-fn: 3.1.0
+ p-settle: 4.1.1
+ dev: true
+ optional: true
+
/p-reduce/2.1.0:
resolution: {integrity: sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==}
engines: {node: '>=8'}
dev: true
+ /p-reflect/2.1.0:
+ resolution: {integrity: sha512-paHV8NUz8zDHu5lhr/ngGWQiW067DK/+IbJ+RfZ4k+s8y4EKyYCz8pGYWjxCg35eHztpJAt+NUgvN4L+GCbPlg==}
+ engines: {node: '>=8'}
+ dev: true
+ optional: true
+
/p-retry/4.6.1:
resolution: {integrity: sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==}
engines: {node: '>=8'}
@@ -9722,6 +10184,29 @@ packages:
retry: 0.13.1
dev: true
+ /p-settle/4.1.1:
+ resolution: {integrity: sha512-6THGh13mt3gypcNMm0ADqVNCcYa3BK6DWsuJWFCuEKP1rpY+OKGp7gaZwVmLspmic01+fsg/fN57MfvDzZ/PuQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-limit: 2.3.0
+ p-reflect: 2.1.0
+ dev: true
+ optional: true
+
+ /p-timeout/3.2.0:
+ resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==}
+ engines: {node: '>=8'}
+ dependencies:
+ p-finally: 1.0.0
+ dev: true
+ optional: true
+
+ /p-timeout/4.1.0:
+ resolution: {integrity: sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==}
+ engines: {node: '>=10'}
+ dev: true
+ optional: true
+
/p-try/1.0.0:
resolution: {integrity: sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=}
engines: {node: '>=4'}
@@ -9965,6 +10450,22 @@ packages:
load-json-file: 4.0.0
dev: true
+ /pkg-dir/4.2.0:
+ resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ find-up: 4.1.0
+ dev: true
+ optional: true
+
+ /pkg-dir/5.0.0:
+ resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==}
+ engines: {node: '>=10'}
+ dependencies:
+ find-up: 5.0.0
+ dev: true
+ optional: true
+
/plur/4.0.0:
resolution: {integrity: sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==}
engines: {node: '>=10'}
@@ -10595,6 +11096,14 @@ packages:
resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
dev: true
+ /resolve-cwd/3.0.0:
+ resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==}
+ engines: {node: '>=8'}
+ dependencies:
+ resolve-from: 5.0.0
+ dev: true
+ optional: true
+
/resolve-dir/1.0.1:
resolution: {integrity: sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=}
engines: {node: '>=0.10.0'}
@@ -10641,6 +11150,15 @@ packages:
supports-preserve-symlinks-flag: 1.0.0
dev: true
+ /resolve/1.22.0:
+ resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.8.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+ dev: true
+
/resolve/1.7.1:
resolution: {integrity: sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==}
dependencies:
@@ -10714,7 +11232,7 @@ packages:
resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==}
hasBin: true
dependencies:
- glob: 7.2.0
+ glob: 7.1.6
dev: true
/rimraf/3.0.2:
@@ -10739,7 +11257,7 @@ packages:
resolution: {integrity: sha512-omv1DIv5z1kV+zDAEjaDjWSkx8w5TbFp5NZoPwUipwzYVcor/4So9ZU3bUyQ1c8lxY5Q0Es/ztWW7PGjY7to0Q==}
hasBin: true
dependencies:
- '@babel/parser': 7.16.10
+ '@babel/parser': 7.16.12
'@babel/traverse': 7.16.10
'@babel/types': 7.16.8
bent: 7.3.12
@@ -10797,6 +11315,12 @@ packages:
resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==}
dev: true
+ /scoped-regex/2.1.0:
+ resolution: {integrity: sha512-g3WxHrqSWCZHGHlSrF51VXFdjImhwvH8ZO/pryFH56Qi0cDsZfylQa/t0jCzVQFNbNvM00HfHjkDPEuarKDSWQ==}
+ engines: {node: '>=8'}
+ dev: true
+ optional: true
+
/scslre/0.1.6:
resolution: {integrity: sha512-JORxVRlQTfjvlOAaiQKebgFElyAm5/W8b50lgaZ0OkEnKnagJW2ufDh3xRfU75UD9z3FGIu1gL1IyR3Poa6Qmw==}
dependencies:
@@ -11072,6 +11596,12 @@ packages:
string-break: 1.2.0
dev: true
+ /slice-ansi/0.0.4:
+ resolution: {integrity: sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=}
+ engines: {node: '>=0.10.0'}
+ dev: true
+ optional: true
+
/slice-ansi/2.1.0:
resolution: {integrity: sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==}
engines: {node: '>=6'}
@@ -11562,6 +12092,18 @@ packages:
engines: {node: '>= 0.4'}
dev: true
+ /symbol-observable/1.2.0:
+ resolution: {integrity: sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+ optional: true
+
+ /symbol-observable/3.0.0:
+ resolution: {integrity: sha512-6tDOXSHiVjuCaasQSWTmHUWn4PuG7qa3+1WT031yTc/swT7+rLiw3GOrFxaH1E3lLP09dH3bVuVDf2gK5rxG3Q==}
+ engines: {node: '>=0.10'}
+ dev: true
+ optional: true
+
/table-layout/1.0.2:
resolution: {integrity: sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==}
engines: {node: '>=8.0.0'}
@@ -11734,6 +12276,12 @@ packages:
engines: {node: '>=6'}
dev: true
+ /to-readable-stream/2.1.0:
+ resolution: {integrity: sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w==}
+ engines: {node: '>=8'}
+ dev: true
+ optional: true
+
/to-regex-range/2.1.1:
resolution: {integrity: sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=}
engines: {node: '>=0.10.0'}
@@ -11923,7 +12471,7 @@ packages:
js-yaml: 3.14.1
minimatch: 3.0.4
mkdirp: 0.5.5
- resolve: 1.21.0
+ resolve: 1.22.0
semver: 5.7.1
tslib: 1.14.1
tsutils: 2.29.0
@@ -12004,6 +12552,12 @@ packages:
engines: {node: '>=4'}
dev: true
+ /type-fest/0.10.0:
+ resolution: {integrity: sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw==}
+ engines: {node: '>=8'}
+ dev: true
+ optional: true
+
/type-fest/0.16.0:
resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==}
engines: {node: '>=10'}
@@ -12029,6 +12583,12 @@ packages:
engines: {node: '>=6'}
dev: true
+ /type-fest/0.4.1:
+ resolution: {integrity: sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==}
+ engines: {node: '>=6'}
+ dev: true
+ optional: true
+
/type-fest/0.6.0:
resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==}
engines: {node: '>=8'}
@@ -12207,6 +12767,27 @@ packages:
xdg-basedir: 4.0.0
dev: true
+ /update-notifier/5.1.0:
+ resolution: {integrity: sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==}
+ engines: {node: '>=10'}
+ dependencies:
+ boxen: 5.1.2
+ chalk: 4.1.2
+ configstore: 5.0.1
+ has-yarn: 2.1.0
+ import-lazy: 2.1.0
+ is-ci: 2.0.0
+ is-installed-globally: 0.4.0
+ is-npm: 5.0.0
+ is-yarn-global: 0.3.0
+ latest-version: 5.1.0
+ pupa: 2.1.1
+ semver: 7.3.5
+ semver-diff: 3.1.1
+ xdg-basedir: 4.0.0
+ dev: true
+ optional: true
+
/uri-js/4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
dependencies:
@@ -12264,6 +12845,12 @@ packages:
resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==}
dev: true
+ /vali-date/1.0.0:
+ resolution: {integrity: sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=}
+ engines: {node: '>=0.10.0'}
+ dev: true
+ optional: true
+
/validate-npm-package-license/3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
dependencies:
@@ -12271,6 +12858,13 @@ packages:
spdx-expression-parse: 3.0.1
dev: true
+ /validate-npm-package-name/3.0.0:
+ resolution: {integrity: sha1-X6kS2B630MdK/BQN5zF/DKffQ34=}
+ dependencies:
+ builtins: 1.0.3
+ dev: true
+ optional: true
+
/verror/1.10.0:
resolution: {integrity: sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=}
engines: {'0': node >=0.6.0}
@@ -12469,7 +13063,7 @@ packages:
/wide-align/1.1.5:
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
dependencies:
- string-width: 4.2.3
+ string-width: 1.0.2
dev: true
/widest-line/3.1.0:
@@ -12507,6 +13101,15 @@ packages:
typical: 5.2.0
dev: true
+ /wrap-ansi/3.0.1:
+ resolution: {integrity: sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=}
+ engines: {node: '>=4'}
+ dependencies:
+ string-width: 2.1.1
+ strip-ansi: 4.0.0
+ dev: true
+ optional: true
+
/wrap-ansi/6.2.0:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
engines: {node: '>=8'}
diff --git a/poetry.lock b/poetry.lock
index a689f289..a27014b9 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -24,7 +24,7 @@ setupext = "*"
[[package]]
name = "ansible-compat"
-version = "0.5.0"
+version = "1.0.0"
description = "Ansible compatibility goodies"
category = "dev"
optional = false
@@ -32,6 +32,7 @@ python-versions = ">=3.6"
[package.dependencies]
PyYAML = "*"
+subprocess-tee = ">=0.3.5"
[package.extras]
test = ["coverage", "flaky", "pip-tools", "pytest", "pytest-markdown", "pytest-mock", "pytest-plus"]
@@ -67,13 +68,14 @@ rich = "*"
[[package]]
name = "ansibler"
-version = "0.1.169"
+version = "0.2.3"
description = "Generate JSON data that describes the dependencies of an Ansible playbook/role. Also, automatically generate OS compatibility charts using Molecule."
category = "dev"
optional = false
python-versions = "*"
[package.dependencies]
+requests = "*"
"ruamel.yaml" = "*"
[[package]]
@@ -164,11 +166,11 @@ test = ["tox", "pytest", "pytest-mock"]
[[package]]
name = "cachetools"
-version = "4.2.4"
+version = "5.0.0"
description = "Extensible memoizing collections and decorators"
category = "dev"
optional = false
-python-versions = "~=3.5"
+python-versions = "~=3.7"
[[package]]
name = "cerberus"
@@ -207,7 +209,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "charset-normalizer"
-version = "2.0.9"
+version = "2.0.10"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "main"
optional = false
@@ -324,7 +326,7 @@ tls = ["pyOpenSSL (>=17.5.0)", "cryptography (>=3.4.7)", "idna (>=2.0.0)"]
[[package]]
name = "enrich"
-version = "1.2.6"
+version = "1.2.7"
description = "enrich"
category = "dev"
optional = false
@@ -411,7 +413,7 @@ grpc = ["grpcio (>=1.0rc1)", "google-gax (>=0.12.3,<0.13dev)", "gax-google-pubsu
[[package]]
name = "google-api-core"
-version = "2.3.2"
+version = "2.4.0"
description = "Google API client core library"
category = "dev"
optional = false
@@ -430,7 +432,7 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2)"]
[[package]]
name = "google-api-python-client"
-version = "2.33.0"
+version = "2.36.0"
description = "Google API Client Library for Python"
category = "dev"
optional = false
@@ -441,18 +443,18 @@ google-api-core = ">=1.21.0,<3.0.0dev"
google-auth = ">=1.16.0,<3.0.0dev"
google-auth-httplib2 = ">=0.1.0"
httplib2 = ">=0.15.0,<1dev"
-uritemplate = ">=3.0.0,<5"
+uritemplate = ">=3.0.1,<5"
[[package]]
name = "google-auth"
-version = "2.3.3"
+version = "2.4.0"
description = "Google Authentication Library"
category = "dev"
optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*"
[package.dependencies]
-cachetools = ">=2.0.0,<5.0"
+cachetools = ">=2.0.0,<6.0"
pyasn1-modules = ">=0.2.1"
rsa = {version = ">=3.1.4,<5", markers = "python_version >= \"3.6\""}
six = ">=1.9.0"
@@ -608,7 +610,7 @@ jinja2 = "*"
name = "junit-xml"
version = "1.9"
description = "Creates JUnit XML test result documents that can be read by tools such as Jenkins"
-category = "main"
+category = "dev"
optional = false
python-versions = "*"
@@ -780,7 +782,7 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
[[package]]
name = "paramiko"
-version = "2.8.1"
+version = "2.9.2"
description = "SSH2 protocol library"
category = "dev"
optional = false
@@ -807,11 +809,11 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
[[package]]
name = "platformdirs"
-version = "2.4.0"
+version = "2.4.1"
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
[package.extras]
docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
@@ -847,7 +849,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "pre-commit-hooks"
-version = "4.0.1"
+version = "4.1.0"
description = "Some out-of-the-box hooks for pre-commit."
category = "dev"
optional = false
@@ -926,7 +928,7 @@ python-versions = "*"
[[package]]
name = "pycryptodome"
-version = "3.12.0"
+version = "3.13.0"
description = "Cryptographic library for Python"
category = "dev"
optional = false
@@ -942,7 +944,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "pygments"
-version = "2.10.0"
+version = "2.11.2"
description = "Pygments is a syntax highlighting package written in Python."
category = "dev"
optional = false
@@ -950,15 +952,14 @@ python-versions = ">=3.5"
[[package]]
name = "pynacl"
-version = "1.4.0"
+version = "1.5.0"
description = "Python binding to the Networking and Cryptography (NaCl) library"
category = "dev"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=3.6"
[package.dependencies]
cffi = ">=1.4.1"
-six = "*"
[package.extras]
docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"]
@@ -966,7 +967,7 @@ tests = ["pytest (>=3.2.1,!=3.3.0)", "hypothesis (>=3.27.0)"]
[[package]]
name = "pyparsing"
-version = "3.0.6"
+version = "3.0.7"
description = "Python parsing module"
category = "main"
optional = false
@@ -1044,7 +1045,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
[[package]]
name = "requests"
-version = "2.26.0"
+version = "2.27.1"
description = "Python HTTP for Humans."
category = "main"
optional = false
@@ -1089,7 +1090,7 @@ test = ["commentjson", "packaging", "pytest"]
[[package]]
name = "rich"
-version = "10.16.1"
+version = "11.0.0"
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
category = "dev"
optional = false
@@ -1116,16 +1117,27 @@ pyasn1 = ">=0.1.3"
[[package]]
name = "ruamel.yaml"
-version = "0.17.17"
+version = "0.17.20"
description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order"
category = "dev"
optional = false
python-versions = ">=3"
+[package.dependencies]
+"ruamel.yaml.clib" = {version = ">=0.2.6", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""}
+
[package.extras]
docs = ["ryd"]
jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"]
+[[package]]
+name = "ruamel.yaml.clib"
+version = "0.2.6"
+description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml"
+category = "dev"
+optional = false
+python-versions = ">=3.5"
+
[[package]]
name = "selinux"
version = "0.2.1"
@@ -1206,7 +1218,7 @@ python-versions = ">=3.6"
[[package]]
name = "urllib3"
-version = "1.26.7"
+version = "1.26.8"
description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "main"
optional = false
@@ -1253,7 +1265,7 @@ pyyaml = "*"
[metadata]
lock-version = "1.1"
python-versions = ">=3.10.0,<4.0.0"
-content-hash = "9ddb036a6e5927f80fd9d41ea792dc468d2da099689e764a29f55ad1f6090ab6"
+content-hash = "6bd6d033da6a2a230c67e9a4434c29847310a2bd2d417ff256d3ac5be9a8f4a5"
[metadata.files]
ansible = [
@@ -1263,8 +1275,8 @@ ansible-autodoc-fork = [
{file = "ansible-autodoc-fork-0.5.6.tar.gz", hash = "sha256:5718ede0383731ea366280004863f140c6a0e33dbcd0e7f3eb14da49e7b1320c"},
]
ansible-compat = [
- {file = "ansible-compat-0.5.0.tar.gz", hash = "sha256:0730fbbb32710d19f4244a4cabad9c6b33b4b92ddf72aee353484e17543405f5"},
- {file = "ansible_compat-0.5.0-py3-none-any.whl", hash = "sha256:3a696842689e108a827d3b60a1c32d53a546c94fe4fb244166259cbc25268c28"},
+ {file = "ansible-compat-1.0.0.tar.gz", hash = "sha256:2ade2acbd1d7868eeb602c682afe92bc8c05480333205c328b4c2a1b09f970a4"},
+ {file = "ansible_compat-1.0.0-py3-none-any.whl", hash = "sha256:8b9c9678e82c328df9574cd7eb3777e7f25cf1530bc48e612597213bc6e4bd0d"},
]
ansible-core = [
{file = "ansible-core-2.11.7.tar.gz", hash = "sha256:b87188beacfac1bb6dc5cf65663f3c52e66e0f9990742db00a3dca71ebae2eee"},
@@ -1274,7 +1286,7 @@ ansible-lint = [
{file = "ansible_lint-4.3.7-py2.py3-none-any.whl", hash = "sha256:300e841f690b556a08d44902d6414283dc101079b27909e3a892f1cf1d10d7ff"},
]
ansibler = [
- {file = "ansibler-0.1.169.tar.gz", hash = "sha256:d056b730b1475c13c3114c11594863327dd06413a03b4509287ae057c85e9f92"},
+ {file = "ansibler-0.2.3.tar.gz", hash = "sha256:0481922ad8a2bb0131dd448e98831c5fc9e994bb4408d6f4df417bb5947e0b1d"},
]
apache-libcloud = [
{file = "apache-libcloud-3.4.1.tar.gz", hash = "sha256:88f18da0cf3fac0af723e743fb741d9d1be251881edab7a5a0d1629955b5011b"},
@@ -1306,8 +1318,8 @@ blocklint = [
{file = "blocklint-0.2.3.tar.gz", hash = "sha256:b6c154b126dd605f8b66d6af9aa9c138ebbf08d184a1ad76e3ea2cb57155c9c5"},
]
cachetools = [
- {file = "cachetools-4.2.4-py3-none-any.whl", hash = "sha256:92971d3cb7d2a97efff7c7bb1657f21a8f5fb309a37530537c71b1774189f2d1"},
- {file = "cachetools-4.2.4.tar.gz", hash = "sha256:89ea6f1b638d5a73a4f9226be57ac5e4f399d22770b92355f92dcb0f7f001693"},
+ {file = "cachetools-5.0.0-py3-none-any.whl", hash = "sha256:8fecd4203a38af17928be7b90689d8083603073622229ca7077b72d8e5a976e4"},
+ {file = "cachetools-5.0.0.tar.gz", hash = "sha256:486471dfa8799eb7ec503a8059e263db000cdda20075ce5e48903087f79d5fd6"},
]
cerberus = [
{file = "Cerberus-1.3.2.tar.gz", hash = "sha256:302e6694f206dd85cb63f13fd5025b31ab6d38c99c50c6d769f8fa0b0f299589"},
@@ -1373,8 +1385,8 @@ chardet = [
{file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"},
]
charset-normalizer = [
- {file = "charset-normalizer-2.0.9.tar.gz", hash = "sha256:b0b883e8e874edfdece9c28f314e3dd5badf067342e42fb162203335ae61aa2c"},
- {file = "charset_normalizer-2.0.9-py3-none-any.whl", hash = "sha256:1eecaa09422db5be9e29d7fc65664e6c33bd06f9ced7838578ba40d58bdf3721"},
+ {file = "charset-normalizer-2.0.10.tar.gz", hash = "sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd"},
+ {file = "charset_normalizer-2.0.10-py3-none-any.whl", hash = "sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455"},
]
click = [
{file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"},
@@ -1427,8 +1439,8 @@ docker = [
{file = "docker-5.0.3.tar.gz", hash = "sha256:d916a26b62970e7c2f554110ed6af04c7ccff8e9f81ad17d0d40c75637e227fb"},
]
enrich = [
- {file = "enrich-1.2.6-py3-none-any.whl", hash = "sha256:ed0b3ac33495cc95f1ccafaf6c7ec0a0fcabb20f7f7a90121f37eb83a85bf82b"},
- {file = "enrich-1.2.6.tar.gz", hash = "sha256:0e99ff57d87f7b5def0ca79917e88fb9351aa0d52e228ee38bff7cd858315fe4"},
+ {file = "enrich-1.2.7-py3-none-any.whl", hash = "sha256:f29b2c8c124b4dbd7c975ab5c3568f6c7a47938ea3b7d2106c8a3bd346545e4f"},
+ {file = "enrich-1.2.7.tar.gz", hash = "sha256:0a2ab0d2931dff8947012602d1234d2a3ee002d9a355b5d70be6bf5466008893"},
]
flake8 = [
{file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"},
@@ -1447,16 +1459,16 @@ gcloud = [
{file = "gcloud-0.18.3.tar.gz", hash = "sha256:0af2dec59fce20561752f86e42d981c6a255e306a6c5e5d1fa3d358a8857e4fb"},
]
google-api-core = [
- {file = "google-api-core-2.3.2.tar.gz", hash = "sha256:c8889f45cf58deca522888ae1d39b2a25e93e7d1b019ae8cee6456d5c726a40c"},
- {file = "google_api_core-2.3.2-py2.py3-none-any.whl", hash = "sha256:3c562d393aed7e3d2011fcd1f103b490c411dcf5644b6312ca11a166a6ea8faf"},
+ {file = "google-api-core-2.4.0.tar.gz", hash = "sha256:ba8787b7c61632cd0340f095e1c036bef9426b2594f10afb290ba311ae8cb2cb"},
+ {file = "google_api_core-2.4.0-py2.py3-none-any.whl", hash = "sha256:58e2c1171a3d51778bf4e428fbb4bf79cbd05007b4b44deaa80cf73c80eebc0f"},
]
google-api-python-client = [
- {file = "google-api-python-client-2.33.0.tar.gz", hash = "sha256:38e98611794632a12479fafbabe0b5027e8fcfc412e8375f1b23db0bc0209181"},
- {file = "google_api_python_client-2.33.0-py2.py3-none-any.whl", hash = "sha256:1322d026110bc62eb29a4a25a15895dac51486b30a29b5943bc456318677280b"},
+ {file = "google-api-python-client-2.36.0.tar.gz", hash = "sha256:533c69e8ddce6630a2ce5b98348f6a58a23df49cb92040a0086315df979404af"},
+ {file = "google_api_python_client-2.36.0-py2.py3-none-any.whl", hash = "sha256:9e8863dec46224d4375cf3834e27ffd4bce79858f0f00a6109a51e3e62b4f3c2"},
]
google-auth = [
- {file = "google-auth-2.3.3.tar.gz", hash = "sha256:d83570a664c10b97a1dc6f8df87e5fdfff012f48f62be131e449c20dfc32630e"},
- {file = "google_auth-2.3.3-py2.py3-none-any.whl", hash = "sha256:a348a50b027679cb7dae98043ac8dbcc1d7951f06d8387496071a1e05a2465c0"},
+ {file = "google-auth-2.4.0.tar.gz", hash = "sha256:ef6f4827f6a3f9c5ff884616e2ba779acb5d690486fb70ca5e3091ed85ad932a"},
+ {file = "google_auth-2.4.0-py2.py3-none-any.whl", hash = "sha256:d1fad279d9d97e7d6b4a09a53e851ab2ee6d36d5c19547354a3f47a8a6ae41b9"},
]
google-auth-httplib2 = [
{file = "google-auth-httplib2-0.1.0.tar.gz", hash = "sha256:a07c39fd632becacd3f07718dfd6021bf396978f03ad3ce4321d060015cc30ac"},
@@ -1655,16 +1667,16 @@ packaging = [
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
]
paramiko = [
- {file = "paramiko-2.8.1-py2.py3-none-any.whl", hash = "sha256:7b5910f5815a00405af55da7abcc8a9e0d9657f57fcdd9a89894fdbba1c6b8a8"},
- {file = "paramiko-2.8.1.tar.gz", hash = "sha256:85b1245054e5d7592b9088cc6d08da22445417912d3a3e48138675c7a8616438"},
+ {file = "paramiko-2.9.2-py2.py3-none-any.whl", hash = "sha256:04097dbd96871691cdb34c13db1883066b8a13a0df2afd4cb0a92221f51c2603"},
+ {file = "paramiko-2.9.2.tar.gz", hash = "sha256:944a9e5dbdd413ab6c7951ea46b0ab40713235a9c4c5ca81cfe45c6f14fa677b"},
]
pathspec = [
{file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
{file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
]
platformdirs = [
- {file = "platformdirs-2.4.0-py3-none-any.whl", hash = "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"},
- {file = "platformdirs-2.4.0.tar.gz", hash = "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2"},
+ {file = "platformdirs-2.4.1-py3-none-any.whl", hash = "sha256:1d7385c7db91728b83efd0ca99a5afb296cab9d0ed8313a45ed8ba17967ecfca"},
+ {file = "platformdirs-2.4.1.tar.gz", hash = "sha256:440633ddfebcc36264232365d7840a970e75e1018d15b4327d11f91909045fda"},
]
pluggy = [
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
@@ -1678,8 +1690,8 @@ poyo = [
{file = "poyo-0.5.0.tar.gz", hash = "sha256:e26956aa780c45f011ca9886f044590e2d8fd8b61db7b1c1cf4e0869f48ed4dd"},
]
pre-commit-hooks = [
- {file = "pre_commit_hooks-4.0.1-py2.py3-none-any.whl", hash = "sha256:6efe92c7613c311abc7dd06817fc016f222d9289fe24b261e64412b0af96c662"},
- {file = "pre_commit_hooks-4.0.1.tar.gz", hash = "sha256:99f1b9fc00a82e6588990b6b92edcdf4bec9c3d65c6272b8867be389055ce05e"},
+ {file = "pre_commit_hooks-4.1.0-py2.py3-none-any.whl", hash = "sha256:ba95316b79038e56ce998cdacb1ce922831ac0e41744c77bcc2b9677bf183206"},
+ {file = "pre_commit_hooks-4.1.0.tar.gz", hash = "sha256:b6361865d1877c5da5ac3a944aab19ce6bd749a534d2ede28e683d07194a57e1"},
]
proselint = [
{file = "proselint-0.12.0-py3-none-any.whl", hash = "sha256:3c111aa1df0f4917c35d8aedab4211960653123726cdc045037663c14d1a1d83"},
@@ -1747,68 +1759,60 @@ pycrypto = [
{file = "pycrypto-2.6.1.tar.gz", hash = "sha256:f2ce1e989b272cfcb677616763e0a2e7ec659effa67a88aa92b3a65528f60a3c"},
]
pycryptodome = [
- {file = "pycryptodome-3.12.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:90ad3381ccdc6a24cc2841e295706a168f32abefe64c679695712acac71fd5da"},
- {file = "pycryptodome-3.12.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e80f7469b0b3ea0f694230477d8501dc5a30a717e94fddd4821e6721f3053eae"},
- {file = "pycryptodome-3.12.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:b91404611767a7485837a6f1fd20cf9a5ae0ad362040a022cd65827ecb1b0d00"},
- {file = "pycryptodome-3.12.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:db66ccda65d5d20c17b00768e462a86f6f540f9aea8419a7f76cc7d9effd82cd"},
- {file = "pycryptodome-3.12.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:dc88355c4b261ed259268e65705b28b44d99570337694d593f06e3b1698eaaf3"},
- {file = "pycryptodome-3.12.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:6f8f5b7b53516da7511951910ab458e799173722c91fea54e2ba2f56d102e4aa"},
- {file = "pycryptodome-3.12.0-cp27-cp27m-win32.whl", hash = "sha256:93acad54a72d81253242eb0a15064be559ec9d989e5173286dc21cad19f01765"},
- {file = "pycryptodome-3.12.0-cp27-cp27m-win_amd64.whl", hash = "sha256:5a8c24d39d4a237dbfe181ea6593792bf9b5582c7fcfa7b8e0e12fda5eec07af"},
- {file = "pycryptodome-3.12.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:32d15da81959faea6cbed95df2bb44f7f796211c110cf90b5ad3b2aeeb97fc8e"},
- {file = "pycryptodome-3.12.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:aed7eb4b64c600fbc5e6d4238991ad1b4179a558401f203d1fcbd24883748982"},
- {file = "pycryptodome-3.12.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:341c6bbf932c406b4f3ee2372e8589b67ac0cf4e99e7dc081440f43a3cde9f0f"},
- {file = "pycryptodome-3.12.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:de0b711d673904dd6c65307ead36cb76622365a393569bf880895cba21195b7a"},
- {file = "pycryptodome-3.12.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:3558616f45d8584aee3eba27559bc6fd0ba9be6c076610ed3cc62bd5229ffdc3"},
- {file = "pycryptodome-3.12.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:a78e4324e566b5fbc2b51e9240950d82fa9e1c7eb77acdf27f58712f65622c1d"},
- {file = "pycryptodome-3.12.0-cp35-abi3-manylinux1_i686.whl", hash = "sha256:3f2f3dd596c6128d91314e60a6bcf4344610ef0e97f4ae4dd1770f86dd0748d8"},
- {file = "pycryptodome-3.12.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:e05f994f30f1cda3cbe57441f41220d16731cf99d868bb02a8f6484c454c206b"},
- {file = "pycryptodome-3.12.0-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:4cded12e13785bbdf4ba1ff5fb9d261cd98162145f869e4fbc4a4b9083392f0b"},
- {file = "pycryptodome-3.12.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:1181c90d1a6aee68a84826825548d0db1b58d8541101f908d779d601d1690586"},
- {file = "pycryptodome-3.12.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:6bb0d340c93bcb674ea8899e2f6408ec64c6c21731a59481332b4b2a8143cc60"},
- {file = "pycryptodome-3.12.0-cp35-abi3-win32.whl", hash = "sha256:39da5807aa1ff820799c928f745f89432908bf6624b9e981d2d7f9e55d91b860"},
- {file = "pycryptodome-3.12.0-cp35-abi3-win_amd64.whl", hash = "sha256:212c7f7fe11cad9275fbcff50ca977f1c6643f13560d081e7b0f70596df447b8"},
- {file = "pycryptodome-3.12.0-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:b07a4238465eb8c65dd5df2ab8ba6df127e412293c0ed7656c003336f557a100"},
- {file = "pycryptodome-3.12.0-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:a6e1bcd9d5855f1a3c0f8d585f44c81b08f39a02754007f374fb8db9605ba29c"},
- {file = "pycryptodome-3.12.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:aceb1d217c3a025fb963849071446cf3aca1353282fe1c3cb7bd7339a4d47947"},
- {file = "pycryptodome-3.12.0-pp27-pypy_73-win32.whl", hash = "sha256:f699360ae285fcae9c8f53ca6acf33796025a82bb0ccd7c1c551b04c1726def3"},
- {file = "pycryptodome-3.12.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d845c587ceb82ac7cbac7d0bf8c62a1a0fe7190b028b322da5ca65f6e5a18b9e"},
- {file = "pycryptodome-3.12.0-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:d8083de50f6dec56c3c6f270fb193590999583a1b27c9c75bc0b5cac22d438cc"},
- {file = "pycryptodome-3.12.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:9ea2f6674c803602a7c0437fccdc2ea036707e60456974fe26ca263bd501ec45"},
- {file = "pycryptodome-3.12.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:5d4264039a2087977f50072aaff2346d1c1c101cb359f9444cf92e3d1f42b4cd"},
- {file = "pycryptodome-3.12.0.zip", hash = "sha256:12c7343aec5a3b3df5c47265281b12b611f26ec9367b6129199d67da54b768c1"},
+ {file = "pycryptodome-3.13.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:e468724173df02f9d83f3fea830bf0d04aa291b5add22b4a78e01c97aab04873"},
+ {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1fb7a6f222072412f320b9e48d3ce981920efbfce37b06d028ec9bd94093b37f"},
+ {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4f1b594d0cf35bd12ec4244df1155a7f565bf6e6245976ac36174c1564688c90"},
+ {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:9ea70f6c3f6566159e3798e4593a4a8016994a0080ac29a45200615b45091a1b"},
+ {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f7aad304575d075faf2806977b726b67da7ba294adc97d878f92a062e357a56a"},
+ {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:702446a012fd9337b9327d168bb0c7dc714eb93ad361f6f61af9ca8305a301f1"},
+ {file = "pycryptodome-3.13.0-cp27-cp27m-win32.whl", hash = "sha256:681ac47c538c64305d710eaed2bb49532f62b3f4c93aa7c423c520df981392e5"},
+ {file = "pycryptodome-3.13.0-cp27-cp27m-win_amd64.whl", hash = "sha256:7b3478a187d897f003b2aa1793bcc59463e8d57a42e2aafbcbbe9cd47ec46863"},
+ {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:eec02d9199af4b1ccfe1f9c587691a07a1fa39d949d2c1dc69d079ab9af8212f"},
+ {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:9c8e0e6c5e982699801b20fa74f43c19aa080d2b53a39f3c132d35958e153bd4"},
+ {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:f5457e44d3f26d9946091e92b28f3e970a56538b96c87b4b155a84e32a40b7b5"},
+ {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:88d6d54e83cf9bbd665ce1e7b9079983ee2d97a05f42e0569ff00a70f1dd8b1e"},
+ {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:72de8c4d71e6b11d54528bb924447fa4fdabcbb3d76cc0e7f61d3b6075def6b3"},
+ {file = "pycryptodome-3.13.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:008ef2c631f112cd5a58736e0b29f4a28b4bb853e68878689f8b476fd56e0691"},
+ {file = "pycryptodome-3.13.0-cp35-abi3-manylinux1_i686.whl", hash = "sha256:51ebe9624ad0a0b4da1aaaa2d43aabadf8537737fd494cee0ffa37cd6326de02"},
+ {file = "pycryptodome-3.13.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:deede160bdf87ddb71f0a1314ad5a267b1a960be314ea7dc6b7ad86da6da89a3"},
+ {file = "pycryptodome-3.13.0-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:857c16bffd938254e3a834cd6b2a755ed24e1a953b1a86e33da136d3e4c16a6f"},
+ {file = "pycryptodome-3.13.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:ca6db61335d07220de0b665bfee7b8e9615b2dfc67a54016db4826dac34c2dd2"},
+ {file = "pycryptodome-3.13.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:073dedf0f9c490ae22ca081b86357646ac9b76f3e2bd89119d137fc697a9e3b6"},
+ {file = "pycryptodome-3.13.0-cp35-abi3-win32.whl", hash = "sha256:e3affa03c49cce7b0a9501cc7f608d4f8e61fb2522b276d599ac049b5955576d"},
+ {file = "pycryptodome-3.13.0-cp35-abi3-win_amd64.whl", hash = "sha256:e5d72be02b17e6bd7919555811264403468d1d052fa67c946e402257c3c29a27"},
+ {file = "pycryptodome-3.13.0-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:0896d5d15ffe584d46cb9b69a75cf14a2bc8f6daf635b7bf16c1b041342a44b1"},
+ {file = "pycryptodome-3.13.0-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:e420cdfca73f80fe15f79bb34756959945231a052440813e5fce531e6e96331a"},
+ {file = "pycryptodome-3.13.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:720fafdf3e5c5de93039d8308f765cc60b8e9e7e852ad7135aa65dd89238191f"},
+ {file = "pycryptodome-3.13.0-pp27-pypy_73-win32.whl", hash = "sha256:7a8b0e526ff239b4f4c61dd6898e2474d609843ffc437267f3a27ddff626e6f6"},
+ {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d92a5eddffb0ad39f582f07c1de26e9daf6880e3e782a94bb7ebaf939567f8bf"},
+ {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:cb9453c981554984c6f5c5ce7682d7286e65e2173d7416114c3593a977a01bf5"},
+ {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:765b8b16bc1fd699e183dde642c7f2653b8f3c9c1a50051139908e9683f97732"},
+ {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:b3af53dddf848afb38b3ac2bae7159ddad1feb9bac14aa3acec6ef1797b82f8d"},
+ {file = "pycryptodome-3.13.0.tar.gz", hash = "sha256:95bacf9ff7d1b90bba537d3f5f6c834efe6bfbb1a0195cb3573f29e6716ef08d"},
]
pyflakes = [
{file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"},
{file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"},
]
pygments = [
- {file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"},
- {file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"},
+ {file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"},
+ {file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"},
]
pynacl = [
- {file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"},
- {file = "PyNaCl-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514"},
- {file = "PyNaCl-1.4.0-cp27-cp27m-win32.whl", hash = "sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574"},
- {file = "PyNaCl-1.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80"},
- {file = "PyNaCl-1.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7"},
- {file = "PyNaCl-1.4.0-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122"},
- {file = "PyNaCl-1.4.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d"},
- {file = "PyNaCl-1.4.0-cp35-abi3-win32.whl", hash = "sha256:4e10569f8cbed81cb7526ae137049759d2a8d57726d52c1a000a3ce366779634"},
- {file = "PyNaCl-1.4.0-cp35-abi3-win_amd64.whl", hash = "sha256:c914f78da4953b33d4685e3cdc7ce63401247a21425c16a39760e282075ac4a6"},
- {file = "PyNaCl-1.4.0-cp35-cp35m-win32.whl", hash = "sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4"},
- {file = "PyNaCl-1.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25"},
- {file = "PyNaCl-1.4.0-cp36-cp36m-win32.whl", hash = "sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4"},
- {file = "PyNaCl-1.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6"},
- {file = "PyNaCl-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f"},
- {file = "PyNaCl-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f"},
- {file = "PyNaCl-1.4.0-cp38-cp38-win32.whl", hash = "sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96"},
- {file = "PyNaCl-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420"},
- {file = "PyNaCl-1.4.0.tar.gz", hash = "sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505"},
+ {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"},
+ {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"},
+ {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"},
+ {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"},
+ {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"},
+ {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"},
+ {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"},
+ {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"},
+ {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"},
+ {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"},
]
pyparsing = [
- {file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"},
- {file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"},
+ {file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"},
+ {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"},
]
python-dateutil = [
{file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
@@ -1871,8 +1875,8 @@ pyyaml = [
{file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"},
]
requests = [
- {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"},
- {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"},
+ {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"},
+ {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"},
]
requests-ntlm = [
{file = "requests_ntlm-1.1.0-py2.py3-none-any.whl", hash = "sha256:1eb43d1026b64d431a8e0f1e8a8c8119ac698e72e9b95102018214411a8463ea"},
@@ -1883,16 +1887,43 @@ resolvelib = [
{file = "resolvelib-0.5.5.tar.gz", hash = "sha256:123de56548c90df85137425a3f51eb93df89e2ba719aeb6a8023c032758be950"},
]
rich = [
- {file = "rich-10.16.1-py3-none-any.whl", hash = "sha256:bbe04dd6ac09e4b00d22cb1051aa127beaf6e16c3d8687b026e96d3fca6aad52"},
- {file = "rich-10.16.1.tar.gz", hash = "sha256:4949e73de321784ef6664ebbc854ac82b20ff60b2865097b93f3b9b41e30da27"},
+ {file = "rich-11.0.0-py3-none-any.whl", hash = "sha256:d7a8086aa1fa7e817e3bba544eee4fd82047ef59036313147759c11475f0dafd"},
+ {file = "rich-11.0.0.tar.gz", hash = "sha256:c32a8340b21c75931f157466fefe81ae10b92c36a5ea34524dff3767238774a4"},
]
rsa = [
{file = "rsa-4.8-py3-none-any.whl", hash = "sha256:95c5d300c4e879ee69708c428ba566c59478fd653cc3a22243eeb8ed846950bb"},
{file = "rsa-4.8.tar.gz", hash = "sha256:5c6bd9dc7a543b7fe4304a631f8a8a3b674e2bbfc49c2ae96200cdbe55df6b17"},
]
"ruamel.yaml" = [
- {file = "ruamel.yaml-0.17.17-py3-none-any.whl", hash = "sha256:9af3ec5d7f8065582f3aa841305465025d0afd26c5fb54e15b964e11838fc74f"},
- {file = "ruamel.yaml-0.17.17.tar.gz", hash = "sha256:9751de4cbb57d4bfbf8fc394e125ed4a2f170fbff3dc3d78abf50be85924f8be"},
+ {file = "ruamel.yaml-0.17.20-py3-none-any.whl", hash = "sha256:810eef9c46523a3f77479c66267a4708255ebe806a2d540078408c2227f011af"},
+ {file = "ruamel.yaml-0.17.20.tar.gz", hash = "sha256:4b8a33c1efb2b443a93fcaafcfa4d2e445f8e8c29c528d9f5cdafb7cc9e4004c"},
+]
+"ruamel.yaml.clib" = [
+ {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6e7be2c5bcb297f5b82fee9c665eb2eb7001d1050deaba8471842979293a80b0"},
+ {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:221eca6f35076c6ae472a531afa1c223b9c29377e62936f61bc8e6e8bdc5f9e7"},
+ {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win32.whl", hash = "sha256:1070ba9dd7f9370d0513d649420c3b362ac2d687fe78c6e888f5b12bf8bc7bee"},
+ {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:77df077d32921ad46f34816a9a16e6356d8100374579bc35e15bab5d4e9377de"},
+ {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:cfdb9389d888c5b74af297e51ce357b800dd844898af9d4a547ffc143fa56751"},
+ {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7b2927e92feb51d830f531de4ccb11b320255ee95e791022555971c466af4527"},
+ {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win32.whl", hash = "sha256:ada3f400d9923a190ea8b59c8f60680c4ef8a4b0dfae134d2f2ff68429adfab5"},
+ {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win_amd64.whl", hash = "sha256:de9c6b8a1ba52919ae919f3ae96abb72b994dd0350226e28f3686cb4f142165c"},
+ {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d67f273097c368265a7b81e152e07fb90ed395df6e552b9fa858c6d2c9f42502"},
+ {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:72a2b8b2ff0a627496aad76f37a652bcef400fd861721744201ef1b45199ab78"},
+ {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win32.whl", hash = "sha256:9efef4aab5353387b07f6b22ace0867032b900d8e91674b5d8ea9150db5cae94"},
+ {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win_amd64.whl", hash = "sha256:846fc8336443106fe23f9b6d6b8c14a53d38cef9a375149d61f99d78782ea468"},
+ {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0847201b767447fc33b9c235780d3aa90357d20dd6108b92be544427bea197dd"},
+ {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:78988ed190206672da0f5d50c61afef8f67daa718d614377dcd5e3ed85ab4a99"},
+ {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win32.whl", hash = "sha256:a49e0161897901d1ac9c4a79984b8410f450565bbad64dbfcbf76152743a0cdb"},
+ {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win_amd64.whl", hash = "sha256:bf75d28fa071645c529b5474a550a44686821decebdd00e21127ef1fd566eabe"},
+ {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a32f8d81ea0c6173ab1b3da956869114cae53ba1e9f72374032e33ba3118c233"},
+ {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7f7ecb53ae6848f959db6ae93bdff1740e651809780822270eab111500842a84"},
+ {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win32.whl", hash = "sha256:89221ec6d6026f8ae859c09b9718799fea22c0e8da8b766b0b2c9a9ba2db326b"},
+ {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win_amd64.whl", hash = "sha256:31ea73e564a7b5fbbe8188ab8b334393e06d997914a4e184975348f204790277"},
+ {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dc6a613d6c74eef5a14a214d433d06291526145431c3b964f5e16529b1842bed"},
+ {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:1866cf2c284a03b9524a5cc00daca56d80057c5ce3cdc86a52020f4c720856f0"},
+ {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win32.whl", hash = "sha256:3fb9575a5acd13031c57a62cc7823e5d2ff8bc3835ba4d94b921b4e6ee664104"},
+ {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win_amd64.whl", hash = "sha256:825d5fccef6da42f3c8eccd4281af399f21c02b32d98e113dbc631ea6a6ecbc7"},
+ {file = "ruamel.yaml.clib-0.2.6.tar.gz", hash = "sha256:4ff604ce439abb20794f05613c374759ce10e3595d1867764dd1ae675b85acbd"},
]
selinux = [
{file = "selinux-0.2.1-py2.py3-none-any.whl", hash = "sha256:820adcf1b4451c9cc7759848797703263ba0eb6a4cad76d73548a9e0d57b7926"},
@@ -1930,8 +1961,8 @@ uritemplate = [
{file = "uritemplate-4.1.1.tar.gz", hash = "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0"},
]
urllib3 = [
- {file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"},
- {file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"},
+ {file = "urllib3-1.26.8-py2.py3-none-any.whl", hash = "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed"},
+ {file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"},
]
websocket-client = [
{file = "websocket-client-1.2.3.tar.gz", hash = "sha256:1315816c0acc508997eb3ae03b9d3ff619c9d12d544c9a9b553704b1cc4f6af5"},
diff --git a/pyproject.toml b/pyproject.toml
index 593a53d8..04675070 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -58,7 +58,7 @@ pywinrm = ">=0.3.0"
[tool.poetry.dev-dependencies]
ansible-lint = "<5.0.0"
-ansibler = "^0.1.14"
+ansibler = "^0.2.2"
apache-libcloud = "^3.4.1"
black = "^21.10b0"
blocklint = "^0.2.3"
diff --git a/start.sh b/start.sh
new file mode 100644
index 00000000..c380a48b
--- /dev/null
+++ b/start.sh
@@ -0,0 +1,334 @@
+#!/usr/bin/env bash
+
+# @file .config/scripts/start.sh
+# @brief Ensures Task is installed and up-to-date and then runs `task start`
+# @description
+# This script will ensure [Task](https://github.com/go-task/task) is up-to-date
+# and then run the `start` task which is generally a good entrypoint for any repository
+# that is using the Megabyte Labs templating/taskfile system. The `start` task will
+# ensure that the latest upstream changes are retrieved, that the project is
+# properly generated with them, and that all the development dependencies are installed.
+
+set -eo pipefail
+
+# @description Ensure .config/log is executable
+if [ -f .config/log ]; then
+ chmod +x .config/log
+fi
+
+# @description Installs package when user is root on Linux
+#
+# @example
+# ensureRootPackageInstalled "sudo"
+#
+# @arg $1 string The name of the package that must be present
+#
+# @exitcode 0 The package was successfully installed
+# @exitcode 1+ If there was an error, the package needs to be installed manually, or if the OS is unsupported
+function ensureRootPackageInstalled() {
+ if ! type "$1" &> /dev/null; then
+ if [[ "$OSTYPE" == 'linux'* ]]; then
+ if [ -f "/etc/redhat-release" ]; then
+ yum update
+ yum install -y "$1"
+ elif [ -f "/etc/lsb-release" ]; then
+ apt update
+ apt install -y "$1"
+ elif [ -f "/etc/arch-release" ]; then
+ pacman update
+ pacman -S "$1"
+ elif [ -f "/etc/alpine-release" ]; then
+ apk update
+ apk add -y "$1"
+ fi
+ fi
+ fi
+}
+
+# @description If the user is running this script as root, then create a new user named
+# megabyte and restart the script with that user. This is required because Homebrew
+# can only be invoked by non-root users.
+if [ "$EUID" -eq 0 ] && [ -z "$INIT_CWD" ] && type useradd &> /dev/null; then
+ # shellcheck disable=SC2016
+ echo 'INFO: Running as root - creating seperate user named `megabyte` to run script with'
+ echo "megabyte ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
+ useradd -m -s "$(which bash)" -c "Megabyte Labs Homebrew Account" megabyte
+ ensureRootPackageInstalled "sudo"
+ # shellcheck disable=SC2016
+ echo 'INFO: Reloading the script with the `megabyte` user'
+ exec su megabyte "$0" -- "$@"
+fi
+
+# @description Detect script paths
+BASH_SRC="$(dirname "${BASH_SOURCE[0]}")"
+SOURCE_PATH="$(
+ cd "$BASH_SRC"
+ pwd -P
+)"
+PROJECT_BASE_DIR="$SOURCE_PATH/../.."
+
+# @description Ensures ~/.local/bin is in the PATH variable on *nix machines and
+# exits with an error on unsupported OS types
+#
+# @example
+# ensureLocalPath
+#
+# @set PATH string The updated PATH with a reference to ~/.local/bin
+#
+# @noarg
+#
+# @exitcode 0 If the PATH was appropriately updated or did not need updating
+# @exitcode 1+ If the OS is unsupported
+function ensureLocalPath() {
+ if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux'* ]]; then
+ # shellcheck disable=SC2016
+ PATH_STRING='PATH="$HOME/.local/bin:$PATH"'
+ mkdir -p "$HOME/.local/bin"
+ if grep -L "$PATH_STRING" "$HOME/.profile" > /dev/null; then
+ echo -e "${PATH_STRING}\n" >> "$HOME/.profile"
+ echo "INFO: Updated the PATH variable to include ~/.local/bin in $HOME/.profile"
+ fi
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "FreeBSD support not added yet" && exit 1
+ else
+ echo "System type not recognized"
+ fi
+}
+
+# @description Ensures given package is installed on a system.
+#
+# @example
+# ensurePackageInstalled "curl"
+#
+# @arg $1 string The name of the package that must be present
+#
+# @exitcode 0 The package(s) were successfully installed
+# @exitcode 1+ If there was an error, the package needs to be installed manually, or if the OS is unsupported
+function ensurePackageInstalled() {
+ if ! type "$1" &> /dev/null; then
+ if [[ "$OSTYPE" == 'darwin'* ]]; then
+ brew install "$1"
+ elif [[ "$OSTYPE" == 'linux'* ]]; then
+ if [ -f "/etc/redhat-release" ]; then
+ sudo yum update
+ sudo yum install -y "$1"
+ elif [ -f "/etc/lsb-release" ]; then
+ sudo apt update
+ sudo apt install -y "$1"
+ elif [ -f "/etc/arch-release" ]; then
+ sudo pacman update
+ sudo pacman -S "$1"
+ elif [ -f "/etc/alpine-release" ]; then
+ apk update
+ apk add -y "$1"
+ else
+ echo "ERROR: $1 is missing. Please install $1 to continue." && exit 1
+ fi
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "ERROR: Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "ERROR: FreeBSD support not added yet" && exit 1
+ else
+ echo "ERROR: System type not recognized"
+ fi
+ fi
+}
+
+# @description Ensures the latest version of Task is installed to `/usr/local/bin` (or `~/.local/bin`, as
+# a fallback.
+#
+# @example
+# ensureTaskInstalled
+#
+# @noarg
+#
+# @exitcode 0 If the package is already present and up-to-date or if it was installed/updated
+# @exitcode 1+ If the OS is unsupported or if there was an error either installing the package or setting the PATH
+function ensureTaskInstalled() {
+ # @description Release API URL used to get the latest release's version
+ TASK_RELEASE_API="https://api.github.com/repos/go-task/task/releases/latest"
+ if ! type task &> /dev/null; then
+ if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl' ]]; then
+ installTask
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "ERROR: Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "ERROR: FreeBSD support not added yet" && exit 1
+ else
+ echo "ERROR: System type not recognized. You must install task manually." && exit 1
+ fi
+ else
+ echo "INFO: Checking for latest version of Task"
+ CURRENT_VERSION="$(task --version | cut -d' ' -f3 | cut -c 2-)"
+ LATEST_VERSION="$(curl -s "$TASK_RELEASE_API" | grep tag_name | cut -c 17- | sed 's/\",//')"
+ if printf '%s\n%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V -c &> /dev/null; then
+ echo "INFO: Task is already up-to-date"
+ else
+ echo "INFO: A new version of Task is available (version $LATEST_VERSION)"
+ echo "INFO: The current version of Task installed is $CURRENT_VERSION"
+ # Replace with rm "$(which task)" &> /dev/null when ready
+ if ! type task &> /dev/null; then
+ installTask
+ else
+ echo "WARNING: Unable to remove previous version of Task"
+ fi
+ fi
+ fi
+}
+
+# @description Helper function for ensureTaskInstalled that performs the installation of Task.
+#
+# @see ensureTaskInstalled
+#
+# @example
+# installTask
+#
+# @noarg
+#
+# @exitcode 0 If Task installs/updates properly
+# @exitcode 1+ If the installation fails
+function installTask() {
+ # @description Release URL to use when downloading [Task](https://github.com/go-task/task)
+ TASK_RELEASE_URL="https://github.com/go-task/task/releases/latest"
+ CHECKSUM_DESTINATION=/tmp/megabytelabs/task_checksums.txt
+ CHECKSUMS_URL="$TASK_RELEASE_URL/download/task_checksums.txt"
+ DOWNLOAD_DESTINATION=/tmp/megabytelabs/task.tar.gz
+ TMP_DIR=/tmp/megabytelabs
+ if [[ "$OSTYPE" == 'darwin'* ]]; then
+ DOWNLOAD_URL="$TASK_RELEASE_URL/download/task_darwin_amd64.tar.gz"
+ else
+ DOWNLOAD_URL="$TASK_RELEASE_URL/download/task_linux_amd64.tar.gz"
+ fi
+ mkdir -p "$(dirname "$DOWNLOAD_DESTINATION")"
+ echo "INFO: Downloading latest version of Task"
+ curl -sSL "$DOWNLOAD_URL" -o "$DOWNLOAD_DESTINATION"
+ curl -sSL "$CHECKSUMS_URL" -o "$CHECKSUM_DESTINATION"
+ DOWNLOAD_BASENAME="$(basename "$DOWNLOAD_URL")"
+ DOWNLOAD_SHA256="$(grep "$DOWNLOAD_BASENAME" < "$CHECKSUM_DESTINATION" | cut -d ' ' -f 1)"
+ sha256 "$DOWNLOAD_DESTINATION" "$DOWNLOAD_SHA256" > /dev/null
+ echo "SUCCESS: Validated checksum"
+ mkdir -p "$TMP_DIR/task"
+ tar -xzvf "$DOWNLOAD_DESTINATION" -C "$TMP_DIR/task" > /dev/null
+ if type task &> /dev/null && [ -w "$(which task)" ]; then
+ TARGET_DEST="$(which task)"
+ else
+ if [ -w /usr/local/bin ]; then
+ TARGET_BIN_DIR='/usr/local/bin'
+ else
+ TARGET_BIN_DIR="$HOME/.local/bin"
+ fi
+ TARGET_DEST="$TARGET_BIN_DIR/task"
+ mkdir -p "$TARGET_BIN_DIR"
+ fi
+ mv "$TMP_DIR/task/task" "$TARGET_DEST"
+ echo "SUCCESS: Installed Task to $TARGET_DEST"
+ rm "$CHECKSUM_DESTINATION"
+ rm "$DOWNLOAD_DESTINATION"
+}
+
+# @description Verifies the SHA256 checksum of a file
+#
+# @example
+# sha256 myfile.tar.gz 5b30f9c042553141791ec753d2f96786c60a4968fd809f75bb0e8db6c6b4529b
+#
+# @arg $1 string Path to the file
+# @arg $2 string The SHA256 signature
+#
+# @exitcode 0 The checksum is valid or the system is unrecognized
+# @exitcode 1+ The OS is unsupported or if the checksum is invalid
+function sha256() {
+ echo "$2"
+ echo "$1"
+ if [[ "$OSTYPE" == 'darwin'* ]]; then
+ if type brew &> /dev/null && ! type sha256sum &> /dev/null; then
+ brew install coreutils
+ else
+ echo "WARNING: Brew is not installed - this may cause issues"
+ fi
+ if type brew &> /dev/null; then
+ PATH="$(brew --prefix)/opt/coreutils/libexec/gnubin:$PATH"
+ fi
+ if type sha256sum &> /dev/null; then
+ echo "$2 $1" | sha256sum -c
+ else
+ echo "WARNING: Checksum validation is being skipped for $1 because the sha256sum program is not available"
+ fi
+ elif [[ "$OSTYPE" == 'linux-gnu'* ]]; then
+ if ! type shasum &> /dev/null; then
+ echo "WARNING: Checksum validation is being skipped for $1 because the shasum program is not installed"
+ else
+ echo "$2 $1" | shasum -s -a 256 -c
+ fi
+ elif [[ "$OSTYPE" == 'linux-musl' ]]; then
+ if ! type sha256sum &> /dev/null; then
+ echo "WARNING: Checksum validation is being skipped for $1 because the sha256sum program is not available"
+ else
+ echo "$2 $1" | sha256sum -c
+ fi
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "ERROR: Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "ERROR: FreeBSD support not added yet" && exit 1
+ else
+ echo "WARNING: System type not recognized. Skipping checksum validation."
+ fi
+}
+
+##### Main Logic #####
+
+if [ ! -f "$HOME/.profile" ]; then
+ touch "$HOME/.profile"
+fi
+
+# @description Ensures ~/.local/bin is in PATH
+ensureLocalPath
+
+# @description Ensures base dependencies are installed
+if [[ "$OSTYPE" == 'darwin'* ]]; then
+ if ! type curl &> /dev/null && type brew &> /dev/null; then
+ brew install curl
+ else
+ echo "ERROR: Neither curl nor brew are installed. Install one of them manually and try again."
+ fi
+ if ! type git &> /dev/null; then
+ # shellcheck disable=SC2016
+ echo 'INFO: Git is not present. A password may be required to run `sudo xcode-select --install`'
+ sudo xcode-select --install
+ fi
+elif [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl'* ]]; then
+ if ! type curl &> /dev/null || ! type git &> /dev/null; then
+ ensurePackageInstalled "curl"
+ ensurePackageInstalled "git"
+ fi
+fi
+
+# @description Ensures Homebrew and Poetry are installed
+if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl'* ]]; then
+ if ! type brew &> /dev/null && [ -z "$INIT_CWD" ]; then
+ echo "WARNING: Homebrew is not installed. The script will attempt to install Homebrew and you might be prompted for your password."
+ bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
+ fi
+fi
+
+# @description Attempts to pull the latest changes if the folder is a git repository
+cd "$PROJECT_BASE_DIR" || exit
+if [ -d .git ] && type git &> /dev/null; then
+ HTTPS_VERSION="$(git remote get-url origin | sed 's/git@gitlab.com:/https:\/\/gitlab.com\//')"
+ git pull "$HTTPS_VERSION" master --ff-only
+ git submodule update --init --recursive
+fi
+
+# @description Ensures Task is installed and properly configured
+ensureTaskInstalled
+
+# @description Run the start logic, if appropriate
+cd "$PROJECT_BASE_DIR" || exit
+if [ -z "$GITLAB_CI" ] && [ -z "$INIT_CWD" ]; then
+ # shellcheck disable=SC1091
+ . "$HOME/.profile"
+ task start
+ # shellcheck disable=SC2028
+ echo 'INFO: There may have been changes to your PATH variable. You may have to reload your terminal or run:\n\n`. '"$HOME/.profile"'`'
+fi
diff --git a/update-init.sh b/update-init.sh
new file mode 100644
index 00000000..c380a48b
--- /dev/null
+++ b/update-init.sh
@@ -0,0 +1,334 @@
+#!/usr/bin/env bash
+
+# @file .config/scripts/start.sh
+# @brief Ensures Task is installed and up-to-date and then runs `task start`
+# @description
+# This script will ensure [Task](https://github.com/go-task/task) is up-to-date
+# and then run the `start` task which is generally a good entrypoint for any repository
+# that is using the Megabyte Labs templating/taskfile system. The `start` task will
+# ensure that the latest upstream changes are retrieved, that the project is
+# properly generated with them, and that all the development dependencies are installed.
+
+set -eo pipefail
+
+# @description Ensure .config/log is executable
+if [ -f .config/log ]; then
+ chmod +x .config/log
+fi
+
+# @description Installs package when user is root on Linux
+#
+# @example
+# ensureRootPackageInstalled "sudo"
+#
+# @arg $1 string The name of the package that must be present
+#
+# @exitcode 0 The package was successfully installed
+# @exitcode 1+ If there was an error, the package needs to be installed manually, or if the OS is unsupported
+function ensureRootPackageInstalled() {
+ if ! type "$1" &> /dev/null; then
+ if [[ "$OSTYPE" == 'linux'* ]]; then
+ if [ -f "/etc/redhat-release" ]; then
+ yum update
+ yum install -y "$1"
+ elif [ -f "/etc/lsb-release" ]; then
+ apt update
+ apt install -y "$1"
+ elif [ -f "/etc/arch-release" ]; then
+ pacman update
+ pacman -S "$1"
+ elif [ -f "/etc/alpine-release" ]; then
+ apk update
+ apk add -y "$1"
+ fi
+ fi
+ fi
+}
+
+# @description If the user is running this script as root, then create a new user named
+# megabyte and restart the script with that user. This is required because Homebrew
+# can only be invoked by non-root users.
+if [ "$EUID" -eq 0 ] && [ -z "$INIT_CWD" ] && type useradd &> /dev/null; then
+ # shellcheck disable=SC2016
+ echo 'INFO: Running as root - creating seperate user named `megabyte` to run script with'
+ echo "megabyte ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
+ useradd -m -s "$(which bash)" -c "Megabyte Labs Homebrew Account" megabyte
+ ensureRootPackageInstalled "sudo"
+ # shellcheck disable=SC2016
+ echo 'INFO: Reloading the script with the `megabyte` user'
+ exec su megabyte "$0" -- "$@"
+fi
+
+# @description Detect script paths
+BASH_SRC="$(dirname "${BASH_SOURCE[0]}")"
+SOURCE_PATH="$(
+ cd "$BASH_SRC"
+ pwd -P
+)"
+PROJECT_BASE_DIR="$SOURCE_PATH/../.."
+
+# @description Ensures ~/.local/bin is in the PATH variable on *nix machines and
+# exits with an error on unsupported OS types
+#
+# @example
+# ensureLocalPath
+#
+# @set PATH string The updated PATH with a reference to ~/.local/bin
+#
+# @noarg
+#
+# @exitcode 0 If the PATH was appropriately updated or did not need updating
+# @exitcode 1+ If the OS is unsupported
+function ensureLocalPath() {
+ if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux'* ]]; then
+ # shellcheck disable=SC2016
+ PATH_STRING='PATH="$HOME/.local/bin:$PATH"'
+ mkdir -p "$HOME/.local/bin"
+ if grep -L "$PATH_STRING" "$HOME/.profile" > /dev/null; then
+ echo -e "${PATH_STRING}\n" >> "$HOME/.profile"
+ echo "INFO: Updated the PATH variable to include ~/.local/bin in $HOME/.profile"
+ fi
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "FreeBSD support not added yet" && exit 1
+ else
+ echo "System type not recognized"
+ fi
+}
+
+# @description Ensures given package is installed on a system.
+#
+# @example
+# ensurePackageInstalled "curl"
+#
+# @arg $1 string The name of the package that must be present
+#
+# @exitcode 0 The package(s) were successfully installed
+# @exitcode 1+ If there was an error, the package needs to be installed manually, or if the OS is unsupported
+function ensurePackageInstalled() {
+ if ! type "$1" &> /dev/null; then
+ if [[ "$OSTYPE" == 'darwin'* ]]; then
+ brew install "$1"
+ elif [[ "$OSTYPE" == 'linux'* ]]; then
+ if [ -f "/etc/redhat-release" ]; then
+ sudo yum update
+ sudo yum install -y "$1"
+ elif [ -f "/etc/lsb-release" ]; then
+ sudo apt update
+ sudo apt install -y "$1"
+ elif [ -f "/etc/arch-release" ]; then
+ sudo pacman update
+ sudo pacman -S "$1"
+ elif [ -f "/etc/alpine-release" ]; then
+ apk update
+ apk add -y "$1"
+ else
+ echo "ERROR: $1 is missing. Please install $1 to continue." && exit 1
+ fi
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "ERROR: Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "ERROR: FreeBSD support not added yet" && exit 1
+ else
+ echo "ERROR: System type not recognized"
+ fi
+ fi
+}
+
+# @description Ensures the latest version of Task is installed to `/usr/local/bin` (or `~/.local/bin`, as
+# a fallback.
+#
+# @example
+# ensureTaskInstalled
+#
+# @noarg
+#
+# @exitcode 0 If the package is already present and up-to-date or if it was installed/updated
+# @exitcode 1+ If the OS is unsupported or if there was an error either installing the package or setting the PATH
+function ensureTaskInstalled() {
+ # @description Release API URL used to get the latest release's version
+ TASK_RELEASE_API="https://api.github.com/repos/go-task/task/releases/latest"
+ if ! type task &> /dev/null; then
+ if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl' ]]; then
+ installTask
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "ERROR: Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "ERROR: FreeBSD support not added yet" && exit 1
+ else
+ echo "ERROR: System type not recognized. You must install task manually." && exit 1
+ fi
+ else
+ echo "INFO: Checking for latest version of Task"
+ CURRENT_VERSION="$(task --version | cut -d' ' -f3 | cut -c 2-)"
+ LATEST_VERSION="$(curl -s "$TASK_RELEASE_API" | grep tag_name | cut -c 17- | sed 's/\",//')"
+ if printf '%s\n%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V -c &> /dev/null; then
+ echo "INFO: Task is already up-to-date"
+ else
+ echo "INFO: A new version of Task is available (version $LATEST_VERSION)"
+ echo "INFO: The current version of Task installed is $CURRENT_VERSION"
+ # Replace with rm "$(which task)" &> /dev/null when ready
+ if ! type task &> /dev/null; then
+ installTask
+ else
+ echo "WARNING: Unable to remove previous version of Task"
+ fi
+ fi
+ fi
+}
+
+# @description Helper function for ensureTaskInstalled that performs the installation of Task.
+#
+# @see ensureTaskInstalled
+#
+# @example
+# installTask
+#
+# @noarg
+#
+# @exitcode 0 If Task installs/updates properly
+# @exitcode 1+ If the installation fails
+function installTask() {
+ # @description Release URL to use when downloading [Task](https://github.com/go-task/task)
+ TASK_RELEASE_URL="https://github.com/go-task/task/releases/latest"
+ CHECKSUM_DESTINATION=/tmp/megabytelabs/task_checksums.txt
+ CHECKSUMS_URL="$TASK_RELEASE_URL/download/task_checksums.txt"
+ DOWNLOAD_DESTINATION=/tmp/megabytelabs/task.tar.gz
+ TMP_DIR=/tmp/megabytelabs
+ if [[ "$OSTYPE" == 'darwin'* ]]; then
+ DOWNLOAD_URL="$TASK_RELEASE_URL/download/task_darwin_amd64.tar.gz"
+ else
+ DOWNLOAD_URL="$TASK_RELEASE_URL/download/task_linux_amd64.tar.gz"
+ fi
+ mkdir -p "$(dirname "$DOWNLOAD_DESTINATION")"
+ echo "INFO: Downloading latest version of Task"
+ curl -sSL "$DOWNLOAD_URL" -o "$DOWNLOAD_DESTINATION"
+ curl -sSL "$CHECKSUMS_URL" -o "$CHECKSUM_DESTINATION"
+ DOWNLOAD_BASENAME="$(basename "$DOWNLOAD_URL")"
+ DOWNLOAD_SHA256="$(grep "$DOWNLOAD_BASENAME" < "$CHECKSUM_DESTINATION" | cut -d ' ' -f 1)"
+ sha256 "$DOWNLOAD_DESTINATION" "$DOWNLOAD_SHA256" > /dev/null
+ echo "SUCCESS: Validated checksum"
+ mkdir -p "$TMP_DIR/task"
+ tar -xzvf "$DOWNLOAD_DESTINATION" -C "$TMP_DIR/task" > /dev/null
+ if type task &> /dev/null && [ -w "$(which task)" ]; then
+ TARGET_DEST="$(which task)"
+ else
+ if [ -w /usr/local/bin ]; then
+ TARGET_BIN_DIR='/usr/local/bin'
+ else
+ TARGET_BIN_DIR="$HOME/.local/bin"
+ fi
+ TARGET_DEST="$TARGET_BIN_DIR/task"
+ mkdir -p "$TARGET_BIN_DIR"
+ fi
+ mv "$TMP_DIR/task/task" "$TARGET_DEST"
+ echo "SUCCESS: Installed Task to $TARGET_DEST"
+ rm "$CHECKSUM_DESTINATION"
+ rm "$DOWNLOAD_DESTINATION"
+}
+
+# @description Verifies the SHA256 checksum of a file
+#
+# @example
+# sha256 myfile.tar.gz 5b30f9c042553141791ec753d2f96786c60a4968fd809f75bb0e8db6c6b4529b
+#
+# @arg $1 string Path to the file
+# @arg $2 string The SHA256 signature
+#
+# @exitcode 0 The checksum is valid or the system is unrecognized
+# @exitcode 1+ The OS is unsupported or if the checksum is invalid
+function sha256() {
+ echo "$2"
+ echo "$1"
+ if [[ "$OSTYPE" == 'darwin'* ]]; then
+ if type brew &> /dev/null && ! type sha256sum &> /dev/null; then
+ brew install coreutils
+ else
+ echo "WARNING: Brew is not installed - this may cause issues"
+ fi
+ if type brew &> /dev/null; then
+ PATH="$(brew --prefix)/opt/coreutils/libexec/gnubin:$PATH"
+ fi
+ if type sha256sum &> /dev/null; then
+ echo "$2 $1" | sha256sum -c
+ else
+ echo "WARNING: Checksum validation is being skipped for $1 because the sha256sum program is not available"
+ fi
+ elif [[ "$OSTYPE" == 'linux-gnu'* ]]; then
+ if ! type shasum &> /dev/null; then
+ echo "WARNING: Checksum validation is being skipped for $1 because the shasum program is not installed"
+ else
+ echo "$2 $1" | shasum -s -a 256 -c
+ fi
+ elif [[ "$OSTYPE" == 'linux-musl' ]]; then
+ if ! type sha256sum &> /dev/null; then
+ echo "WARNING: Checksum validation is being skipped for $1 because the sha256sum program is not available"
+ else
+ echo "$2 $1" | sha256sum -c
+ fi
+ elif [[ "$OSTYPE" == 'cygwin' ]] || [[ "$OSTYPE" == 'msys' ]] || [[ "$OSTYPE" == 'win32' ]]; then
+ echo "ERROR: Windows is not directly supported. Use WSL or Docker." && exit 1
+ elif [[ "$OSTYPE" == 'freebsd'* ]]; then
+ echo "ERROR: FreeBSD support not added yet" && exit 1
+ else
+ echo "WARNING: System type not recognized. Skipping checksum validation."
+ fi
+}
+
+##### Main Logic #####
+
+if [ ! -f "$HOME/.profile" ]; then
+ touch "$HOME/.profile"
+fi
+
+# @description Ensures ~/.local/bin is in PATH
+ensureLocalPath
+
+# @description Ensures base dependencies are installed
+if [[ "$OSTYPE" == 'darwin'* ]]; then
+ if ! type curl &> /dev/null && type brew &> /dev/null; then
+ brew install curl
+ else
+ echo "ERROR: Neither curl nor brew are installed. Install one of them manually and try again."
+ fi
+ if ! type git &> /dev/null; then
+ # shellcheck disable=SC2016
+ echo 'INFO: Git is not present. A password may be required to run `sudo xcode-select --install`'
+ sudo xcode-select --install
+ fi
+elif [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl'* ]]; then
+ if ! type curl &> /dev/null || ! type git &> /dev/null; then
+ ensurePackageInstalled "curl"
+ ensurePackageInstalled "git"
+ fi
+fi
+
+# @description Ensures Homebrew and Poetry are installed
+if [[ "$OSTYPE" == 'darwin'* ]] || [[ "$OSTYPE" == 'linux-gnu'* ]] || [[ "$OSTYPE" == 'linux-musl'* ]]; then
+ if ! type brew &> /dev/null && [ -z "$INIT_CWD" ]; then
+ echo "WARNING: Homebrew is not installed. The script will attempt to install Homebrew and you might be prompted for your password."
+ bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
+ fi
+fi
+
+# @description Attempts to pull the latest changes if the folder is a git repository
+cd "$PROJECT_BASE_DIR" || exit
+if [ -d .git ] && type git &> /dev/null; then
+ HTTPS_VERSION="$(git remote get-url origin | sed 's/git@gitlab.com:/https:\/\/gitlab.com\//')"
+ git pull "$HTTPS_VERSION" master --ff-only
+ git submodule update --init --recursive
+fi
+
+# @description Ensures Task is installed and properly configured
+ensureTaskInstalled
+
+# @description Run the start logic, if appropriate
+cd "$PROJECT_BASE_DIR" || exit
+if [ -z "$GITLAB_CI" ] && [ -z "$INIT_CWD" ]; then
+ # shellcheck disable=SC1091
+ . "$HOME/.profile"
+ task start
+ # shellcheck disable=SC2028
+ echo 'INFO: There may have been changes to your PATH variable. You may have to reload your terminal or run:\n\n`. '"$HOME/.profile"'`'
+fi