@@ -2423,7 +2423,6 @@ impl WorkspaceDirectory {
24232423 } ;
24242424 self . exclude_includes_with_member_for_base_for_root ( & mut config. files ) ;
24252425 combine_files_config_with_cli_args ( & mut config. files , cli_args) ;
2426- self . append_workspace_members_to_exclude ( & mut config. files ) ;
24272426 Ok ( Some ( config) )
24282427 }
24292428
@@ -6558,4 +6557,259 @@ pub mod test {
65586557 . trim_end_matches ( '/' ) ,
65596558 )
65606559 }
6560+
6561+ // --- Deploy config tests ---
6562+
6563+ #[ test]
6564+ fn test_deploy_config_in_root_does_not_exclude_members ( ) {
6565+ // Regression test: when deploy config is in the workspace root and the
6566+ // user runs `deno deploy` from the root, workspace member directories
6567+ // should NOT be excluded from the file patterns.
6568+ let sys = InMemorySys :: default ( ) ;
6569+ let root_config = root_dir ( ) . join ( "deno.json" ) ;
6570+ sys. fs_insert_json (
6571+ root_config. clone ( ) ,
6572+ json ! ( {
6573+ "workspace" : [ "./packages/backend" , "./packages/types" ] ,
6574+ "deploy" : {
6575+ "org" : "myorg" ,
6576+ "app" : "myapp"
6577+ }
6578+ } ) ,
6579+ ) ;
6580+ sys. fs_insert_json (
6581+ root_dir ( ) . join ( "packages/backend/deno.json" ) ,
6582+ json ! ( {
6583+ "version" : "0.1.0" ,
6584+ "exclude" : [ "coverage/" ]
6585+ } ) ,
6586+ ) ;
6587+ sys. fs_insert (
6588+ root_dir ( ) . join ( "packages/backend/main.ts" ) ,
6589+ "Deno.serve(() => new Response('hello'));" ,
6590+ ) ;
6591+ sys. fs_insert_json (
6592+ root_dir ( ) . join ( "packages/types/deno.json" ) ,
6593+ json ! ( {
6594+ "name" : "@myapp/types" ,
6595+ "exports" : "./mod.ts"
6596+ } ) ,
6597+ ) ;
6598+ sys. fs_insert (
6599+ root_dir ( ) . join ( "packages/types/mod.ts" ) ,
6600+ "export type Foo = string;" ,
6601+ ) ;
6602+
6603+ // Discover from workspace root
6604+ let workspace_dir = workspace_at_start_dir ( & sys, & root_dir ( ) ) ;
6605+ let deploy_config = workspace_dir
6606+ . to_deploy_config ( FilePatterns :: new_with_base ( workspace_dir. dir_path ( ) ) )
6607+ . unwrap ( ) ;
6608+
6609+ assert ! ( deploy_config. is_some( ) , "deploy config should be resolved" ) ;
6610+ let deploy_config = deploy_config. unwrap ( ) ;
6611+ assert_eq ! ( deploy_config. org, "myorg" ) ;
6612+ assert_eq ! ( deploy_config. app, Some ( "myapp" . to_string( ) ) ) ;
6613+
6614+ // The critical check: workspace member paths must NOT be excluded
6615+ let backend_dir = root_dir ( ) . join ( "packages/backend" ) ;
6616+ let types_dir = root_dir ( ) . join ( "packages/types" ) ;
6617+ assert ! (
6618+ deploy_config
6619+ . files
6620+ . matches_path( & backend_dir, PathKind :: Directory ) ,
6621+ "packages/backend should not be excluded from deploy files"
6622+ ) ;
6623+ assert ! (
6624+ deploy_config
6625+ . files
6626+ . matches_path( & types_dir, PathKind :: Directory ) ,
6627+ "packages/types should not be excluded from deploy files"
6628+ ) ;
6629+ assert ! (
6630+ deploy_config. files. matches_path(
6631+ & root_dir( ) . join( "packages/backend/main.ts" ) ,
6632+ PathKind :: File ,
6633+ ) ,
6634+ "packages/backend/main.ts should be included in deploy files"
6635+ ) ;
6636+ }
6637+
6638+ #[ test]
6639+ fn test_deploy_config_in_both_root_and_member ( ) {
6640+ // When both root and member have deploy configs, running from the
6641+ // member directory should resolve the deploy config and not exclude
6642+ // member files.
6643+ let sys = InMemorySys :: default ( ) ;
6644+ sys. fs_insert_json (
6645+ root_dir ( ) . join ( "deno.json" ) ,
6646+ json ! ( {
6647+ "workspace" : [ "./member" ] ,
6648+ "deploy" : {
6649+ "org" : "rootorg"
6650+ }
6651+ } ) ,
6652+ ) ;
6653+ sys. fs_insert_json (
6654+ root_dir ( ) . join ( "member/deno.json" ) ,
6655+ json ! ( {
6656+ "deploy" : {
6657+ "org" : "myorg" ,
6658+ "app" : "myapp"
6659+ }
6660+ } ) ,
6661+ ) ;
6662+ sys. fs_insert (
6663+ root_dir ( ) . join ( "member/main.ts" ) ,
6664+ "Deno.serve(() => new Response('hello'));" ,
6665+ ) ;
6666+
6667+ let workspace_dir =
6668+ workspace_at_start_dir ( & sys, & root_dir ( ) . join ( "member" ) ) ;
6669+ let deploy_config = workspace_dir
6670+ . to_deploy_config ( FilePatterns :: new_with_base ( workspace_dir. dir_path ( ) ) )
6671+ . unwrap ( ) ;
6672+
6673+ assert ! ( deploy_config. is_some( ) , "deploy config should be resolved" ) ;
6674+ let deploy_config = deploy_config. unwrap ( ) ;
6675+ // Member's org takes precedence over root's
6676+ assert_eq ! ( deploy_config. org, "myorg" ) ;
6677+
6678+ // Member's own files must match
6679+ assert ! (
6680+ deploy_config
6681+ . files
6682+ . matches_path( & root_dir( ) . join( "member/main.ts" ) , PathKind :: File , ) ,
6683+ "member/main.ts should be included"
6684+ ) ;
6685+ }
6686+
6687+ #[ test]
6688+ fn test_deploy_config_root_only_no_member_deploy ( ) {
6689+ // deploy:{org,app} in root, NO deploy in any member.
6690+ // When running from root, to_deploy_config should return Some.
6691+ let sys = InMemorySys :: default ( ) ;
6692+ sys. fs_insert_json (
6693+ root_dir ( ) . join ( "deno.json" ) ,
6694+ json ! ( {
6695+ "workspace" : [
6696+ "./packages/backend" ,
6697+ "./packages/types" ,
6698+ "./packages/schema"
6699+ ] ,
6700+ "deploy" : {
6701+ "org" : "sfdevtools" ,
6702+ "app" : "prod"
6703+ }
6704+ } ) ,
6705+ ) ;
6706+ sys. fs_insert_json (
6707+ root_dir ( ) . join ( "packages/backend/deno.json" ) ,
6708+ json ! ( { "version" : "0.1.0" } ) ,
6709+ ) ;
6710+ sys. fs_insert (
6711+ root_dir ( ) . join ( "packages/backend/main.ts" ) ,
6712+ "Deno.serve(() => new Response('hello'));" ,
6713+ ) ;
6714+ sys. fs_insert_json (
6715+ root_dir ( ) . join ( "packages/types/deno.json" ) ,
6716+ json ! ( { "name" : "@myapp/types" , "exports" : "./mod.ts" } ) ,
6717+ ) ;
6718+ sys. fs_insert (
6719+ root_dir ( ) . join ( "packages/types/mod.ts" ) ,
6720+ "export type Foo = string;" ,
6721+ ) ;
6722+ sys. fs_insert_json (
6723+ root_dir ( ) . join ( "packages/schema/deno.json" ) ,
6724+ json ! ( { "name" : "@myapp/schema" , "exports" : "./mod.ts" } ) ,
6725+ ) ;
6726+ sys. fs_insert (
6727+ root_dir ( ) . join ( "packages/schema/mod.ts" ) ,
6728+ "export const VERSION = 1;" ,
6729+ ) ;
6730+
6731+ let workspace_dir = workspace_at_start_dir ( & sys, & root_dir ( ) ) ;
6732+ let deploy_config = workspace_dir
6733+ . to_deploy_config ( FilePatterns :: new_with_base ( workspace_dir. dir_path ( ) ) )
6734+ . unwrap ( ) ;
6735+
6736+ assert ! (
6737+ deploy_config. is_some( ) ,
6738+ "deploy config should be resolved when only root has deploy field"
6739+ ) ;
6740+ let deploy_config = deploy_config. unwrap ( ) ;
6741+ assert_eq ! ( deploy_config. org, "sfdevtools" ) ;
6742+
6743+ // All workspace member directories must be accessible
6744+ for member in & [ "packages/backend" , "packages/types" , "packages/schema" ] {
6745+ let member_dir = root_dir ( ) . join ( member) ;
6746+ assert ! (
6747+ deploy_config
6748+ . files
6749+ . matches_path( & member_dir, PathKind :: Directory ) ,
6750+ "{member} should not be excluded from deploy files"
6751+ ) ;
6752+ }
6753+ // Entrypoint must be accessible
6754+ assert ! (
6755+ deploy_config. files. matches_path(
6756+ & root_dir( ) . join( "packages/backend/main.ts" ) ,
6757+ PathKind :: File ,
6758+ ) ,
6759+ "packages/backend/main.ts must be included"
6760+ ) ;
6761+ }
6762+
6763+ #[ test]
6764+ fn test_deploy_config_with_exclude ( ) {
6765+ // Deploy config with explicit exclude should respect it but not
6766+ // additionally exclude workspace members.
6767+ let sys = InMemorySys :: default ( ) ;
6768+ sys. fs_insert_json (
6769+ root_dir ( ) . join ( "deno.json" ) ,
6770+ json ! ( {
6771+ "workspace" : [ "./packages/backend" , "./packages/types" ] ,
6772+ "exclude" : [ "docs/" ] ,
6773+ "deploy" : {
6774+ "org" : "myorg" ,
6775+ "app" : "myapp"
6776+ }
6777+ } ) ,
6778+ ) ;
6779+ sys
6780+ . fs_insert_json ( root_dir ( ) . join ( "packages/backend/deno.json" ) , json ! ( { } ) ) ;
6781+ sys. fs_insert (
6782+ root_dir ( ) . join ( "packages/backend/main.ts" ) ,
6783+ "Deno.serve(() => new Response('hello'));" ,
6784+ ) ;
6785+ sys. fs_insert_json ( root_dir ( ) . join ( "packages/types/deno.json" ) , json ! ( { } ) ) ;
6786+ sys. fs_insert (
6787+ root_dir ( ) . join ( "packages/types/mod.ts" ) ,
6788+ "export type Foo = string;" ,
6789+ ) ;
6790+
6791+ let workspace_dir = workspace_at_start_dir ( & sys, & root_dir ( ) ) ;
6792+ let deploy_config = workspace_dir
6793+ . to_deploy_config ( FilePatterns :: new_with_base ( workspace_dir. dir_path ( ) ) )
6794+ . unwrap ( ) ;
6795+
6796+ assert ! ( deploy_config. is_some( ) ) ;
6797+ let deploy_config = deploy_config. unwrap ( ) ;
6798+
6799+ // Workspace members should NOT be excluded
6800+ assert ! (
6801+ deploy_config. files. matches_path(
6802+ & root_dir( ) . join( "packages/backend/main.ts" ) ,
6803+ PathKind :: File ,
6804+ ) ,
6805+ "workspace member files should not be excluded"
6806+ ) ;
6807+ // docs/ should be excluded (from top-level exclude)
6808+ assert ! (
6809+ !deploy_config
6810+ . files
6811+ . matches_path( & root_dir( ) . join( "docs/readme.md" ) , PathKind :: File ) ,
6812+ "docs/ should be excluded"
6813+ ) ;
6814+ }
65616815}
0 commit comments