diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index 70f8fd3fe..4bdb21722 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -22,17 +22,39 @@ jobs: - name: Get version id: version run: | - # Match both "'version' => '4.3.12'" and "'version' => env('COOLIFY_VERSION') ?: '4.3.12'" - # (greedy .* means the capture takes the last quoted string on the line) - BASE_VERSION=$(sed -n "s/.*'version' => .*'\([^']*\)'.*/\1/p" config/constants.php | head -1) - if [ -z "$BASE_VERSION" ]; then - echo "ERROR: could not extract base version from config/constants.php" >&2 - exit 1 - fi + # Reads one version constant out of config/constants.php. + # The match is anchored at the start of the line, so a nested key on + # another line (e.g. "'nightly' => ['version' => '5.9.9']") cannot be + # picked up, and the trailing greedy .* takes the LAST quoted string on + # the line, so both upstream shapes work: + # 'version' => '4.2.0', + # 'version' => env('COOLIFY_VERSION') ?: '4.3.12', + # Empty or non-version results fail the build instead of tagging the + # image and versions.json with garbage. + extract_version() { + key="$1" + value=$(sed -n "s/^[[:space:]]*'${key}' => .*'\([^']*\)'.*/\1/p" config/constants.php | head -1) + if [ -z "$value" ]; then + echo "ERROR: could not extract '${key}' from config/constants.php" >&2 + grep -n "'${key}' =>" config/constants.php >&2 || true + exit 1 + fi + if ! printf '%s' "$value" | grep -Eq '^[0-9]+(\.[0-9]+)+([-.][0-9A-Za-z.]+)?$'; then + echo "ERROR: extracted ${key} '${value}' does not look like a version." >&2 + echo " The '${key}' entry in config/constants.php probably changed shape;" >&2 + echo " see docs/operations/COOLIFY_FORK.md (How version bumping works)." >&2 + exit 1 + fi + printf '%s' "$value" + } + + # `exit 1` inside the function only leaves the command substitution's + # subshell, so each call needs its own `|| exit 1`. + BASE_VERSION=$(extract_version version) || exit 1 + HELPER_VERSION=$(extract_version helper_version) || exit 1 + REALTIME_VERSION=$(extract_version realtime_version) || exit 1 TIMESTAMP=$(date -u +%Y%m%d%H%M) VERSION="${BASE_VERSION}.${TIMESTAMP}" - HELPER_VERSION=$(sed -n "s/.*'helper_version' => '\([^']*\)'.*/\1/p" config/constants.php) - REALTIME_VERSION=$(sed -n "s/.*'realtime_version' => '\([^']*\)'.*/\1/p" config/constants.php) echo "VERSION=${VERSION}" >> "$GITHUB_OUTPUT" echo "HELPER_VERSION=${HELPER_VERSION}" >> "$GITHUB_OUTPUT" echo "REALTIME_VERSION=${REALTIME_VERSION}" >> "$GITHUB_OUTPUT" diff --git a/docker/production/Dockerfile b/docker/production/Dockerfile index 264bac448..277ab3a77 100644 --- a/docker/production/Dockerfile +++ b/docker/production/Dockerfile @@ -151,9 +151,23 @@ COPY --chown=www-data:www-data config ./config # MapleDeploy: inject build version into constants.php at build time. # The version in git stays at the upstream value to avoid rebase conflicts. # CI passes the timestamped version (e.g. 4.0.0-beta.468.202603140006) as a build arg. +# The substitution replaces the whole 'version' line rather than matching a +# quoted literal, so it works for both upstream constant shapes: +# 'version' => '4.2.0', +# 'version' => env('COOLIFY_VERSION') ?: '4.3.12', +# and it collapses the env() indirection to a literal so the image always +# reports the version it was built as, regardless of runtime env. +# The grep is a hard gate: a silently unmatched sed used to ship an image +# tagged with a timestamped version while reporting the upstream base version. ARG MAPLEDEPLOY_VERSION="" RUN if [ -n "$MAPLEDEPLOY_VERSION" ]; then \ - sed -i "s/'version' => '[^']*'/'version' => '$MAPLEDEPLOY_VERSION'/" config/constants.php && \ + sed -i -E "s|^([[:space:]]*'version' => ).*|\1'$MAPLEDEPLOY_VERSION',|" config/constants.php; \ + if ! grep -qF "'version' => '$MAPLEDEPLOY_VERSION'," config/constants.php; then \ + echo "ERROR: MapleDeploy version injection failed: no 'version' entry in config/constants.php matched the expected shape."; \ + echo " See docs/operations/COOLIFY_FORK.md (How version bumping works) before changing this step."; \ + grep -n "'version' =>" config/constants.php || true; \ + exit 1; \ + fi; \ chown www-data:www-data config/constants.php; \ fi