@@ -51,7 +51,14 @@ def index(
5151 output : Optional [Path ] = typer .Option (None , "--output" , "-o" , help = "Path to write rendered index.html." ),
5252 target : str = typer .Option ("staging" , "--target" , help = "Deploy target: staging or prod." ),
5353 deploy : bool = typer .Option (
54- False , "--deploy" , help = "After rendering, upload index.html to the manifest's deploy target."
54+ False ,
55+ "--deploy" ,
56+ help = "After rendering, upload index.html to the manifest's deploy target." ,
57+ ),
58+ service_account : bool = typer .Option (
59+ False ,
60+ "--service-account" ,
61+ help = "For GH action only, use --service-account. Credentials pass through GH runner." ,
5562 ),
5663) -> None :
5764 """Render the portfolio landing page from a sites.yml manifest."""
@@ -68,7 +75,12 @@ def index(
6875
6976 if deploy :
7077 target_url = _resolve_target_url (manifest .deploy , target , source_label = "sites.yml" )
71- _require_auth ()
78+
79+ # For service account, GH action generates a hash that is used as credential
80+ if service_account :
81+ pass
82+ else :
83+ _require_auth ()
7284 deployer .upload_file (target_url , output_path )
7385 typer .echo (f"deployed { output_path } -> { target_url } " )
7486
@@ -100,9 +112,15 @@ def build(
100112 "-o" ,
101113 help = "Where to write build artifacts. Defaults to `<yml dir>/<yml stem>/`." ,
102114 ),
103- execute : bool = typer .Option (True , "--execute/--no-execute" , help = "Skip calls to papermill when --no-execute." ),
115+ execute : bool = typer .Option (
116+ True ,
117+ "--execute/--no-execute" ,
118+ help = "Skip calls to papermill when --no-execute." ,
119+ ),
104120 show_stderr : bool = typer .Option (
105- False , "--show-stderr" , help = "Keep stderr stream in cell outputs (default: strip)."
121+ False ,
122+ "--show-stderr" ,
123+ help = "Keep stderr stream in cell outputs (default: strip)." ,
106124 ),
107125 prepare_only : bool = typer .Option (False , help = "Pass-through to papermill; if true, cells are not executed." ),
108126 continue_on_error : bool = typer .Option (False , help = "Continue building remaining chapters on papermill error." ),
@@ -115,18 +133,29 @@ def build(
115133 limit : Optional [int ] = typer .Option (None , "--limit" , help = "Build only the first N chapters in source order." ),
116134 readme_only : bool = typer .Option (False , "--readme-only" , help = "Build just the landing page; skip all chapters." ),
117135 toc_only : bool = typer .Option (
118- False , "--toc-only" , help = "Re-render myst.yml and run jupyter-book; skip papermill and readme copy."
136+ False ,
137+ "--toc-only" ,
138+ help = "Re-render myst.yml and run jupyter-book; skip papermill and readme copy." ,
119139 ),
120140) -> None :
121141 """Build a static site from a parameterized notebook portfolio."""
122142 if readme_only and toc_only :
123- typer .secho ("error: --readme-only and --toc-only are mutually exclusive" , fg = typer .colors .RED )
143+ typer .secho (
144+ "error: --readme-only and --toc-only are mutually exclusive" ,
145+ fg = typer .colors .RED ,
146+ )
124147 raise typer .Exit (code = 2 )
125148 if readme_only and (only or limit is not None ):
126- typer .secho ("error: --readme-only cannot be combined with --only or --limit" , fg = typer .colors .RED )
149+ typer .secho (
150+ "error: --readme-only cannot be combined with --only or --limit" ,
151+ fg = typer .colors .RED ,
152+ )
127153 raise typer .Exit (code = 2 )
128154 if toc_only and (only or limit is not None ):
129- typer .secho ("error: --toc-only cannot be combined with --only or --limit" , fg = typer .colors .RED )
155+ typer .secho (
156+ "error: --toc-only cannot be combined with --only or --limit" ,
157+ fg = typer .colors .RED ,
158+ )
130159 raise typer .Exit (code = 2 )
131160
132161 papermill_runs = execute and not prepare_only and not readme_only and not toc_only
@@ -181,7 +210,9 @@ def deploy(
181210 help = "Directory of HTML to upload if not using site yml" ,
182211 ),
183212 target_url : Optional [str ] = typer .Option (
184- None , "--target-url" , help = "gs://bucket/prefix to upload to if not using site yml"
213+ None ,
214+ "--target-url" ,
215+ help = "gs://bucket/prefix to upload to if not using site yml" ,
185216 ),
186217) -> None :
187218 """Upload built HTML to GCS. Defaults to <site>/_build/html and the yml's deploy target."""
@@ -242,6 +273,15 @@ def login() -> None:
242273 raise typer .Exit (code = returncode )
243274
244275
276+ @app .command ()
277+ def login_service_account () -> None :
278+ """Authenticate to Google Cloud using the Cal-ITP login config bundled with this tool."""
279+ if auth .is_valid ():
280+ returncode = 0
281+ elif returncode != 0 :
282+ raise typer .Exit (code = returncode )
283+
284+
245285_WCAG_PRESETS = {
246286 "a" : ["wcag2a" ],
247287 "aa" : ["wcag2a" , "wcag2aa" , "wcag21aa" ],
@@ -253,7 +293,11 @@ def login() -> None:
253293@app .command (name = "axe-check" )
254294def axe_check (
255295 site_yml : Optional [Path ] = typer .Argument (
256- None , exists = True , dir_okay = False , readable = True , help = "Site yml; build dir is derived."
296+ None ,
297+ exists = True ,
298+ dir_okay = False ,
299+ readable = True ,
300+ help = "Site yml; build dir is derived." ,
257301 ),
258302 html : Optional [Path ] = typer .Option (None , "--html" , exists = True , file_okay = False , help = "Scan this directory." ),
259303 wcag : str = typer .Option ("aa" , "--wcag" , help = "WCAG conformance level: a, aa, or aaa." ),
@@ -262,10 +306,16 @@ def axe_check(
262306 "--impact" ,
263307 help = "Comma-separated impact levels to show. Use 'all' for everything." ,
264308 ),
265- no_dedupe : bool = typer .Option (False , "--no-dedupe" , help = "Show one entry per page instead of grouping by rule." ),
309+ no_dedupe : bool = typer .Option (
310+ False ,
311+ "--no-dedupe" ,
312+ help = "Show one entry per page instead of grouping by rule." ,
313+ ),
266314 skip_axe_check : bool = typer .Option (False , "--skip-axe-check" , help = "Skip the axe CLI pre-flight." ),
267315 report : bool = typer .Option (
268- False , "--report" , help = f"Write the full axe JSON report to { DEFAULT_REPORT_FILENAME } in the current directory."
316+ False ,
317+ "--report" ,
318+ help = f"Write the full axe JSON report to { DEFAULT_REPORT_FILENAME } in the current directory." ,
269319 ),
270320 serve : Optional [bool ] = typer .Option (
271321 None ,
0 commit comments