diff --git a/build-push/bin/main.sh b/build-push/bin/main.sh index 0a92d905..7db68f26 100644 --- a/build-push/bin/main.sh +++ b/build-push/bin/main.sh @@ -11,10 +11,15 @@ # resulting image. # # The second argument to this script is the relative path to the build context -# subdirectory. The basename of this subdirectory indicates the -# type of image being built (i.e. `upstream`, `testing`, or `stable`). -# Depending on this value, the image may be pushed to multiple container -# registries. +# subdirectory. The basename of this subdirectory may indicates the +# image flavor (i.e. `upstream`, `testing`, or `stable`). Depending +# on this value, the image may be pushed to multiple container registries +# under slightly different rules (see the next option). +# +# If the basename of the context directory (second argument) does NOT reflect +# the image flavor, this name may be passed in as a third argument. Handling +# of this argument may be repository-specific, so check the actual code below +# to understand it's behavior. set -eo pipefail @@ -59,14 +64,23 @@ REPO_URL="$1" REPO_NAME=$(basename "${REPO_URL%.git}") # Second arg (CTX_SUB) is the context subdirectory relative to the clone path CTX_SUB="$2" -# Basename of second arg names the image contents -CTX_NAME=$(basename "$CTX_SUB") +# Historically, the basename of second arg set the image flavor(i.e. `upstream`, +# `testing`, or `stable`). For cases where this convention doesn't fit, +# it's possible to pass the flavor-name as the third argument. Both methods +# will populate a "FLAVOR" build-arg value. +if [[ "$#" -lt 3 ]]; then + FLAVOR_NAME=$(basename "$CTX_SUB") +elif [[ "$#" -ge 3 ]]; then + FLAVOR_NAME="$3" # An empty-value is valid +else + die "Expecting a non-empty third argument indicating the FLAVOR build-arg value." +fi _REG="quay.io" if [[ "$REPO_NAME" =~ testing ]]; then _REG="example.com" fi -REPO_FQIN="$_REG/$REPO_NAME/$CTX_NAME" -req_env_vars REPO_URL REPO_NAME CTX_SUB CTX_NAME +REPO_FQIN="$_REG/$REPO_NAME/$FLAVOR_NAME" +req_env_vars REPO_URL REPO_NAME CTX_SUB FLAVOR_NAME # Common library defines SCRIPT_FILENAME # shellcheck disable=SC2154 @@ -74,7 +88,7 @@ dbg "$SCRIPT_FILENAME operating constants: REPO_URL=$REPO_URL REPO_NAME=$REPO_NAME CTX_SUB=$CTX_SUB - CTX_NAME=$CTX_NAME + FLAVOR_NAME=$FLAVOR_NAME REPO_FQIN=$REPO_FQIN " @@ -89,6 +103,11 @@ fi ### MAIN +declare -a build_args +if [[ -n "$FLAVOR_NAME" ]]; then + build_args=(--build-arg "FLAVOR=$FLAVOR_NAME") +fi + head_sha=$(git rev-parse HEAD) dbg "HEAD is $head_sha" # Labels to add to all images @@ -99,14 +118,13 @@ lblargs="\ --label=org.opencontainers.image.created=$(date -u --iso-8601=seconds)" dbg "lblargs=$lblargs" -# tag_version.sh is sensitive to this value if set -export img_cmd_version="" +modcmdarg="tag_version.sh $FLAVOR_NAME" # For stable images, the version number of the command is needed for tagging. -if [[ "$CTX_NAME" == "stable" ]]; then +if [[ "$FLAVOR_NAME" == "stable" ]]; then # only native arch is needed to extract the version dbg "Building local-arch image to extract stable version number" - podman build -t $REPO_FQIN ./$CTX_SUB + podman build -t $REPO_FQIN "${build_args[@]}" ./$CTX_SUB case "$REPO_NAME" in skopeo) version_cmd="--version" ;; @@ -131,14 +149,18 @@ if [[ "$CTX_NAME" == "stable" ]]; then dbg "Un-tagging $REPO_FQIN" podman untag $REPO_FQIN + # tag-version.sh expects this arg. when FLAVOR_NAME=stable + modcmdarg+=" $img_cmd_version" + # Stable images get pushed to 'containers' namespace as latest & version-tagged build-push.sh \ $_DRNOPUSH \ --arches=$ARCHES \ - --modcmd=tag_version.sh \ + --modcmd="$modcmdarg" \ $_REG/containers/$REPO_NAME \ ./$CTX_SUB \ - $lblargs + $lblargs \ + "${build_args[@]}" fi # All images are pushed to quay.io/, both @@ -146,7 +168,8 @@ fi build-push.sh \ $_DRNOPUSH \ --arches=$ARCHES \ - --modcmd=tag_version.sh \ + --modcmd="$modcmdarg" \ $REPO_FQIN \ ./$CTX_SUB \ - $lblargs + $lblargs \ + "${build_args[@]}" diff --git a/build-push/bin/tag_version.sh b/build-push/bin/tag_version.sh index f797ec36..8be79c81 100644 --- a/build-push/bin/tag_version.sh +++ b/build-push/bin/tag_version.sh @@ -17,35 +17,46 @@ else fi # Vars defined by build-push.sh spec. for mod scripts -req_env_vars SCRIPT_FILEPATH RUNTIME PLATFORMOS FQIN CONTEXT \ +req_env_vars SCRIPT_FILENAME SCRIPT_FILEPATH RUNTIME PLATFORMOS FQIN CONTEXT \ PUSH ARCHES REGSERVER NAMESPACE IMGNAME MODCMD -# As in main.sh, the context name comes from subdir basename -# shellcheck disable=SC2154 -CTX_NAME=$(basename "$CONTEXT") # upstream, testing, or stable +if [[ "$#" -ge 1 ]]; then + FLAVOR_NAME="$1" # upstream, testing, or stable +fi + +if [[ "$#" -ge 2 ]]; then + # Enforce all version-tags start with a 'v' + VERSION="v${2#v}" # output of $version_cmd +fi + +if [[ -z "$FLAVOR_NAME" ]]; then + # Defined by common_lib.sh + # shellcheck disable=SC2154 + warn "$SCRIPT_FILENAME passed empty flavor-name argument (optional)." +elif [[ -z "$VERSION" ]]; then + warn "$SCRIPT_FILENAME received empty version argument (req. for FLAVOR_NAME=stable)." +fi # shellcheck disable=SC2154 -dbg "Mod-command operating on $FQIN in $CTX_NAME context" +dbg "Mod-command operating on $FQIN in '$FLAVOR_NAME' flavor" -if [[ "$CTX_NAME" == "stable" ]]; then +if [[ "$FLAVOR_NAME" == "stable" ]]; then # Stable images must all be tagged with a version number. - # Confirm this value is passed in by shell env. var. since - # retrieving it from the image content is beyond the scope - # of this script. - req_env_vars img_cmd_version - img_cmd_version=v${img_cmd_version#v} - if egrep -q '^v[0-9]+\.[0-9]+\.[0-9]+'<<<"$img_cmd_version"; then - msg "Found image command version '$img_cmd_version'" + # Confirm this value is passed in by caller. + req_env_vars VERSION + VERSION=v${VERSION#v} + if egrep -q '^v[0-9]+\.[0-9]+\.[0-9]+'<<<"$VERSION"; then + msg "Found image command version '$VERSION'" else - die "Encountered unexpected/non-conforming version '$img_cmd_version'" + die "Encountered unexpected/non-conforming version '$VERSION'" fi # shellcheck disable=SC2154 - $RUNTIME tag $FQIN:latest $FQIN:$img_cmd_version - msg "Successfully tagged $FQIN:$img_cmd_version" + $RUNTIME tag $FQIN:latest $FQIN:$VERSION + msg "Successfully tagged $FQIN:$VERSION" # Tag as x.y to provide a consistent tag even for a future z+1 - xy_ver=$(awk -F '.' '{print $1"."$2}'<<<"$img_cmd_version") + xy_ver=$(awk -F '.' '{print $1"."$2}'<<<"$VERSION") $RUNTIME tag $FQIN:latest $FQIN:$xy_ver msg "Successfully tagged $FQIN:$xy_ver" @@ -54,5 +65,5 @@ if [[ "$CTX_NAME" == "stable" ]]; then $RUNTIME tag $FQIN:latest $FQIN:$x_ver msg "Successfully tagged $FQIN:$x_ver" else - warn "Not tagging '$CTX_NAME' context of '$FQIN'" + warn "$SCRIPT_FILENAME not version-tagging for '$FLAVOR_NAME' stage of '$FQIN'" fi diff --git a/build-push/test.sh b/build-push/test.sh index f72fd564..dd6957ef 100644 --- a/build-push/test.sh +++ b/build-push/test.sh @@ -53,9 +53,14 @@ cd "contrib/testimage/stable" echo "build-push-test version v$FAKE_VERSION" | tee "FAKE_VERSION" cat < /FLAVOUR EOF +cd .. +# Also test passing flavor as an argument +ln -s stable foobar cd $SRC_TMP/testing git add --all git commit -m 'test repo initial commit' @@ -71,44 +76,68 @@ env A_DEBUG=1 main.sh git://testing contrib/testimage/stable # Because this is a 'stable' image, verify that main.sh will properly # version-tagged both FQINs. No need to check 'latest'. -msg " +verify_built_images() { + msg " ##### Testing execution of images arches $TESTARCHES #####" -podman --version -req_env_vars TESTARCHES FAKE_VERSION TEST_FQIN TEST_FQIN2 -for _fqin in $TEST_FQIN $TEST_FQIN2; do - for _arch in $TESTARCHES; do - # As of podman 3.4.4, the --arch=$arch argument will cause failures - # looking up the image in local storage. This bug is fixed in later - # versions. For now, query the manifest directly for the image sha256. - _q='.manifests[] | select(.platform.architecture == "'"$_arch"'") | .digest' - _s=$(podman manifest inspect $_fqin:v$FAKE_VERSION | jq -r "$_q") - msg "Found '$_arch' in manifest-list $_fqin:v$FAKE_VERSION as digest $_s" - if [[ -z "$_s" ]]; then - die "Failed to get sha256 for FQIN '$_fqin:v$FAKE_VERSION' ($_arch)" - fi - msg "Testing container can ping localhost" - showrun podman run -i --rm "$_fqin@$_s" ping -q -c 1 127.0.0.1 - - xy_ver="v$FAKE_VER_X.$FAKE_VER_Y" - msg "Testing tag '$xy_ver'" - if ! podman manifest inspect $_fqin:$xy_ver &> /dev/null; then - die "Failed to find manifest-list tagged '$xy_ver'" - fi - - x_ver="v$FAKE_VER_X" - msg "Testing tag '$x_ver'" - if ! podman manifest inspect $_fqin:$x_ver &> /dev/null; then - die "Failed to find manifest-list tagged '$x_ver'" - fi - - #TODO: Test org.opencontainers.image.source value - #TODO: fails, returns null for some reason - #msg "Confirming version-label matches tag" - #_q='.[0].Labels."org.opencontainers.image.version"' - #_v=$(podman image inspect "$_fqin@$_s" | jq -r "$_q") - #showrun test $_v -eq $FAKE_VERSION + podman --version + req_env_vars TESTARCHES FAKE_VERSION TEST_FQIN TEST_FQIN2 + for _fqin in $TEST_FQIN $TEST_FQIN2; do + for _arch in $TESTARCHES; do + # As of podman 3.4.4, the --arch=$arch argument will cause failures + # looking up the image in local storage. This bug is fixed in later + # versions. For now, query the manifest directly for the image sha256. + _q='.manifests[] | select(.platform.architecture == "'"$_arch"'") | .digest' + _s=$(podman manifest inspect $_fqin:v$FAKE_VERSION | jq -r "$_q") + msg "Found '$_arch' in manifest-list $_fqin:v$FAKE_VERSION as digest $_s" + if [[ -z "$_s" ]]; then + die "Failed to get sha256 for FQIN '$_fqin:v$FAKE_VERSION' ($_arch)" + fi + msg "Testing container can ping localhost" + showrun podman run -i --rm "$_fqin@$_s" ping -q -c 1 127.0.0.1 + + msg "Testing container FLAVOR build-arg passed correctly" + showrun podman run -i --rm "$_fqin@$_s" cat /FLAVOUR | \ + tee /dev/stderr | \ + grep -q 'FLAVOUR=stable' + + xy_ver="v$FAKE_VER_X.$FAKE_VER_Y" + msg "Testing tag '$xy_ver'" + if ! podman manifest inspect $_fqin:$xy_ver &> /dev/null; then + die "Failed to find manifest-list tagged '$xy_ver'" + fi + + x_ver="v$FAKE_VER_X" + msg "Testing tag '$x_ver'" + if ! podman manifest inspect $_fqin:$x_ver &> /dev/null; then + die "Failed to find manifest-list tagged '$x_ver'" + fi + + #TODO: Test org.opencontainers.image.source value + #TODO: fails, returns null for some reason + #msg "Confirming version-label matches tag" + #_q='.[0].Labels."org.opencontainers.image.version"' + #_v=$(podman image inspect "$_fqin@$_s" | jq -r "$_q") + #showrun test $_v -eq $FAKE_VERSION + done + done +} + +untag_built_images() { + for _fqin in $TEST_FQIN $TEST_FQIN2; do + for tag in latest v$FAKE_VERSION v$FAKE_VER_X.$FAKE_VER_Y v$FAKE_VER_X; do + # Don't care if this fails + podman untag $_fqin:$tag || true + done done -done +} + +verify_built_images +msg " +##### Testing build-push multi-arch flavour build of '$TEST_FQIN'/'$TEST_FQIN2' #####" +untag_built_images +# This should use cache +env A_DEBUG=1 main.sh git://testing contrib/testimage/foobar stable +verify_built_images # This script verifies it's only/ever running inside CI. Use a fake # main.sh to verify it auto-updates itself w/o actually performing