From cc340ae5f2ff546d18a6d3f4f1493f3d3169d91b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Manso?= Date: Sun, 26 Jul 2026 11:40:55 +0100 Subject: [PATCH] fix(build): make Makefile $(shell) probes work under native Windows cmd (#1953) --- .github/workflows/backend-tests.yml | 4 +++ Makefile | 16 +++++++++-- apps/backend/Makefile | 31 ++++++++++++++++++--- scripts/check-make-shells | 42 +++++++++++++++++++++++++++-- 4 files changed, 86 insertions(+), 7 deletions(-) diff --git a/.github/workflows/backend-tests.yml b/.github/workflows/backend-tests.yml index ade001d461..665e985116 100644 --- a/.github/workflows/backend-tests.yml +++ b/.github/workflows/backend-tests.yml @@ -5,6 +5,9 @@ on: branches: [main] paths: - "apps/backend/**" + # check-make-shells also lints the root Makefile's $(shell ...) probes, so + # a change there has to be able to trip it. + - "Makefile" - "scripts/check-make-shells" - ".github/workflows/backend-tests.yml" - "!**/*.md" @@ -14,6 +17,7 @@ on: branches: [main] paths: - "apps/backend/**" + - "Makefile" - "scripts/check-make-shells" - ".github/workflows/backend-tests.yml" - "!**/*.md" diff --git a/Makefile b/Makefile index c7c95d0469..0e2fcffe1f 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,18 @@ else RMDIR = rm -rf endif +# stderr redirect for $(shell ...) probes. Keyed on $(OS)$(MSYSTEM) rather than +# $(OS) alone: Git Bash sets OS=Windows_NT yet runs commands through sh, so it +# needs the POSIX path. Under native cmd there is no /dev/null, and cmd resolves +# redirections before running the command — `2>/dev/null` would abort the probe +# and silently force its fallback. Holds the whole token so callers can blank it. +# Mirrors apps/backend/Makefile. +ifeq ($(OS)$(MSYSTEM),Windows_NT) + NULL_REDIR := 2>NUL +else + NULL_REDIR := 2>/dev/null +endif + # Colors for terminal output RESET := \033[0m BOLD := \033[1m @@ -33,10 +45,10 @@ YELLOW := \033[33m MAGENTA := \033[35m VERBOSE ?= 0 -NODE ?= $(shell command -v node 2>/dev/null || echo node) +NODE ?= $(shell command -v node $(NULL_REDIR) || echo node) SERVICE_LAUNCHER := $(CURDIR)/dist/kandev/bin/kandev SERVICE_BUNDLE_DIR := $(CURDIR)/dist/kandev -SERVICE_VERSION := $(shell git rev-parse --short HEAD 2>/dev/null || echo dev) +SERVICE_VERSION := $(shell git rev-parse --short HEAD $(NULL_REDIR) || echo dev) SERVICE_ENV := KANDEV_BUNDLE_DIR="$(SERVICE_BUNDLE_DIR)" KANDEV_VERSION="$(SERVICE_VERSION)" SERVICE_PORT_FLAG := $(if $(PORT),--port $(PORT),) SERVICE_HOME_DIR_FLAG := $(if $(HOME_DIR),--home-dir "$(HOME_DIR)",) diff --git a/apps/backend/Makefile b/apps/backend/Makefile index 5c1f61d61e..e8d7091caf 100644 --- a/apps/backend/Makefile +++ b/apps/backend/Makefile @@ -95,9 +95,34 @@ else endif # Build info -VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev") -COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown") -BUILD_TIME := $(shell date -u '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || powershell -c "Get-Date -Format 'yyyy-MM-ddTHH:mm:ssZ'" 2>/dev/null || echo "unknown") +# +# Keyed on $(OS)$(MSYSTEM) like the shell-syntax block above. cmd.exe has no +# /dev/null and resolves redirections *before* running the command, so under +# native cmd/PowerShell `2>/dev/null` aborts each command outright and hands +# every value to its fallback — stamping local Windows builds dev/unknown/unknown +# while printing "The system cannot find the path specified." per assignment. +# cmd's own `date` is no substitute: given arguments it prompts for input and +# still exits 0, so it would swallow the `||`. Git Bash sets MSYSTEM and runs +# recipes through sh, so it takes the POSIX branch. +# +# Fallbacks are unquoted: sh strips the quotes, cmd's `echo` would keep them. +# +# NULL_REDIR holds the whole redirect token, not just the device path, so a +# caller simulating another platform can blank it (`make NULL_REDIR=`) instead +# of naming a device this shell would misread — see scripts/check-make-shells. +ifeq ($(OS)$(MSYSTEM),Windows_NT) + NULL_REDIR := 2>NUL + # `Get-Date -Format` renders *local* time with a literal Z; UtcNow is real UTC. + # InvariantCulture is not optional: ToString uses the current culture's + # calendar, so a th-TH host stamps year 2569 and ar-SA stamps 1448. + BUILD_TIME := $(shell powershell -NoProfile -Command "[DateTime]::UtcNow.ToString('yyyy-MM-ddTHH:mm:ssZ',[Globalization.CultureInfo]::InvariantCulture)" $(NULL_REDIR) || echo unknown) +else + NULL_REDIR := 2>/dev/null + BUILD_TIME := $(shell date -u '+%Y-%m-%dT%H:%M:%SZ' $(NULL_REDIR) || echo unknown) +endif + +VERSION ?= $(shell git describe --tags --always --dirty $(NULL_REDIR) || echo dev) +COMMIT := $(shell git rev-parse --short HEAD $(NULL_REDIR) || echo unknown) LDFLAGS += -X main.Version=$(VERSION) -X main.Commit=$(COMMIT) -X main.BuildTime=$(BUILD_TIME) diff --git a/scripts/check-make-shells b/scripts/check-make-shells index aacb723bf6..a4786fba65 100755 --- a/scripts/check-make-shells +++ b/scripts/check-make-shells @@ -29,7 +29,15 @@ status=0 # expect