@@ -35,7 +35,6 @@ def __call__(self, session: Session) -> Callable[[bool], None]:
35
35
SRC_DIR = ROOT_DIR / "src"
36
36
CLIENT_DIR = SRC_DIR / "client"
37
37
REACTPY_DIR = SRC_DIR / "reactpy"
38
- LANGUAGE_TYPES : list [LanguageName ] = ["py" , "js" ]
39
38
TAG_PATTERN = re .compile (
40
39
# start
41
40
r"^"
@@ -46,7 +45,6 @@ def __call__(self, session: Session) -> Callable[[bool], None]:
46
45
# end
47
46
r"$"
48
47
)
49
- print (TAG_PATTERN .pattern )
50
48
REMAINING_ARGS = Option (nargs = REMAINDER , type = str )
51
49
52
50
@@ -60,6 +58,7 @@ def __call__(self, session: Session) -> Callable[[bool], None]:
60
58
def setup_checks (session : Session ) -> None :
61
59
session .install ("--upgrade" , "pip" )
62
60
session .run ("pip" , "--version" )
61
+ session .run ("npm" , "--version" , external = True )
63
62
64
63
65
64
@group .setup ("check-javascript" )
@@ -88,6 +87,12 @@ def format(session: Session) -> None:
88
87
session .run ("npm" , "run" , "format" , external = True )
89
88
90
89
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
+
91
96
@group .session
92
97
def example (session : Session ) -> None :
93
98
"""Run an example"""
@@ -232,21 +237,24 @@ def check_docs(session: Session) -> None:
232
237
233
238
234
239
@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 )
238
242
239
243
240
244
@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 )
244
247
245
248
246
249
@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 )
250
258
251
259
252
260
@group .session
@@ -266,16 +274,38 @@ def build_python(session: Session) -> None:
266
274
267
275
268
276
@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 :
270
288
packages = get_packages (session )
271
289
272
290
release_prep : dict [LanguageName , ReleasePrepFunc ] = {
273
291
"js" : prepare_javascript_release ,
274
292
"py" : prepare_python_release ,
275
293
}
276
294
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
+
277
307
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 :
279
309
if tag_pkg not in packages :
280
310
session .error (f"Tag { tag } references package { tag_pkg } that does not exist" )
281
311
@@ -293,7 +323,7 @@ def publish(session: Session, dry_run: bool = False) -> None:
293
323
for pkg_path , publish in publishers :
294
324
session .log (f"Publishing { pkg_path } ..." )
295
325
session .chdir (pkg_path )
296
- publish (dry_run )
326
+ publish (publish_dry_run )
297
327
298
328
299
329
# --- Utilities ------------------------------------------------------------------------
@@ -386,23 +416,28 @@ def get_packages(session: Session) -> dict[str, PackageInfo]:
386
416
}
387
417
388
418
# 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
393
431
394
432
pkg_json = json .loads (pkg_json_file .read_text ())
395
433
396
434
pkg_name = pkg_json .get ("name" )
397
435
pkg_version = pkg_json .get ("version" )
398
436
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" )
401
439
continue
402
440
403
- if pkg_name is None :
404
- session .error (f"Package { pkg } has no name in package.json" )
405
-
406
441
if pkg_name in packages :
407
442
session .error (f"Duplicate package name { pkg_name } " )
408
443
@@ -417,7 +452,7 @@ class PackageInfo(NamedTuple):
417
452
version : str
418
453
419
454
420
- def get_current_tags (session : Session ) -> list [TagInfo ]:
455
+ def get_current_tags (session : Session ) -> list [str ]:
421
456
"""Get tags for the current commit"""
422
457
# check if unstaged changes
423
458
try :
@@ -465,24 +500,16 @@ def get_current_tags(session: Session) -> list[TagInfo]:
465
500
if not tags :
466
501
session .error ("No tags found for current commit" )
467
502
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
482
506
483
- session .log (f"Found tags: { [info .tag for info in parsed_tags ]} " )
484
507
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" ])
486
513
487
514
488
515
class TagInfo (NamedTuple ):
@@ -506,5 +533,4 @@ def get_reactpy_package_version(session: Session) -> str: # type: ignore[return
506
533
# remove the quotes
507
534
[1 :- 1 ]
508
535
)
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