diff --git a/config b/config new file mode 100644 index 00000000..31f0b8a9 --- /dev/null +++ b/config @@ -0,0 +1 @@ +baseuri https://nodejs.org/dist diff --git a/functions.sh b/functions.sh index 3779097b..175c1396 100755 --- a/functions.sh +++ b/functions.sh @@ -2,6 +2,17 @@ # Utlity functions +info() { + printf "%s\\n" "$@" +} + +fatal() { + printf "**********\\n" + printf "Fatal Error: %s\\n" "$@" + printf "**********\\n" + exit 1 +} + # Get system architecture # # This is used to get the target architecture for docker image. @@ -40,10 +51,14 @@ function get_arch() { # ,... # ,... function get_variants() { + local dir + dir=${1:-.} + shift + local arch arch=$(get_arch) local variants - variants=$(grep "^$arch" architectures | sed -E 's/'"$arch"'\s*//' | sed -E 's/,/ /g') + variants=$(grep "^$arch" "$dir/architectures" | sed -E 's/'"$arch"'[[:space:]]*//' | sed -E 's/,/ /g') echo "$variants" } @@ -58,15 +73,146 @@ function get_supported_arches () { local version local variant local arches + local lines + local line version="$1"; shift variant="$1"; shift # Get default supported arches - arches=$( grep "$variant" architectures 2>/dev/null | cut -d' ' -f1 ) + lines=$( grep "$variant" "$(dirname "$version")"/architectures 2>/dev/null | cut -d' ' -f1 ) # Get version specific supported architectures if there is specialized information if [ -a "$version"/architectures ]; then - arches=$( grep "$variant" "$version"/architectures 2>/dev/null | cut -d' ' -f1 ) + lines=$( grep "$variant" "$version"/architectures 2>/dev/null | cut -d' ' -f1 ) fi - echo "$arches" + + while IFS='' read -r line; do + arches+=( "$line" ) + done <<< "$lines" + + echo "${arches[@]}" +} + +# Get configuration values from the config file +# +# The configuration entries are simple key/value pairs which are whitespace separated. +function get_config () { + local dir + dir=${1:-.} + shift + + local name + name=$1 + shift + + local value + value=$(grep "^$name" "$dir/config" | sed -E 's/'"$name"'[[:space:]]*//') + echo "$value" +} + +# Get available versions for a given path +# +# If full or partial versions are provided then they are processed and +# validated. e.g. "4 chakracore" returns "4 chakracore/8" since it processed the +# chakracore entry and found it to be a fork rather than a complete version. +# +# The result is a list of valid versions. +function get_versions () { + local prefix + prefix=${1:-.} + shift + + local versions + local dirs=( "$@" ) + if [ ${#dirs[@]} -eq 0 ]; then + IFS=' ' read -ra dirs <<< "$(echo "${prefix%/}/"*/)" + fi + + for dir in "${dirs[@]}"; do + if [ -a "$dir/config" ]; then + local subdirs + IFS=' ' read -ra subdirs <<< "$(get_versions "${dir#./}")" + for subdir in "${subdirs[@]}"; do + versions+=( "$subdir" ) + done + elif [ -a "$dir/Dockerfile" ]; then + versions+=( "${dir#./}" ) + fi + done + + if [ ${#versions[@]} -gt 0 ]; then + echo "${versions[@]%/}" + fi +} + +function get_fork_name () { + local version + version=$1 + shift + + IFS='/' read -ra versionparts <<< "$version" + if [ ${#versionparts[@]} -gt 1 ]; then + echo "${versionparts[0]}" + fi +} + +function get_full_version () { + local version + version=$1 + shift + + grep -m1 'ENV NODE_VERSION ' "$version/Dockerfile" | cut -d' ' -f3 +} + +function get_major_minor_version () { + local version + version=$1 + shift + + local fullversion + fullversion=$(get_full_version "$version") + + echo "$(echo "$fullversion" | cut -d'.' -f1).$(echo "$fullversion" | cut -d'.' -f2)" +} + +function get_tag () { + local version + version=$1 + shift + + local versiontype + versiontype=${1:-full} + shift + + local tagversion + if [ "$versiontype" = full ]; then + tagversion=$(get_full_version "$version") + elif [ "$versiontype" = majorminor ]; then + tagversion=$(get_major_minor_version "$version") + fi + + local tagparts + IFS=' ' read -ra tagparts <<< "$(get_fork_name "$version") $tagversion" + IFS='-'; echo "${tagparts[*]}"; unset IFS +} + +function sort_versions () { + local versions=( "$@" ) + local sorted + local lines + local line + + IFS=$'\n' + lines="${versions[*]}" + unset IFS + + while IFS='' read -r line; do + sorted+=( "$line" ) + done <<< "$(echo "$lines" | grep "^[0-9]" | sort -r)" + + while IFS='' read -r line; do + sorted+=( "$line" ) + done <<< "$(echo "$lines" | grep -v "^[0-9]" | sort -r)" + + echo "${sorted[@]}" } diff --git a/generate-stackbrew-library.sh b/generate-stackbrew-library.sh index 0d74039c..8a76665d 100755 --- a/generate-stackbrew-library.sh +++ b/generate-stackbrew-library.sh @@ -18,13 +18,10 @@ cd "$(cd "${0%/*}" && pwd -P)"; self="$(basename "${BASH_SOURCE[0]}")" -versions=( */ ) -versions=( "${versions[@]%/}" ) +IFS=' ' read -ra versions <<< "$(get_versions)" +IFS=' ' read -ra versions <<< "$(sort_versions "${versions[@]}")" url='https://github.com/nodejs/docker-node' -# sort version numbers with highest first -IFS=$'\n'; versions=( $(echo "${versions[*]}" | sort -r) ); unset IFS - # get the most recent commit which modified any of "$@" fileCommit() { git log -1 --format='format:%H' HEAD -- "$@" @@ -43,18 +40,25 @@ join() { echo "${out#$sep}" } +get_stub() { + local version="$1"; shift + IFS='/' read -ra versionparts <<< "$version" + local stub; eval stub="$(join '_' "${versionparts[@]}" | awk -F. '{ print "$array_" $1 }')"; + echo "$stub" +} + for version in "${versions[@]}"; do # Skip "docs" and other non-docker directories [ -f "$version/Dockerfile" ] || continue - eval stub="$(echo "$version" | awk -F. '{ print "$array_" $1 }')"; + stub=$(get_stub "$version") commit="$(fileCommit "$version")" - fullVersion="$(grep -m1 'ENV NODE_VERSION ' "$version/Dockerfile" | cut -d' ' -f3)" - minorVersion="$(echo "$fullVersion" | cut -d'.' -f2)" + fullVersion="$(get_tag "$version" full)" + majorMinorVersion="$(get_tag "$version" majorminor)" - versionAliases=( $fullVersion $version.$minorVersion ${stub} ) + IFS=' ' read -ra versionAliases <<< "$fullVersion $majorMinorVersion $stub" # Get supported architectures for a specific version. See details in function.sh - supportedArches=( $(get_supported_arches "$version" "default") ) + IFS=' ' read -ra supportedArches <<< "$(get_supported_arches "$version" "default")" echo "Tags: $(join ', ' "${versionAliases[@]}")" echo "Architectures: $(join ', ' "${supportedArches[@]}")" @@ -64,7 +68,7 @@ for version in "${versions[@]}"; do # Get supported variants according to the target architecture. # See details in function.sh - variants=$(get_variants | tr ' ' '\n') + variants=$(get_variants "$(dirname "$version")") for variant in $variants; do # Skip non-docker directories [ -f "$version/$variant/Dockerfile" ] || continue @@ -76,7 +80,7 @@ for version in "${versions[@]}"; do variantAliases=( "${variantAliases[@]//latest-/}" ) # Get supported architectures for a specific version and variant. # See details in function.sh - supportedArches=( $(get_supported_arches "$version" "$variant") ) + IFS=' ' read -ra supportedArches <<< "$(get_supported_arches "$version" "$variant")" echo "Tags: $(join ', ' "${variantAliases[@]}")" echo "Architectures: $(join ', ' "${supportedArches[@]}")" diff --git a/test-build.sh b/test-build.sh index e0492e96..22b500d9 100755 --- a/test-build.sh +++ b/test-build.sh @@ -3,34 +3,22 @@ # Run a test build for all images. set -uo pipefail -IFS=$'\n\t' . functions.sh -info() { - printf "%s\n" "$@" -} - -fatal() { - printf "**********\n" - printf "%s\n" "$@" - printf "**********\n" - exit 1 -} - cd "$(cd "${0%/*}" && pwd -P)" || exit; -versions=( "$@" ) +IFS=' ' read -ra versions <<< "$(get_versions . "$@")" if [ ${#versions[@]} -eq 0 ]; then - versions=( */ ) + fatal "No valid versions found!" fi -versions=( "${versions[@]%/}" ) for version in "${versions[@]}"; do # Skip "docs" and other non-docker directories [ -f "$version/Dockerfile" ] || continue - tag=$(grep "ENV NODE_VERSION" "$version/Dockerfile" | cut -d' ' -f3) + tag=$(get_tag "$version") + full_version=$(get_full_version "$version") info "Building $tag..." @@ -40,14 +28,14 @@ for version in "${versions[@]}"; do info "Build of $tag succeeded." OUTPUT=$(docker run --rm -it node:"$tag" node -e "process.stdout.write(process.versions.node)") - if [ "$OUTPUT" != "$tag" ]; then + if [ "$OUTPUT" != "$full_version" ]; then fatal "Test of $tag failed!" fi info "Test of $tag succeeded." # Get supported variants according to the target architecture. # See details in function.sh - variants=$(get_variants | tr ' ' '\n') + variants=$(get_variants "$(dirname "$version")") for variant in $variants; do # Skip non-docker directories @@ -61,7 +49,7 @@ for version in "${versions[@]}"; do info "Build of $tag-$variant succeeded." OUTPUT=$(docker run --rm -it node:"$tag-$variant" node -e "process.stdout.write(process.versions.node)") - if [ "$OUTPUT" != "$tag" ]; then + if [ "$OUTPUT" != "$full_version" ]; then fatal "Test of $tag-$variant failed!" fi info "Test of $tag-$variant succeeded." diff --git a/update.sh b/update.sh index 83622ee9..b9168c4e 100755 --- a/update.sh +++ b/update.sh @@ -1,15 +1,14 @@ #!/bin/bash -set -e +set -ue . functions.sh cd "$(cd "${0%/*}" && pwd -P)"; -versions=( "$@" ) +IFS=' ' read -ra versions <<< "$(get_versions . "$@")" if [ ${#versions[@]} -eq 0 ]; then - versions=( */ ) + fatal "No valid versions found!" fi -versions=( "${versions[@]%/}" ) # Global variables # Get architecure and use this as target architecture for docker image @@ -21,6 +20,10 @@ yarnVersion="$(curl -sSL --compressed https://yarnpkg.com/latest-version)" function update_node_version { + local baseuri=$1 + shift + local version=$1 + shift local template=$1 shift local dockerfile=$1 @@ -31,12 +34,12 @@ function update_node_version { shift fi - fullVersion="$(curl -sSL --compressed 'https://nodejs.org/dist' | grep '