Skip to content

Commit 55a7310

Browse files
committed
Warn on Vercel system env vars
1 parent dee9834 commit 55a7310

File tree

5 files changed

+117
-9
lines changed

5 files changed

+117
-9
lines changed

crates/next-core/src/next_client/context.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ use crate::{
6868
get_typescript_transform_options,
6969
},
7070
util::{
71-
OptionEnvMap, defines, foreign_code_context_condition, internal_assets_conditions,
71+
OptionEnvMap, defines, foreign_code_context_condition,
72+
free_var_references_with_vercel_system_env_warnings, internal_assets_conditions,
7273
module_styles_rule_condition,
7374
},
7475
};
@@ -81,7 +82,7 @@ async fn next_client_defines(define_env: Vc<OptionEnvMap>) -> Result<Vc<CompileT
8182
#[turbo_tasks::function]
8283
async fn next_client_free_vars(define_env: Vc<OptionEnvMap>) -> Result<Vc<FreeVarReferences>> {
8384
Ok(free_var_references!(
84-
..defines(&*define_env.await?).into_iter(),
85+
..free_var_references_with_vercel_system_env_warnings(defines(&*define_env.await?)),
8586
Buffer = FreeVarReference::EcmaScriptModule {
8687
request: rcstr!("node:buffer"),
8788
lookup_path: None,

crates/next-core/src/next_edge/context.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ use crate::{
3030
ModuleFeatureReportResolvePlugin, NextSharedRuntimeResolvePlugin,
3131
get_invalid_client_only_resolve_plugin, get_invalid_styled_jsx_resolve_plugin,
3232
},
33-
util::{NextRuntime, OptionEnvMap, defines, foreign_code_context_condition},
33+
util::{
34+
NextRuntime, OptionEnvMap, defines, foreign_code_context_condition,
35+
free_var_references_with_vercel_system_env_warnings,
36+
},
3437
};
3538

3639
#[turbo_tasks::function]
@@ -46,7 +49,7 @@ async fn next_edge_free_vars(
4649
define_env: Vc<OptionEnvMap>,
4750
) -> Result<Vc<FreeVarReferences>> {
4851
Ok(free_var_references!(
49-
..defines(&*define_env.await?).into_iter(),
52+
..free_var_references_with_vercel_system_env_warnings(defines(&*define_env.await?)),
5053
Buffer = FreeVarReference::EcmaScriptModule {
5154
request: rcstr!("buffer"),
5255
lookup_path: Some(project_path),

crates/next-core/src/next_server/context.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use turbopack_core::{
2121
compile_time_defines,
2222
compile_time_info::{CompileTimeDefines, CompileTimeInfo, FreeVarReferences},
2323
environment::{Environment, ExecutionEnvironment, NodeJsEnvironment, NodeJsVersion},
24-
free_var_references,
2524
module_graph::binding_usage_info::OptionBindingUsageInfo,
2625
target::CompileTarget,
2726
};
@@ -73,8 +72,8 @@ use crate::{
7372
},
7473
util::{
7574
NextRuntime, OptionEnvMap, defines, foreign_code_context_condition,
76-
get_transpiled_packages, internal_assets_conditions, load_next_js_jsonc_file,
77-
module_styles_rule_condition,
75+
free_var_references_with_vercel_system_env_warnings, get_transpiled_packages,
76+
internal_assets_conditions, load_next_js_jsonc_file, module_styles_rule_condition,
7877
},
7978
};
8079

@@ -357,7 +356,7 @@ async fn next_server_defines(define_env: Vc<OptionEnvMap>) -> Result<Vc<CompileT
357356

358357
#[turbo_tasks::function]
359358
async fn next_server_free_vars(define_env: Vc<OptionEnvMap>) -> Result<Vc<FreeVarReferences>> {
360-
Ok(free_var_references!(..defines(&*define_env.await?).into_iter()).cell())
359+
Ok(free_var_references_with_vercel_system_env_warnings(defines(&*define_env.await?)).cell())
361360
}
362361

363362
#[turbo_tasks::function]

crates/next-core/src/util.rs

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ use turbo_tasks_fs::{File, FileContent, FileJsonContent, FileSystem, FileSystemP
1010
use turbopack::module_options::RuleCondition;
1111
use turbopack_core::{
1212
asset::AssetContent,
13-
compile_time_info::{CompileTimeDefineValue, CompileTimeDefines, DefinableNameSegment},
13+
compile_time_info::{
14+
CompileTimeDefineValue, CompileTimeDefines, DefinableNameSegment, FreeVarReference,
15+
FreeVarReferences,
16+
},
1417
condition::ContextCondition,
1518
source::Source,
1619
virtual_source::VirtualSource,
@@ -58,6 +61,99 @@ pub fn defines(define_env: &FxIndexMap<RcStr, Option<RcStr>>) -> CompileTimeDefi
5861
CompileTimeDefines(defines)
5962
}
6063

64+
/// Emits warnings or errors when inlining frequently changing system env vars
65+
pub fn free_var_references_with_vercel_system_env_warnings(
66+
defines: CompileTimeDefines,
67+
) -> FreeVarReferences {
68+
// constant:
69+
// VERCEL
70+
// CI
71+
// VERCEL_PROJECT_PRODUCTION_URL
72+
// VERCEL_REGION
73+
// VERCEL_SKEW_PROTECTION_ENABLED
74+
// VERCEL_AUTOMATION_BYPASS_SECRET
75+
// VERCEL_PROJECT_ID
76+
// VERCEL_GIT_PROVIDER
77+
// VERCEL_GIT_REPO_SLUG
78+
// VERCEL_GIT_REPO_OWNER
79+
// VERCEL_GIT_REPO_ID
80+
81+
// suboptimal (changes production main branch VS preview branches):
82+
// VERCEL_ENV
83+
// VERCEL_TARGET_ENV
84+
85+
// bad (changes per branch):
86+
// VERCEL_BRANCH_URL
87+
// VERCEL_GIT_COMMIT_REF
88+
// VERCEL_GIT_PULL_REQUEST_ID
89+
90+
// catastrophic (changes per commit):
91+
// VERCEL_URL
92+
// VERCEL_DEPLOYMENT_ID
93+
// VERCEL_OIDC_TOKEN
94+
// VERCEL_GIT_COMMIT_SHA
95+
// VERCEL_GIT_COMMIT_MESSAGE
96+
// VERCEL_GIT_COMMIT_AUTHOR_LOGIN
97+
// VERCEL_GIT_COMMIT_AUTHOR_NAME
98+
// VERCEL_GIT_PREVIOUS_SHA
99+
100+
let should_error = std::env::var("NEXT_TURBOPACK_SYSTEM_ENV_ERROR")
101+
.ok()
102+
.is_some_and(|v| !v.is_empty());
103+
104+
FreeVarReferences(
105+
defines
106+
.0
107+
.into_iter()
108+
.map(|(k, value)| {
109+
const LIST: [&str; 11] = [
110+
"VERCEL_BRANCH_URL",
111+
"VERCEL_DEPLOYMENT_ID",
112+
"VERCEL_GIT_COMMIT_AUTHOR_LOGIN",
113+
"VERCEL_GIT_COMMIT_AUTHOR_NAME",
114+
"VERCEL_GIT_COMMIT_MESSAGE",
115+
"VERCEL_GIT_COMMIT_REF",
116+
"VERCEL_GIT_COMMIT_SHA",
117+
"VERCEL_GIT_PREVIOUS_SHA",
118+
"VERCEL_GIT_PULL_REQUEST_ID",
119+
"VERCEL_OIDC_TOKEN",
120+
"VERCEL_URL",
121+
];
122+
123+
let value = if let &[
124+
DefinableNameSegment::Name(a),
125+
DefinableNameSegment::Name(b),
126+
DefinableNameSegment::Name(c),
127+
] = &&*k
128+
&& a == "process"
129+
&& b == "env"
130+
&& c.strip_prefix("NEXT_PUBLIC_")
131+
.is_some_and(|n| LIST.binary_search(&n).is_ok())
132+
{
133+
let message = format!(
134+
"The system environment variable {} is being inlined. This variable \
135+
changes on every deployment, causing slower deploy times and worse \
136+
browser client-side caching.",
137+
c
138+
)
139+
.into();
140+
if should_error {
141+
FreeVarReference::Error(message)
142+
} else {
143+
FreeVarReference::Warning {
144+
message,
145+
inner: Box::new(FreeVarReference::Value(value)),
146+
}
147+
}
148+
} else {
149+
FreeVarReference::Value(value)
150+
};
151+
(k, value)
152+
})
153+
.collect(),
154+
)
155+
}
156+
61157
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TaskInput, TraceRawVcs, Encode, Decode)]
62158
pub enum PathType {
63159
PagesPage,

turbopack/crates/turbopack-core/src/compile_time_info.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,15 @@ impl FreeVarReferences {
392392
}
393393
}
394394

395+
impl IntoIterator for FreeVarReferences {
396+
type Item = (Vec<DefinableNameSegment>, FreeVarReference);
397+
type IntoIter = indexmap::map::IntoIter<Vec<DefinableNameSegment>, FreeVarReference>;
398+
399+
fn into_iter(self) -> Self::IntoIter {
400+
self.0.into_iter()
401+
}
402+
}
403+
395404
#[turbo_tasks::value(shared)]
396405
#[derive(Debug, Clone)]
397406
pub struct CompileTimeInfo {

0 commit comments

Comments
 (0)