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 <yunchang.lo@suse.com>
  • Loading branch information
COLDTURNIP authored and derekbit committed Feb 14, 2025
1 parent 71c42b8 commit f2d94df
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 76 deletions.
101 changes: 50 additions & 51 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,58 @@ jobs:
build:
name: Build binaries
runs-on: ubuntu-latest
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

# Build binaries
- 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/' <<<${{ github.ref_name }} )
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 and verify binaries
- name: Run ci
run: make ci
run: NO_PACKAGE=true make ci

- uses: codecov/codecov-action@v4
with:
files: ./coverage.out
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-latest
Expand All @@ -40,55 +72,22 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- name: Download binaries
uses: actions/download-artifact@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
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/
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

# 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-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-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-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 }}
TARGET_PLATFORMS: linux/amd64,linux/arm64
run: make workflow-image-build-push
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
*.o
*.a
*.so
/coverage.out

# Folders
_obj
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.dapper
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ ENV HOST_ARCH=${DAPPER_HOST_ARCH} ARCH=${DAPPER_HOST_ARCH}
ENV DAPPER_SOURCE /go/src/github.com/longhorn/longhorn-manager
ENV DAPPER_OUTPUT ./bin coverage.out
ENV DAPPER_DOCKER_SOCKET true
ENV DAPPER_ENV IMAGE REPO VERSION TAG TESTS DRONE_REPO DRONE_PULL_REQUEST DRONE_COMMIT_REF
ENV DAPPER_ENV IMAGE REPO VERSION TAG TESTS DRONE_REPO DRONE_PULL_REQUEST DRONE_COMMIT_REF NO_PACKAGE ARCHS
ENV DAPPER_RUN_ARGS --privileged --tmpfs /go/src/github.com/longhorn/longhorn/integration/.venv:exec --tmpfs /go/src/github.com/longhorn/longhorn/integration/.tox:exec -v /dev:/host/dev
ENV TRASH_CACHE ${DAPPER_SOURCE}/.trash-cache
ENV HOME ${DAPPER_SOURCE}
Expand Down
22 changes: 22 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
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

.dapper:
@echo Downloading dapper
Expand All @@ -9,6 +14,23 @@ TARGETS := $(shell ls scripts)

$(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

generate:
bash k8s/generate_code.sh

Expand Down
18 changes: 15 additions & 3 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 builder

FROM registry.suse.com/bci/bci-base:15.6
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 release

ARG TARGETPLATFORM
RUN if [ "$TARGETPLATFORM" != "linux/amd64" ] && [ "$TARGETPLATFORM" != "linux/arm64" ]; then \
Expand All @@ -16,9 +28,9 @@ RUN zypper -n ref && \
RUN zypper -n install iputils iproute2 nfs-client cifs-utils bind-utils e2fsprogs xfsprogs zip unzip kmod && \
rm -rf /var/cache/zypp/*

COPY package/bin/longhorn-manager-${ARCH} /usr/local/sbin/longhorn-manager
COPY --from=builder /app/bin/longhorn-manager-${ARCH} /usr/local/sbin/longhorn-manager

COPY package/launch-manager package/nsmounter /usr/local/sbin/
COPY --from=builder /app/package/launch-manager /app/package/nsmounter /usr/local/sbin/

EXPOSE 9500
CMD ["launch-manager"]
21 changes: 19 additions & 2 deletions scripts/build
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,22 @@ cd $(dirname $0)/..

mkdir -p bin

CGO_ENABLED=0 GOARCH=amd64 go build -o bin/longhorn-manager-amd64 -ldflags "$LINKFLAGS $OTHER_LINKFLAGS" $COVER $COVERPKG
CGO_ENABLED=0 GOARCH=arm64 go build -o bin/longhorn-manager-arm64 -ldflags "$LINKFLAGS $OTHER_LINKFLAGS" $COVER $COVERPKG
ARCHS=${ARCHS:-''}
if [[ -z "${ARCHS}" ]]; then
case $(uname -m) in
aarch64 | arm64)
ARCHS=(arm64)
;;
x86_64)
ARCHS=(amd64)
;;
*)
echo "$(uname -a): unsupported architecture"
exit 1
esac
else
IFS=' ' read -r -a ARCHS <<<"${ARCHS}"
fi
for arch in "${ARCHS[@]}"; do
CGO_ENABLED=0 GOARCH=${arch} go build -o bin/longhorn-manager-${arch} -ldflags "${LINKFLAGS} ${OTHER_LINKFLAGS}" ${COVER} ${COVERPKG}
done
11 changes: 7 additions & 4 deletions scripts/ci
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ cd $(dirname $0)
./build
./validate
./test -cover
./package

image=`cat ../bin/latest_image`
if [[ -z "${NO_PACKAGE}" ]]; then
./package

echo
echo Longhorn Manager image: ${image}
IMAGE=$(cat ../bin/latest_image)

echo
echo "Longhorn Manager IMAGE: ${IMAGE}"
fi
60 changes: 45 additions & 15 deletions scripts/package
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,55 @@ source $(dirname $0)/version

cd $(dirname $0)/..

TAG=${TAG:-${IMAGE_TAG_PREFIX}}
REPO=${REPO:-longhornio}
IMAGE=${IMAGE:-${REPO}/longhorn-manager:${TAG}}
command -v buildx >/dev/null && BUILD_CMD=(buildx) || BUILD_CMD=(docker buildx)

if [ ! -e ./bin/longhorn-manager-amd64 ] || [ ! -e ./bin/longhorn-manager-arm64 ]; then
echo "Building longhorn-manager binary before packaging"
./scripts/build
fi
# read configurable parameters
REPO=${REPO:-longhornio}
IMAGE_NAME=${IMAGE_NAME:-'longhorn-manager'}
TAG=${TAG:-${IMAGE_TAG_PREFIX}}
PUSH=${PUSH:-'false'}
IS_SECURE=${IS_SECURE:-'false'}
MACHINE=${MACHINE:-''}
TARGET_PLATFORMS=${TARGET_PLATFORMS:-''}
IID_FILE=${IID_FILE:-''}
IID_FILE_FLAG=${IID_FILE_FLAG:-''}

cp -r bin package/
IMAGE="${REPO}/${IMAGE_NAME}:${TAG}"

trap 'rm -rf ./package/bin' exit
BUILDER_ARGS=()
[[ ${MACHINE} ]] && BUILDER_ARGS+=('--builder' "${MACHINE}")

# update base image to get latest changes
BASE_IMAGE=`grep FROM package/Dockerfile | awk '{print $2}'`
docker pull ${BASE_IMAGE}
IFS=' ' read -r -a IID_FILE_ARGS <<<"${IID_FILE_FLAG}"
[[ -n "${IID_FILE}" && ${#IID_FILE_ARGS} == 0 ]] && IID_FILE_ARGS=('--iidfile' "${IID_FILE}")

buildx build --load -t ${IMAGE} -f package/Dockerfile .
BUILDX_ARGS=()

echo Built ${IMAGE}
if [[ "${PUSH}" == 'true' ]]; then
BUILDX_ARGS+=('--push')
else
BUILDX_ARGS+=('--load')
fi

echo ${IMAGE} > ./bin/latest_image
[[ ${IS_SECURE} == 'true' ]] && BUILDX_ARGS+=('--sbom=true' '--attest' 'type=provenance,mode=max')
[[ ${TARGET_PLATFORMS} ]] && BUILDX_ARGS+=('--platform' "${TARGET_PLATFORMS}")

# update base IMAGE to get latest changes
grep 'FROM.*/' package/Dockerfile | awk '{print $2}' | while read -r BASE_IMAGE
do
docker pull "${BASE_IMAGE}"
done

IMAGE_BUILD_CMD_ARGS=(
build --no-cache \
"${BUILDER_ARGS[@]}" \
"${IID_FILE_ARGS[@]}" \
"${BUILDX_ARGS[@]}" \
-t "${IMAGE}" -f package/Dockerfile .
)
echo "${BUILD_CMD[@]}" "${IMAGE_BUILD_CMD_ARGS[@]}"
"${BUILD_CMD[@]}" "${IMAGE_BUILD_CMD_ARGS[@]}"

echo "Built ${IMAGE}"

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

0 comments on commit f2d94df

Please sign in to comment.