@@ -35,7 +35,6 @@ def __call__(self, session: Session) -> Callable[[bool], None]:
3535SRC_DIR = ROOT_DIR / "src"
3636CLIENT_DIR = SRC_DIR / "client"
3737REACTPY_DIR = SRC_DIR / "reactpy"
38- LANGUAGE_TYPES : list [LanguageName ] = ["py" , "js" ]
3938TAG_PATTERN = re .compile (
4039 # start
4140 r"^"
@@ -46,7 +45,6 @@ def __call__(self, session: Session) -> Callable[[bool], None]:
4645 # end
4746 r"$"
4847)
49- print (TAG_PATTERN .pattern )
5048REMAINING_ARGS = Option (nargs = REMAINDER , type = str )
5149
5250
@@ -60,6 +58,7 @@ def __call__(self, session: Session) -> Callable[[bool], None]:
6058def setup_checks (session : Session ) -> None :
6159 session .install ("--upgrade" , "pip" )
6260 session .run ("pip" , "--version" )
61+ session .run ("npm" , "--version" , external = True )
6362
6463
6564@group .setup ("check-javascript" )
@@ -88,6 +87,12 @@ def format(session: Session) -> None:
8887 session .run ("npm" , "run" , "format" , external = True )
8988
9089
90+ @group .session
91+ def tsc (session : Session ) -> None :
92+ session .chdir (CLIENT_DIR )
93+ session .run ("npx" , "tsc" , "-b" , "-w" , "packages/app" , external = True )
94+
95+
9196@group .session
9297def example (session : Session ) -> None :
9398 """Run an example"""
@@ -232,21 +237,24 @@ def check_docs(session: Session) -> None:
232237
233238
234239@group .session
235- def check_javascript_suite (session : Session ) -> None :
236- """Run the Javascript-based test suite and ensure it bundles succesfully"""
237- session .run ("npm" , "run" , "test" , external = True )
240+ def check_javascript_tests (session : Session ) -> None :
241+ session .run ("npm" , "run" , "check:tests" , external = True )
238242
239243
240244@group .session
241- def check_javascript_build (session : Session ) -> None :
242- """Run the Javascript-based test suite and ensure it bundles succesfully"""
243- session .run ("npm" , "run" , "test" , external = True )
245+ def check_javascript_format (session : Session ) -> None :
246+ session .run ("npm" , "run" , "check:format" , external = True )
244247
245248
246249@group .session
247- def check_javascript_format (session : Session ) -> None :
248- """Check that Javascript style guidelines are being followed"""
249- session .run ("npm" , "run" , "check-format" , external = True )
250+ def check_javascript_types (session : Session ) -> None :
251+ session .run ("npm" , "run" , "build" , external = True )
252+ session .run ("npm" , "run" , "check:types" , external = True )
253+
254+
255+ @group .session
256+ def check_javascript_build (session : Session ) -> None :
257+ session .run ("npm" , "run" , "build" , external = True )
250258
251259
252260@group .session
@@ -266,16 +274,38 @@ def build_python(session: Session) -> None:
266274
267275
268276@group .session
269- def publish (session : Session , dry_run : bool = False ) -> None :
277+ def publish (
278+ session : Session ,
279+ publish_dry_run : Annotated [
280+ bool ,
281+ Option (help = "whether to test the release process" ),
282+ ] = False ,
283+ publish_fake_tags : Annotated [
284+ Sequence [str ],
285+ Option (nargs = "*" , type = str , help = "fake tags to use for a dry run release" ),
286+ ] = (),
287+ ) -> None :
270288 packages = get_packages (session )
271289
272290 release_prep : dict [LanguageName , ReleasePrepFunc ] = {
273291 "js" : prepare_javascript_release ,
274292 "py" : prepare_python_release ,
275293 }
276294
295+ if publish_fake_tags and not publish_dry_run :
296+ session .error ("Cannot specify --publish-fake-tags without --publish-dry-run" )
297+
298+ parsed_tags : list [TagInfo ] = []
299+ for tag in publish_fake_tags or get_current_tags (session ):
300+ tag_info = parse_tag (tag )
301+ if tag_info is None :
302+ session .error (
303+ f"Invalid tag { tag } - must be of the form <package>-<language>-<version>"
304+ )
305+ parsed_tags .append (tag_info ) # type: ignore
306+
277307 publishers : list [tuple [Path , Callable [[bool ], None ]]] = []
278- for tag , tag_pkg , tag_ver in get_current_tags ( session ) :
308+ for tag , tag_pkg , tag_ver in parsed_tags :
279309 if tag_pkg not in packages :
280310 session .error (f"Tag { tag } references package { tag_pkg } that does not exist" )
281311
@@ -293,7 +323,7 @@ def publish(session: Session, dry_run: bool = False) -> None:
293323 for pkg_path , publish in publishers :
294324 session .log (f"Publishing { pkg_path } ..." )
295325 session .chdir (pkg_path )
296- publish (dry_run )
326+ publish (publish_dry_run )
297327
298328
299329# --- Utilities ------------------------------------------------------------------------
@@ -386,23 +416,28 @@ def get_packages(session: Session) -> dict[str, PackageInfo]:
386416 }
387417
388418 # collect javascript packages
389- for pkg in (CLIENT_DIR / "packages" ).glob ("*" ):
390- pkg_json_file = pkg / "package.json"
391- if not pkg_json_file .exists ():
392- session .error (f"package.json not found in { pkg } " )
419+ js_package_paths : list [Path ] = []
420+ for maybed_pkg in (CLIENT_DIR / "packages" ).glob ("*" ):
421+ if not (maybed_pkg / "package.json" ).exists ():
422+ for nmaybe_namespaced_pkg in maybed_pkg .glob ("*" ):
423+ if (nmaybe_namespaced_pkg / "package.json" ).exists ():
424+ js_package_paths .append (nmaybe_namespaced_pkg )
425+ else :
426+ js_package_paths .append (maybed_pkg )
427+
428+ # get javascript package info
429+ for pkg in js_package_paths :
430+ pkg_json_file = pkg / "package.json" # we already know this exists
393431
394432 pkg_json = json .loads (pkg_json_file .read_text ())
395433
396434 pkg_name = pkg_json .get ("name" )
397435 pkg_version = pkg_json .get ("version" )
398436
399- if pkg_version is None :
400- session .log (f"Skipping - { pkg_name } has no name or version in package.json" )
437+ if pkg_version is None or pkg_name is None :
438+ session .log (f"Skipping - { pkg_name } has no name/ version in package.json" )
401439 continue
402440
403- if pkg_name is None :
404- session .error (f"Package { pkg } has no name in package.json" )
405-
406441 if pkg_name in packages :
407442 session .error (f"Duplicate package name { pkg_name } " )
408443
@@ -417,7 +452,7 @@ class PackageInfo(NamedTuple):
417452 version : str
418453
419454
420- def get_current_tags (session : Session ) -> list [TagInfo ]:
455+ def get_current_tags (session : Session ) -> list [str ]:
421456 """Get tags for the current commit"""
422457 # check if unstaged changes
423458 try :
@@ -465,24 +500,16 @@ def get_current_tags(session: Session) -> list[TagInfo]:
465500 if not tags :
466501 session .error ("No tags found for current commit" )
467502
468- parsed_tags : list [TagInfo ] = []
469- for tag in tags :
470- match = TAG_PATTERN .match (tag )
471- if not match :
472- session .error (
473- f"Invalid tag { tag } - must be of the form <package>-<language>-<version>"
474- )
475- parsed_tags .append (
476- TagInfo (
477- tag ,
478- match ["name" ], # type: ignore[index]
479- match ["version" ], # type: ignore[index]
480- )
481- )
503+ session .log (f"Found tags: { tags } " )
504+
505+ return tags
482506
483- session .log (f"Found tags: { [info .tag for info in parsed_tags ]} " )
484507
485- return parsed_tags
508+ def parse_tag (tag : str ) -> TagInfo | None :
509+ match = TAG_PATTERN .match (tag )
510+ if not match :
511+ return None
512+ return TagInfo (tag , match ["name" ], match ["version" ])
486513
487514
488515class TagInfo (NamedTuple ):
@@ -506,5 +533,4 @@ def get_reactpy_package_version(session: Session) -> str: # type: ignore[return
506533 # remove the quotes
507534 [1 :- 1 ]
508535 )
509- else :
510- session .error (f"No version found in { pkg_root_init_file } " )
536+ session .error (f"No version found in { pkg_root_init_file } " )
0 commit comments