Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion jenkins-support
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,37 @@ substitute_env_vars() {
echo "${content}" > "${file}"
}

# compare if numeric dotted version1 < numeric dotted version2
numericVersionLT() {
local version1 version2 i part1 part2 max
local -a parts1 parts2
version1=$1
version2=$2

IFS=. read -r -a parts1 <<< "$version1"
IFS=. read -r -a parts2 <<< "$version2"
max=${#parts1[@]}
if (( ${#parts2[@]} > max )); then
max=${#parts2[@]}
fi

for (( i = 0; i < max; i++ )); do
part1=${parts1[i]:-0}
part2=${parts2[i]:-0}
if (( 10#$part1 < 10#$part2 )); then
return 0
fi
if (( 10#$part1 > 10#$part2 )); then
return 1
fi
done

return 1
}

# compare if version1 < version2
versionLT() {
local normalized_version1 normalized_version2 first_part_of_1 other_part_of_1 first_char_other_part_of_1 first_part_of_2 other_part_of_2 first_char_other_part_of_2
local normalized_version1 normalized_version2 first_part_of_1 other_part_of_1 first_char_other_part_of_1 first_part_of_2 other_part_of_2 first_char_other_part_of_2 numeric_prefix_1 numeric_prefix_2 jenkins_suffix_1 jenkins_suffix_2

# Quick check for equality
if [ "$1" = "$2" ]; then
Expand Down Expand Up @@ -75,6 +103,30 @@ versionLT() {
fi
fi

# Semver-prefix + Jenkins CD release suffix special case.
# Ex: 9.10-211.v7d13903b_a_d89 < 9.10.1-216.va_9256d3b_844b_
# `sort --version-sort` compares 9.10.211 with 9.10.1.216 after the
# generic "-" -> "." normalization below, so it treats the older upstream
# 9.10 line as newer than 9.10.1. When both sides have a numeric wrapped
# component version prefix before the Jenkins CD release suffix, compare
# that prefix first and fall back to the existing behavior only when the
# prefixes are equal. Keep non-CD suffixes on the existing path.
# Tracked at https://github.com/jenkinsci/docker/issues/2361
if [[ "$1" == *-* && "$2" == *-* ]]; then
numeric_prefix_1=${1%%-*}
numeric_prefix_2=${2%%-*}
jenkins_suffix_1=${1#*-}
jenkins_suffix_2=${2#*-}
if [[ "$numeric_prefix_1" =~ ^[0-9]+(\.[0-9]+)*$ && "$numeric_prefix_2" =~ ^[0-9]+(\.[0-9]+)*$ && "$jenkins_suffix_1" =~ ^[0-9]+\.v.+$ && "$jenkins_suffix_2" =~ ^[0-9]+\.v.+$ ]]; then
if numericVersionLT "$numeric_prefix_1" "$numeric_prefix_2"; then
return 0
fi
if numericVersionLT "$numeric_prefix_2" "$numeric_prefix_1"; then
return 1
fi
fi
fi

if [ "$normalized_version1" = "$(printf '%s\n%s\n' "$normalized_version1" "$normalized_version2" | sort --version-sort | head -n1)" ]; then
return 0
else
Expand Down
43 changes: 42 additions & 1 deletion jenkins-support.psm1
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
# compare if numeric dotted version1 < numeric dotted version2
function Compare-NumericVersionLessThan([string] $version1 = '', [string] $version2 = '') {
$version1Parts = $version1.Split('.')
$version2Parts = $version2.Split('.')
$maxLength = [Math]::Max($version1Parts.Length, $version2Parts.Length)

for ($i = 0; $i -lt $maxLength; $i++) {
$version1part = if ($i -lt $version1Parts.Length) { [int64]$version1Parts[$i] } else { 0 }
$version2part = if ($i -lt $version2Parts.Length) { [int64]$version2Parts[$i] } else { 0 }

if ($version1part -lt $version2part) {
return $true
}
if ($version1part -gt $version2part) {
return $false
}
}

return $false
}

# compare if version1 < version2
function Compare-VersionLessThan([string] $version1 = '', [string] $version2 = '') {
Expand All @@ -13,6 +33,27 @@ function Compare-VersionLessThan([string] $version1 = '', [string] $version2 = '
$version1Parts = $normalizedVersion1.Split('.')
$version2Parts = $normalizedVersion2.Split('.')

# Semver-prefix + Jenkins CD release suffix special case.
# Ex: 9.10-211.v7d13903b_a_d89 < 9.10.1-216.va_9256d3b_844b_
# The generic "-" -> "." normalization compares 9.10.211 with 9.10.1.216,
# so it treats the older upstream 9.10 line as newer than 9.10.1.
# Keep non-CD suffixes on the existing path.
# Tracked at https://github.com/jenkinsci/docker/issues/2361
if (($version1 -like '*-*') -and ($version2 -like '*-*')) {
$numericPrefix1 = ($version1 -split '-', 2)[0]
$numericPrefix2 = ($version2 -split '-', 2)[0]
$jenkinsSuffix1 = ($version1 -split '-', 2)[1]
$jenkinsSuffix2 = ($version2 -split '-', 2)[1]
if (($numericPrefix1 -match '^[0-9]+(\.[0-9]+)*$') -and ($numericPrefix2 -match '^[0-9]+(\.[0-9]+)*$') -and ($jenkinsSuffix1 -match '^[0-9]+\.v.+$') -and ($jenkinsSuffix2 -match '^[0-9]+\.v.+$')) {
if (Compare-NumericVersionLessThan $numericPrefix1 $numericPrefix2) {
return $true
}
if (Compare-NumericVersionLessThan $numericPrefix2 $numericPrefix1) {
return $false
}
}
}

# Compare major versions
if ($version1Parts[0] -lt $version2parts[0]) {
return $true
Expand Down Expand Up @@ -251,4 +292,4 @@ function Copy-ReferenceFile($file) {
Add-Content -Path $COPY_REFERENCE_FILE_LOG -Value "$action $rel : $reason"
}
}
}
}
17 changes: 17 additions & 0 deletions tests/functions.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,23 @@ Describe "[functions > $global:TEST_TAG] Check-VersionLessThan" -Skip:(-not $glo
docker run --rm $global:SUT_IMAGE "Import-Module -DisableNameChecking -Force C:/ProgramData/Jenkins/jenkins-support.psm1 ; if(`$(Compare-VersionLessThan '4106.4108.v841a_e1819d4d' '4151.v5406e29e3c90')) { exit 0 } else { exit -1 }"
$LastExitCode | Should -Be 0
}
## Real world examples from https://github.com/jenkinsci/docker/issues/2361
It 'has left side greater (apache-httpcomponents-client-5-api-plugin, semver prefix with CD release suffix)' {
docker run --rm $global:SUT_IMAGE "Import-Module -DisableNameChecking -Force C:/ProgramData/Jenkins/jenkins-support.psm1 ; if(`$(Compare-VersionLessThan '5.6.1-195.v65ffe15189a_d' '5.6-191.vb_47e2b_41c698')) { exit 0 } else { exit -1 }"
$LastExitCode | Should -Be -1
}
It 'has right side greater (apache-httpcomponents-client-5-api-plugin, semver prefix with CD release suffix)' {
docker run --rm $global:SUT_IMAGE "Import-Module -DisableNameChecking -Force C:/ProgramData/Jenkins/jenkins-support.psm1 ; if(`$(Compare-VersionLessThan '5.6-191.vb_47e2b_41c698' '5.6.1-195.v65ffe15189a_d')) { exit 0 } else { exit -1 }"
$LastExitCode | Should -Be 0
}
It 'has left side greater (asm-api-plugin, semver prefix with CD release suffix)' {
docker run --rm $global:SUT_IMAGE "Import-Module -DisableNameChecking -Force C:/ProgramData/Jenkins/jenkins-support.psm1 ; if(`$(Compare-VersionLessThan '9.10.1-216.va_9256d3b_844b_' '9.10-211.v7d13903b_a_d89')) { exit 0 } else { exit -1 }"
$LastExitCode | Should -Be -1
}
It 'has right side greater (asm-api-plugin, semver prefix with CD release suffix)' {
docker run --rm $global:SUT_IMAGE "Import-Module -DisableNameChecking -Force C:/ProgramData/Jenkins/jenkins-support.psm1 ; if(`$(Compare-VersionLessThan '9.10-211.v7d13903b_a_d89' '9.10.1-216.va_9256d3b_844b_')) { exit 0 } else { exit -1 }"
$LastExitCode | Should -Be 0
}
}

# Only test on Java 21, one JDK is enough to test all versions
Expand Down
12 changes: 12 additions & 0 deletions tests/functions.bats
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ SUT_DESCRIPTION="${IMAGE}-functions"
# role-strategy-plugin, reverse-direction
run docker run --rm $SUT_IMAGE bash -c "source /usr/local/bin/jenkins-support && versionLT 587.588.v850a_20a_30162 587.v2872c41fa_e51"
assert_failure
## https://github.com/jenkinsci/docker/issues/2361
## Semver-prefix + Jenkins CD release suffix cases: compare the numeric upstream prefix before the suffix.
# apache-httpcomponents-client-5-api-plugin
run docker run --rm $SUT_IMAGE bash -c "source /usr/local/bin/jenkins-support && versionLT 5.6.1-195.v65ffe15189a_d 5.6-191.vb_47e2b_41c698"
assert_failure
run docker run --rm $SUT_IMAGE bash -c "source /usr/local/bin/jenkins-support && versionLT 5.6-191.vb_47e2b_41c698 5.6.1-195.v65ffe15189a_d"
assert_success
# asm-api-plugin
run docker run --rm $SUT_IMAGE bash -c "source /usr/local/bin/jenkins-support && versionLT 9.10.1-216.va_9256d3b_844b_ 9.10-211.v7d13903b_a_d89"
assert_failure
run docker run --rm $SUT_IMAGE bash -c "source /usr/local/bin/jenkins-support && versionLT 9.10-211.v7d13903b_a_d89 9.10.1-216.va_9256d3b_844b_"
assert_success
}

@test "[${SUT_DESCRIPTION}] permissions are propagated from override file" {
Expand Down