#################################
#          Variables            #
#################################
# check=skip=SecretsUsedInArgOrEnv

# Versioning
ARG RUBY_VERSION="3.2"
ARG BUNDLER_VERSION="2.7.1"
ARG NODEJS_VERSION="16"
ARG YARN_VERSION="1.22.19"
ARG DEBIAN_VERSION="trixie"

# Packages
ARG BUILD_PACKAGES="nodejs git build-essential libpq-dev libvips42"
ARG RUN_PACKAGES="shared-mime-info pkg-config libpq-dev libjemalloc-dev libjemalloc2 libvips42 libicu76"
ARG EXTRA_PACKAGES=""

# Scripts
ARG PRE_INSTALL_SCRIPT="\
  apt-get update && \
  apt-get install -y ca-certificates curl gnupg && \
  mkdir -p /etc/apt/keyrings && \
  curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
  echo 'deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_${NODEJS_VERSION}.x nodistro main' > /etc/apt/sources.list.d/nodesource.list && \
  echo 'Package: nodejs' >> /etc/apt/preferences.d/preferences && \
  echo 'Pin: origin deb.nodesource.com' >> /etc/apt/preferences.d/preferences && \
  echo 'Pin-Priority: 1001' >> /etc/apt/preferences.d/preferences \
"
ARG INSTALL_SCRIPT="node -v && npm -v && npm install -g yarn && yarn set version ${YARN_VERSION}"
ARG PRE_BUILD_SCRIPT="\
     git submodule status | tee WAGON_VERSIONS; \
     rm -rf hitobito/.git; \
     mv hitobito/* hitobito/.?* .; \
     mkdir -p vendor/wagons; \
     for wagon_dir in hitobito_*; do if [[ -d \$wagon_dir ]]; then rm -r \$wagon_dir/.git && mv \$wagon_dir vendor/wagons/; fi; done; \
     rm -rf hitobito; \
     cp -v Wagonfile.production Wagonfile; \
     bundle lock; \
"
ARG BUILD_SCRIPT="RAILS_DB_ADAPTER=nulldb bundle exec rake assets:precompile"

ARG POST_BUILD_SCRIPT=" \
     echo \"(built at: $(date '+%Y-%m-%d %H:%M:%S'))\" > /app-src/BUILD_INFO; \
     bundle exec bootsnap precompile app/ lib/; \
"

# Bundler specific
ARG BUNDLE_WITHOUT_GROUPS="development:metrics:test"

# App specific
ARG RAILS_ENV="production"
ARG RACK_ENV="production"
ARG NODE_ENV="production"
ARG RAILS_HOST_NAME="unused.example.net"
ARG SECRET_KEY_BASE="needs-to-be-set"

# Runtime ENV vars
ARG SENTRY_CURRENT_ENV
ARG HOME=/app-src
ARG PS1="[\$SENTRY_CURRENT_ENV] `uname -n`:\$PWD\$ "
ARG TZ="Europe/Zurich"



#################################
#          Build Stage          #
#################################

FROM ruby:${RUBY_VERSION}-${DEBIAN_VERSION} AS build

# arguments for steps
ARG HOME
ARG PRE_INSTALL_SCRIPT
ARG BUILD_PACKAGES
ARG EXTRA_PACKAGES
ARG INSTALL_SCRIPT
ARG BUNDLER_VERSION
ARG PRE_BUILD_SCRIPT
ARG BUNDLE_WITHOUT_GROUPS
ARG BUILD_SCRIPT
ARG POST_BUILD_SCRIPT

# arguments potentially used by steps
ARG NODE_ENV
ARG RACK_ENV
ARG RAILS_ENV
ARG RAILS_HOST_NAME
ARG SECRET_KEY_BASE
ARG TZ

# Set build shell
SHELL ["/bin/bash", "-c"]

# Use root user
USER root

RUN bash -vxc "${PRE_INSTALL_SCRIPT:-"echo 'no PRE_INSTALL_SCRIPT provided'"}"

# Install dependencies
RUN    export DEBIAN_FRONTEND=noninteractive \
    && apt-get update \
    && apt-get upgrade -y \
    && apt-get install -y --no-install-recommends ${BUILD_PACKAGES} ${EXTRA_PACKAGES}

RUN bash -vxc "${INSTALL_SCRIPT:-"echo 'no INSTALL_SCRIPT provided'"}"

# Explicitly install specific versions of bundler
# (not required with newer bundler versions?)
RUN gem install bundler:${BUNDLER_VERSION} --no-document

# TODO: Load artifacts

# set up app-src directory
WORKDIR $HOME

# copy entire submodule structure because it is needed for the PRE_BUILD_SCRIPT
COPY . .

# only copy things needed for bundling
# COPY Gemfile Gemfile.lock Wagonfile.production ./

RUN bash -vxc "${PRE_BUILD_SCRIPT:-"echo 'no PRE_BUILD_SCRIPT provided'"}"

# install gems and build the app
RUN    bundle config set --local deployment 'true' \
    && bundle config set --local without ${BUNDLE_WITHOUT_GROUPS} \
    && bundle install \
    && bundle clean \
    && bundle exec bootsnap precompile --gemfile

# only copy things needed for yarning
# COPY package.json yarn.lock ./
# COPY .yarn ./.yarn/
# install npms for the frontend
RUN yarn install --immutable

# copy entire application code after dependencies are built
# COPY . .

RUN bash -vxc "${BUILD_SCRIPT:-"echo 'no BUILD_SCRIPT provided'"}"

RUN bash -vxc "${POST_BUILD_SCRIPT:-"echo 'no POST_BUILD_SCRIPT provided'"}"

# TODO: Save artifacts

RUN rm -rf vendor/cache/ .git spec/ node_modules/ .npm/

#################################
#         Run/App Stage         #
#################################

# This image will be replaced by Openshift
FROM ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS app

# Set runtime shell
SHELL ["/bin/bash", "-c"]

# arguments for steps
ARG RUN_PACKAGES
ARG EXTRA_PACKAGES
ARG BUNDLER_VERSION
ARG BUNDLE_WITHOUT_GROUPS

# arguments potentially used by steps
ARG NODE_ENV
ARG RACK_ENV
ARG RAILS_ENV

# data persisted in the image
ARG HOME
ARG PS1
ARG TZ

# Set environment variables available in the image
ENV PS1="${PS1}" \
    TZ="${TZ}" \
    HOME="${HOME}" \
    PATH="${HOME}/bin:$PATH" \
    NODE_ENV="${NODE_ENV}" \
    RAILS_ENV="${RAILS_ENV}" \
    RACK_ENV="${RACK_ENV}"

# Install dependencies, remove apt!
RUN    export DEBIAN_FRONTEND=noninteractive \
    && apt-get update \
    && apt-get upgrade -y \
    && apt-get install -y ${RUN_PACKAGES} ${EXTRA_PACKAGES} adduser vim curl less \
    && apt-get clean \
    && rm -rf /var/cache/apt/archives/* /var/lib/apt/lists/* /tmp/* /var/tmp/* \
    && truncate -s 0 /var/log/*log

# Add user
RUN adduser --disabled-password --uid 1001 --gid 0 --comment "" app

# only after it has been installed
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2

# Copy deployment ready source code from build
COPY --from=build $HOME $HOME
WORKDIR $HOME

# Create pids folder for puma and
# set group permissions to folders that need write permissions.
RUN mkdir -p tmp/pids log \
    && chgrp 0 $HOME \
    && chgrp -R 0 $HOME/tmp \
    && chgrp -R 0 $HOME/log \
    && chmod u+w,g=u $HOME \
    && chmod -R u+w,g=u $HOME/tmp \
    && chmod -R u+w,g=u $HOME/log \
    && chmod a+w $HOME/db/schema.rb \
    && chmod a+w $HOME/vendor/wagons/*/db/seeds/

# Install specific versions of dependencies
# (not required with newer bundler versions)
RUN gem install bundler:${BUNDLER_VERSION} --no-document

# Use cached gems
RUN    bundle config set --local deployment 'true' \
    && bundle config set --local without ${BUNDLE_WITHOUT_GROUPS} \
    && bundle install

# These args contain build information. Also see build stage.
# They change with each build, so only define them here for optimal layer caching.
# Also see https://docs.docker.com/engine/reference/builder/#impact-on-build-caching
ARG BUILD_REPO
ARG BUILD_REF
# ARG BUILD_DATE
ARG BUILD_COMMIT
ARG HITOBITO_PROJECT
ARG HITOBITO_STAGE

ENV BUILD_REPO="${BUILD_REPO}" \
    BUILD_REF="${BUILD_REF}" \
    # BUILD_DATE="${BUILD_DATE}" \
    BUILD_COMMIT="${BUILD_COMMIT}" \
    HITOBITO_PROJECT="${HITOBITO_PROJECT}" \
    HITOBITO_STAGE="${HITOBITO_STAGE}"

# Set runtime user (although OpenShift uses a custom user per project instead)
USER 1001

CMD ["bundle", "exec", "puma"]
