WIP MIL-007: fetch the framework's qc, follow links, default configuration files
- git submodule update --init --recursive after adding or reusing the framework - Follow links to the script so SCRIPT_DIR and the checkout are the real ones - config.env and .env: --config/--env, else ./ in the working folder, else the checkout's - Name the files used; a file from the working folder needs a yes before any request - MIL-007 accepted; test fixtures for the qc checklists; tests/test-launch.sh Work in progress: the README section is not written yet, and four tests of test-launch.sh fail and two shellcheck warnings remain; they are fixed next. Task: MIL-007#1 Task: MIL-007#2 Refs #47 Refs #48 Refs #51
This commit is contained in:
+31
-9
@@ -86,18 +86,39 @@ if ((BASH_VERSINFO[0] < 4 || (BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] < 4)));
|
||||
fi
|
||||
|
||||
# Where this script lives; the library files and the project root are found
|
||||
# from here, never from the current directory.
|
||||
readonly SCRIPT_FILE="${BASH_SOURCE[0]}"
|
||||
case "${BASH_SOURCE[0]}" in
|
||||
*/*) script_path_dir="${BASH_SOURCE[0]%/*}" ;;
|
||||
# from here, never from the current directory. A link to the script (a
|
||||
# command in a folder on PATH) is followed to the real file, however many
|
||||
# links lie on the way; readlink without -f exists on Linux, macOS and Git
|
||||
# Bash alike.
|
||||
script_path="${BASH_SOURCE[0]}"
|
||||
script_link_count=0
|
||||
while [[ -L $script_path ]]; do
|
||||
((++script_link_count <= 40)) || {
|
||||
printf 'error: too many links when following %s\n' "${BASH_SOURCE[0]}" >&2
|
||||
exit 1
|
||||
}
|
||||
script_link_target="$(readlink -- "$script_path")"
|
||||
case "$script_link_target" in
|
||||
/*) script_path="$script_link_target" ;;
|
||||
*)
|
||||
case "$script_path" in
|
||||
*/*) script_path="${script_path%/*}/$script_link_target" ;;
|
||||
*) script_path="$script_link_target" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
done
|
||||
readonly SCRIPT_FILE="$script_path"
|
||||
case "$script_path" in
|
||||
*/*) script_path_dir="${script_path%/*}" ;;
|
||||
*) script_path_dir="." ;;
|
||||
esac
|
||||
SCRIPT_DIR="$(cd "$script_path_dir" && pwd)"
|
||||
SCRIPT_DIR="$(cd -P "$script_path_dir" && pwd -P)"
|
||||
readonly SCRIPT_DIR
|
||||
unset script_path_dir
|
||||
# The script lives in src/; the configuration files live one level up, in
|
||||
# the project root, next to config.env.example and .env.example.
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
unset script_path script_path_dir script_link_count script_link_target
|
||||
# The script lives in src/; the checkout is one level up, next to
|
||||
# config.env.example and .env.example.
|
||||
PROJECT_ROOT="$(cd -P "$SCRIPT_DIR/.." && pwd -P)"
|
||||
readonly PROJECT_ROOT
|
||||
|
||||
# shellcheck source=lib/constants.sh
|
||||
@@ -163,6 +184,7 @@ main() {
|
||||
trap finish EXIT
|
||||
is_valid_repo_name "$PROJECT_NAME" ||
|
||||
die "REPOFOUNDRY_NAME is not a valid project name"
|
||||
WORKING_FOLDER="$(pwd -P)"
|
||||
parse_args "$@"
|
||||
check_tools
|
||||
setup_temp_dir
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: ${0##*/} [--apply] [--config FILE] [--env FILE]
|
||||
Without --config and --env, ./config.env and ./.env in the current folder
|
||||
are read, then the ones in the checkout.
|
||||
${0##*/} --help | --version
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -198,9 +198,56 @@ warn_if_env_unsafe() {
|
||||
fi
|
||||
}
|
||||
|
||||
# locate_config_file NAME FLAG FILE_VAR ORIGIN_VAR: the file named with FLAG;
|
||||
# otherwise ./NAME in the working folder; otherwise NAME in the checkout.
|
||||
# The origin is "named", "folder" or "checkout".
|
||||
locate_config_file() {
|
||||
local name="$1" flag="$2"
|
||||
local -n file_ref="$3" origin_ref="$4"
|
||||
if [[ -n $file_ref ]]; then
|
||||
origin_ref="named"
|
||||
elif [[ $WORKING_FOLDER != "$PROJECT_ROOT" && -f $WORKING_FOLDER/$name ]]; then
|
||||
file_ref="$WORKING_FOLDER/$name"
|
||||
origin_ref="folder"
|
||||
elif [[ -f $PROJECT_ROOT/$name ]]; then
|
||||
file_ref="$PROJECT_ROOT/$name"
|
||||
origin_ref="checkout"
|
||||
else
|
||||
die "$name is not named with $flag and is in neither the working folder ($WORKING_FOLDER) nor the checkout ($PROJECT_ROOT); name it with $flag FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# origin_words ORIGIN: how the origin of a configuration file reads.
|
||||
origin_words() {
|
||||
case "$1" in
|
||||
named) printf 'named on the command line' ;;
|
||||
folder) printf 'from the working folder' ;;
|
||||
*) printf 'from the checkout' ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# confirm_folder_files: a file taken from the working folder may point the
|
||||
# Gitea address elsewhere and so send the token there, so it is named with
|
||||
# the address and needs a yes (default no) before the first request.
|
||||
confirm_folder_files() {
|
||||
local files=()
|
||||
[[ $CONFIG_ORIGIN == folder ]] && files+=("$CONFIG_FILE")
|
||||
[[ $ENV_ORIGIN == folder ]] && files+=("$ENV_FILE")
|
||||
((${#files[@]} > 0)) || return 0
|
||||
say "The working folder supplies: ${files[*]}"
|
||||
say "Gitea would be ${CONFIG[GITEA_URL]}; the token from the credentials file is sent there."
|
||||
prompt_yes_no "Use ${files[*]}" n
|
||||
((REPLY)) || die "stopped before any request: choose the files with --config and --env, or run from the checkout"
|
||||
}
|
||||
|
||||
load_configuration() {
|
||||
locate_config_file config.env --config CONFIG_FILE CONFIG_ORIGIN
|
||||
locate_config_file .env --env ENV_FILE ENV_ORIGIN
|
||||
say "Config file : $CONFIG_FILE ($(origin_words "$CONFIG_ORIGIN"))"
|
||||
say "Credentials file: $ENV_FILE ($(origin_words "$ENV_ORIGIN"))"
|
||||
parse_env_file "$CONFIG_FILE" CONFIG_KEYS CONFIG
|
||||
validate_config
|
||||
confirm_folder_files
|
||||
parse_env_file "$ENV_FILE" CREDENTIAL_KEYS CREDENTIALS
|
||||
validate_credentials
|
||||
warn_if_env_unsafe "$ENV_FILE"
|
||||
|
||||
@@ -37,8 +37,14 @@ readonly CONFIG_KEYS=(GITHUB_API_URL GITHUB_WEB_URL GITEA_URL GITEA_API_URL
|
||||
GITHUB_OWNER PROJECT_DIRECTORY ENABLE_PLAN_GATE PROJECT_LICENSE)
|
||||
readonly CREDENTIAL_KEYS=(GITHUB_PAT GITHUB_USER GITEA_TOKEN)
|
||||
|
||||
CONFIG_FILE="$PROJECT_ROOT/config.env"
|
||||
ENV_FILE="$PROJECT_ROOT/.env"
|
||||
# The configuration files: named by --config and --env, or chosen by
|
||||
# locate_config_file. The origin is named, folder or checkout.
|
||||
CONFIG_FILE=""
|
||||
ENV_FILE=""
|
||||
CONFIG_ORIGIN=""
|
||||
ENV_ORIGIN=""
|
||||
# The folder the Maintainer started the script in.
|
||||
WORKING_FOLDER=""
|
||||
TMP_DIR=""
|
||||
HAS_JQ=0
|
||||
HTTP_STATUS=0
|
||||
|
||||
+15
-1
@@ -4,7 +4,7 @@
|
||||
#
|
||||
# Part of create-project.sh: sourced by it, never run on its own.
|
||||
#
|
||||
# Provides: is_framework_skipped, add_framework, run_framework_script, install_skills, install_hooks, install_framework, copy_template, copy_templates
|
||||
# Provides: is_framework_skipped, init_framework_submodules, add_framework, run_framework_script, install_skills, install_hooks, install_framework, copy_template, copy_templates
|
||||
|
||||
# is_framework_skipped: succeed when the framework steps are left out because
|
||||
# SSH to Gitea is not available (the Maintainer agreed to that).
|
||||
@@ -12,6 +12,18 @@ is_framework_skipped() {
|
||||
[[ ${STATE[skip_framework]:-0} == 1 ]]
|
||||
}
|
||||
|
||||
# init_framework_submodules DIR: fetch the submodules the framework holds
|
||||
# itself (the qc checklists). Without a submodule of its own this changes
|
||||
# nothing. A failure names the command to run by hand.
|
||||
init_framework_submodules() {
|
||||
local dir="$1" err
|
||||
make_temp_file
|
||||
err="$REPLY"
|
||||
if ! git_project "$dir" submodule update -q --init --recursive 2>"$err"; then
|
||||
die "the framework was added but git could not fetch its own submodules (the qc checklists). Run in $dir: git submodule update --init --recursive. Git said: $(head -n 2 "$err" | tr '\n' ' ')"
|
||||
fi
|
||||
}
|
||||
|
||||
# add_framework: git submodule add of the framework as "framework". SSH is
|
||||
# needed for it; a failure says how to test the access.
|
||||
add_framework() {
|
||||
@@ -27,6 +39,7 @@ add_framework() {
|
||||
if [[ $existing != "$url" ]]; then
|
||||
die "'framework' already exists in $dir and is not the framework submodule ($url)"
|
||||
fi
|
||||
init_framework_submodules "$dir"
|
||||
finish_step "$label" "reused" "$url (already a submodule)"
|
||||
return 0
|
||||
fi
|
||||
@@ -35,6 +48,7 @@ add_framework() {
|
||||
if ! git_project "$dir" submodule add -q "$url" framework 2>"$err"; then
|
||||
die "git could not add the framework from $url. Check the SSH access first: ssh -p ${CONFIG[GITEA_SSH_PORT]} -T git@$(gitea_host). Git said: $(head -n 2 "$err" | tr '\n' ' ')"
|
||||
fi
|
||||
init_framework_submodules "$dir"
|
||||
finish_step "$label" "created" "$url"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user