From 333a3eea028866bc0250f6b0124f9f17d978b291 Mon Sep 17 00:00:00 2001 From: VPhung24 Date: Mon, 14 Oct 2024 16:20:36 +0000 Subject: [PATCH 1/5] nextjs build-app updates --- .../cerc-nextjs-base/scripts/build-app.sh | 289 ++++++++---------- 1 file changed, 125 insertions(+), 164 deletions(-) diff --git a/stack_orchestrator/data/container-build/cerc-nextjs-base/scripts/build-app.sh b/stack_orchestrator/data/container-build/cerc-nextjs-base/scripts/build-app.sh index 26d7db9e..9b72511e 100755 --- a/stack_orchestrator/data/container-build/cerc-nextjs-base/scripts/build-app.sh +++ b/stack_orchestrator/data/container-build/cerc-nextjs-base/scripts/build-app.sh @@ -1,16 +1,13 @@ #!/bin/bash -if [ -n "$CERC_SCRIPT_DEBUG" ]; then +set -euo pipefail + +if [ -n "${CERC_SCRIPT_DEBUG:-}" ]; then set -x fi -CERC_MIN_NEXTVER=13.4.2 -CERC_DEFAULT_WEBPACK_VER="5.93.0" - -CERC_NEXT_VERSION="${CERC_NEXT_VERSION:-keep}" -CERC_WEBPACK_VERSION="${CERC_WEBPACK_VERSION:-keep}" - -CERC_BUILD_TOOL="${CERC_BUILD_TOOL}" +# Determine the build tool +CERC_BUILD_TOOL="${CERC_BUILD_TOOL:-}" if [ -z "$CERC_BUILD_TOOL" ]; then if [ -f "pnpm-lock.yaml" ]; then CERC_BUILD_TOOL=pnpm @@ -23,11 +20,36 @@ if [ -z "$CERC_BUILD_TOOL" ]; then fi fi -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +SCRIPT_DIR=$(dirname "$(readlink -f "$0")") WORK_DIR="${1:-/app}" cd "${WORK_DIR}" || exit 1 +# Get the app's Next.js version +CERC_NEXT_VERSION=$(jq -r '.dependencies.next' package.json) +echo "Using Next.js version: $CERC_NEXT_VERSION" + +# Determine webpack version based on Next.js version (unused if already installed) +determine_webpack_version() { + local next_version=$1 + local major_version=${next_version%%.*} + case $major_version in + 13) + echo "5.75.0" + ;; + 14) + echo "5.88.0" + ;; + *) + echo "5.93.0" # Default to latest stable version if unknown + ;; + esac +} + +CERC_WEBPACK_VERSION=$(determine_webpack_version "$CERC_NEXT_VERSION") +echo "Using webpack version: $CERC_WEBPACK_VERSION" + +# Determine the Next.js config file if [ -f "next.config.mjs" ]; then NEXT_CONFIG_JS="next.config.mjs" IMPORT_OR_REQUIRE="import" @@ -41,203 +63,142 @@ if [ ! -f "${NEXT_CONFIG_JS}" ]; then touch ${NEXT_CONFIG_JS} fi +# Backup the original config if not already done if [ ! -f "next.config.dist" ]; then - cp $NEXT_CONFIG_JS next.config.dist + cp "$NEXT_CONFIG_JS" next.config.dist fi -which js-beautify >/dev/null -if [ $? -ne 0 ]; then - npm i -g js-beautify -fi +# Install js-beautify if not present +command -v js-beautify >/dev/null || npm i -g js-beautify -# js-beautify formats NEXTJS_CONFIG_FILE (ie next.config.js / next.config.mjs) so we can reliably transformable later -js-beautify next.config.dist > ${NEXT_CONFIG_JS} -echo "" >> ${NEXT_CONFIG_JS} +# Beautify the config file +js-beautify "$NEXT_CONFIG_JS" > "${NEXT_CONFIG_JS}.pretty" +mv "${NEXT_CONFIG_JS}.pretty" "$NEXT_CONFIG_JS" -if [ "${IMPORT_OR_REQUIRE}" == "require" ]; then - WEBPACK_REQ_LINE=$(grep -n "require([\'\"]webpack[\'\"])" ${NEXT_CONFIG_JS} | cut -d':' -f1) - if [ -z "$WEBPACK_REQ_LINE" ]; then - cat > ${NEXT_CONFIG_JS}.0 < ${NEXT_CONFIG_JS}.0 <> ${NEXT_CONFIG_JS}.0 < ${NEXT_CONFIG_JS}.1 <> "$NEXT_CONFIG_JS" + let envMap; try { - // .env-list.json provides us a list of identifiers which should be replaced at runtime. envMap = require('./.env-list.json').reduce((a, v) => { - a[v] = \`"CERC_RUNTIME_ENV_\${v.split(/\./).pop()}"\`; + a[v] = JSON.stringify(`CERC_RUNTIME_ENV_${v.split(/\./).pop()}`); return a; }, {}); } catch (e) { - console.error(e); - // If .env-list.json cannot be loaded, we are probably running in dev mode, so use process.env instead. + console.error('Error loading .env-list.json:', e); envMap = Object.keys(process.env).reduce((a, v) => { if (v.startsWith('CERC_')) { - a[\`process.env.\${v}\`] = JSON.stringify(process.env[v]); + a[`process.env.${v}`] = JSON.stringify(process.env[v]); } return a; }, {}); } -console.log(envMap); +console.log('Environment map:', envMap); EOF +fi -grep 'withPWA' ${NEXT_CONFIG_JS} >/dev/null && HAS_WITHPWA=true || HAS_WITHPWA=false +# Add or update webpack configuration +if ! grep -q '__xCfg__' "$NEXT_CONFIG_JS"; then + cat << 'EOF' >> "$NEXT_CONFIG_JS" -if [ "$HAS_WITHPWA" == "true" ]; then - if [ "$IMPORT_OR_REQUIRE" == "import" ]; then - cat > ${NEXT_CONFIG_JS}.2 < { - const realPWA = withPWA(p); - return (nextConfig) => { - const modConfig = {...nextConfig}; - - modConfig.webpack = (config) => { +const __xCfg__ = (nextConfig) => { + return { + ...nextConfig, + webpack: (config, options) => { config.plugins.push(new webpack.DefinePlugin(envMap)); - return nextConfig.webpack ? nextConfig.webpack(config) : config; - }; - - return realPWA(modConfig); + if (typeof nextConfig.webpack === 'function') { + return nextConfig.webpack(config, options); + } + return config; + }, }; }; + EOF + + # Update the export/module.exports line + if [ "$IMPORT_OR_REQUIRE" = "import" ]; then + sed -i 's/export default/const __orig_cfg__ =/' "$NEXT_CONFIG_JS" + echo "export default __xCfg__(__orig_cfg__);" >> "$NEXT_CONFIG_JS" else - cat > ${NEXT_CONFIG_JS}.3 < { - const modConfig = {...nextConfig}; - - modConfig.webpack = (config) => { - config.plugins.push(new webpack.DefinePlugin(envMap)); - return nextConfig.webpack ? nextConfig.webpack(config) : config; - }; - - return withPWA(modConfig); -}; -EOF - fi - - cat ${NEXT_CONFIG_JS} | js-beautify | sed 's/withPWA(/__xPWA__(/g' > ${NEXT_CONFIG_JS}.4 -else - cat > ${NEXT_CONFIG_JS}.3 < { - const modConfig = {...nextConfig}; - - modConfig.webpack = (config) => { - config.plugins.push(new webpack.DefinePlugin(envMap)); - return nextConfig.webpack ? nextConfig.webpack(config) : config; - }; - - return modConfig; - }; -EOF - if [ "$IMPORT_OR_REQUIRE" == "import" ]; then - cat ${NEXT_CONFIG_JS} | js-beautify | sed 's/export\s\+default\s\+/const __orig_cfg__ = /g' > ${NEXT_CONFIG_JS}.4 - echo "export default __xCfg__(__orig_cfg__);" > ${NEXT_CONFIG_JS}.5 - else - cat ${NEXT_CONFIG_JS} | js-beautify | sed 's/module.exports\s\+=\s\+/const __orig_cfg__ = /g' > ${NEXT_CONFIG_JS}.4 - echo "module.exports = __xCfg__(__orig_cfg__);" > ${NEXT_CONFIG_JS}.5 + sed -i 's/module.exports =/const __orig_cfg__ =/' "$NEXT_CONFIG_JS" + echo "module.exports = __xCfg__(__orig_cfg__);" >> "$NEXT_CONFIG_JS" fi fi +# Clean up the config file +js-beautify "$NEXT_CONFIG_JS" > "${NEXT_CONFIG_JS}.pretty" +mv "${NEXT_CONFIG_JS}.pretty" "$NEXT_CONFIG_JS" -rm -f ${NEXT_CONFIG_JS} -for ((i=0; i <= 10; i++)); do - if [ -s "${NEXT_CONFIG_JS}.${i}" ]; then - if [ $i -le 2 ] ; then - cat ${NEXT_CONFIG_JS}.${i} >> ${NEXT_CONFIG_JS} - else - cat ${NEXT_CONFIG_JS}.${i} | sed 's/^ *//g' | js-beautify | grep -v 'process\.\env\.' | js-beautify >> ${NEXT_CONFIG_JS} - fi - fi -done -rm ${NEXT_CONFIG_JS}.* -cat ${NEXT_CONFIG_JS} | js-beautify > ${NEXT_CONFIG_JS}.pretty -mv ${NEXT_CONFIG_JS}.pretty ${NEXT_CONFIG_JS} - +# Generate .env-list.json "${SCRIPT_DIR}/find-env.sh" "$(pwd)" > .env-list.json -if [ ! -f "package.dist" ]; then - cp package.json package.dist -fi +# Update package.json +[ ! -f "package.dist" ] && cp package.json package.dist -CUR_NEXT_VERSION="`jq -r '.dependencies.next' package.json`" - -if [ "$CERC_NEXT_VERSION" != "keep" ] && [ "$CUR_NEXT_VERSION" != "$CERC_NEXT_VERSION" ]; then - echo "Changing 'next' version specifier from '$CUR_NEXT_VERSION' to '$CERC_NEXT_VERSION' (set with '--extra-build-args \"--build-arg CERC_NEXT_VERSION=$CERC_NEXT_VERSION\"')" - cat package.json | jq ".dependencies.next = \"$CERC_NEXT_VERSION\"" > package.json.$$ - mv package.json.$$ package.json -fi - -CUR_WEBPACK_VERSION="`jq -r '.dependencies.webpack' package.json`" -if [ -z "$CUR_WEBPACK_VERSION" ]; then - CUR_WEBPACK_VERSION="`jq -r '.devDependencies.webpack' package.json`" -fi -if [ "${CERC_WEBPACK_VERSION}" != "keep" ] || [ "${CUR_WEBPACK_VERSION}" == "null" ]; then - if [ -z "$CERC_WEBPACK_VERSION" ] || [ "$CERC_WEBPACK_VERSION" == "keep" ]; then - CERC_WEBPACK_VERSION="${CERC_DEFAULT_WEBPACK_VER}" - fi - echo "Webpack is required for env variable substitution. Adding to webpack@$CERC_WEBPACK_VERSION to dependencies..." 1>&2 - cat package.json | jq ".dependencies.webpack = \"$CERC_WEBPACK_VERSION\"" > package.json.$$ - mv package.json.$$ package.json -fi - -time $CERC_BUILD_TOOL install || exit 1 - -CUR_NEXT_VERSION=`jq -r '.version' node_modules/next/package.json` - -# See https://github.com/vercel/next.js/discussions/46544 -semver -p -r ">=14.2.0" "$CUR_NEXT_VERSION" -if [ $? -eq 0 ]; then - # For >= 14.2.0 - CERC_NEXT_COMPILE_COMMAND="next build --experimental-build-mode compile" - CERC_NEXT_GENERATE_COMMAND="next build --experimental-build-mode generate" +# Check if webpack is already in package.json +if WEBPACK_VERSION=$(jq -r '.dependencies.webpack // .devDependencies.webpack // empty' package.json); then + if [ -n "$WEBPACK_VERSION" ]; then + echo "Using existing webpack version: $WEBPACK_VERSION" + else + WEBPACK_VERSION=$(determine_webpack_version "$CERC_NEXT_VERSION") + echo "Determined webpack version based on Next.js: $WEBPACK_VERSION" + # Add webpack to devDependencies + jq ".devDependencies.webpack = \"$WEBPACK_VERSION\"" package.json > package.json.tmp && mv package.json.tmp package.json + fi else - # For 13.4.2 to 14.1.x - CERC_NEXT_COMPILE_COMMAND="next experimental-compile" - CERC_NEXT_GENERATE_COMMAND="next experimental-generate" + WEBPACK_VERSION=$(determine_webpack_version "$CERC_NEXT_VERSION") + echo "Determined webpack version based on Next.js: $WEBPACK_VERSION" + # Add webpack to devDependencies + jq ".devDependencies.webpack = \"$WEBPACK_VERSION\"" package.json > package.json.tmp && mv package.json.tmp package.json fi +# Install dependencies +$CERC_BUILD_TOOL install || exit 1 + +# Get the build command from package.json +BUILD_COMMAND=`jq -r '.scripts.build // ""' package.json` + +if [ -z "$BUILD_COMMAND" ]; then + echo "No build command found in package.json. Using default 'next build'." + BUILD_COMMAND="next build" +fi + +# Determine the appropriate build commands based on the Next.js version +if semver -p -r ">=14.2.0" "$CERC_NEXT_VERSION"; then + # For >= 14.2.0 + CERC_NEXT_COMPILE_COMMAND="${BUILD_COMMAND/next build/next build --experimental-build-mode compile}" + CERC_NEXT_GENERATE_COMMAND="${BUILD_COMMAND/next build/next build --experimental-build-mode generate}" +elif semver -p -r ">=13.4.2" "$CERC_NEXT_VERSION"; then + # For 13.4.2 to 14.1.x + CERC_NEXT_COMPILE_COMMAND="${BUILD_COMMAND/next build/next experimental-compile}" + CERC_NEXT_GENERATE_COMMAND="${BUILD_COMMAND/next build/next experimental-generate}" +else + # For versions before 13.4.2 + CERC_NEXT_COMPILE_COMMAND="$BUILD_COMMAND" + CERC_NEXT_GENERATE_COMMAND="$BUILD_COMMAND" +fi + +# Update package.json with the appropriate scripts cat package.json | jq ".scripts.cerc_compile = \"$CERC_NEXT_COMPILE_COMMAND\"" | jq ".scripts.cerc_generate = \"$CERC_NEXT_GENERATE_COMMAND\"" > package.json.$$ mv package.json.$$ package.json -semver -p -r ">=$CERC_MIN_NEXTVER" $CUR_NEXT_VERSION -if [ $? -ne 0 ]; then - cat <" - -############################################################################### - -EOF - cat package.json | jq ".dependencies.next = \"^$CERC_MIN_NEXTVER\"" > package.json.$$ - mv package.json.$$ package.json - time $CERC_BUILD_TOOL install || exit 1 -fi - +# Run the compile command time $CERC_BUILD_TOOL run cerc_compile || exit 1 -exit 0 +exit 0 \ No newline at end of file -- 2.45.2 From fcf2584a3a9b238f1c16e680d081c88392d88e8d Mon Sep 17 00:00:00 2001 From: VPhung24 Date: Tue, 15 Oct 2024 19:53:41 +0000 Subject: [PATCH 2/5] webpack based on app next version --- .../cerc-nextjs-base/scripts/build-app.sh | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/stack_orchestrator/data/container-build/cerc-nextjs-base/scripts/build-app.sh b/stack_orchestrator/data/container-build/cerc-nextjs-base/scripts/build-app.sh index 9b72511e..55fa7749 100755 --- a/stack_orchestrator/data/container-build/cerc-nextjs-base/scripts/build-app.sh +++ b/stack_orchestrator/data/container-build/cerc-nextjs-base/scripts/build-app.sh @@ -46,8 +46,22 @@ determine_webpack_version() { esac } -CERC_WEBPACK_VERSION=$(determine_webpack_version "$CERC_NEXT_VERSION") -echo "Using webpack version: $CERC_WEBPACK_VERSION" +# Check if webpack is already in package.json +if CERC_WEBPACK_VERSION=$(jq -r '.dependencies.webpack // .devDependencies.webpack // empty' package.json); then + if [ -n "$CERC_WEBPACK_VERSION" ]; then + echo "Using existing webpack version: $CERC_WEBPACK_VERSION" + else + CERC_WEBPACK_VERSION=$(determine_webpack_version "$CERC_NEXT_VERSION") + echo "Determined webpack version based on Next.js: $CERC_WEBPACK_VERSION" + # Add webpack to devDependencies + jq ".devDependencies.webpack = \"$CERC_WEBPACK_VERSION\"" package.json > package.json.tmp && mv package.json.tmp package.json + fi +else + CERC_WEBPACK_VERSION=$(determine_webpack_version "$CERC_NEXT_VERSION") + echo "Determined webpack version based on Next.js: $CERC_WEBPACK_VERSION" + # Add webpack to devDependencies + jq ".devDependencies.webpack = \"$CERC_WEBPACK_VERSION\"" package.json > package.json.tmp && mv package.json.tmp package.json +fi # Determine the Next.js config file if [ -f "next.config.mjs" ]; then @@ -151,23 +165,6 @@ mv "${NEXT_CONFIG_JS}.pretty" "$NEXT_CONFIG_JS" # Update package.json [ ! -f "package.dist" ] && cp package.json package.dist -# Check if webpack is already in package.json -if WEBPACK_VERSION=$(jq -r '.dependencies.webpack // .devDependencies.webpack // empty' package.json); then - if [ -n "$WEBPACK_VERSION" ]; then - echo "Using existing webpack version: $WEBPACK_VERSION" - else - WEBPACK_VERSION=$(determine_webpack_version "$CERC_NEXT_VERSION") - echo "Determined webpack version based on Next.js: $WEBPACK_VERSION" - # Add webpack to devDependencies - jq ".devDependencies.webpack = \"$WEBPACK_VERSION\"" package.json > package.json.tmp && mv package.json.tmp package.json - fi -else - WEBPACK_VERSION=$(determine_webpack_version "$CERC_NEXT_VERSION") - echo "Determined webpack version based on Next.js: $WEBPACK_VERSION" - # Add webpack to devDependencies - jq ".devDependencies.webpack = \"$WEBPACK_VERSION\"" package.json > package.json.tmp && mv package.json.tmp package.json -fi - # Install dependencies $CERC_BUILD_TOOL install || exit 1 -- 2.45.2 From f982b7fd339cfe534ecdd6e463dbef9e785481c3 Mon Sep 17 00:00:00 2001 From: VPhung24 Date: Wed, 16 Oct 2024 18:50:51 +0000 Subject: [PATCH 3/5] nextjs-snowball --- .../cerc-nextjs-snowball/Dockerfile | 51 +++++ .../cerc-nextjs-snowball/Dockerfile.webapp | 9 + .../cerc-nextjs-snowball/build.sh | 35 +++ .../scripts/apply-runtime-env.sh | 52 +++++ .../cerc-nextjs-snowball/scripts/build-app.sh | 201 ++++++++++++++++++ .../cerc-nextjs-snowball/scripts/find-env.sh | 31 +++ .../scripts/start-serving-app.sh | 65 ++++++ 7 files changed, 444 insertions(+) create mode 100644 stack_orchestrator/data/container-build/cerc-nextjs-snowball/Dockerfile create mode 100644 stack_orchestrator/data/container-build/cerc-nextjs-snowball/Dockerfile.webapp create mode 100755 stack_orchestrator/data/container-build/cerc-nextjs-snowball/build.sh create mode 100755 stack_orchestrator/data/container-build/cerc-nextjs-snowball/scripts/apply-runtime-env.sh create mode 100755 stack_orchestrator/data/container-build/cerc-nextjs-snowball/scripts/build-app.sh create mode 100755 stack_orchestrator/data/container-build/cerc-nextjs-snowball/scripts/find-env.sh create mode 100755 stack_orchestrator/data/container-build/cerc-nextjs-snowball/scripts/start-serving-app.sh diff --git a/stack_orchestrator/data/container-build/cerc-nextjs-snowball/Dockerfile b/stack_orchestrator/data/container-build/cerc-nextjs-snowball/Dockerfile new file mode 100644 index 00000000..1cc29945 --- /dev/null +++ b/stack_orchestrator/data/container-build/cerc-nextjs-snowball/Dockerfile @@ -0,0 +1,51 @@ +# Originally from: https://github.com/devcontainers/images/blob/main/src/javascript-node/.devcontainer/Dockerfile +# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster +ARG VARIANT=20-bullseye-slim +FROM node:${VARIANT} + +ARG USERNAME=node +ARG NPM_GLOBAL=/usr/local/share/npm-global + +# Add NPM global to PATH. +ENV PATH=${NPM_GLOBAL}/bin:${PATH} +# Prevents npm from printing version warnings +ENV NPM_CONFIG_UPDATE_NOTIFIER=false + +RUN \ + # Configure global npm install location, use group to adapt to UID/GID changes + if ! cat /etc/group | grep -e "^npm:" > /dev/null 2>&1; then groupadd -r npm; fi \ + && usermod -a -G npm ${USERNAME} \ + && umask 0002 \ + && mkdir -p ${NPM_GLOBAL} \ + && touch /usr/local/etc/npmrc \ + && chown ${USERNAME}:npm ${NPM_GLOBAL} /usr/local/etc/npmrc \ + && chmod g+s ${NPM_GLOBAL} \ + && npm config -g set prefix ${NPM_GLOBAL} \ + && su ${USERNAME} -c "npm config -g set prefix ${NPM_GLOBAL}" \ + # Install eslint + && su ${USERNAME} -c "umask 0002 && npm install -g eslint" \ + # Install semver + && su ${USERNAME} -c "umask 0002 && npm install -g semver" \ + # Install pnpm + && su ${USERNAME} -c "umask 0002 && npm install -g pnpm" \ + # Install bun + && su ${USERNAME} -c "umask 0002 && npm install -g bun@1.1.x" \ + && npm cache clean --force > /dev/null 2>&1 + +# [Optional] Uncomment this section to install additional OS packages. +RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ + && apt-get -y install --no-install-recommends jq gettext-base procps + +# [Optional] Uncomment if you want to install more global node modules +# RUN su node -c "npm install -g " + +# We do this to get a yq binary from the published container, for the correct architecture we're building here +COPY --from=docker.io/mikefarah/yq:latest /usr/bin/yq /usr/local/bin/yq + +# Expose port for http +EXPOSE 80 + +COPY /scripts /scripts + +# Default command sleeps forever so docker doesn't kill it +ENTRYPOINT ["/scripts/start-serving-app.sh"] diff --git a/stack_orchestrator/data/container-build/cerc-nextjs-snowball/Dockerfile.webapp b/stack_orchestrator/data/container-build/cerc-nextjs-snowball/Dockerfile.webapp new file mode 100644 index 00000000..51664deb --- /dev/null +++ b/stack_orchestrator/data/container-build/cerc-nextjs-snowball/Dockerfile.webapp @@ -0,0 +1,9 @@ +FROM cerc/nextjs-base:local + +ARG CERC_NEXT_VERSION=keep +ARG CERC_BUILD_TOOL + +WORKDIR /app +COPY . . +RUN rm -rf node_modules build .next* +RUN /scripts/build-app.sh /app diff --git a/stack_orchestrator/data/container-build/cerc-nextjs-snowball/build.sh b/stack_orchestrator/data/container-build/cerc-nextjs-snowball/build.sh new file mode 100755 index 00000000..bb3983cf --- /dev/null +++ b/stack_orchestrator/data/container-build/cerc-nextjs-snowball/build.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# Build cerc/laconic-registry-cli + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh + +# See: https://stackoverflow.com/a/246128/1701505 +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +CERC_CONTAINER_BUILD_WORK_DIR=${CERC_CONTAINER_BUILD_WORK_DIR:-$SCRIPT_DIR} +CERC_CONTAINER_BUILD_DOCKERFILE=${CERC_CONTAINER_BUILD_DOCKERFILE:-$SCRIPT_DIR/Dockerfile} +CERC_CONTAINER_BUILD_TAG=${CERC_CONTAINER_BUILD_TAG:-cerc/nextjs-base:local} + +docker build -t $CERC_CONTAINER_BUILD_TAG ${build_command_args} -f $CERC_CONTAINER_BUILD_DOCKERFILE $CERC_CONTAINER_BUILD_WORK_DIR +rc=$? + +if [ $rc -ne 0 ]; then + echo "BUILD FAILED" 1>&2 + exit $rc +fi + +if [ "$CERC_CONTAINER_BUILD_TAG" != "cerc/nextjs-base:local" ]; then + cat < $TMP_ENV + set -a + source .env + source $TMP_ENV + set +a + rm -f $TMP_ENV +fi + +for f in $(find . -type f \( -regex '.*.html?' -or -regex ".*.[tj]s\(x\|on\)?$" \) | grep -v 'node_modules' | grep -v '.git'); do + for e in $(cat "${f}" | tr -s '[:blank:]' '\n' | tr -s '["/\\{},();]' '\n' | tr -s "[']" '\n' | egrep -o -e '^CERC_RUNTIME_ENV_.+$' -e '^LACONIC_HOSTED_CONFIG_.+$'); do + orig_name=$(echo -n "${e}" | sed 's/"//g') + cur_name=$(echo -n "${orig_name}" | sed 's/CERC_RUNTIME_ENV_//g') + cur_val=$(echo -n "\$${cur_name}" | envsubst) + if [ "$CERC_RETAIN_ENV_QUOTES" != "true" ]; then + cur_val=$(sed "s/^[\"']//" <<< "$cur_val" | sed "s/[\"']//") + fi + esc_val=$(sed 's/[&/\]/\\&/g' <<< "$cur_val") + echo "$f: $cur_name=$cur_val" + sed -i "s/$orig_name/$esc_val/g" $f + done +done diff --git a/stack_orchestrator/data/container-build/cerc-nextjs-snowball/scripts/build-app.sh b/stack_orchestrator/data/container-build/cerc-nextjs-snowball/scripts/build-app.sh new file mode 100755 index 00000000..55fa7749 --- /dev/null +++ b/stack_orchestrator/data/container-build/cerc-nextjs-snowball/scripts/build-app.sh @@ -0,0 +1,201 @@ +#!/bin/bash + +set -euo pipefail + +if [ -n "${CERC_SCRIPT_DEBUG:-}" ]; then + set -x +fi + +# Determine the build tool +CERC_BUILD_TOOL="${CERC_BUILD_TOOL:-}" +if [ -z "$CERC_BUILD_TOOL" ]; then + if [ -f "pnpm-lock.yaml" ]; then + CERC_BUILD_TOOL=pnpm + elif [ -f "yarn.lock" ]; then + CERC_BUILD_TOOL=yarn + elif [ -f "bun.lockb" ]; then + CERC_BUILD_TOOL=bun + else + CERC_BUILD_TOOL=npm + fi +fi + +SCRIPT_DIR=$(dirname "$(readlink -f "$0")") +WORK_DIR="${1:-/app}" + +cd "${WORK_DIR}" || exit 1 + +# Get the app's Next.js version +CERC_NEXT_VERSION=$(jq -r '.dependencies.next' package.json) +echo "Using Next.js version: $CERC_NEXT_VERSION" + +# Determine webpack version based on Next.js version (unused if already installed) +determine_webpack_version() { + local next_version=$1 + local major_version=${next_version%%.*} + case $major_version in + 13) + echo "5.75.0" + ;; + 14) + echo "5.88.0" + ;; + *) + echo "5.93.0" # Default to latest stable version if unknown + ;; + esac +} + +# Check if webpack is already in package.json +if CERC_WEBPACK_VERSION=$(jq -r '.dependencies.webpack // .devDependencies.webpack // empty' package.json); then + if [ -n "$CERC_WEBPACK_VERSION" ]; then + echo "Using existing webpack version: $CERC_WEBPACK_VERSION" + else + CERC_WEBPACK_VERSION=$(determine_webpack_version "$CERC_NEXT_VERSION") + echo "Determined webpack version based on Next.js: $CERC_WEBPACK_VERSION" + # Add webpack to devDependencies + jq ".devDependencies.webpack = \"$CERC_WEBPACK_VERSION\"" package.json > package.json.tmp && mv package.json.tmp package.json + fi +else + CERC_WEBPACK_VERSION=$(determine_webpack_version "$CERC_NEXT_VERSION") + echo "Determined webpack version based on Next.js: $CERC_WEBPACK_VERSION" + # Add webpack to devDependencies + jq ".devDependencies.webpack = \"$CERC_WEBPACK_VERSION\"" package.json > package.json.tmp && mv package.json.tmp package.json +fi + +# Determine the Next.js config file +if [ -f "next.config.mjs" ]; then + NEXT_CONFIG_JS="next.config.mjs" + IMPORT_OR_REQUIRE="import" +else + NEXT_CONFIG_JS="next.config.js" + IMPORT_OR_REQUIRE="require" +fi + +# If this file doesn't exist at all, we'll get errors below. +if [ ! -f "${NEXT_CONFIG_JS}" ]; then + touch ${NEXT_CONFIG_JS} +fi + +# Backup the original config if not already done +if [ ! -f "next.config.dist" ]; then + cp "$NEXT_CONFIG_JS" next.config.dist +fi + +# Install js-beautify if not present +command -v js-beautify >/dev/null || npm i -g js-beautify + +# Beautify the config file +js-beautify "$NEXT_CONFIG_JS" > "${NEXT_CONFIG_JS}.pretty" +mv "${NEXT_CONFIG_JS}.pretty" "$NEXT_CONFIG_JS" + +# Add webpack import/require if not present +if [ "$IMPORT_OR_REQUIRE" = "import" ]; then + if ! grep -q "import.*webpack" "$NEXT_CONFIG_JS"; then + sed -i '1iimport webpack from "webpack";' "$NEXT_CONFIG_JS" + fi + if ! grep -q "import.*createRequire" "$NEXT_CONFIG_JS"; then + sed -i '2iimport { createRequire } from "module";\nconst require = createRequire(import.meta.url);' "$NEXT_CONFIG_JS" + fi +else + if ! grep -q "require.*webpack" "$NEXT_CONFIG_JS"; then + sed -i '1iconst webpack = require("webpack");' "$NEXT_CONFIG_JS" + fi +fi + +# Add environment mapping logic if not present +if ! grep -q "let envMap;" "$NEXT_CONFIG_JS"; then + cat << 'EOF' >> "$NEXT_CONFIG_JS" + +let envMap; +try { + envMap = require('./.env-list.json').reduce((a, v) => { + a[v] = JSON.stringify(`CERC_RUNTIME_ENV_${v.split(/\./).pop()}`); + return a; + }, {}); +} catch (e) { + console.error('Error loading .env-list.json:', e); + envMap = Object.keys(process.env).reduce((a, v) => { + if (v.startsWith('CERC_')) { + a[`process.env.${v}`] = JSON.stringify(process.env[v]); + } + return a; + }, {}); +} +console.log('Environment map:', envMap); +EOF +fi + +# Add or update webpack configuration +if ! grep -q '__xCfg__' "$NEXT_CONFIG_JS"; then + cat << 'EOF' >> "$NEXT_CONFIG_JS" + +const __xCfg__ = (nextConfig) => { + return { + ...nextConfig, + webpack: (config, options) => { + config.plugins.push(new webpack.DefinePlugin(envMap)); + if (typeof nextConfig.webpack === 'function') { + return nextConfig.webpack(config, options); + } + return config; + }, + }; +}; + +EOF + + # Update the export/module.exports line + if [ "$IMPORT_OR_REQUIRE" = "import" ]; then + sed -i 's/export default/const __orig_cfg__ =/' "$NEXT_CONFIG_JS" + echo "export default __xCfg__(__orig_cfg__);" >> "$NEXT_CONFIG_JS" + else + sed -i 's/module.exports =/const __orig_cfg__ =/' "$NEXT_CONFIG_JS" + echo "module.exports = __xCfg__(__orig_cfg__);" >> "$NEXT_CONFIG_JS" + fi +fi + +# Clean up the config file +js-beautify "$NEXT_CONFIG_JS" > "${NEXT_CONFIG_JS}.pretty" +mv "${NEXT_CONFIG_JS}.pretty" "$NEXT_CONFIG_JS" + +# Generate .env-list.json +"${SCRIPT_DIR}/find-env.sh" "$(pwd)" > .env-list.json + +# Update package.json +[ ! -f "package.dist" ] && cp package.json package.dist + +# Install dependencies +$CERC_BUILD_TOOL install || exit 1 + +# Get the build command from package.json +BUILD_COMMAND=`jq -r '.scripts.build // ""' package.json` + +if [ -z "$BUILD_COMMAND" ]; then + echo "No build command found in package.json. Using default 'next build'." + BUILD_COMMAND="next build" +fi + +# Determine the appropriate build commands based on the Next.js version +if semver -p -r ">=14.2.0" "$CERC_NEXT_VERSION"; then + # For >= 14.2.0 + CERC_NEXT_COMPILE_COMMAND="${BUILD_COMMAND/next build/next build --experimental-build-mode compile}" + CERC_NEXT_GENERATE_COMMAND="${BUILD_COMMAND/next build/next build --experimental-build-mode generate}" +elif semver -p -r ">=13.4.2" "$CERC_NEXT_VERSION"; then + # For 13.4.2 to 14.1.x + CERC_NEXT_COMPILE_COMMAND="${BUILD_COMMAND/next build/next experimental-compile}" + CERC_NEXT_GENERATE_COMMAND="${BUILD_COMMAND/next build/next experimental-generate}" +else + # For versions before 13.4.2 + CERC_NEXT_COMPILE_COMMAND="$BUILD_COMMAND" + CERC_NEXT_GENERATE_COMMAND="$BUILD_COMMAND" +fi + +# Update package.json with the appropriate scripts +cat package.json | jq ".scripts.cerc_compile = \"$CERC_NEXT_COMPILE_COMMAND\"" | jq ".scripts.cerc_generate = \"$CERC_NEXT_GENERATE_COMMAND\"" > package.json.$$ +mv package.json.$$ package.json + +# Run the compile command +time $CERC_BUILD_TOOL run cerc_compile || exit 1 + +exit 0 \ No newline at end of file diff --git a/stack_orchestrator/data/container-build/cerc-nextjs-snowball/scripts/find-env.sh b/stack_orchestrator/data/container-build/cerc-nextjs-snowball/scripts/find-env.sh new file mode 100755 index 00000000..508017fc --- /dev/null +++ b/stack_orchestrator/data/container-build/cerc-nextjs-snowball/scripts/find-env.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +WORK_DIR="${1:-./}" +TMPF=$(mktemp) + +cd "$WORK_DIR" || exit 1 + +for d in $(find . -maxdepth 1 -type d | grep -v '\./\.' | grep '/' | cut -d'/' -f2); do + egrep "/$d[/$]?" .gitignore >/dev/null 2>/dev/null + if [ $? -eq 0 ]; then + continue + fi + + for f in $(find "$d" -regex ".*.[tj]sx?$" -type f); do + cat "$f" | tr -s '[:blank:]' '\n' | tr -s '[{},()]' '\n' | egrep -o 'process.env.[A-Za-z0-9_]+' >> $TMPF + done +done + +NEXT_CONF="next.config.mjs next.config.js next.config.dist" +for f in $NEXT_CONF; do + if [ -f "$f" ]; then + cat "$f" | tr -s '[:blank:]' '\n' | tr -s '[{},()]' '\n' | egrep -o 'process.env.[A-Za-z0-9_]+' >> $TMPF + fi +done + +cat $TMPF | sort -u | jq --raw-input . | jq --slurp . +rm -f $TMPF diff --git a/stack_orchestrator/data/container-build/cerc-nextjs-snowball/scripts/start-serving-app.sh b/stack_orchestrator/data/container-build/cerc-nextjs-snowball/scripts/start-serving-app.sh new file mode 100755 index 00000000..03457574 --- /dev/null +++ b/stack_orchestrator/data/container-build/cerc-nextjs-snowball/scripts/start-serving-app.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +CERC_MAX_GENERATE_TIME=${CERC_MAX_GENERATE_TIME:-120} +tpid="" + +ctrl_c() { + kill $tpid $(ps -ef | grep node | grep next | awk '{print $2}') 2>/dev/null +} + +trap ctrl_c INT + +CERC_BUILD_TOOL="${CERC_BUILD_TOOL}" +if [ -z "$CERC_BUILD_TOOL" ]; then + if [ -f "pnpm-lock.yaml" ]; then + CERC_BUILD_TOOL=pnpm + elif [ -f "yarn.lock" ]; then + CERC_BUILD_TOOL=yarn + elif [ -f "bun.lockb" ]; then + CERC_BUILD_TOOL=bun + else + CERC_BUILD_TOOL=npm + fi +fi + +CERC_WEBAPP_FILES_DIR="${CERC_WEBAPP_FILES_DIR:-/app}" +cd "$CERC_WEBAPP_FILES_DIR" + +"$SCRIPT_DIR/apply-runtime-env.sh" "`pwd`" .next .next-r +mv .next .next.old +mv .next-r/.next . + +if [ "$CERC_NEXTJS_SKIP_GENERATE" != "true" ]; then + jq -e '.scripts.cerc_generate' package.json >/dev/null + if [ $? -eq 0 ]; then + npm run cerc_generate > gen.out 2>&1 & + tail -f gen.out & + tpid=$! + + count=0 + generate_done="false" + while [ $count -lt $CERC_MAX_GENERATE_TIME ] && [ "$generate_done" == "false" ]; do + sleep 1 + count=$((count + 1)) + grep 'rendered as static' gen.out > /dev/null + if [ $? -eq 0 ]; then + generate_done="true" + fi + done + + if [ $generate_done != "true" ]; then + echo "ERROR: 'npm run cerc_generate' not successful within CERC_MAX_GENERATE_TIME" 1>&2 + exit 1 + fi + + kill $tpid $(ps -ef | grep node | grep next | grep generate | awk '{print $2}') 2>/dev/null + tpid="" + fi +fi + +$CERC_BUILD_TOOL start . -- -p ${CERC_LISTEN_PORT:-80} -- 2.45.2 From a00a600588f092112701d099b79c9d9c7bc717e1 Mon Sep 17 00:00:00 2001 From: VPhung24 Date: Wed, 16 Oct 2024 18:52:17 +0000 Subject: [PATCH 4/5] return to original build-app.sh --- .../cerc-nextjs-base/scripts/build-app.sh | 280 ++++++++++-------- 1 file changed, 161 insertions(+), 119 deletions(-) diff --git a/stack_orchestrator/data/container-build/cerc-nextjs-base/scripts/build-app.sh b/stack_orchestrator/data/container-build/cerc-nextjs-base/scripts/build-app.sh index 55fa7749..1b3c3cc3 100755 --- a/stack_orchestrator/data/container-build/cerc-nextjs-base/scripts/build-app.sh +++ b/stack_orchestrator/data/container-build/cerc-nextjs-base/scripts/build-app.sh @@ -1,13 +1,16 @@ #!/bin/bash -set -euo pipefail - -if [ -n "${CERC_SCRIPT_DEBUG:-}" ]; then +if [ -n "$CERC_SCRIPT_DEBUG" ]; then set -x fi -# Determine the build tool -CERC_BUILD_TOOL="${CERC_BUILD_TOOL:-}" +CERC_MIN_NEXTVER=13.4.2 +CERC_DEFAULT_WEBPACK_VER="5.93.0" + +CERC_NEXT_VERSION="${CERC_NEXT_VERSION:-keep}" +CERC_WEBPACK_VERSION="${CERC_WEBPACK_VERSION:-keep}" + +CERC_BUILD_TOOL="${CERC_BUILD_TOOL}" if [ -z "$CERC_BUILD_TOOL" ]; then if [ -f "pnpm-lock.yaml" ]; then CERC_BUILD_TOOL=pnpm @@ -20,50 +23,11 @@ if [ -z "$CERC_BUILD_TOOL" ]; then fi fi -SCRIPT_DIR=$(dirname "$(readlink -f "$0")") +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) WORK_DIR="${1:-/app}" cd "${WORK_DIR}" || exit 1 -# Get the app's Next.js version -CERC_NEXT_VERSION=$(jq -r '.dependencies.next' package.json) -echo "Using Next.js version: $CERC_NEXT_VERSION" - -# Determine webpack version based on Next.js version (unused if already installed) -determine_webpack_version() { - local next_version=$1 - local major_version=${next_version%%.*} - case $major_version in - 13) - echo "5.75.0" - ;; - 14) - echo "5.88.0" - ;; - *) - echo "5.93.0" # Default to latest stable version if unknown - ;; - esac -} - -# Check if webpack is already in package.json -if CERC_WEBPACK_VERSION=$(jq -r '.dependencies.webpack // .devDependencies.webpack // empty' package.json); then - if [ -n "$CERC_WEBPACK_VERSION" ]; then - echo "Using existing webpack version: $CERC_WEBPACK_VERSION" - else - CERC_WEBPACK_VERSION=$(determine_webpack_version "$CERC_NEXT_VERSION") - echo "Determined webpack version based on Next.js: $CERC_WEBPACK_VERSION" - # Add webpack to devDependencies - jq ".devDependencies.webpack = \"$CERC_WEBPACK_VERSION\"" package.json > package.json.tmp && mv package.json.tmp package.json - fi -else - CERC_WEBPACK_VERSION=$(determine_webpack_version "$CERC_NEXT_VERSION") - echo "Determined webpack version based on Next.js: $CERC_WEBPACK_VERSION" - # Add webpack to devDependencies - jq ".devDependencies.webpack = \"$CERC_WEBPACK_VERSION\"" package.json > package.json.tmp && mv package.json.tmp package.json -fi - -# Determine the Next.js config file if [ -f "next.config.mjs" ]; then NEXT_CONFIG_JS="next.config.mjs" IMPORT_OR_REQUIRE="import" @@ -77,125 +41,203 @@ if [ ! -f "${NEXT_CONFIG_JS}" ]; then touch ${NEXT_CONFIG_JS} fi -# Backup the original config if not already done if [ ! -f "next.config.dist" ]; then - cp "$NEXT_CONFIG_JS" next.config.dist + cp $NEXT_CONFIG_JS next.config.dist fi -# Install js-beautify if not present -command -v js-beautify >/dev/null || npm i -g js-beautify +which js-beautify >/dev/null +if [ $? -ne 0 ]; then + npm i -g js-beautify +fi -# Beautify the config file -js-beautify "$NEXT_CONFIG_JS" > "${NEXT_CONFIG_JS}.pretty" -mv "${NEXT_CONFIG_JS}.pretty" "$NEXT_CONFIG_JS" +# js-beautify formats NEXTJS_CONFIG_FILE (ie next.config.js / next.config.mjs) so we can reliably transformable later +js-beautify next.config.dist > ${NEXT_CONFIG_JS} +echo "" >> ${NEXT_CONFIG_JS} -# Add webpack import/require if not present -if [ "$IMPORT_OR_REQUIRE" = "import" ]; then - if ! grep -q "import.*webpack" "$NEXT_CONFIG_JS"; then - sed -i '1iimport webpack from "webpack";' "$NEXT_CONFIG_JS" - fi - if ! grep -q "import.*createRequire" "$NEXT_CONFIG_JS"; then - sed -i '2iimport { createRequire } from "module";\nconst require = createRequire(import.meta.url);' "$NEXT_CONFIG_JS" +if [ "${IMPORT_OR_REQUIRE}" == "require" ]; then + WEBPACK_REQ_LINE=$(grep -n "require([\'\"]webpack[\'\"])" ${NEXT_CONFIG_JS} | cut -d':' -f1) + if [ -z "$WEBPACK_REQ_LINE" ]; then + cat > ${NEXT_CONFIG_JS}.0 < ${NEXT_CONFIG_JS}.0 <> ${NEXT_CONFIG_JS}.0 <> "$NEXT_CONFIG_JS" - +cat > ${NEXT_CONFIG_JS}.1 < { - a[v] = JSON.stringify(`CERC_RUNTIME_ENV_${v.split(/\./).pop()}`); + a[v] = \`"CERC_RUNTIME_ENV_\${v.split(/\./).pop()}"\`; return a; }, {}); } catch (e) { - console.error('Error loading .env-list.json:', e); + console.error(e); + // If .env-list.json cannot be loaded, we are probably running in dev mode, so use process.env instead. envMap = Object.keys(process.env).reduce((a, v) => { if (v.startsWith('CERC_')) { - a[`process.env.${v}`] = JSON.stringify(process.env[v]); + a[\`process.env.\${v}\`] = JSON.stringify(process.env[v]); } return a; }, {}); } -console.log('Environment map:', envMap); +console.log(envMap); EOF -fi -# Add or update webpack configuration -if ! grep -q '__xCfg__' "$NEXT_CONFIG_JS"; then - cat << 'EOF' >> "$NEXT_CONFIG_JS" +grep 'withPWA' ${NEXT_CONFIG_JS} >/dev/null && HAS_WITHPWA=true || HAS_WITHPWA=false -const __xCfg__ = (nextConfig) => { - return { - ...nextConfig, - webpack: (config, options) => { +if [ "$HAS_WITHPWA" == "true" ]; then + if [ "$IMPORT_OR_REQUIRE" == "import" ]; then + cat > ${NEXT_CONFIG_JS}.2 < { + const realPWA = withPWA(p); + return (nextConfig) => { + const modConfig = {...nextConfig}; + + modConfig.webpack = (config) => { config.plugins.push(new webpack.DefinePlugin(envMap)); - if (typeof nextConfig.webpack === 'function') { - return nextConfig.webpack(config, options); - } - return config; - }, + return nextConfig.webpack ? nextConfig.webpack(config) : config; + }; + + return realPWA(modConfig); }; }; - EOF - - # Update the export/module.exports line - if [ "$IMPORT_OR_REQUIRE" = "import" ]; then - sed -i 's/export default/const __orig_cfg__ =/' "$NEXT_CONFIG_JS" - echo "export default __xCfg__(__orig_cfg__);" >> "$NEXT_CONFIG_JS" else - sed -i 's/module.exports =/const __orig_cfg__ =/' "$NEXT_CONFIG_JS" - echo "module.exports = __xCfg__(__orig_cfg__);" >> "$NEXT_CONFIG_JS" + cat > ${NEXT_CONFIG_JS}.3 < { + const modConfig = {...nextConfig}; + + modConfig.webpack = (config) => { + config.plugins.push(new webpack.DefinePlugin(envMap)); + return nextConfig.webpack ? nextConfig.webpack(config) : config; + }; + + return withPWA(modConfig); +}; +EOF + fi + + cat ${NEXT_CONFIG_JS} | js-beautify | sed 's/withPWA(/__xPWA__(/g' > ${NEXT_CONFIG_JS}.4 +else + cat > ${NEXT_CONFIG_JS}.3 < { + const modConfig = {...nextConfig}; + + modConfig.webpack = (config) => { + config.plugins.push(new webpack.DefinePlugin(envMap)); + return nextConfig.webpack ? nextConfig.webpack(config) : config; + }; + + return modConfig; + }; +EOF + if [ "$IMPORT_OR_REQUIRE" == "import" ]; then + cat ${NEXT_CONFIG_JS} | js-beautify | sed 's/export\s\+default\s\+/const __orig_cfg__ = /g' > ${NEXT_CONFIG_JS}.4 + echo "export default __xCfg__(__orig_cfg__);" > ${NEXT_CONFIG_JS}.5 + else + cat ${NEXT_CONFIG_JS} | js-beautify | sed 's/module.exports\s\+=\s\+/const __orig_cfg__ = /g' > ${NEXT_CONFIG_JS}.4 + echo "module.exports = __xCfg__(__orig_cfg__);" > ${NEXT_CONFIG_JS}.5 fi fi -# Clean up the config file -js-beautify "$NEXT_CONFIG_JS" > "${NEXT_CONFIG_JS}.pretty" -mv "${NEXT_CONFIG_JS}.pretty" "$NEXT_CONFIG_JS" -# Generate .env-list.json +rm -f ${NEXT_CONFIG_JS} +for ((i=0; i <= 10; i++)); do + if [ -s "${NEXT_CONFIG_JS}.${i}" ]; then + if [ $i -le 2 ] ; then + cat ${NEXT_CONFIG_JS}.${i} >> ${NEXT_CONFIG_JS} + else + cat ${NEXT_CONFIG_JS}.${i} | sed 's/^ *//g' | js-beautify | grep -v 'process\.\env\.' | js-beautify >> ${NEXT_CONFIG_JS} + fi + fi +done +rm ${NEXT_CONFIG_JS}.* +cat ${NEXT_CONFIG_JS} | js-beautify > ${NEXT_CONFIG_JS}.pretty +mv ${NEXT_CONFIG_JS}.pretty ${NEXT_CONFIG_JS} + "${SCRIPT_DIR}/find-env.sh" "$(pwd)" > .env-list.json -# Update package.json -[ ! -f "package.dist" ] && cp package.json package.dist - -# Install dependencies -$CERC_BUILD_TOOL install || exit 1 - -# Get the build command from package.json -BUILD_COMMAND=`jq -r '.scripts.build // ""' package.json` - -if [ -z "$BUILD_COMMAND" ]; then - echo "No build command found in package.json. Using default 'next build'." - BUILD_COMMAND="next build" +if [ ! -f "package.dist" ]; then + cp package.json package.dist fi -# Determine the appropriate build commands based on the Next.js version -if semver -p -r ">=14.2.0" "$CERC_NEXT_VERSION"; then +CUR_NEXT_VERSION="`jq -r '.dependencies.next' package.json`" + +if [ "$CERC_NEXT_VERSION" != "keep" ] && [ "$CUR_NEXT_VERSION" != "$CERC_NEXT_VERSION" ]; then + echo "Changing 'next' version specifier from '$CUR_NEXT_VERSION' to '$CERC_NEXT_VERSION' (set with '--extra-build-args \"--build-arg CERC_NEXT_VERSION=$CERC_NEXT_VERSION\"')" + cat package.json | jq ".dependencies.next = \"$CERC_NEXT_VERSION\"" > package.json.$$ + mv package.json.$$ package.json +fi + +CUR_WEBPACK_VERSION="`jq -r '.dependencies.webpack' package.json`" +if [ -z "$CUR_WEBPACK_VERSION" ]; then + CUR_WEBPACK_VERSION="`jq -r '.devDependencies.webpack' package.json`" +fi +if [ "${CERC_WEBPACK_VERSION}" != "keep" ] || [ "${CUR_WEBPACK_VERSION}" == "null" ]; then + if [ -z "$CERC_WEBPACK_VERSION" ] || [ "$CERC_WEBPACK_VERSION" == "keep" ]; then + CERC_WEBPACK_VERSION="${CERC_DEFAULT_WEBPACK_VER}" + fi + echo "Webpack is required for env variable substitution. Adding to webpack@$CERC_WEBPACK_VERSION to dependencies..." 1>&2 + cat package.json | jq ".dependencies.webpack = \"$CERC_WEBPACK_VERSION\"" > package.json.$$ + mv package.json.$$ package.json +fi + +time $CERC_BUILD_TOOL install || exit 1 + +CUR_NEXT_VERSION=`jq -r '.version' node_modules/next/package.json` + +# See https://github.com/vercel/next.js/discussions/46544 +semver -p -r ">=14.2.0" "$CUR_NEXT_VERSION" +if [ $? -eq 0 ]; then # For >= 14.2.0 - CERC_NEXT_COMPILE_COMMAND="${BUILD_COMMAND/next build/next build --experimental-build-mode compile}" - CERC_NEXT_GENERATE_COMMAND="${BUILD_COMMAND/next build/next build --experimental-build-mode generate}" -elif semver -p -r ">=13.4.2" "$CERC_NEXT_VERSION"; then - # For 13.4.2 to 14.1.x - CERC_NEXT_COMPILE_COMMAND="${BUILD_COMMAND/next build/next experimental-compile}" - CERC_NEXT_GENERATE_COMMAND="${BUILD_COMMAND/next build/next experimental-generate}" + CERC_NEXT_COMPILE_COMMAND="next build --experimental-build-mode compile" + CERC_NEXT_GENERATE_COMMAND="next build --experimental-build-mode generate" else - # For versions before 13.4.2 - CERC_NEXT_COMPILE_COMMAND="$BUILD_COMMAND" - CERC_NEXT_GENERATE_COMMAND="$BUILD_COMMAND" + # For 13.4.2 to 14.1.x + CERC_NEXT_COMPILE_COMMAND="next experimental-compile" + CERC_NEXT_GENERATE_COMMAND="next experimental-generate" fi -# Update package.json with the appropriate scripts cat package.json | jq ".scripts.cerc_compile = \"$CERC_NEXT_COMPILE_COMMAND\"" | jq ".scripts.cerc_generate = \"$CERC_NEXT_GENERATE_COMMAND\"" > package.json.$$ mv package.json.$$ package.json -# Run the compile command +semver -p -r ">=$CERC_MIN_NEXTVER" $CUR_NEXT_VERSION +if [ $? -ne 0 ]; then + cat <" + +############################################################################### + +EOF + cat package.json | jq ".dependencies.next = \"^$CERC_MIN_NEXTVER\"" > package.json.$$ + mv package.json.$$ package.json + time $CERC_BUILD_TOOL install || exit 1 +fi + time $CERC_BUILD_TOOL run cerc_compile || exit 1 exit 0 \ No newline at end of file -- 2.45.2 From 69f558ecaa353d846c0953c8ae58a0769acd5ca3 Mon Sep 17 00:00:00 2001 From: VPhung24 Date: Wed, 16 Oct 2024 18:55:55 +0000 Subject: [PATCH 5/5] app type webapp/snowball/nextjs --- stack_orchestrator/deploy/webapp/util.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stack_orchestrator/deploy/webapp/util.py b/stack_orchestrator/deploy/webapp/util.py index c6b6a786..1e6b1058 100644 --- a/stack_orchestrator/deploy/webapp/util.py +++ b/stack_orchestrator/deploy/webapp/util.py @@ -481,6 +481,8 @@ def determine_base_container(clone_dir, app_type="webapp"): raise Exception(f"Unsupported app_type {app_type}") base_container = "cerc/webapp-base" + if app_type == "webapp/snowball/nextjs": + base_container = "cerc/nextjs-snowball" if app_type == "webapp/next": base_container = "cerc/nextjs-base" elif app_type == "webapp": -- 2.45.2