blob: 0d344974c0682bdf0a70c90449e2cc9ef1bbb728 [file]
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
name: Main (Build/Test/Publish)
on:
workflow_call:
inputs:
spark:
description: The Spark version of Spark image.
required: true
type: string
default: 3.3.0
scala:
description: The Scala version of Spark image.
required: true
type: string
default: 2.12
java:
description: The Java version of Spark image.
required: true
type: string
default: 11
build:
description: Build the image or not.
required: false
type: boolean
default: true
publish:
description: Publish the image or not.
required: false
type: boolean
default: false
repository:
description: The registry to be published/tested. (Available only in publish/test workflow)
required: false
type: string
default: ghcr.io/apache/spark-docker
image-type:
description: The image type of the image (all, python, scala, r).
required: false
type: string
default: python
image-tag:
type: string
description: The image tag to be tested. (Available only in test workflow)
required: false
default: latest
jobs:
main:
runs-on: ubuntu-latest
# Due to the multi-platform images cannot be exported with the `docker` export type,
# https://github.com/docker/buildx/issues/59
# So, the local registry (push) is used here rather than local build (load):
# https://github.com/docker/build-push-action/blob/master/docs/advanced/local-registry.md
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
- name: Checkout Spark Docker repository
uses: actions/checkout@v3
- name: Free up disk space
shell: 'script -q -e -c "bash {0}"'
run: |
chmod +x tools/ci_runner_cleaner/free_disk_space_container.sh
tools/ci_runner_cleaner/free_disk_space_container.sh
chmod +x tools/ci_runner_cleaner/free_disk_space.sh
tools/ci_runner_cleaner/free_disk_space.sh
- name: Prepare - Generate tags
run: |
case "${{ inputs.image-type }}" in
all) SUFFIX=python3-r-ubuntu
;;
python) SUFFIX=python3-ubuntu
;;
r) SUFFIX=r-ubuntu
;;
scala) SUFFIX=ubuntu
;;
esac
BASE_IMGAE_TAG=${{ inputs.spark }}-scala${{ inputs.scala }}-java${{ inputs.java }}-ubuntu
TAG=scala${{ inputs.scala }}-java${{ inputs.java }}-$SUFFIX
IMAGE_NAME=spark
IMAGE_PATH=${{ inputs.spark }}/$TAG
BASE_IMAGE_PATH=${{ inputs.spark }}/scala${{ inputs.scala }}-java${{ inputs.java }}-ubuntu
if [ "${{ inputs.build }}" == "true" ]; then
# Use the local registry to build and test
REPO_OWNER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
TEST_REPO=localhost:5000/$REPO_OWNER/spark-docker
UNIQUE_IMAGE_TAG=${{ inputs.spark }}-$TAG
else
# Use specified {repository}/spark:{image-tag} image to test
TEST_REPO=${{ inputs.repository }}
UNIQUE_IMAGE_TAG=${{ inputs.image-tag }}
fi
# We can't use the real image for build because we haven't publish the image yet.
# The base image for build, it's something like localhost:5000/$REPO_OWNER/spark-docker/spark:3.3.0-scala2.12-java11-ubuntu
BASE_IMAGE_URL=$TEST_REPO/$IMAGE_NAME:$BASE_IMGAE_TAG
IMAGE_URL=$TEST_REPO/$IMAGE_NAME:$UNIQUE_IMAGE_TAG
PUBLISH_REPO=${{ inputs.repository }}
PUBLISH_IMAGE_URL=`tools/manifest.py tags -i ${PUBLISH_REPO}/${IMAGE_NAME} -p ${{ inputs.spark }}/${TAG}`
# Unique image tag in each version: 3.3.0-scala2.12-java11-python3-ubuntu
echo "UNIQUE_IMAGE_TAG=${UNIQUE_IMAGE_TAG}" >> $GITHUB_ENV
# Test repo: ghcr.io/apache/spark-docker
echo "TEST_REPO=${TEST_REPO}" >> $GITHUB_ENV
# Image name: spark
echo "IMAGE_NAME=${IMAGE_NAME}" >> $GITHUB_ENV
# Base Image Dockerfile: 3.3.0/scala2.12-java11-ubuntu
echo "BASE_IMAGE_PATH=${BASE_IMAGE_PATH}" >> $GITHUB_ENV
# Image dockerfile path: 3.3.0/scala2.12-java11-python3-ubuntu
echo "IMAGE_PATH=${IMAGE_PATH}" >> $GITHUB_ENV
# Base Image URL: spark:3.3.0-scala2.12-java11-ubuntu
echo "BASE_IMAGE_URL=${BASE_IMAGE_URL}" >> $GITHUB_ENV
# Image URL: ghcr.io/apache/spark-docker/spark:3.3.0-scala2.12-java11-python3-ubuntu
echo "IMAGE_URL=${IMAGE_URL}" >> $GITHUB_ENV
echo "PUBLISH_REPO=${PUBLISH_REPO}" >> $GITHUB_ENV
echo "PUBLISH_IMAGE_URL=${PUBLISH_IMAGE_URL}" >> $GITHUB_ENV
- name: Prepare - Print Image tags
run: |
echo "UNIQUE_IMAGE_TAG: "${UNIQUE_IMAGE_TAG}
echo "TEST_REPO: "${TEST_REPO}
echo "IMAGE_NAME: "${IMAGE_NAME}
echo "IMAGE_PATH: "${IMAGE_PATH}
echo "IMAGE_URL: "${IMAGE_URL}
echo "BASE_IMAGE_PATH: "${BASE_IMAGE_PATH}
echo "BASE_IMAGE_URL: "${BASE_IMAGE_URL}
echo "PUBLISH_REPO:"${PUBLISH_REPO}
echo "PUBLISH_IMAGE_URL:"${PUBLISH_IMAGE_URL}
- name: Build - Set up QEMU
if: ${{ inputs.build }}
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a
with:
## Temporary due to bug in qemu: https://github.com/docker/setup-qemu-action/issues/198
image: tonistiigi/binfmt:qemu-v7.0.0-28
- name: Build - Set up Docker Buildx
if: ${{ inputs.build }}
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd
with:
# This required by local registry
driver-opts: network=host
- name: Build - Build the base image
# Don't need to build the base image when publish
if: ${{ inputs.build && !inputs.publish }}
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f
with:
context: ${{ env.BASE_IMAGE_PATH }}
tags: ${{ env.BASE_IMAGE_URL }}
platforms: linux/amd64,linux/arm64
push: true
- name: Build - Use the test image repo when build
# Don't need to build the base image when publish
if: ${{ inputs.build && !inputs.publish }}
working-directory: ${{ env.IMAGE_PATH }}
run: |
sed -i "s@FROM spark@FROM $TEST_REPO/spark@g" ./Dockerfile
- name: Build - Use real image repo when publish
# Don't need to build the base image when publish
if: ${{ inputs.publish }}
working-directory: ${{ env.IMAGE_PATH }}
run: |
sed -i "s@FROM spark@FROM $PUBLISH_REPO/spark@g" ./Dockerfile
- name: Build - Build and push test image
if: ${{ inputs.build }}
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f
with:
context: ${{ env.IMAGE_PATH }}
tags: ${{ env.IMAGE_URL }}
platforms: linux/amd64,linux/arm64
push: true
- name : Test - Run spark application for standalone cluster on docker
run: testing/run_tests.sh --image-url $IMAGE_URL --scala-version ${{ inputs.scala }} --spark-version ${{ inputs.spark }}
- name: Test - Checkout Spark repository for Spark 3.3.0 (with fetch-depth 0)
if: inputs.spark == '3.3.0'
uses: actions/checkout@v3
with:
fetch-depth: 0
repository: apache/spark
ref: v${{ inputs.spark }}
path: ${{ github.workspace }}/spark
- name: Test - Checkout Spark repository
if: inputs.spark != '3.3.0'
uses: actions/checkout@v3
with:
repository: apache/spark
ref: v${{ inputs.spark }}
path: ${{ github.workspace }}/spark
- name: Test - Cherry pick commits
# Apache Spark enable resource limited k8s IT since v3.3.1, cherry-pick patches for old release
# https://github.com/apache/spark/pull/36087#issuecomment-1251756266
if: inputs.spark == '3.3.0'
working-directory: ${{ github.workspace }}/spark
run: |
# SPARK-38802: Add driverRequestCores/executorRequestCores supported
# https://github.com/apache/spark/commit/83963828b54bffe99527a004057272bc584cbc26
git -c user.name='Apache Spark Test Account' -c user.email='sparktestacc@gmail.com' cherry-pick 83963828b54bffe99527a004057272bc584cbc26
# SPARK-38803: Lower minio cpu to 250m
# https://github.com/apache/spark/commit/5ea2b386eb866e20540660cdb6ed43792cb29969
git -c user.name='Apache Spark Test Account' -c user.email='sparktestacc@gmail.com' cherry-pick 5ea2b386eb866e20540660cdb6ed43792cb29969
- name: Test - Install Java ${{ inputs.java }}
uses: actions/setup-java@v3
with:
# This is required after v2, now just keep same distribution with v1
# https://github.com/actions/setup-java/releases/tag/v2.0.0
distribution: 'zulu'
java-version: ${{ inputs.java }}
- name: Test - Cache Scala, SBT and Maven
uses: actions/cache@v3
with:
path: |
build/apache-maven-*
build/scala-*
build/*.jar
~/.sbt
key: build-${{ inputs.spark }}-scala${{ inputs.scala }}-java${{ inputs.java }}
- name: Test - Cache Coursier local repository
uses: actions/cache@v3
with:
path: ~/.cache/coursier
key: build-${{ inputs.spark }}-scala${{ inputs.scala }}-java${{ inputs.java }}-coursier
- name: Install R
run: |
sudo apt update
sudo apt-get install r-base
- name: Test - Start minikube
uses: medyagh/setup-minikube@e9e035a86bbc3caea26a450bd4dbf9d0c453682e # v0.0.21
with:
cpus: 2
memory: 6144m
- name: Test - Print K8S pods and nodes info
run: |
kubectl get pods -A
kubectl describe node
- name: Test - Run Spark on K8S integration test (With driver cpu 0.5, executor cpu 0.2 limited)
working-directory: ${{ github.workspace }}/spark
run: |
kubectl create clusterrolebinding serviceaccounts-cluster-admin --clusterrole=cluster-admin --group=system:serviceaccounts || true
minikube image load ${{ env.IMAGE_URL }}
sed -i '/<id>volcano<\/id>/,/<\/profile>/ s|<activeByDefault>true</activeByDefault>|<activeByDefault>false</activeByDefault>|' resource-managers/kubernetes/integration-tests/pom.xml
eval $(minikube docker-env)
OPTS="-Pkubernetes -Pkubernetes-integration-tests "
OPTS+="-Dspark.kubernetes.test.driverRequestCores=0.5 -Dspark.kubernetes.test.executorRequestCores=0.2 "
OPTS+="-Dspark.kubernetes.test.deployMode=minikube "
OPTS+="-Dspark.kubernetes.test.imageRepo=${TEST_REPO} -Dspark.kubernetes.test.imageTag=${UNIQUE_IMAGE_TAG} "
OPTS+="-Dspark.kubernetes.test.jvmImage=${IMAGE_NAME} "
OPTS+="-Dspark.kubernetes.test.pythonImage=${IMAGE_NAME} "
OPTS+="-Dspark.kubernetes.test.rImage=${IMAGE_NAME} "
if [ "${{ inputs.image-type }}" = "all" ]; then
# Prepare test jar for client tests
CONTAINER_TMP_NAME=spark-example-image
docker create -ti --name $CONTAINER_TMP_NAME ${{ env.IMAGE_URL }} bash
docker cp $CONTAINER_TMP_NAME:/opt/spark/examples/jars/spark-examples_${{ inputs.scala }}-${{ inputs.spark }}.jar .
docker rm -f $CONTAINER_TMP_NAME
# Prepare PV test
PVC_TMP_DIR=$(mktemp -d)
export PVC_TESTS_HOST_PATH=$PVC_TMP_DIR
export PVC_TESTS_VM_PATH=$PVC_TMP_DIR
minikube mount ${PVC_TESTS_HOST_PATH}:${PVC_TESTS_VM_PATH} --gid=0 --uid=185 &
# Run all K8s test for all in one image
build/sbt $OPTS 'kubernetes-integration-tests/testOnly'
else
# Run basic test for Scala/PySpark/SparkR image
build/sbt $OPTS 'kubernetes-integration-tests/testOnly -- -z "Run SparkPi"'
# Run basic test for PySpark image
if [ "${{ inputs.image-type }}" = "python" ]; then
build/sbt $OPTS 'kubernetes-integration-tests/testOnly -- -z "Run PySpark"'
fi
# Run basic test for SparkR image
if [ "${{ inputs.image-type }}" = "r" ]; then
OPTS+="-Psparkr -Dtest.include.tags=r "
build/sbt $OPTS 'kubernetes-integration-tests/testOnly'
fi
fi
- name: Test - Upload Spark on K8S integration tests log files
if: failure()
uses: actions/upload-artifact@v4
with:
name: spark-on-kubernetes-it-log
path: "**/target/integration-tests.log"
- name: Publish - Login to GitHub Container Registry
if: ${{ inputs.publish }}
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Publish - Login to Dockerhub Registry
if: ${{ inputs.publish }}
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Publish - Push Image
if: ${{ inputs.publish }}
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f
with:
context: ${{ env.IMAGE_PATH }}
push: true
tags: ${{ env.PUBLISH_IMAGE_URL }}
platforms: linux/amd64,linux/arm64