Skip to content

Commit

Permalink
refactor: update build.sh command-line arguments (#968)
Browse files Browse the repository at this point in the history
- Refactors the `build.sh` script to support operating system selection, distribution, version, and edition via command-line arguments.
- Updates the help menu to reflect the new options and parameters.
- Implements an `--auto-continue` option to skip manual prompts, enabling smoother automation.

Signed-off-by: ClemTheStudent <[email protected]>
  • Loading branch information
ClemCreator authored Oct 31, 2024
1 parent 6127cf1 commit fb37d5e
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 36 deletions.
173 changes: 144 additions & 29 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,21 @@ info() {
show_help() {
local exit_after=${1:-"exit"}
script_name=$(basename "$0")
printf "Usage: %s [options]\n\n" "$script_name"
printf "Options:\n"
printf " --help, -h, -H Display this help message.\n\n"
printf " --deps, -d, -D Check the dependencies.\n"
printf " --debug, -b, -B Enable debug mode.\n"
printf " --json, -j, -J Specify the JSON file path.\n"
printf " --show, -s, -S Display the build command used to build the image.\n"

printf "\033[0;32m Usage\033[0m: %s [options]\n\n" "$script_name"
printf "\033[0;34m Options:\033[0m\n"
printf " \033[0;34m --help, -h, -H\033[0m Display this help message.\n\n"
printf " \033[0;34m --deps, -d, -D\033[0m Check the dependencies.\n"
printf " \033[0;34m --debug, -b, -B\033[0m Enable debug mode.\n"
printf " \033[0;34m --json, -j, -J\033[0m Specify the JSON file path.\n"
printf " \033[0;34m --os\033[0m Specify the operating system (Linux, Windows).\n"
printf " \033[0;34m --dist\033[0m Specify the distribution (e.g., 'Ubuntu', 'Windows Server').\n"
printf " \033[0;34m --version\033[0m Specify the version of the distribution.\n"
printf " \033[0;34m --edition\033[0m Specify the edition (e.g., 'Standard', 'Datacenter').\n"
printf " \033[0;34m --auto-continue\033[0m Automatically continue without user prompts.\n"
printf " \033[0;34m --show, -s, -S\033[0m Display the build command used to build the image.\n"

# Handle user input or exit.
if [[ -z "$input" ]]; then
[ "$exit_after" = "exit" ] && exit 0
else
Expand Down Expand Up @@ -195,6 +203,12 @@ check_dependencies() {
}

show_command=0
os=""
dist=""
version=""
edition=""
auto_continue=false

# Script options.
while (("$#")); do
case "$1" in
Expand All @@ -207,6 +221,26 @@ while (("$#")); do
check_dependencies
shift
;;
--os)
os="$2"
shift 2
;;
--dist)
dist="$2"
shift 2
;;
--edition)
edition="$2"
shift 2
;;
--version)
version="$2"
shift 2
;;
--auto-continue)
auto_continue=true
shift
;;
--show | -s | -S)
show_command=1
shift
Expand Down Expand Up @@ -296,6 +330,9 @@ logfile_filename=$(get_settings build_logging_filename)

# This function prompts the user to go back or quit.
prompt_user() {
if [ "$auto_continue" = true ]; then
return
fi
printf "Enter \033[32mb\033[0m to go back, or \033[31mq\033[0m to quit.\n\n"
}

Expand Down Expand Up @@ -368,6 +405,21 @@ print_title() {
# This function selects the guest operating system family.
# Only `Linux` and `Windows` are supported presently in the JSON file.
select_os() {
if [[ -n "$os" ]]; then
# Check if the OS is supported.
if [[ ! " ${os_array[@]} " =~ " $os " ]]; then
printf "\033[0;31m✘ Error:\033[0m Unsupported OS: \033[0;33m$os\033[0m.\n"
printf "\033[0;34mℹ Supported OS options are:\033[0m\n"
for os_item in "${os_array[@]}"; do
printf "\033[0;34m- %s\033[0m\n" "$os_item"
done
exit 1
fi
echo -e "\033[0;32m✔ Selected OS:\033[0m $os"
select_distribution
return
fi

clear
print_title
printf "\nSelect a guest operating system:\n\n"
Expand All @@ -394,9 +446,8 @@ select_os() {
done
}


select_distribution() {
# Check if the selected guest operating system is Linux or Windows.
print_title
case "$os" in
"Linux")
dist_descriptions=$(jq -r --arg os "$os" '.os[] | select(.name == $os) | .distributions[] | .description' "$json_path")
Expand All @@ -423,6 +474,23 @@ select_distribution() {
IFS=$'\n' dist_array=($(sort <<<"${dist_array[*]}"))
unset IFS

if [[ -n "$dist" ]]; then
# Check if the distribution is supported.
if [[ ! " ${dist_array[@]} " =~ " $dist " ]]; then
printf "\033[0;31m✘ Error:\033[0m Unsupported distribution: \033[0;33m$dist\033[0m.\n"
printf "\033[0;34mℹ Supported distributions for \033[0;36m$os\033[0;34m are:\033[0m\n"
for dist_item in "${dist_array[@]}"; do
printf "\033[0;34m- %s\033[0m\n" "$dist_item"
done
exit 1
fi
echo -e "\033[0;32m✔ Selected distribution:\033[0m $dist"
select_version
return
fi

print_title

# Print the submenu.
clear
print_title
Expand Down Expand Up @@ -454,7 +522,7 @@ select_distribution() {

# This function selects the version based on the guest operating system's distribution or type.
select_version() {
# Check if the selected guest operating system is Windows.

if [[ "$dist" == *"Windows"* ]]; then
# Parse the JSON file to get the versions for the selected distribution Windows
version_descriptions=$(jq -r --arg os "$os" --arg dist "$dist" '.os[] | select(.name == $os) | .types[] | select(.description == $dist) | .versions | to_entries[] | select(.value[] | .enabled == "true") | .key' "$json_path")
Expand All @@ -464,6 +532,24 @@ select_version() {

# Convert the version descriptions to an array and sort it in descending order.
IFS=$'\n' read -rd '' -a version_array <<<"$(echo "$version_descriptions" | sort -r)"
if [[ -n "$version" ]]; then
# Check if the version is supported.
if [[ ! " ${version_array[@]} " =~ " $version " ]]; then
printf "\033[0;31m✘ Error:\033[0m Unsupported version: \033[0;33m$version\033[0m.\n"
printf "\033[0;34mℹ Supported versions for \033[0;36m$dist\033[0;34m are:\033[0m\n"
for version_item in "${version_array[@]}"; do
printf "\033[0;34m- %s\033[0m\n" "$version_item"
done
exit 1
fi
echo -e "\033[0;32m✔ Selected version:\033[0m $version"
if [[ "$dist" == *"Windows"* ]]; then
select_edition
else
select_build
fi
return
fi

# Print the submenu.
clear
Expand All @@ -475,7 +561,6 @@ select_version() {
printf "\n"
prompt_user

# Select a version.
while true; do
read -r -p "Select a version: " version_input
if [[ "$version_input" == [qQ] ]]; then
Expand Down Expand Up @@ -503,6 +588,21 @@ select_edition() {
edition_descriptions=$(jq -r --arg os "$os" --arg dist "$dist" --arg version "$version" '.os[] | select(.name == $os) | .types[] | select(.description == $dist) | .versions[$version][] | .editions[] | select(.enabled == "true") | .edition' "$json_path")
IFS=$'\n' read -rd '' -a edition_array <<<"$(echo "$edition_descriptions" | sort -r)"

if [[ -n "$edition" ]]; then
# Check if the edition is supported.
if [[ ! " ${edition_array[@]} " =~ " $edition " ]]; then
printf "\033[0;31m✘ Error:\033[0m Unsupported edition: \033[0;33m$edition\033[0m.\n"
printf "\033[0;34mℹ Supported editions for \033[0;36m$dist\033[0;34m version \033[0;36m$version\033[0;34m are:\033[0m\n"
for edition_item in "${edition_array[@]}"; do
printf "\033[0;34m- %s\033[0m\n" "$edition_item"
done
exit 1
fi
echo -e "\033[0;32m✔ Selected edition:\033[0m $edition"
select_build
return
fi

# Print the submenu.
clear
printf "\nSelect an edition:\n\n"
Expand Down Expand Up @@ -552,32 +652,41 @@ select_build() {

if [[ "$dist" == *"Ubuntu"* ]]; then
version=$version
version=$(echo "$version" | sed 's/\./-/g')-LTS
# Check if the suffix "-LTS" is already present before adding it.
if [[ "$version" != *"-LTS" ]]; then
version=$(echo "$version" | sed 's/\./-/g')-LTS
else
version=$(echo "$version" | sed 's/\./-/g')
fi
INPUT_PATH="$script_path"/builds/$(echo "$os" | tr '[:upper:]' '[:lower:]')/$(echo "$dist_name" | tr '[:upper:]' '[:lower:]')/$(echo "$version" | tr '[:upper:]' '[:lower:]')/
else
version=$(echo "$version" | tr '[:upper:]' '[:lower:]')
INPUT_PATH="$script_path"/builds/$(echo "$os" | tr '[:upper:]' '[:lower:]')/$(echo "$dist_name" | tr '[:upper:]' '[:lower:]')/$version/
fi

if [ ! -d "$INPUT_PATH" ]; then
printf "\n"
print_message error "\033[31mError:\033[0m The build directory does not exist: \e[34m$INPUT_PATH\e[0m."
while true; do
read -r -p "$(echo -e '\n\nWould you like to go (\e[33mb\e[0m)ack or (\e[31mq\e[0m)uit? ')" action
log_message "info" "User selected: $action"
case $action in
[b]*)
# Go back to the previous menu or step.
select_version
break
;;
[q]*)
# Quit the script.
exit 0
;;
esac
done
printf "\n\033[0;31m✘ Error:\033[0m The build directory does not exist: \033[0;34m$INPUT_PATH\033[0m.\n"

if [ "$auto_continue" = true ]; then
printf "\n\033[0;36m➜ Auto-continue is enabled. Skipping user prompt and retrying...\033[0m\n"
select_version # Retry automatically.
else
while true; do
printf "\nWould you like to go (\033[0;33mb\033[0m)ack or (\033[0;31mq\033[0m)uit?\n"
read -r action
case $action in
[bB]*)
select_version # Go back to version selection.
break
;;
[qQ]*)
exit 0
;;
esac
done
fi
fi

BUILD_PATH=${INPUT_PATH#"${script_path}/builds/"}
BUILD_VARS="$(echo "${BUILD_PATH%/}" | tr -s '/' | tr '/' '-').pkrvars.hcl"

Expand All @@ -589,6 +698,12 @@ select_build() {
fi

while true; do
if [ "$auto_continue" = true ]; then
# If auto-continue is enabled, proceed without prompt.
printf "\nAuto-continue is enabled. Skipping user prompt...\n"
break
fi

prompt=$(printf '\nWould you like to (\e[32mc\e[0m)ontinue, go (\e[33mb\e[0m)ack, or (\e[31mq\e[0m)uit? ')
read -r -p "$prompt" action
log_message "info" "User selected: $action"
Expand Down
43 changes: 36 additions & 7 deletions docs/getting-started/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ icon: octicons/play-24

## Using the Build Script

### Interactive Mode

1. Start a build by running the build script (`./build.sh`).

This example will look for the configuration files in the `config` directory.
Expand Down Expand Up @@ -70,20 +72,47 @@ icon: octicons/play-24
vsphere-iso.linux-ubuntu: output will be in this color.
```

### Demo
#### Demo

![](../assets/images/build.gif)


### Command-Line Mode

You can also run the build script using command-line options to specify the operating system, distribution, version, and edition, allowing for non-interactive builds. This is useful for automation or scripting purposes.

#### Examples:

- Build an Ubuntu Server 24.04 LTS image:

```shell
./build.sh --os "Linux" --dist "Ubuntu Server" --version "24.04 LTS" --auto-continue
```

???+ note "Info"
This will start the build process for Ubuntu Server 24.04 LTS without any user prompts.

- Build a Windows Server 2022 Standard edition image:

```
./build.sh --os "Windows" --dist "Windows Server" --version "2022" --edition "Standard" --auto-continue
```
## Build Script Options
You can use the following options with the script.
| Option | Short Form | Description |
| -------- | ---------- | --------------------------------------------------------------- |
| `--help` | `-h`, `-H` | Display the help. |
| `--deps` | `-d`, `-D` | Run a dependency check before running a build. |
| `--json` | `-j`, `-J` | Override the default JSON configuration file. |
| `--show` | `-s`, `-S` | Display the command that the script uses to initialize a build. |
| Option | Short Form | Description |
| ----------------- | -------------- | --------------------------------------------------------------- |
| `--help` | `-h`, `-H` | Display the help. |
| `--deps` | `-d`, `-D` | Run a dependency check before running a build. |
| `--json` | `-j`, `-J` | Override the default JSON configuration file. |
| `--show` | `-s`, `-S` | Display the command that the script uses to initialize a build. |
| `--os` | | Specify the operating system (`Linux` or `Windows`). |
| `--dist` | | Specify the distribution (e.g., `Ubuntu Server`). |
| `--version` | | Specify the version of the distribution. |
| `--edition` | | Specify the edition if applicable (e.g., `Standard`). |
| `--auto-continue` | | Automatically continue without user prompts. |
## Build Directly with Packer
Expand Down

0 comments on commit fb37d5e

Please sign in to comment.