diff --git a/.github/workflows/build-image-main.yml b/.github/workflows/build-image-main.yml new file mode 100644 index 00000000..4ec2a0ba --- /dev/null +++ b/.github/workflows/build-image-main.yml @@ -0,0 +1,51 @@ +name: Main container image build and tag + +on: + push: + branches: [ 'main' ] + +env: + QUAY_IMG_REPO: model-registry + QUAY_USERNAME: ${{ secrets.QUAY_USERNAME }} + QUAY_PASSWORD: ${{ secrets.QUAY_PASSWORD }} + PUSH_IMAGE: true + +jobs: + build-image: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Generate Tag + shell: bash + id: tags + run: | + commit_sha=${{ github.event.after }} + tag=main-${commit_sha:0:7} + echo "tag=${tag}" >> $GITHUB_OUTPUT + - name: Build and Push Image + shell: bash + env: + VERSION: ${{ steps.tags.outputs.tag }} + run: ./scripts/build_deploy.sh + - name: Tag Latest + shell: bash + env: + IMG: quay.io/${{ env.QUAY_ORG }}/${{ env.QUAY_IMG_REPO }} + BUILD_IMAGE: false + NEWEST_TAG: ${{ steps.tags.outputs.tag }} + VERSION: latest + run: | + docker tag ${{ env.IMG }}:${{ env.NEWEST_TAG }} ${{ env.IMG }}:${{ env.VERSION }} + # BUILD_IMAGE=false skip the build + ./scripts/build_deploy.sh + - name: Tag Main + shell: bash + env: + IMG: quay.io/${{ env.QUAY_ORG }}/${{ env.QUAY_IMG_REPO }} + BUILD_IMAGE: false + NEWEST_TAG: ${{ steps.tags.outputs.tag }} + VERSION: main + run: | + docker tag ${{ env.IMG }}:${{ env.NEWEST_TAG }} ${{ env.IMG }}:${{ env.VERSION }} + # BUILD_IMAGE=false skip the build + ./scripts/build_deploy.sh diff --git a/.github/workflows/build-image-pr.yml b/.github/workflows/build-image-pr.yml new file mode 100644 index 00000000..008ae021 --- /dev/null +++ b/.github/workflows/build-image-pr.yml @@ -0,0 +1,27 @@ +name: Test container image build + +on: + pull_request_target: + branches: [ '*' ] + +env: + QUAY_IMG_REPO: model-registry + PUSH_IMAGE: false + +jobs: + build-image: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Generate Tag + shell: bash + id: tags + run: | + commit_sha=${{ github.event.after }} + tag=main-${commit_sha:0:7} + echo "tag=${tag}" >> $GITHUB_OUTPUT + - name: Build Image + shell: bash + env: + VERSION: ${{ steps.tags.outputs.tag }} + run: ./scripts/build_deploy.sh \ No newline at end of file diff --git a/.github/workflows/container-image.yml b/.github/workflows/container-image.yml deleted file mode 100644 index 27833bbb..00000000 --- a/.github/workflows/container-image.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Test Container Image build - -on: - push: - branches: [ 'main' ] - pull_request: - branches: [ '*' ] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Build the Docker image - run: docker build . --file Dockerfile --tag model-registry:$(date +%s) diff --git a/Makefile b/Makefile index 6638beb6..f957b803 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,22 @@ PROJECT_BIN := $(PROJECT_PATH)/bin # add tools bin directory PATH := $(PROJECT_BIN):$(PATH) + +# docker executable +DOCKER ?= docker +# default Dockerfile +DOCKERFILE ?= Dockerfile +# container registry +IMG_REGISTRY ?= quay.io +# container image organization +IMG_ORG ?= opendatahub +# container image version +IMG_VERSION ?= main +# container image repository +IMG_REPO ?= model-registry +# container image +IMG := ${IMG_REGISTRY}/$(IMG_ORG)/$(IMG_REPO) + model-registry: build internal/ml_metadata/proto/%.pb.go: api/grpc/ml_metadata/proto/%.proto @@ -145,4 +161,19 @@ run/client: gen serve: build ./model-registry serve --logtostderr=true +# login to docker +.PHONY: docker/login +docker/login: + $(DOCKER) login -u "${DOCKER_USER}" -p "${DOCKER_PWD}" "${IMG_REGISTRY}" + +# build docker image +.PHONY: image/build +image/build: + ${DOCKER} build . -f ${DOCKERFILE} -t ${IMG}:$(IMG_VERSION) + +# push docker image +.PHONY: image/push +image/push: + ${DOCKER} push ${IMG}:$(IMG_VERSION) + all: model-registry diff --git a/scripts/build_deploy.sh b/scripts/build_deploy.sh new file mode 100755 index 00000000..9855569f --- /dev/null +++ b/scripts/build_deploy.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +set -e + +# quay.io credentials +QUAY_REGISTRY=quay.io +QUAY_ORG="${QUAY_ORG:-opendatahub}" +QUAY_IMG_REPO="${QUAY_IMG_REPO:-model-registry}" +QUAY_USERNAME="${QUAY_USERNAME}" +QUAY_PASSWORD="${QUAY_PASSWORD}" + +# image version +HASH="$(git rev-parse --short=7 HEAD)" +VERSION="${VERSION:-$HASH}" + +# if set to 0 skip image build +# otherwise build it +BUILD_IMAGE="${BUILD_IMAGE:-true}" + +# if set to 0 skip push to registry +# otherwise push it +PUSH_IMAGE="${PUSH_IMAGE:-false}" + +# skip if image already existing on registry +SKIP_IF_EXISTING="${SKIP_IF_EXISTING:-false}" + +# assure docker exists +docker -v foo >/dev/null 2>&1 || { echo >&2 "::error:: Docker is required. Aborting."; exit 1; } + +# skip if image already existing +if [[ "${SKIP_IF_EXISTING,,}" == "true" ]]; then + TAGS=$(curl --request GET "https://$QUAY_REGISTRY/api/v1/repository/${QUAY_ORG}/${QUAY_IMG_REPO}/tag/?specificTag=${VERSION}") + LATEST_TAG_HAS_END_TS=$(echo $TAGS | jq .tags - | jq 'sort_by(.start_ts) | reverse' | jq '.[0].end_ts') + NOT_EMPTY=$(echo ${TAGS} | jq .tags - | jq any) + + # Image only exists if there is a tag that does not have "end_ts" (i.e. it is still present). + if [[ "$NOT_EMPTY" == "true" && $LATEST_TAG_HAS_END_TS == "null" ]]; then + echo "::error:: The image ${QUAY_ORG}/${QUAY_IMG_REPO}:${VERSION} already exists" + exit 1 + else + echo "Image does not exist...proceeding with build & push." + fi +fi + +# build docker image, login is not required at this step +if [[ "${BUILD_IMAGE,,}" == "true" ]]; then + echo "Building container image.." + make \ + IMG_REGISTRY="${QUAY_REGISTRY}" \ + IMG_ORG="${QUAY_ORG}" \ + IMG_REPO="${QUAY_IMG_REPO}" \ + IMG_VERSION="${VERSION}" \ + image/build +else + echo "Skip container image build." +fi + +# push container image to registry, requires login +if [[ "${PUSH_IMAGE,,}" == "true" ]]; then + echo "Pushing container image.." + make \ + IMG_REGISTRY="${QUAY_REGISTRY}" \ + IMG_ORG="${QUAY_ORG}" \ + IMG_REPO="${QUAY_IMG_REPO}" \ + IMG_VERSION="${VERSION}" \ + DOCKER_USER="${QUAY_USERNAME} "\ + DOCKER_PWD="${QUAY_PASSWORD}" \ + docker/login \ + image/push +else + echo "Skip container image push." +fi \ No newline at end of file