Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:MarketSquare Robotframework browser Inv Build

From Leeroopedia
Revision as of 11:29, 16 February 2026 by Admin (talk | contribs) (Auto-imported from implementations/MarketSquare_Robotframework_browser_Inv_Build.md)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Document Type

API Doc -- Documents the Invoke build tasks that constitute the project's multi-stage build pipeline, including dependency installation, protobuf compilation, Node.js compilation, test app building, and type stub generation.

API Summary

The build task is the top-level entry point that orchestrates the full build pipeline through Invoke's task dependency system. It depends on deps, protobuf, node_build, and create_test_app.

Source References

File Lines Description
tasks.py L287-289 build task (top-level)
tasks.py L114-158 deps task (dependency installation)
tasks.py L206-264 protobuf task and helpers
tasks.py L274-279 node_build task
tasks.py L282-284 create_test_app task
tasks.py L267-271 _gen_stub helper function

CLI Usage

inv build

This single command runs the entire build pipeline in dependency order.

Task: build

@task(deps, protobuf, node_build, create_test_app)
def build(c: Context):
    _gen_stub(c)

Parameters:

  • c (Context) -- Invoke execution context

Dependencies: deps, protobuf, node_build, create_test_app (run in dependency order)

Behavior: After all dependencies complete, calls _gen_stub(c) to regenerate Python type stubs. This ensures stubs reflect any changes from the build process.

Task: deps

@task
def deps(c, system=False, force=False, uv=False):
    """Install dependencies for development."""

CLI: inv deps, inv deps --force, inv deps --system

Parameters:

Parameter Type Default Description
system bool False Install to system Python instead of virtualenv
force bool False Force npm install even if package-lock.json unchanged
uv bool False Skip pip install step (assumes uv is already available)

Behavior:

  1. Checks if pip is available; if not, sets uv=True
  2. Unless uv=True, upgrades pip and installs uv
  3. Installs dev dependencies: uv pip install -r Browser/dev-requirements.txt
  4. Installs project dependencies: uv pip install -r pyproject.toml
  5. In CI (GITHUB_WORKFLOW set): adds --python flag and cleans node_modules
  6. Checks if package-lock.json changed; if so, runs npm install and npx playwright install --with-deps

Task: protobuf

@task
def protobuf(c, force=False):
    """Compile grpc protobuf files."""

CLI: inv protobuf, inv protobuf --force

Parameters:

Parameter Type Default Description
force bool False Force protobuf compilation even if .proto files unchanged

Behavior:

  1. Creates output directories if they do not exist: Browser/generated/ and node/playwright-wrapper/generated/
  2. Creates __init__.py in the Python protobuf directory
  3. Checks if .proto files have changed since last generation
  4. If changed (or forced), runs both Python and Node.js protobuf generation

Python protobuf generation:

def _python_protobuf_gen(c):
    c.run(
        f"python -m grpc_tools.protoc -I protobuf "
        f"--python_out=Browser/generated "
        f"--grpc_python_out={python_protobuf_dir} "
        f"--mypy_out={python_protobuf_dir} protobuf/*.proto"
    )

After generation, it fixes the import path in playwright_pb2_grpc.py to use the absolute import from Browser.generated import playwright_pb2.

Node.js protobuf generation:

def _node_protobuf_gen(c):
    # First pass: JavaScript + gRPC stubs
    cmd = (
        "npm run grpc_tools_node_protoc -- "
        f"--js_out=import_style=commonjs,binary:{node_protobuf_dir} "
        f"--grpc_out=grpc_js:{node_protobuf_dir} "
        f"--plugin=protoc-gen-grpc={protoc_plugin} "
        "-I ./protobuf protobuf/*.proto"
    )
    # Second pass: TypeScript definitions
    cmd = (
        "npm run grpc_tools_node_protoc -- "
        f"--plugin=protoc-gen-ts={protoc_ts_plugin} "
        f"--ts_out={node_protobuf_dir} "
        "-I ./protobuf protobuf/*.proto"
    )

Task: node_build

@task(protobuf)
def node_build(c: Context):
    c.run("npm run build")
    shutil.rmtree(WRAPPER_DIR / "static", ignore_errors=True)
    shutil.copytree(node_dir / "playwright-wrapper" / "static", WRAPPER_DIR / "static")
    _gen_stub(c)

CLI: inv node-build

Dependencies: protobuf (must complete first)

Behavior:

  1. Runs npm run build -- triggers esbuild to compile TypeScript and bundle into Browser/wrapper/index.js
  2. Removes and re-copies the static/ directory from the Node.js source to Browser/wrapper/static/
  3. Generates Python type stubs via _gen_stub

Task: create_test_app

@task
def create_test_app(c):
    c.run("npm run build-test-app")

CLI: inv create-test-app

Behavior: Runs npm run build-test-app to compile the dynamic test application used by acceptance tests.

Helper: _gen_stub

def _gen_stub(c: Context):
    shutil.rmtree("mypy_stub/", ignore_errors=True)
    Path("Browser/browser.pyi").unlink(missing_ok=True)
    c.run("stubgen --output mypy_stub Browser")
    c.run("python -m Browser.gen_stub")

Behavior:

  1. Cleans previous stub outputs (mypy_stub/ directory and Browser/browser.pyi)
  2. Runs stubgen to generate raw stubs from the Browser package
  3. Runs Browser.gen_stub module to post-process stubs into the final browser.pyi

Build Outputs

Output Produced By Description
Browser/generated/playwright_pb2.py protobuf Python protobuf message classes
Browser/generated/playwright_pb2_grpc.py protobuf Python gRPC client/server stubs
Browser/generated/playwright_pb2.pyi protobuf MyPy type stubs for protobuf
node/playwright-wrapper/generated/*.js protobuf Node.js protobuf stubs
node/playwright-wrapper/generated/*.ts protobuf TypeScript definitions for protobuf
Browser/wrapper/index.js node_build Bundled Playwright wrapper
Browser/wrapper/static/ node_build Static files for the wrapper
Browser/browser.pyi _gen_stub Python type stubs for IDE support

Incremental Build

The _sources_changed helper enables incremental builds:

def _sources_changed(source_files: Iterable[Path], timestamp_file: Path):
    if timestamp_file.exists():
        last_built = timestamp_file.lstat().st_mtime
        src_last_modified = [f.lstat().st_mtime for f in source_files]
        return not all(last_built >= modified for modified in src_last_modified)
    return True

Used by both deps (checking package-lock.json) and protobuf (checking .proto files).

Related

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment