[b9e282]: / justfile

Download this file

202 lines (163 with data), 6.1 kB

#!/usr/bin/env -S just --justfile

# https://github.com/casey/just?tab=readme-ov-file#dotenv-settings
set dotenv-load

# https://github.com/casey/just?tab=readme-ov-file#export
set export

# don't fail fast here --> the `setup` command will check this!
COMMIT := `git rev-parse HEAD || true`
IMAGE_TAG := "bionemo2-" + COMMIT
DEV_IMAGE_TAG := "dev-" + IMAGE_TAG
DATE := `date --iso-8601=seconds -u`
LOCAL_ENV := '.env'
DOCKER_REPO_PATH := '/workspace/bionemo2'
LOCAL_REPO_PATH := `realpath $(pwd)`

[private]
default:
  @just --list

###############################################################################

[private]
check_preconditions:
  #!/usr/bin/env bash

  version_ge() {
      # Returns 0 (true) if $1 >= $2, 1 (false) otherwise
      [ "$(printf '%s\n' "$1" "$2" | sort -V | head -n1)" = "$2" ]
  }

  if [[ $(command -v git) ]]; then
    commit=$(git rev-parse HEAD)
    if [[ "$?" != "0" ]]; then
      echo "ERROR: must run from within git repository!"
      exit 1
    fi
  else
    echo "ERROR: git is not installed!"
    exit 1
  fi

  if [[ ! $(command -v docker) ]]; then
    echo "ERROR: docker is not installed!"
    exit 1
  fi

  docker_version=$(docker --version | awk -F'[, ]' '{print $3}')
  required_docker_version='23.0.1'

  if ! version_ge "$docker_version" "$required_docker_version"; then
      echo "Error: Docker version $required_docker_version or higher is required. Current version: $docker_version"
      exit 1
  fi


# Checks for installed programs (docker, git, etc.), their versions, and grabs the latest cache image.
setup: check_preconditions
  ./internal/scripts/setup_env_file.sh
  @echo "Pulling updated cache..."
  docker pull ${IMAGE_REPO}:${CACHE_TAG} || true


[private]
assert_clean_git_repo:
  #!/usr/bin/env bash

  git diff-index --quiet HEAD --
  exit_code="$?"

  if [[ "${exit_code}" == "128" ]]; then
      echo "ERROR: Cannot build image if not in bionemo git repository!"
      exit 1

  elif [[ "${exit_code}" == "1" ]]; then
      echo "ERROR: Repository is dirty! Commit all changes before building image!"
      exit  2

  elif [[ "${exit_code}" == "0" ]]; then
      echo "ok" 2> /dev/null

  else
      echo "ERROR: Unknown exit code for `git diff-index`: ${exit_code}"
      exit 1
  fi

###############################################################################

[private]
build image_tag target: setup assert_clean_git_repo
  DOCKER_BUILDKIT=1 docker buildx build \
  -t ${IMAGE_REPO}:{{image_tag}} \
  --target={{target}} \
  --load \
  --cache-to type=inline \
  --cache-from ${IMAGE_REPO}:${CACHE_TAG} \
  --label com.nvidia.bionemo.git_sha=${COMMIT} \
  --label com.nvidia.bionemo.created_at=${DATE} \
  -f ./Dockerfile \
  .

# Builds the release image.
build-release:
  @just build ${IMAGE_TAG} release

# Builds the development image.
build-dev:
  @just build ${DEV_IMAGE_TAG} development

###############################################################################

[private]
run is_dev is_interactive image_tag cmd: setup
  #!/usr/bin/env bash

  DOCKER_VERSION=$(docker version | grep -i version | head -1 | awk '{print $2}')
  DOCKER_VERSION_WITH_GPU_SUPPORT='19.03.0'
  if [ "$DOCKER_VERSION_WITH_GPU_SUPPORT" == "$(echo -e "$DOCKER_VERSION\n$DOCKER_VERSION_WITH_GPU_SUPPORT" | sort -V | head -1)" ]; then
      PARAM_RUNTIME="--gpus all"
  else
      PARAM_RUNTIME="--runtime=nvidia"
  fi

  docker_cmd="docker run \
  --rm \
  --network host \
  ${PARAM_RUNTIME} \
  -p ${JUPYTER_PORT}:8888 \
  --shm-size=4g \
  -e TMPDIR=/tmp/ \
  -e NUMBA_CACHE_DIR=/tmp/ \
  -e WANDB_API_KEY=$WANDB_API_KEY \
  -e NGC_CLI_API_KEY=$NGC_CLI_API_KEY \
  -e NGC_CLI_ORG=$NGC_CLI_ORG \
  -e NGC_CLI_TEAM=$NGC_CLI_TEAM \
  -e NGC_CLI_FORMAT_TYPE=$NGC_CLI_FORMAT_TYPE \
  -e AWS_ENDPOINT_URL \
  -e AWS_REGION \
  -e AWS_SECRET_ACCESS_KEY \
  -e AWS_ACCESS_KEY_ID \
  -e HOME=${DOCKER_REPO_PATH} \
  -w ${DOCKER_REPO_PATH} \
  -v ${LOCAL_RESULTS_PATH}:${DOCKER_RESULTS_PATH} \
  -v ${LOCAL_DATA_PATH}:${DOCKER_DATA_PATH} \
  -v ${LOCAL_MODELS_PATH}:${DOCKER_MODELS_PATH} \
  -v /etc/passwd:/etc/passwd:ro \
  -v /etc/group:/etc/group:ro \
  -v /etc/shadow:/etc/shadow:ro \
  -v ${HOME}/.ssh:${DOCKER_REPO_PATH}/.ssh:ro \
  -v ${LOCAL_REPO_PATH}/htmlcov:/${DOCKER_REPO_PATH}/htmlcov \
  -u $(id -u):$(id -g)"

  if [[ "{{is_dev}}" == "true" ]]; then
    docker_cmd="${docker_cmd} -v ${LOCAL_REPO_PATH}:${DOCKER_REPO_PATH}"
  fi

  if [[ "{{is_interactive}}" == "true" ]]; then
    docker_cmd="${docker_cmd} -it"
  fi

  docker_cmd="${docker_cmd} ${IMAGE_REPO}:{{image_tag}} {{cmd}}"

  set -xeuo pipefail
  DOCKER_BUILDKIT=1 ${docker_cmd}

[private]
ensure-dev-or-build:
  #!/usr/bin/env bash
  if [[ $(docker images -q "${IMAGE_REPO}:${DEV_IMAGE_TAG}" 2> /dev/null) == "" ]]; then
    echo "Building development image: ${IMAGE_REPO}:${DEV_IMAGE_TAG}"
    just build-dev
  else
    echo "Development image exists:   ${IMAGE_REPO}:${DEV_IMAGE_TAG}"
  fi

# run-dev lets us work with a dirty repository,
# beacuse this is a common state during development
# **AND** we're volume mounting the code, so we'll have the latest state.
# **BUT** we can only do this if we have built an image for DEV_IMAGE_TAG already,
# so we use ensure-dev-or-build which will build the image if it is necessary.
# Image building requires that the git repo state is clean!
#
# Runs an interactive program in the development bionemo image.
run-dev cmd='bash': ensure-dev-or-build
  @just run true true ${DEV_IMAGE_TAG} {{cmd}}

# in contrast, run-release requires a clean repository,
# because users want to know that they're running the **exact** version they expect
# and we're **NOT** volume mounting the code
#
# Runs an interactive program in the release bionemo image.
run-release cmd='bash': build-release assert_clean_git_repo
  @just run false true ${IMAGE_TAG} {{cmd}}


###############################################################################

# Executes pytest in the release image.
test: build-release
  @just run true false ${IMAGE_TAG} 'pytest -v --nbval-lax --cov=bionemo --cov-report term --cov-report=html docs/ scripts/ sub-packages/'