-
Notifications
You must be signed in to change notification settings - Fork 40
Add support for semantic versioning in zopen-install #1153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -184,18 +184,69 @@ installDependencies() | |
|
|
||
| handlePackageInstall() | ||
| { | ||
|
|
||
| fullname="$1" | ||
| isRuntimeDependency=$2 | ||
| if [ -z "$isRuntimeDependency" ]; then | ||
| isRuntimeDependency=false | ||
| fi | ||
| printVerbose "Name to install: ${fullname}, parsing any version ('=') or tag ('%') has been specified" | ||
| name=$(echo "${fullname}" | sed -e 's#[=%].*##') | ||
|
|
||
| operator="" | ||
| versioned="" | ||
| tagged="" | ||
|
|
||
| # Support: name=ver, name>=ver, name>ver, name<=ver, name<ver, name%tag | ||
| name=$(echo "${fullname}" | sed -E 's/[=><%].*//') | ||
| repo="${name}" | ||
| versioned=$(echo "${fullname}" | cut -s -d '=' -f 2) | ||
|
|
||
| # Get everything after the name | ||
| suffix="${fullname#$name}" | ||
|
|
||
| # Extract operator (can be >=, <=, >, <, =) from the beginning of suffix | ||
| operator=$(echo "${suffix}" | sed -E -n 's/^([>=<]{1,2}).*/\1/p') | ||
|
|
||
| if [ -n "${operator}" ]; then | ||
| # Validate operator | ||
| case "${operator}" in | ||
| "="|">"|">="|"<"|"<=") ;; | ||
| *) printError "Invalid operator '${operator}' in package specification. Supported operators are: =, >, >=, <, <=" ;; | ||
| esac | ||
|
|
||
| # Extract version: take everything after operator and before % | ||
| rest="${suffix#$operator}" | ||
| versioned="${rest%%%*}" | ||
|
|
||
| if [ -z "${versioned}" ]; then | ||
| printError "A version must be provided when using an operator (e.g., ${name}${operator}1.0)." | ||
| fi | ||
| else | ||
| # Fallback to older '=' parsing if no explicit operator found but versioned exists | ||
| # (Checking if suffix starts with '=' and taking everything before '%') | ||
| case "${suffix}" in | ||
| =*) | ||
| operator="=" | ||
| rest="${suffix#=}" | ||
| versioned="${rest%%%*}" | ||
| ;; | ||
| esac | ||
| fi | ||
|
|
||
| # Validate that the version string contains valid characters (alphanumeric, dots, hyphens) | ||
| if [ -n "${versioned}" ]; then | ||
| # Strip leading 'v' if present for validation | ||
| v_to_check="${versioned#v}" | ||
| # Must contain at least one digit and only valid chars | ||
| if [ -z "${v_to_check}" ] || ! echo "${v_to_check}" | grep -q "[0-9]" || echo "${v_to_check}" | grep -q "[^0-9a-zA-Z.-]" || echo "${v_to_check}" | grep -q "^\." || echo "${v_to_check}" | grep -q "\.$" || echo "${v_to_check}" | grep -q "\.\."; then | ||
| printError "Invalid version string '${versioned}'. Versions must be numeric segments separated by dots (e.g., 1.2.3) and can include alphanumeric suffixes (e.g., 1.2.3-rc1)." | ||
| fi | ||
| fi | ||
|
|
||
| # Extract tag | ||
| tagged=$(echo "${fullname}" | cut -s -d '%' -f 2) | ||
|
sachintu47 marked this conversation as resolved.
|
||
| printDebug "Name:${name};version:${versioned};tag:${tagged};repo:${repo}" | ||
|
|
||
| if [ -n "${versioned}" ] && [ -n "${tagged}" ]; then | ||
| printError "Ambiguous package specification '${fullname}'. Provide either a version constraint or a tag, but not both." | ||
| fi | ||
| printDebug "Name:${name};operator:${operator};version:${versioned};tag:${tagged};repo:${repo}" | ||
| printInfo "${NC}${HEADERCOLOR}${BOLD}Processing package: ${name}${NC}" | ||
|
|
||
| nameSansPort=$(echo "${name}" | sed -e 's#\(.*\)port$#\1#') | ||
|
|
@@ -242,14 +293,35 @@ handlePackageInstall() | |
| # Options where the user explicitly sets a version/tag/releaseline currently ignore any configured release-line, | ||
| # either for a previous package install or system default | ||
| if [ -n "${versioned}" ]; then | ||
| printVerbose "Specific version ${versioned} requested - checking existence and URL." | ||
| printVerbose "Specific version ${versioned} requested with operator '${operator}' - checking existence and URL." | ||
| requestedMajor=$(echo "${versioned}" | awk -F'.' '{print $1}') | ||
| requestedMinor=$(echo "${versioned}" | awk -F'.' '{print $2}') | ||
| requestedPatch=$(echo "${versioned}" | awk -F'.' '{print $3}') | ||
| requestedSubrelease=$(echo "${versioned}" | awk -F'.' '{print $4}') | ||
| requestedVersion="${requestedMajor}\\\.${requestedMinor}\\\.${requestedPatch}\\\.${requestedSubrelease}" | ||
| printVerbose "Finding URL for latest release matching version prefix: requestedVersion: ${requestedVersion}" | ||
| releaseMetadata=$(/bin/printf "%s" "${releases}" | jq -e -r '. | map(select(.assets[].name | test("'${requestedVersion}'")))[0]') | ||
| if [ -z "${requestedMajor}" ]; then | ||
| printError "A major version must be provided when specifying a version (e.g., ${name}=1)." | ||
| fi | ||
|
|
||
| # Convert requested version string to a JSON array of numbers for jq | ||
| req_v_json=$(echo "${versioned#v}" | tr '.' '\n' | jq -R 'tonumber' | jq -s -c .) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The version validation above allows alphanumeric/hyphen suffixes (e.g. Severity: medium 🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage. |
||
|
|
||
| printVerbose "Finding latest release matching ${operator} ${versioned}" | ||
| # Unified selection logic using jq: | ||
| # 1. to_v: Converts a dot-delimited version string to a numeric array, padded with 0s to length 8 | ||
| # 2. match_v: Handles prefix match for '=' and numeric comparison for others | ||
| releaseMetadata=$(/bin/printf "%s" "${releases}" | jq -e -r --arg op "${operator}" --argjson req_v "${req_v_json}" ' | ||
| def to_v: if . == null then [0] else split(".") | map(tonumber? // 0) end | . + [range(0; 8 - length) | 0]; | ||
| def match_v(rv; op): | ||
| to_v as $av | | ||
| (rv + [range(0; 8 - (rv | length)) | 0]) as $nrv | | ||
| if op == "=" then $av[0:(rv | length)] == rv | ||
| elif op == ">=" then $av >= $nrv | ||
| elif op == ">" then $av > $nrv | ||
| elif op == "<=" then $av <= $nrv | ||
| elif op == "<" then $av < $nrv | ||
| else false end; | ||
| map(select(.assets[0].version != null and (.assets[0].version | match_v($req_v; $op)))) | | ||
| sort_by([(.assets[0].version | to_v), .date, .tag_name]) | reverse | .[0]') | ||
| if [ -z "${releaseMetadata}" ] || [ "${releaseMetadata}" = "null" ]; then | ||
| printError "Could not find a release of '${name}' matching '${operator}${versioned}'" | ||
| fi | ||
| elif [ -n "${tagged}" ]; then | ||
| printVerbose "Explicit tagged version '${tagged}' specified. Checking for match." | ||
| releaseMetadata=$(/bin/printf "%s" "${releases}" | jq -e -r '.[] | select(.tag_name == "'${tagged}'")') | ||
|
|
@@ -861,18 +933,26 @@ if ${all}; then | |
| done | ||
| installArray=$(strtrim "${installArray}") | ||
| else | ||
| chosenRepos=$(echo "${chosenRepos}" | tr ',' ' ' | tr -s ' ') | ||
| chosenRepos=$(strtrim "${chosenRepos}") | ||
| invalidlist="" | ||
| for chosenRepo in $(echo "${chosenRepos}" | tr ',' ' ' | tr -s ' '); do | ||
| for chosenRepo in ${chosenRepos}; do | ||
| printVerbose "Processing repo: ${chosenRepo}" | ||
| printVerbose "Stripping any version (%), tag (#) or port suffixes" | ||
| toolrepo=$(echo "${chosenRepo}" | sed -e 's#%.*##' -e 's#=.*##') | ||
| printVerbose "Stripping any version operator (>, >=, <, <=, =), tag (%) or port suffixes" | ||
|
sachintu47 marked this conversation as resolved.
|
||
| toolrepo=$(echo "${chosenRepo}" | sed -E 's/[=><%].*//') | ||
| toolfound=$(echo "${repo_results}" | awk -vtoolrepo="${toolrepo}" '$0 == toolrepo {print}') | ||
| if [ "${toolfound}" = "${toolrepo}" ]; then | ||
| printVerbose "Adding '${chosenRepo}' to the install queue." | ||
| installArray="${installArray} ${chosenRepo}" | ||
| printVerbose "Removing valid port from input list." | ||
| chosenRepos=$(echo "${chosenRepos}" | sed -e "s#^${chosenRepo}\$##") | ||
| # Safely remove the word from the space-separated list | ||
| newChosenRepos="" | ||
| for r in ${chosenRepos}; do | ||
|
sachintu47 marked this conversation as resolved.
|
||
| if [ "$r" != "${chosenRepo}" ]; then | ||
| newChosenRepos="${newChosenRepos} $r" | ||
| fi | ||
| done | ||
| chosenRepos=$(strtrim "${newChosenRepos}") | ||
| else | ||
| invalidlist=$(/bin/printf "%s %s" "${invalidlist}" "${chosenRepo}") | ||
| fi | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.