Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ga build docker images #3351

Merged
merged 3 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Ignore everything
*

# Except few files and directories
!Jenkins/fast-release/environment.devenv.yml
!packaging/dependencies
!packaging/plugins
!packaging/version.txt
!pyproject.toml
77 changes: 77 additions & 0 deletions .github/actions/docker-build-image/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: "Build docker image if tag is not 'latest'"

description: "Build docker image if tag is not 'latest'"

inputs:
docker-registry:
description: "Docker registry"
required: true
docker-login:
description: "Docker login"
required: true
docker-password:
description: "Docker password"
required: true
dockercontext:
description: "Docker build context"
required: false
default: "."
dockerfile:
description: "Dockerfile"
required: false
default: "Dockerfile"
image-name:
description: "Docker image name"
required: false
default: "${{ github.event.repository.name }}"
image-tag:
description: "Docker image tag"
required: false
default: "latest"
build-args:
description: "Docker build argunebts"
required: false
default: ""

outputs:
docker-image:
description: "Docker image"
value: ${{ steps.image.outputs.value }}

runs:
using: "composite"
steps:
- name: "Set docker image tag"
id: image
shell: bash
run: echo "value=${{ inputs.docker-registry }}/${{ inputs.image-name }}:${{ inputs.image-tag }}" >> $GITHUB_OUTPUT

- name: "Set DOCKER_CONFIG because buildx stores data there"
if: inputs.image-tag != 'latest'
shell: bash
run: echo "DOCKER_CONFIG=./.docker" >> $GITHUB_ENV

- name: "Set up Docker Buildx"
if: inputs.image-tag != 'latest'
uses: docker/setup-buildx-action@v3
with:
buildkitd-flags: --debug
driver: docker

- name: "Login to docker registry"
if: inputs.image-tag != 'latest'
uses: docker/login-action@v3
with:
registry: ${{ inputs.docker-registry }}
username: ${{ inputs.docker-login }}
password: ${{ inputs.docker-password }}

- name: "Build and push"
if: inputs.image-tag != 'latest'
uses: docker/build-push-action@v6
with:
context: ${{ inputs.dockercontext }}
file: ${{ inputs.dockerfile }}
tags: ${{ steps.image.outputs.value }}
build-args: ${{ inputs.build-args }}
push: true
54 changes: 54 additions & 0 deletions .github/actions/docker-tag/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: "Docker image tag"

description: "Get a docker image tag based on changes in a docker build context"

inputs:
dockercontext:
description: "Docker build context"
required: false
default: "."
dockerfile:
description: "Dockerfile"
required: false
default: "Dockerfile"
dockerignore:
description: "Dockerignore file"
required: false
default: ".dockerignore"
defaulttag:
description: "A default docker image tag"
required: false
default: "latest"

outputs:
tag:
description: "Docker image tag"
value: ${{ steps.tag.outputs.value }}

runs:
using: "composite"
steps:
- uses: actions/checkout@v4

- name: "Download '.dockerignore' file parser"
shell: bash
run: |
curl -L "https://github.com/johnstairs/dockerignore-filter/releases/download/v0.1.6/dockerignore-filter_Linux_x86_64" -o dockerignore-filter
chmod +x dockerignore-filter

- name: "Get list of files from the docker build context (including Dockerfile and .dockerignore)"
shell: bash
run: echo "DOCKER_BUILD_CONTEXT_FILES=$(find ${{ inputs.dockercontext }} -type f | ./dockerignore-filter ${{ inputs.dockercontext }}/${{ inputs.dockerignore }} | tr '\n' ' ') ${{ inputs.dockercontext }}/${{ inputs.dockerfile }} ${{ inputs.dockercontext }}/${{ inputs.dockerignore }}" >> $GITHUB_ENV

- name: "Get list of changes files in the docker build context"
shell: bash
run: |
git branch --delete --force ${{ github.event.repository.default_branch }} || true
git fetch --no-tags --force --prune --no-recurse-submodules --depth=1 origin ${{ github.event.repository.default_branch }}:refs/remotes/origin/${{ github.event.repository.default_branch }}
echo "DOCKER_BUILD_CONTEXT_FILES=$(git diff --name-only origin/${{ github.event.repository.default_branch }} -- $DOCKER_BUILD_CONTEXT_FILES | tr '\n' ' ')" >> $GITHUB_ENV

- name: "Set a docker image tag"
id: tag
shell: bash
run: echo "value=$([[ ! -z \"$DOCKER_BUILD_CONTEXT_FILES\" ]] && echo $(git rev-parse --short HEAD) || echo ${{ inputs.defaulttag }})" >> $GITHUB_OUTPUT

11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: CI pipeline

on:
pull_request:
branches: [ develop ]

jobs:
pipeline:
if: github.server_url != 'https://github.com'
uses: ./.github/workflows/pipeline.yml
secrets: inherit
101 changes: 101 additions & 0 deletions .github/workflows/pipeline.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: CI Pipeline

on:
workflow_call:

jobs:
docker-tag:
name: Check if 'latest' tag could be used (no build docker images)
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.tag.outputs.tag }}
steps:
- run: |
sudo apt update -qq
sudo apt install -y git curl jq sudo ca-certificates
sudo update-ca-certificates
- uses: actions/checkout@v4
- uses: ./.github/actions/docker-tag
id: tag
with:
dockerfile: Jenkins/fast-release/Dockerfile.ci

variants:
name: Define supported AIMET variants
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.final.outputs.value }}
steps:
- run: |
sudo apt update -qq
sudo apt install -y git curl jq sudo ca-certificates
sudo update-ca-certificates

- name: Torch variants
run: |
set -x
VALUE=$(echo "${VALUE:-"{}"}" | jq -c '.include += [
{ "VER_PYTHON":"3.10", "VER_TENSORFLOW":"", "VER_TORCH":"2.1.2", "VER_ONNX":"", "VER_CUDA":"" },
{ "VER_PYTHON":"3.10", "VER_TENSORFLOW":"", "VER_TORCH":"2.1.2", "VER_ONNX":"", "VER_CUDA":"11.8.0" }
]')
echo "VALUE=$VALUE" >> $GITHUB_ENV

- name: Tensorflow variants
run: |
set -x
VALUE=$(echo "${VALUE:-"{}"}" | jq -c '.include += [
{ "VER_PYTHON":"3.10", "VER_TENSORFLOW":"2.10.1", "VER_TORCH":"", "VER_ONNX":"", "VER_CUDA":"" },
{ "VER_PYTHON":"3.10", "VER_TENSORFLOW":"2.10.1", "VER_TORCH":"", "VER_ONNX":"", "VER_CUDA":"11.8.0" }
]')
echo "VALUE=$VALUE" >> $GITHUB_ENV

- name: ONNX variants
run: |
set -x
VALUE=$(echo "${VALUE:-"{}"}" | jq -c '.include += [
{ "VER_PYTHON":"3.10", "VER_TENSORFLOW":"", "VER_TORCH":"1.13.1", "VER_ONNX":"1.14.1", "VER_CUDA":"" },
{ "VER_PYTHON":"3.10", "VER_TENSORFLOW":"", "VER_TORCH":"1.13.1", "VER_ONNX":"1.14.1", "VER_CUDA":"11.7.1" }
]')
echo "VALUE=$VALUE" >> $GITHUB_ENV

- name: (Last step) Generate few extra properties for each variant
id: final
run: |
set -x
VALUE=$(echo "$VALUE" | jq -c '.include[] |= . + {
"runs-on":(if .VER_CUDA != "" then "k8s-gpu" else "ubuntu-latest" end),
"id":(""
+(if .VER_TENSORFLOW != "" then "tf-" else "" end)
+(if .VER_ONNX != "" then "onnx-" elif .VER_TORCH != "" then "torch-" else "" end)
+(if .VER_CUDA != "" then "gpu" else "cpu" end)
)
}')
echo "value=$VALUE" >> $GITHUB_OUTPUT

docker-build-image:
name: Docker image ${{ matrix.id }}
runs-on: ubuntu-latest
needs: [docker-tag, variants]
strategy:
matrix: ${{ fromJSON(needs.variants.outputs.matrix) }}
steps:
- run: |
sudo apt update -qq
sudo apt install -y git curl jq sudo ca-certificates
sudo update-ca-certificates
- uses: actions/checkout@v4
- uses: ./.github/actions/docker-build-image
with:
dockerfile: Jenkins/fast-release/Dockerfile.ci
docker-login: ${{ secrets.DOCKER_LOGIN }}
docker-password: ${{ secrets.DOCKER_CREDENTIALS }}
docker-registry: ${{ secrets.DOCKER_REGISTRY }}
image-name: "${{ secrets.DOCKER_IMAGE }}-${{ matrix.id }}"
image-tag: ${{ needs.docker-tag.outputs.tag }}
build-args: |
VER_PYTHON=${{ matrix.VER_PYTHON }}
VER_CUDA=${{ matrix.VER_CUDA }}
VER_TORCH=${{ matrix.VER_TORCH }}
VER_TENSORFLOW=${{ matrix.VER_TENSORFLOW }}
VER_ONNX=${{ matrix.VER_ONNX }}

73 changes: 73 additions & 0 deletions Jenkins/fast-release/Dockerfile.ci
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
ARG BASE_IMAGE=ubuntu:22.04
FROM $BASE_IMAGE AS build

ENV CONDA_PREFIX=/opt/conda
ENV CONDA=${CONDA_PREFIX}/bin/conda
ENV CONDA_DEFAULT_ENV=dev

RUN apt update && \
DEBIAN_FRONTEND=noninteractive apt install --yes --no-install-recommends \
acl \
ca-certificates \
curl \
# manylinux2014 requires gcc 10 and cuda doesn't support gcc>11
g++-10 \
git \
jq \
make \
sudo \
&& rm -rf /var/lib/apt/lists/* \
&& echo '%users ALL = (ALL) NOPASSWD: ALL' > /etc/sudoers.d/passwordless \
&& curl -o /tmp/conda.sh -L 'https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh' \
&& mkdir -m 777 -p ${CONDA_PREFIX} \
&& setfacl -d -m o::rwx ${CONDA_PREFIX} \
&& bash /tmp/conda.sh -u -b -p ${CONDA_PREFIX} \
&& rm /tmp/conda.sh \
&& ${CONDA} config --set channel_priority strict \
&& ${CONDA} init --no-user --system --all \
&& ${CONDA} install -y conda-devenv \
&& ${CONDA} clean --yes --all --verbose \
&& update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 10 --slave /usr/bin/g++ g++ /usr/bin/g++-10 --slave /usr/bin/gcov gcov /usr/bin/gcov-10 \
&& git config --system --add safe.directory '*'

ARG VER_PYTHON=3.8
ARG VER_CUDA=11.7.1
ARG VER_TORCH=""
ARG VER_TENSORFLOW=""
ARG VER_ONNX=""

COPY Jenkins/fast-release/environment.devenv.yml /tmp/
RUN export PATH=$PATH:${CONDA_PREFIX}/bin PIP_NO_CACHE_DIR=1 \
&& ${CONDA} devenv \
--env-var ENV_NAME="${CONDA_DEFAULT_ENV}" \
--env-var VER_PYTHON="${VER_PYTHON}" \
--env-var VER_CUDA="${VER_CUDA}" \
--file /tmp/environment.devenv.yml \
--output-file /tmp/environment.yml \
&& cat /tmp/environment.yml \
&& ${CONDA} clean --yes --all --verbose \
&& echo "conda activate ${CONDA_DEFAULT_ENV}" >> /etc/profile.d/conda.sh \
&& rm -rf ~/.conda*

RUN --mount=type=bind,target=/workspace \
echo "Install all required dependencies" \
&& export PIP_CACHE_DIR=/tmp/pip-cache BUILD_DIR=/tmp/build \
&& mkdir -p $BUILD_DIR \
&& export PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl" \
&& export CMAKE_ARGS="\
-DENABLE_TENSORFLOW=$([ -z ${VER_TENSORFLOW} ]; echo $?) \
-DENABLE_TORCH=$([ -z ${VER_TORCH} ]; echo $?) \
-DENABLE_ONNX=$([ -z ${VER_ONNX} ]; echo $?) \
-DENABLE_CUDA=$([ -z ${VER_CUDA} ]; echo $?) \
" \
&& ${CONDA} run --name ${CONDA_DEFAULT_ENV} --live-stream \
python3 -m pip install --dry-run --report $BUILD_DIR/pip-report.json -C build-dir="$BUILD_DIR/{wheel_tag}" /workspace \
&& ${CONDA} run --name ${CONDA_DEFAULT_ENV} --live-stream \
python3 -m pip install -c /workspace/packaging/dependencies/constraints.txt $(jq -r '.install[0].metadata.requires_dist[] | split(";") | .[0]' $BUILD_DIR/pip-report.json) \
&& rm -rf $PIP_CACHE_DIR $BUILD_DIR

ENV PYTHONPYCACHEPREFIX=/tmp

ENTRYPOINT ["/bin/bash", "--login", "-c", "${0#--} \"$@\""]
CMD ["/bin/bash"]

29 changes: 29 additions & 0 deletions Jenkins/fast-release/environment.devenv.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{% set ENV_NAME = os.environ.get('ENV_NAME', 'dev') %}

{% set VER_PYTHON = os.environ.get('VER_PYTHON') %}
{% set VER_CUDA = os.environ.get('VER_CUDA') %}

{% set CUDA_CHANNEL = 'nvidia/label/cuda-' + VER_CUDA %}
{% set CU = 'cu' + ''.join(VER_CUDA.split('.')[:-1]) if VER_CUDA != '' else 'cpu' %}


name: {{ ENV_NAME }}

{% if CU != 'cpu' %}
channels:
- {{ CUDA_CHANNEL }}
{% endif %}

dependencies:
- auditwheel
- patchelf
- python={{ VER_PYTHON }}
- python-build
- pip
{% if CU != 'cpu' %}
- cuda-gdb
- cuda-nvcc
- cuda-nvtx
- cuda-libraries-dev
- cudnn
{% endif %}
3 changes: 3 additions & 0 deletions packaging/dependencies/constraints.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# pytorch uses setuptools to build C++ extensions
# [ImportError: cannot import name 'packaging' from 'pkg_resources']
setuptools<70
Loading
Loading