Skip to content

Commit

Permalink
Add FLAVOUR build-arg support to build_push
Browse files Browse the repository at this point in the history
This is needed to support image-builds which rely on passing a build-arg
to indicate the flavour-name or type of image.  For example, `upstream`,
`testing`, or `stable`.  Accommodations are also made to continue
supporting the previous method - where the flavour is taken as the
base-name of the context directory.  To prevent any ambiguity, the
flavour argument will be preferred over the sub-directory name.

In all cases, the flavor value will be passed to buildah via
a `--build-arg FLAVOUR=<value>`.  Additionally it will
be passed to the `tag-version.sh` mod-script as the first argument,
with the command version number as the second argument.

Signed-off-by: Chris Evich <[email protected]>
  • Loading branch information
cevich committed Oct 3, 2022
1 parent ee36b6f commit b1cd187
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 75 deletions.
57 changes: 40 additions & 17 deletions build-push/bin/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -59,22 +64,31 @@ 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
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
"

Expand All @@ -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
Expand All @@ -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" ;;
Expand All @@ -131,22 +149,27 @@ 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/<reponame>, both
# latest and version-tagged (if available).
build-push.sh \
$_DRNOPUSH \
--arches=$ARCHES \
--modcmd=tag_version.sh \
--modcmd="$modcmdarg" \
$REPO_FQIN \
./$CTX_SUB \
$lblargs
$lblargs \
"${build_args[@]}"
47 changes: 29 additions & 18 deletions build-push/bin/tag_version.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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
108 changes: 68 additions & 40 deletions build-push/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,62 +53,90 @@ cd "contrib/testimage/stable"
echo "build-push-test version v$FAKE_VERSION" | tee "FAKE_VERSION"
cat <<EOF | tee "Containerfile"
FROM registry.fedoraproject.org/fedora:latest
ARG FLAVOR
ADD /FAKE_VERSION /
RUN dnf install -y iputils
RUN echo "FLAVOUR=\$FLAVOR" > /FLAVOUR
EOF
cd $SRC_TMP/testing/contrib/testimage
cp stable/Containerfile ./
cd $SRC_TMP/testing
git add --all
git commit -m 'test repo initial commit'

msg "
##### Testing build-push multi-arch build of '$TEST_FQIN'/'$TEST_FQIN2' #####"

# Because this is a 'stable' image, verify that main.sh will properly
# version-tagged both FQINs. No need to check 'latest'.
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

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
}

buildah --version
export DRYRUN=1 # Force main.sh not to push anything
req_env_vars ARCHES DRYRUN
# main.sh is sensitive to 'testing' value.
# also confirms main.sh is on $PATH
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'.
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
done
done
##### 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 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
Expand Down

0 comments on commit b1cd187

Please sign in to comment.