Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,27 @@ Always treat environment variable values as sensitive unless they are known test
- Never commit local secret files; if documenting env setup, use placeholder-only examples.
- When sharing command output, summarize and redact sensitive-looking values.

### GitHub SSH Authentication

GitHub SSH authentication may depend on a user-configured SSH agent or key
provider, such as a password manager or hardware-backed key.

If a Git fetch, push, or partial-clone hydration fails or hangs with an SSH
signing error such as:

- `sign_and_send_pubkey: signing failed`
- `communication with agent failed`
- `Permission denied (publickey)`

stop immediately and ask the user to ensure their SSH agent or key provider is
available and unlocked. Do not switch remotes to HTTPS, mutate remote URLs,
retry repeatedly, or attempt another authentication workaround unless the user
explicitly requests it.

Before a force-push or stack rebase that may hydrate partial-clone objects,
prefer a lightweight SSH preflight. If it fails due to the SSH agent or key
provider, ask the user to make it available or unlock it before continuing.

## Specialized Skills

Use skills for conditional, deep workflows. Keep baseline iteration/build/test policy in this file.
Expand Down
2 changes: 1 addition & 1 deletion crates/next-api/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2002,7 +2002,7 @@ impl AppEndpoint {
this.app_project.project(),
Some(app_function_name(&app_entry.original_name).into()),
*module_graphs.full,
vec![*rsc_entry],
*rsc_entry,
))
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/next-api/src/instrumentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ impl InstrumentationEndpoint {
*this.project,
None,
this.project.module_graph(userland_module),
vec![userland_module],
userland_module,
))
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/next-api/src/middleware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ impl MiddlewareEndpoint {
*this.project,
None,
this.project.module_graph(userland_module),
vec![userland_module],
userland_module,
))
}
}
Expand Down
71 changes: 19 additions & 52 deletions crates/next-api/src/next_server_nft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@ use turbo_tasks_hash::HashAlgorithm;
use turbopack::externals_tracing_module_context;
use turbopack_core::{
asset::{Asset, AssetContent},
context::AssetContext,
file_source::FileSource,
module::{Module, Modules},
module_graph::{ModuleGraph, SingleModuleGraph, chunk_group_info::ChunkGroupEntry},
output::{OutputAsset, OutputAssets, OutputAssetsReference},
reference_type::{CommonJsReferenceSubType, ReferenceType},
reference_type::CommonJsReferenceSubType,
resolve::{ResolveErrorMode, origin::PlainResolveOrigin, parse::Request},
};
use turbopack_resolve::ecmascript::cjs_resolve;
Expand Down Expand Up @@ -123,9 +121,9 @@ impl Asset for ServerNftJsonAsset {

let mut server_output_assets = traced_modules_for_entries(
module_graph,
Modules::empty(),
self.entries(),
Some(self.ignores()),
true,
None,
)
.await?
Expand Down Expand Up @@ -219,35 +217,9 @@ impl ServerNftJsonAsset {
get_next_package(project_path.clone()).await?.join("_")?,
));

let cache_handler = self
.project
.next_config()
.cache_handler(project_path.clone())
.await?;
let cache_handlers = self
.project
.next_config()
.cache_handlers(project_path.clone())
.await?;

// These are used by packages/next/src/server/require-hook.ts
let shared_entries = ["styled-jsx", "styled-jsx/style", "styled-jsx/style.js"];

let cache_handler_entries = cache_handler
.iter()
.chain(cache_handlers.iter())
.map(|f| {
asset_context
.process(
Vc::upcast(FileSource::new(f.clone())),
ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined),
)
.module()
})
.map(|m| m.to_resolved())
.try_join()
.await?;

let entries = match self.ty {
ServerNftType::Full => Either::Left(
if is_standalone {
Expand All @@ -270,29 +242,24 @@ impl ServerNftJsonAsset {
};

Ok(Vc::cell(
cache_handler_entries
shared_entries
.into_iter()
.chain(
shared_entries
.into_iter()
.chain(entries)
.map(async |path| {
Ok(cjs_resolve(
next_resolve_origin,
Request::parse_string(path.into()),
CommonJsReferenceSubType::Undefined,
None,
ResolveErrorMode::Error,
)
.await?
.primary_modules()
.await?
.into_iter())
})
.try_flat_join()
.await?,
)
.collect(),
.chain(entries)
.map(async |path| {
Ok(cjs_resolve(
next_resolve_origin,
Request::parse_string(path.into()),
CommonJsReferenceSubType::Undefined,
None,
ResolveErrorMode::Error,
)
.await?
.primary_modules()
.await?
.into_iter())
})
.try_flat_join()
.await?,
))
}

Expand Down
30 changes: 20 additions & 10 deletions crates/next-api/src/nft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub async fn trace_endpoint(
project: ResolvedVc<Project>,
page_name: Option<RcStr>,
module_graph: ResolvedVc<ModuleGraph>,
entry_modules: Vec<ResolvedVc<Box<dyn Module>>>,
entry_module: ResolvedVc<Box<dyn Module>>,
) -> Result<Vc<EndpointTraceResult>> {
let span = tracing::info_span!("trace endpoint", path = debug(&page_name));
async {
Expand All @@ -71,19 +71,21 @@ pub async fn trace_endpoint(
.output_file_tracing_includes(project_path.clone())
.await?;

let traced_entries = project.additional_traced_modules();

// Collect referenced assets and externals from module graph
let all_modules = traced_modules_for_entries(
*module_graph,
Vc::cell(entry_modules.clone()),
Vc::cell(vec![entry_module]),
traced_entries,
tracing_exclude_glob(page_name.clone(), project_path.clone(), next_config)
.await?
.map(|v| *v),
false,
Some(next_config.config_file_path(project_path.clone())),
)
.await?;

let module_data = traced_module_data_for_graph(*module_graph, false)
let module_data = traced_module_data_for_graph(*module_graph, traced_entries)
.to_resolved()
.await?;
let module_paths = module_data.await?.idents;
Expand Down Expand Up @@ -265,13 +267,13 @@ pub async fn tracing_exclude_glob(
pub async fn traced_modules_for_entries(
module_graph: Vc<ModuleGraph>,
entry_modules: Vc<Modules>,
traced_entries: Vc<Modules>,
exclude_glob: Option<Vc<Glob>>,
entries_are_traced: bool,
forbidden_path: Option<Vc<FileSystemPath>>,
) -> Result<Vc<Modules>> {
let exclude_glob_and_module_idents = if let Some(exclude_glob) = exclude_glob {
let exclude_glob = exclude_glob.await?;
let data = traced_module_data_for_graph(module_graph, entries_are_traced).await?;
let data = traced_module_data_for_graph(module_graph, traced_entries).await?;
Some((exclude_glob, data.idents.await?))
} else {
None
Expand All @@ -288,14 +290,20 @@ pub async fn traced_modules_for_entries(
};

let mut forbidden_issues = vec![];
let traced_entries = traced_entries.await?;
let traced_entries_set = traced_entries.iter().copied().collect::<FxHashSet<_>>();

let mut traced_modules = FxIndexSet::default();
module_graph.await?.traverse_edges_dfs(
entry_modules.await?.iter().copied(),
entry_modules
.await?
.iter()
.chain(traced_entries.iter())
.copied(),
&mut (),
|parent, target, _| {
let Some((parent, ref_data)) = parent else {
if entries_are_traced {
if traced_entries_set.contains(&target) {
traced_modules.insert(target);
}
return Ok(GraphTraversalAction::Continue);
Expand Down Expand Up @@ -368,20 +376,22 @@ pub struct TracedModuleData {
#[turbo_tasks::function]
pub async fn traced_module_data_for_graph(
module_graph: Vc<ModuleGraph>,
entries_are_traced: bool,
traced_entries: Vc<Modules>,
) -> Result<Vc<TracedModuleData>> {
// This function is very similar to traced_modules_for_entries, but doesn't apply the glob and
// is executed only once for the whole graph.
let module_graph = module_graph.await?;
let entries = module_graph.graphs.iter().flat_map(|g| g.entry_modules());

let traced_entries = traced_entries.await?.into_iter().collect::<FxHashSet<_>>();

let mut traced_modules = FxHashSet::default();
module_graph.traverse_edges_dfs(
entries,
&mut (),
|parent, target, _| {
let Some((parent, ref_data)) = parent else {
if entries_are_traced {
if traced_entries.contains(&target) {
traced_modules.insert(target);
}
return Ok(GraphTraversalAction::Continue);
Expand Down
2 changes: 1 addition & 1 deletion crates/next-api/src/pages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1569,7 +1569,7 @@ impl PageEndpoint {
this.pages_project.project(),
Some(pages_function_name(&this.original_name).into()),
ssr_module_graph,
vec![*ssr_module],
*ssr_module,
))
}
}
Expand Down
Loading
Loading