diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e19a53e4..7d1d763e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,10 +11,48 @@ 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 + - 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 < "../checksum/$i.sha256"; done && cd - @@ -56,30 +88,6 @@ 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: @@ -87,24 +95,9 @@ jobs: password: ${{ secrets.DOCKER_PASSWORD }} # longhornio/longhorn-cli 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-cli:${{ 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-cli:${{ github.ref_name }} - file: package/Dockerfile - sbom: true \ No newline at end of file + - 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 diff --git a/Makefile b/Makefile index 7a45fda1..2928f989 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,10 @@ +PROJECT := longhorn-cli TARGETS := $(shell ls dapper) +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 @@ -10,6 +16,22 @@ TARGETS := $(shell ls dapper) $(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' IMAGE_NAME=$(PROJECT) bash dapper/package +workflow-image-build-push-secure: buildx-machine + MACHINE=$(MACHINE) PUSH='true' IMAGE_NAME=$(PROJECT) IS_SECURE=true bash dapper/package + .DEFAULT_GOAL := ci .PHONY: $(TARGETS) diff --git a/dapper/package b/dapper/package index a691c815..1bb407c5 100755 --- a/dapper/package +++ b/dapper/package @@ -3,24 +3,52 @@ set -e ROOT_DIR=$(cd "$(dirname "$0")"/.. && pwd) -ARCH=${ARCH:-amd64} -SUFFIX="" -[ "${ARCH}" != "amd64" ] && SUFFIX="_${ARCH}" +source "${ROOT_DIR}/dapper/version" +cd "${ROOT_DIR}" + +command -v buildx >/dev/null && BUILD_CMD=(buildx) || BUILD_CMD=(docker buildx) +# read configurable parameters +REPO=${REPO:-'longhornio'} +IMAGE_NAME=${IMAGE_NAME:-'longhorn-cli'} TAG=${TAG:-v$(date -u +%Y%m%d)} -REPO=${REPO:-longhornio} -IMAGE=${IMAGE:-${REPO}/longhorn-cli:${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:-''} -source "${ROOT_DIR}/dapper/version" -cd "${ROOT_DIR}" +IMAGE="${REPO}/${IMAGE_NAME}:${TAG}" -if [ ! -e ./bin/longhornctl ]; then - ./dapper/build +BUILDER_ARGS=() +[[ ${MACHINE} ]] && BUILDER_ARGS+=('--builder' "${MACHINE}") + +IFS=' ' read -r -a IID_FILE_ARGS <<<"${IID_FILE_FLAG}" +[[ -n "$IID_FILE" && ${#IID_FILE_ARGS} == 0 ]] && IID_FILE_ARGS=('--iidfile' "${IID_FILE}") + +BUILDX_ARGS=() + +if [[ "${PUSH}" == 'true' ]]; then + BUILDX_ARGS+=('--push') +else + BUILDX_ARGS+=('--load') fi -# Build image -buildx build --load -t ${IMAGE} -f package/Dockerfile . +[[ $IS_SECURE == 'true' ]] && BUILDX_ARGS+=('--sbom=true' '--attest' 'type=provenance,mode=max') +[[ $TARGET_PLATFORMS ]] && BUILDX_ARGS+=('--platform' "${TARGET_PLATFORMS}") + +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}" -echo Built "${IMAGE}" -# shellcheck disable=SC2086 -echo ${IMAGE} > ./bin/latest_image +mkdir ./bin || true +echo "${IMAGE}" > ./bin/latest_image diff --git a/package/Dockerfile b/package/Dockerfile index 861114ea..d73ca6e9 100644 --- a/package/Dockerfile +++ b/package/Dockerfile @@ -1,6 +1,19 @@ -# syntax=docker/dockerfile:1.12.1 +# syntax=docker/dockerfile:1.13.0 +FROM registry.suse.com/bci/golang:1.23 AS app_builder -FROM registry.suse.com/bci/golang:1.23 AS builder +WORKDIR /app + +# Copy the build script and source code +COPY . /app + +# Make the build script executable +RUN chmod +x /app/dapper/build + +# Run the build script +RUN /app/dapper/build + + +FROM registry.suse.com/bci/golang:1.23 AS spdk_builder ARG ARCH=amd64 @@ -14,7 +27,7 @@ RUN cd /usr/src && \ git checkout ${SPDK_COMMIT_ID} && \ rm -rf .git -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 \ @@ -30,10 +43,10 @@ RUN zypper -n ref && \ RUN zypper -n install jq && \ rm -rf /var/cache/zypp/* -COPY bin/longhornctl-linux-${ARCH} /usr/local/bin/longhornctl -COPY bin/longhornctl-local-linux-${ARCH} /usr/local/bin/longhornctl-local +COPY --from=app_builder /app/bin/longhornctl-linux-${ARCH} /usr/local/bin/longhornctl +COPY --from=app_builder /app/bin/longhornctl-local-linux-${ARCH} /usr/local/bin/longhornctl-local -COPY --from=builder \ +COPY --from=spdk_builder \ /spdk \ /spdk