Skip to content

Commit

Permalink
feat: self-contained container image build
Browse files Browse the repository at this point in the history
Signed-off-by: Raphanus Lo <[email protected]>
  • Loading branch information
COLDTURNIP authored and derekbit committed Feb 13, 2025
1 parent 742209d commit 4f7e6b2
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 82 deletions.
94 changes: 43 additions & 51 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,48 @@ jobs:
build:
name: Build binaries
runs-on: ubuntu-22.04
outputs:
version_major: ${{ steps.build_info.outputs.version_major }}
version_minor: ${{ steps.build_info.outputs.version_minor }}
version_patch: ${{ steps.build_info.outputs.version_patch }}
image_tag: ${{ steps.build_info.outputs.image_tag }}

steps:
- name: Checkout code
uses: actions/checkout@v4

- id: build_info
name: Declare build info
run: |
version_major=''
version_minor=''
version_patch=''
image_tag=''
branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}
ref=${{ github.ref }}
if [[ "$ref" =~ 'refs/tags/' ]]; then
version=$(sed -E 's/^v([0-9]*\.[0-9]*\.[0-9]*).*$/\1/' <<<$ref )
version_major=$(cut -d. -f1 <<<$version)
version_minor=$(cut -d. -f2 <<<$version)
version_patch=$(cut -d. -f3 <<<$version)
image_tag=${{ github.ref_name }}
elif [[ "$ref" =~ 'refs/heads/' ]]; then
image_tag="${branch}-head"
fi
echo "version_major=${version_major}" >>$GITHUB_OUTPUT
echo "version_minor=${version_minor}" >>$GITHUB_OUTPUT
echo "version_patch=${version_patch}" >>$GITHUB_OUTPUT
echo "image_tag=${image_tag}" >>$GITHUB_OUTPUT
cat <<EOF
version_major=${version_major}
version_minor=${version_minor}
version_patch=${version_patch}
image_tag=${image_tag}
EOF
# Build binaries
- name: Run ci
run: make ci
Expand All @@ -25,12 +63,6 @@ jobs:
flags: unittests
token: ${{ secrets.CODECOV_TOKEN }}

- name: Upload binaries
uses: actions/upload-artifact@v4
with:
name: binaries_artifact
path: ./bin/*

build_push_image:
name: Build and push image
runs-on: ubuntu-22.04
Expand All @@ -40,55 +72,15 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- name: Download binaries
uses: actions/download-artifact@v4
with:
name: binaries_artifact
path: ./bin/

- name: Add executable permission
run: |
chmod +x ./bin/*
- name: Copy bin folder to package
run: |
cp -r ./bin ./package/
# For multi-platform support
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Declare branch
run: |
echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> "$GITHUB_ENV"
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

# longhornio/longhorn-share-manager image
- name: docker-publish
if: ${{ startsWith(github.ref, 'refs/heads/') }}
uses: docker/build-push-action@v5
with:
context: ./
push: true
platforms: linux/amd64,linux/arm64
tags: longhornio/longhorn-share-manager:${{ env.branch }}-head
file: package/Dockerfile
sbom: true

- name: docker-publish-with-tag
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: docker/build-push-action@v5
with:
context: ./
push: true
platforms: linux/amd64,linux/arm64
tags: longhornio/longhorn-share-manager:${{ github.ref_name }}
file: package/Dockerfile
sbom: true
- name: Build and publish image
env:
REPO: docker.io/longhornio
TAG: ${{ needs.build.outputs.image_tag }}
run: make workflow-image-build-push
23 changes: 22 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
TARGETS := $(shell ls scripts)
MACHINE := longhorn
# Define the target platforms that can be used across the ecosystem.
# Note that what would actually be used for a given project will be
# defined in TARGET_PLATFORMS, and must be a subset of the below:
DEFAULT_PLATFORMS := linux/amd64,linux/arm64

export SRC_BRANCH := $(shell bash -c 'wget -q "https://raw.githubusercontent.com/longhorn/dep-versions/main/scripts/common.sh" -O build-common.sh && source build-common.sh && get_branch')
export SRC_BRANCH := $(shell bash -c 'source <(curl -s "https://raw.githubusercontent.com/longhorn/dep-versions/main/scripts/common.sh") && get_branch')
export SRC_TAG := $(shell git tag --points-at HEAD | head -n 1)

.dapper:
Expand All @@ -13,6 +18,22 @@ export SRC_TAG := $(shell git tag --points-at HEAD | head -n 1)
$(TARGETS): .dapper
./.dapper $@

.PHONY: buildx-machine
buildx-machine:
@docker buildx create --name=$(MACHINE) --platform=$(DEFAULT_PLATFORMS) 2>/dev/null || true
docker buildx inspect $(MACHINE)

# variables needed from GHA caller:
# - REPO: image repo, include $registry/$repo_path
# - TAG: image tag
# - TARGET_PLATFORMS: optional, to be passed for buildx's --platform option
# - IID_FILE_FLAG: optional, options to generate image ID file
.PHONY: workflow-image-build-push workflow-image-build-push-secure
workflow-image-build-push: buildx-machine
MACHINE=$(MACHINE) PUSH='true' bash scripts/package
workflow-image-build-push-secure: buildx-machine
MACHINE=$(MACHINE) PUSH='true' IS_SECURE=true bash scripts/package

.DEFAULT_GOAL := ci

.PHONY: $(TARGETS)
24 changes: 18 additions & 6 deletions package/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
# syntax=docker/dockerfile:1.13.0
FROM registry.suse.com/bci/golang:1.23 AS app_builder

FROM registry.suse.com/bci/bci-base:15.6 AS build
WORKDIR /app

# Copy the build script and source code
COPY . /app

# Make the build script executable
RUN chmod +x /app/scripts/build

# Run the build script
RUN /app/scripts/build

FROM registry.suse.com/bci/bci-base:15.6 AS lib_builder

ARG SRC_BRANCH=main
ARG SRC_TAG
Expand Down Expand Up @@ -33,14 +45,14 @@ RUN export REPO_OVERRIDE="" && \
bash /usr/src/dep-versions/scripts/build-nfs-ganesha.sh "${REPO_OVERRIDE}" "${COMMIT_ID_OVERRIDE}"


FROM registry.suse.com/bci/bci-base:15.6
FROM registry.suse.com/bci/bci-base:15.6 AS release

ARG TARGETPLATFORM
RUN if [ "$TARGETPLATFORM" != "linux/amd64" ] && [ "$TARGETPLATFORM" != "linux/arm64" ]; then \
echo "Error: Unsupported TARGETPLATFORM: $TARGETPLATFORM" && \
exit 1; \
fi
ENV ARCH ${TARGETPLATFORM#linux/}
ENV ARCH=${TARGETPLATFORM#linux/}

RUN zypper -n ref && \
zypper update -y
Expand All @@ -64,9 +76,9 @@ RUN sed -i s/systemd// /etc/nsswitch.conf
# ganesha reads /etc/mtab for mounted volumes
RUN ln -sf /proc/self/mounts /etc/mtab

COPY --from=build /usr/local /usr/local/
COPY --from=build /ganesha-extra /
COPY package/bin/longhorn-share-manager-${ARCH} /longhorn-share-manager
COPY --from=lib_builder /usr/local /usr/local/
COPY --from=lib_builder /ganesha-extra /
COPY --from=app_builder /app/bin/longhorn-share-manager-${ARCH} /longhorn-share-manager

# run ldconfig after libs have been copied
RUN ldconfig
Expand Down
100 changes: 76 additions & 24 deletions scripts/package
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,91 @@ source $(dirname $0)/version

cd $(dirname $0)/..

PROJECT=`basename "$PWD"`
PROJECT=$(basename "${PWD}")

if [ ! -x ./bin/longhorn ]; then
./scripts/build
command -v buildx >/dev/null && BUILD_CMD=(buildx) || BUILD_CMD=(docker buildx)

# read configurable parameters
REPO=${REPO:-longhornio}
IMAGE_NAME=${IMAGE_NAME:-${PROJECT}}
TAG=${TAG:-''}
PUSH=${PUSH:-'false'}
IS_SECURE=${IS_SECURE:-'false'}
MACHINE=${MACHINE:-''}
TARGET_PLATFORMS=${TARGET_PLATFORMS:-''}
IID_FILE=${IID_FILE:-''}
IID_FILE_FLAG=${IID_FILE_FLAG:-''}
SRC_BRANCH=${SRC_BRANCH:-''}
SRC_TAG=${SRC_TAG:-''}

BUILDER_ARGS=()
[[ $MACHINE ]] && BUILDER_ARGS+=('--builder' "$MACHINE")

BUILDX_ARGS=()

if [[ ${TARGET_PLATFORMS} ]] ; then
IFS='/' read -r OS ARCH <<<"${TARGET_PLATFORMS}"
BUILDX_ARGS+=('--platform' "${TARGET_PLATFORMS}")
else
case $(uname -m) in
aarch64 | arm64)
ARCH=arm64
;;
x86_64)
ARCH=amd64
;;
*)
echo "$(uname -a): unsupported architecture"
exit 1
esac
BUILDX_ARGS+=('--platform' "linux/${ARCH}")
fi

cp -r bin package/
if [[ -z $TAG ]]; then
if API_VERSION=$(./bin/longhorn-share-manager-"${ARCH}" version --client-only | jq ".clientVersion.apiVersion"); then
TAG="v${API_VERSION}_$(date -u +%Y%m%d)"
else
TAG="${VERSION}"
fi
fi

IMAGE="${REPO}/${IMAGE_NAME}:${TAG}"

IFS=' ' read -r -a IID_FILE_ARGS <<<"${IID_FILE_FLAG}"
[[ -n "${IID_FILE}" && ${#IID_FILE_ARGS} == 0 ]] && IID_FILE_ARGS=('--iidfile' "${IID_FILE}")

arch=$(uname -m)
if [ "$arch" == "aarch64" ]; then
ARCH="arm64"
if [[ "${PUSH}" == 'true' ]]; then
BUILDX_ARGS+=('--push')
else
ARCH="amd64"
BUILDX_ARGS+=('--load')
fi
APIVERSION=`./bin/longhorn-share-manager-"$ARCH" version --client-only|jq ".clientVersion.apiVersion"`

TAG=${TAG:-"v${APIVERSION}_`date -u +%Y%m%d`"}
REPO=${REPO:-longhornio}
IMAGE=${REPO}/${PROJECT}:${TAG}
[[ $IS_SECURE == 'true' ]] && BUILDX_ARGS+=('--sbom=true' '--attest' 'type=provenance,mode=max')

IMAGE_ARGS=(--build-arg ARCH="${ARCH}")
[[ -n "${SRC_BRANCH}" ]] && IMAGE_ARGS+=(--build-arg SRC_BRANCH="${SRC_BRANCH}")
[[ -n "${SRC_TAG}" ]] && IMAGE_ARGS+=(--build-arg SRC_TAG="${SRC_TAG}")

# update base image to get latest changes
BASE_IMAGE=`grep FROM package/Dockerfile | grep -v AS | awk '{print $2}'`
docker pull ${BASE_IMAGE}
# update base IMAGE to get latest changes
grep 'FROM.*/' package/Dockerfile | awk '{print $2}' | while read -r STAGE_BASE_IMAGE
do
docker pull "${STAGE_BASE_IMAGE}"
done
BASE_IMAGE=$(grep 'FROM.*AS release' package/Dockerfile | awk '{print $2}')

echo "Building image ${IMAGE} based on ${BASE_IMAGE} with ARCH=${ARCH} SRC_BRANCH=${SRC_BRANCH} SRC_TAG=${SRC_TAG}"
buildx build \
--load \
--build-arg ARCH="${ARCH}" \
--build-arg SRC_BRANCH="${SRC_BRANCH}" \
--build-arg SRC_TAG="${SRC_TAG}" \
-t "${IMAGE}" \
-f package/Dockerfile .
IMAGE_BUILD_CMD_ARGS=(
build --no-cache \
"${BUILDER_ARGS[@]}" \
"${IID_FILE_ARGS[@]}" \
"${BUILDX_ARGS[@]}" \
"${IMAGE_ARGS[@]}" \
-t "${IMAGE}" -f package/Dockerfile .
)
echo "${BUILD_CMD[@]}" "${IMAGE_BUILD_CMD_ARGS[@]}"
"${BUILD_CMD[@]}" "${IMAGE_BUILD_CMD_ARGS[@]}"

echo Built ${IMAGE}
echo "Built ${IMAGE}"

echo ${IMAGE} > ./bin/latest_image
mkdir ./bin || true
echo "${IMAGE}" > ./bin/latest_image

0 comments on commit 4f7e6b2

Please sign in to comment.