Skip to content

Commit 97ef9ed

Browse files
authored
filter transient env variables from manifest and plugin cache keys (#7056)
motivation: When changing environment variables manifest loader and plugin cache reset too aggressivly changes: * introduce a static list of env variables that are transiant in nature * filter transient env variables from cache keys used in manfiest loader and plugin caches * adjust and add tests rdar://107029374
1 parent 27d1f0d commit 97ef9ed

File tree

4 files changed

+109
-13
lines changed

4 files changed

+109
-13
lines changed

Sources/Basics/EnvironmentVariables.swift

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
import Foundation
13+
import class Foundation.ProcessInfo
1414

1515
public typealias EnvironmentVariables = [String: String]
1616

@@ -58,3 +58,30 @@ extension EnvironmentVariables {
5858
return self[pathArg]
5959
}
6060
}
61+
62+
// filter env variable that should not be included in a cache as they change
63+
// often and should not be considered in business logic
64+
// rdar://107029374
65+
extension EnvironmentVariables {
66+
// internal for testing
67+
internal static let nonCachableKeys: Set<String> = [
68+
"TERM",
69+
"TERM_PROGRAM",
70+
"TERM_PROGRAM_VERSION",
71+
"TERM_SESSION_ID",
72+
"ITERM_PROFILE",
73+
"ITERM_SESSION_ID",
74+
"SECURITYSESSIONID",
75+
"LaunchInstanceID",
76+
"LC_TERMINAL",
77+
"LC_TERMINAL_VERSION",
78+
"CLICOLOR",
79+
"LS_COLORS",
80+
"VSCODE_IPC_HOOK_CLI",
81+
"HYPERFINE_RANDOMIZED_ENVIRONMENT_OFFSET",
82+
]
83+
84+
public var cachable: EnvironmentVariables {
85+
return self.filter { !Self.nonCachableKeys.contains($0.key) }
86+
}
87+
}

Sources/PackageLoading/ManifestLoader.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ public final class ManifestLoader: ManifestLoaderProtocol {
497497
packageLocation: packageLocation,
498498
manifestPath: path,
499499
toolsVersion: toolsVersion,
500-
env: ProcessEnv.vars,
500+
env: ProcessEnv.cachableVars,
501501
swiftpmVersion: SwiftVersion.current.displayString,
502502
fileSystem: fileSystem
503503
)
@@ -1210,3 +1210,9 @@ extension ManifestLoader {
12101210
}
12111211
}
12121212
}
1213+
1214+
extension ProcessEnv {
1215+
fileprivate static var cachableVars: EnvironmentVariables {
1216+
Self.vars.cachable
1217+
}
1218+
}

Sources/Workspace/DefaultPluginScriptRunner.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable {
270270
/// Persisted information about the last time the compiler was invoked.
271271
struct PersistedCompilationState: Codable {
272272
var commandLine: [String]
273-
var environment: [String:String]
273+
var environment: EnvironmentVariables
274274
var inputHash: String?
275275
var output: String
276276
var result: Result
@@ -364,7 +364,7 @@ public struct DefaultPluginScriptRunner: PluginScriptRunner, Cancellable {
364364
// Save the persisted compilation state for possible reuse next time.
365365
let compilationState = PersistedCompilationState(
366366
commandLine: commandLine,
367-
environment: toolchain.swiftCompilerEnvironment,
367+
environment: toolchain.swiftCompilerEnvironment.cachable,
368368
inputHash: compilerInputHash,
369369
output: compilerOutput,
370370
result: .init(process.exitStatus))

Tests/PackageLoadingTests/ManifestLoaderCacheTests.swift

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
import Basics
13+
@testable import Basics
1414
@testable import PackageLoading
1515
import PackageModel
1616
import SPMTestSupport
1717
import XCTest
1818

1919
import class TSCBasic.InMemoryFileSystem
20+
import enum TSCBasic.ProcessEnv
2021
import func TSCTestSupport.withCustomEnv
2122

2223
class ManifestLoaderCacheTests: XCTestCase {
@@ -297,6 +298,21 @@ class ManifestLoaderCacheTests: XCTestCase {
297298
delegate: delegate
298299
)
299300

301+
try check(loader: manifestLoader, expectCached: false)
302+
try check(loader: manifestLoader, expectCached: true)
303+
304+
try withCustomEnv(["SWIFTPM_MANIFEST_CACHE_TEST": "1"]) {
305+
try check(loader: manifestLoader, expectCached: false)
306+
try check(loader: manifestLoader, expectCached: true)
307+
}
308+
309+
try withCustomEnv(["SWIFTPM_MANIFEST_CACHE_TEST": "2"]) {
310+
try check(loader: manifestLoader, expectCached: false)
311+
try check(loader: manifestLoader, expectCached: true)
312+
}
313+
314+
try check(loader: manifestLoader, expectCached: true)
315+
300316
func check(loader: ManifestLoader, expectCached: Bool) throws {
301317
delegate.clear()
302318
delegate.prepare(expectParsing: !expectCached)
@@ -315,18 +331,65 @@ class ManifestLoaderCacheTests: XCTestCase {
315331
XCTAssertEqual(manifest.displayName, "Trivial")
316332
XCTAssertEqual(manifest.targets[0].name, "foo")
317333
}
334+
}
335+
}
318336

319-
try check(loader: manifestLoader, expectCached: false)
320-
try check(loader: manifestLoader, expectCached: true)
337+
func testCacheDoNotInvalidationExpectedEnv() throws {
338+
try testWithTemporaryDirectory { path in
339+
let fileSystem = InMemoryFileSystem()
340+
let observability = ObservabilitySystem.makeForTesting()
321341

322-
try withCustomEnv(["SWIFTPM_MANIFEST_CACHE_TEST": "1"]) {
323-
try check(loader: manifestLoader, expectCached: false)
324-
try check(loader: manifestLoader, expectCached: true)
342+
let manifestPath = path.appending(components: "pkg", "Package.swift")
343+
try fileSystem.createDirectory(manifestPath.parentDirectory, recursive: true)
344+
try fileSystem.writeFileContents(
345+
manifestPath,
346+
string: """
347+
import PackageDescription
348+
let package = Package(
349+
name: "Trivial",
350+
targets: [
351+
.target(
352+
name: "foo",
353+
dependencies: []),
354+
]
355+
)
356+
"""
357+
)
358+
359+
let delegate = ManifestTestDelegate()
360+
361+
let manifestLoader = ManifestLoader(
362+
toolchain: try UserToolchain.default,
363+
cacheDir: path,
364+
delegate: delegate
365+
)
366+
367+
func check(loader: ManifestLoader, expectCached: Bool) throws {
368+
delegate.clear()
369+
delegate.prepare(expectParsing: !expectCached)
370+
371+
let manifest = try XCTUnwrap(loader.load(
372+
manifestPath: manifestPath,
373+
packageKind: .root(manifestPath.parentDirectory),
374+
toolsVersion: .current,
375+
fileSystem: fileSystem,
376+
observabilityScope: observability.topScope
377+
))
378+
379+
XCTAssertNoDiagnostics(observability.diagnostics)
380+
XCTAssertEqual(try delegate.loaded(timeout: .now() + 1), [manifestPath])
381+
XCTAssertEqual(try delegate.parsed(timeout: .now() + 1).count, expectCached ? 0 : 1)
382+
XCTAssertEqual(manifest.displayName, "Trivial")
383+
XCTAssertEqual(manifest.targets[0].name, "foo")
325384
}
326385

327-
try withCustomEnv(["SWIFTPM_MANIFEST_CACHE_TEST": "2"]) {
328-
try check(loader: manifestLoader, expectCached: false)
329-
try check(loader: manifestLoader, expectCached: true)
386+
try check(loader: manifestLoader, expectCached: false)
387+
try check(loader: manifestLoader, expectCached: true)
388+
389+
for key in EnvironmentVariables.nonCachableKeys {
390+
try withCustomEnv([key: UUID().uuidString]) {
391+
try check(loader: manifestLoader, expectCached: true)
392+
}
330393
}
331394

332395
try check(loader: manifestLoader, expectCached: true)

0 commit comments

Comments
 (0)