- Refactored `Command.help_signature` to return `(usage, description, tags)` instead of a Rich `Padding`/`Panel`. - Replaced `show_help()` with `render_help()` in `Command` and `Falyx`. - Updated Falyx help rendering to use Rich `Panel`/`Padding` consistently for cleaner UI. - Swapped `print()` calls for `console.print()` for styled output. - Added hooks to `ProcessAction` to announce analysis start/finish. - Added spinners to test and deploy steps; simplified retry setup. - Converted `remove()` to `async def remove()` for consistency. - Added async lock to prevent concurrent Live loop start/stop races. - Added debug logging when starting/stopping the Live loop. - Updated `spinner_teardown_hook` to `await sm.remove(...)` to align with async `remove()`. - Removed `rich.panel`/`rich.padding` from `Command` since panels are now built in `Falyx` help rendering. - Bumped `rich` dependency to `^14.0`. - Bumped version to 0.1.78. This commit polishes help display, demo UX, and spinner lifecycle safety—making spinners thread/async safe and help output more structured and readable.
122 lines
3.0 KiB
Python
122 lines
3.0 KiB
Python
import asyncio
|
|
import random
|
|
import time
|
|
|
|
from falyx import Falyx
|
|
from falyx.action import Action, ActionGroup, ChainedAction, ProcessAction
|
|
from falyx.console import console
|
|
|
|
|
|
# Step 1: Fast I/O-bound setup (standard Action)
|
|
async def checkout_code():
|
|
console.print("🔄 Checking out code...")
|
|
await asyncio.sleep(0.5)
|
|
console.print("📦 Code checked out successfully.")
|
|
|
|
|
|
# Step 2: CPU-bound task (ProcessAction)
|
|
def run_static_analysis():
|
|
total = 0
|
|
for i in range(10_000_000):
|
|
total += i % 3
|
|
time.sleep(2)
|
|
return total
|
|
|
|
|
|
# Step 3: Simulated flaky test with retry
|
|
async def flaky_tests():
|
|
console.print("🧪 Running tests...")
|
|
await asyncio.sleep(0.3)
|
|
if random.random() < 0.3:
|
|
raise RuntimeError("❌ Random test failure!")
|
|
console.print("🧪 Tests passed.")
|
|
return "ok"
|
|
|
|
|
|
# Step 4: Multiple deploy targets (parallel ActionGroup)
|
|
async def deploy_to(target: str):
|
|
console.print(f"🚀 Deploying to {target}...")
|
|
await asyncio.sleep(random.randint(2, 6))
|
|
console.print(f"✅ Deployment to {target} complete.")
|
|
return f"{target} complete"
|
|
|
|
|
|
def build_pipeline():
|
|
# Base actions
|
|
checkout = Action("Checkout", checkout_code)
|
|
analysis = ProcessAction(
|
|
"Static Analysis",
|
|
run_static_analysis,
|
|
spinner=True,
|
|
spinner_message="Analyzing code...",
|
|
)
|
|
analysis.hooks.register(
|
|
"before", lambda ctx: console.print("🧠 Running static analysis (CPU-bound)...")
|
|
)
|
|
analysis.hooks.register("after", lambda ctx: console.print("🧠 Analysis complete!"))
|
|
tests = Action(
|
|
"Run Tests",
|
|
flaky_tests,
|
|
retry=True,
|
|
spinner=True,
|
|
spinner_message="Running tests...",
|
|
)
|
|
|
|
# Parallel deploys
|
|
deploy_group = ActionGroup(
|
|
"Deploy to All",
|
|
[
|
|
Action(
|
|
"Deploy US",
|
|
deploy_to,
|
|
args=("us-west",),
|
|
spinner=True,
|
|
spinner_message="Deploying US...",
|
|
),
|
|
Action(
|
|
"Deploy EU",
|
|
deploy_to,
|
|
args=("eu-central",),
|
|
spinner=True,
|
|
spinner_message="Deploying EU...",
|
|
),
|
|
Action(
|
|
"Deploy Asia",
|
|
deploy_to,
|
|
args=("asia-east",),
|
|
spinner=True,
|
|
spinner_message="Deploying Asia...",
|
|
),
|
|
],
|
|
)
|
|
|
|
# Full pipeline
|
|
return ChainedAction("CI/CD Pipeline", [checkout, analysis, tests, deploy_group])
|
|
|
|
|
|
pipeline = build_pipeline()
|
|
|
|
|
|
# Run the pipeline
|
|
async def main():
|
|
|
|
flx = Falyx(
|
|
hide_menu_table=True, program="pipeline_demo.py", show_placeholder_menu=True
|
|
)
|
|
flx.add_command(
|
|
"P",
|
|
"Run Pipeline",
|
|
pipeline,
|
|
spinner=True,
|
|
spinner_type="line",
|
|
spinner_message="Running pipeline...",
|
|
tags=["pipeline", "demo"],
|
|
help_text="Run the full CI/CD pipeline demo.",
|
|
)
|
|
|
|
await flx.run()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|