From 4db66a8e48a55fcc7e319d313a095dfffbbbbab4 Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Mon, 15 Jan 2024 17:40:50 +0100
Subject: [PATCH 1/2] Added integration test

---
 .../compile_3/compile_env_var_test.go         | 60 +++++++++++++++++++
 .../compile_3/testdata/printenv/.gitignore    |  1 +
 .../compile_3/testdata/printenv/main.go       | 12 ++++
 3 files changed, 73 insertions(+)
 create mode 100644 internal/integrationtest/compile_3/compile_env_var_test.go
 create mode 100644 internal/integrationtest/compile_3/testdata/printenv/.gitignore
 create mode 100644 internal/integrationtest/compile_3/testdata/printenv/main.go

diff --git a/internal/integrationtest/compile_3/compile_env_var_test.go b/internal/integrationtest/compile_3/compile_env_var_test.go
new file mode 100644
index 00000000000..ee786c2d881
--- /dev/null
+++ b/internal/integrationtest/compile_3/compile_env_var_test.go
@@ -0,0 +1,60 @@
+// This file is part of arduino-cli.
+//
+// Copyright 2024 ARDUINO SA (http://www.arduino.cc/)
+//
+// This software is released under the GNU General Public License version 3,
+// which covers the main part of arduino-cli.
+// The terms of this license can be found at:
+// https://www.gnu.org/licenses/gpl-3.0.en.html
+//
+// You can be released from the requirements of the above licenses by purchasing
+// a commercial license. Buying such a license is mandatory if you want to
+// modify or otherwise use the software for commercial activities involving the
+// Arduino software without disclosing the source code of your own applications.
+// To purchase a commercial license, send an email to license@arduino.cc.
+
+package compile_test
+
+import (
+	"testing"
+
+	"github.com/arduino/arduino-cli/internal/integrationtest"
+	"github.com/arduino/go-paths-helper"
+	"github.com/stretchr/testify/require"
+)
+
+func TestCompileEnvVarOnNewProcess(t *testing.T) {
+	// See: https://github.com/arduino/arduino-cli/issues/2499
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Run update-index with our test index
+	_, _, err := cli.Run("core", "install", "arduino:avr@1.8.6")
+	require.NoError(t, err)
+
+	// Prepare sketchbook and sketch
+	sketch, err := paths.New("testdata", "bare_minimum").Abs()
+	require.NoError(t, err)
+
+	// Build "printenv" helper insider testdata/printenv
+	printenvDir, err := paths.New("testdata", "printenv").Abs()
+	require.NoError(t, err)
+	builder, err := paths.NewProcess(nil, "go", "build")
+	require.NoError(t, err)
+	builder.SetDir(printenvDir.String())
+	require.NoError(t, builder.Run())
+	printenv := printenvDir.Join("printenv")
+
+	// Patch avr core to run printenv instead of size
+	plTxt, err := cli.DataDir().Join("packages", "arduino", "hardware", "avr", "1.8.6", "platform.txt").Append()
+	require.NoError(t, err)
+	_, err = plTxt.WriteString("recipe.size.pattern=" + printenv.String() + "\n")
+	require.NoError(t, err)
+	require.NoError(t, plTxt.Close())
+
+	// Run compile and get ENV
+	_, stderr, err := cli.Run("compile", "-v", "-b", "arduino:avr:uno", sketch.String())
+	require.NoError(t, err)
+	require.Contains(t, string(stderr), "ENV> ARDUINO_USER_AGENT=")
+}
diff --git a/internal/integrationtest/compile_3/testdata/printenv/.gitignore b/internal/integrationtest/compile_3/testdata/printenv/.gitignore
new file mode 100644
index 00000000000..8094186ae54
--- /dev/null
+++ b/internal/integrationtest/compile_3/testdata/printenv/.gitignore
@@ -0,0 +1 @@
+printenv
diff --git a/internal/integrationtest/compile_3/testdata/printenv/main.go b/internal/integrationtest/compile_3/testdata/printenv/main.go
new file mode 100644
index 00000000000..0701e4f1594
--- /dev/null
+++ b/internal/integrationtest/compile_3/testdata/printenv/main.go
@@ -0,0 +1,12 @@
+package main
+
+import (
+	"fmt"
+	"os"
+)
+
+func main() {
+	for _, env := range os.Environ() {
+		fmt.Fprintln(os.Stderr, "ENV>", env)
+	}
+}

From 94b5c5054b2cad555f89ab6327b2e3cf289b25cd Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Mon, 15 Jan 2024 17:41:09 +0100
Subject: [PATCH 2/2] Fixed missing ARDUINO_USER_AGENT env var

---
 commands/compile/compile.go         | 1 +
 internal/arduino/builder/builder.go | 6 +++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/commands/compile/compile.go b/commands/compile/compile.go
index 75e86b8f52d..0beebfa56ca 100644
--- a/commands/compile/compile.go
+++ b/commands/compile/compile.go
@@ -199,6 +199,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
 		paths.NewPathList(req.GetLibrary()...),
 		outStream, errStream, req.GetVerbose(), req.GetWarnings(),
 		progressCB,
+		pme.GetEnvVarsForSpawnedProcess(),
 	)
 	if err != nil {
 		if strings.Contains(err.Error(), "invalid build properties") {
diff --git a/internal/arduino/builder/builder.go b/internal/arduino/builder/builder.go
index 7cbe0544a26..40ca74e44d2 100644
--- a/internal/arduino/builder/builder.go
+++ b/internal/arduino/builder/builder.go
@@ -92,6 +92,8 @@ type Builder struct {
 
 	libsDetector *detector.SketchLibrariesDetector
 
+	toolEnv []string
+
 	// This is a function used to parse the output of the compiler
 	// It is used to extract errors and warnings
 	compilerOutputParser diagnostics.CompilerOutputParserCB
@@ -133,6 +135,7 @@ func NewBuilder(
 	libraryDirs paths.PathList,
 	stdout, stderr io.Writer, verbose bool, warningsLevel string,
 	progresCB rpc.TaskProgressCB,
+	toolEnv []string,
 ) (*Builder, error) {
 	buildProperties := properties.NewMap()
 	if boardBuildProperties != nil {
@@ -216,6 +219,7 @@ func NewBuilder(
 		buildArtifacts:                &buildArtifacts{},
 		targetPlatform:                targetPlatform,
 		actualPlatform:                actualPlatform,
+		toolEnv:                       toolEnv,
 		libsDetector: detector.NewSketchLibrariesDetector(
 			libsManager, libsResolver,
 			useCachedLibrariesResolution,
@@ -521,7 +525,7 @@ func (b *Builder) prepareCommandForRecipe(buildProperties *properties.Map, recip
 		}
 	}
 
-	command, err := paths.NewProcess(nil, parts...)
+	command, err := paths.NewProcess(b.toolEnv, parts...)
 	if err != nil {
 		return nil, err
 	}