looker-demo-cli 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- looker_demo_cli-0.1.0/.github/workflows/publish.yml +35 -0
- looker_demo_cli-0.1.0/.gitignore +41 -0
- looker_demo_cli-0.1.0/AGENTS.md +36 -0
- looker_demo_cli-0.1.0/LICENSE +21 -0
- looker_demo_cli-0.1.0/PKG-INFO +168 -0
- looker_demo_cli-0.1.0/README.md +147 -0
- looker_demo_cli-0.1.0/looker_demo_cli/__init__.py +3 -0
- looker_demo_cli-0.1.0/looker_demo_cli/cli.py +209 -0
- looker_demo_cli-0.1.0/looker_demo_cli/config.py +100 -0
- looker_demo_cli-0.1.0/looker_demo_cli/generators/__init__.py +13 -0
- looker_demo_cli-0.1.0/looker_demo_cli/generators/embed_scaffolder.py +94 -0
- looker_demo_cli-0.1.0/looker_demo_cli/generators/lookml_generator.py +252 -0
- looker_demo_cli-0.1.0/looker_demo_cli/generators/schema_generator.py +30 -0
- looker_demo_cli-0.1.0/looker_demo_cli/precheck/__init__.py +13 -0
- looker_demo_cli-0.1.0/looker_demo_cli/precheck/gcp_auth.py +201 -0
- looker_demo_cli-0.1.0/looker_demo_cli/precheck/looker_auth.py +60 -0
- looker_demo_cli-0.1.0/looker_demo_cli/precheck/mcp_checker.py +131 -0
- looker_demo_cli-0.1.0/looker_demo_cli/precheck/skills_organizer.py +157 -0
- looker_demo_cli-0.1.0/looker_demo_cli/utils/__init__.py +21 -0
- looker_demo_cli-0.1.0/looker_demo_cli/utils/bigquery_client.py +94 -0
- looker_demo_cli-0.1.0/looker_demo_cli/utils/console.py +34 -0
- looker_demo_cli-0.1.0/looker_demo_cli/workflow/__init__.py +4 -0
- looker_demo_cli-0.1.0/looker_demo_cli/workflow/runner.py +71 -0
- looker_demo_cli-0.1.0/looker_demo_cli/workflow/state.py +49 -0
- looker_demo_cli-0.1.0/looker_demo_cli/workflow/steps/__init__.py +15 -0
- looker_demo_cli-0.1.0/looker_demo_cli/workflow/steps/step_bigquery_upload.py +37 -0
- looker_demo_cli-0.1.0/looker_demo_cli/workflow/steps/step_dataset_decision.py +24 -0
- looker_demo_cli-0.1.0/looker_demo_cli/workflow/steps/step_embed_scaffold.py +34 -0
- looker_demo_cli-0.1.0/looker_demo_cli/workflow/steps/step_looker_deploy.py +154 -0
- looker_demo_cli-0.1.0/looker_demo_cli/workflow/steps/step_lookml_generation.py +32 -0
- looker_demo_cli-0.1.0/looker_demo_cli/workflow/steps/step_schema_synthesis.py +19 -0
- looker_demo_cli-0.1.0/pyproject.toml +29 -0
- looker_demo_cli-0.1.0/skills/looker-demo-orchestrator/SKILL.md +111 -0
- looker_demo_cli-0.1.0/uv.lock +1116 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
pypi-publish:
|
|
10
|
+
name: Build and upload to PyPI
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write # Required for PyPI Trusted Publishing
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout repository
|
|
17
|
+
uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Install uv
|
|
20
|
+
uses: astral-sh/setup-uv@v3
|
|
21
|
+
with:
|
|
22
|
+
version: "latest"
|
|
23
|
+
|
|
24
|
+
- name: Set up Python
|
|
25
|
+
uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.12"
|
|
28
|
+
|
|
29
|
+
- name: Build package distributions
|
|
30
|
+
run: uv build
|
|
31
|
+
|
|
32
|
+
- name: Publish package distributions to PyPI
|
|
33
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
34
|
+
with:
|
|
35
|
+
packages-dir: dist/
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
|
|
23
|
+
# Virtual Environments
|
|
24
|
+
.venv/
|
|
25
|
+
env/
|
|
26
|
+
venv/
|
|
27
|
+
ENV/
|
|
28
|
+
|
|
29
|
+
# Testing & Coverage
|
|
30
|
+
.pytest_cache/
|
|
31
|
+
.coverage
|
|
32
|
+
htmlcov/
|
|
33
|
+
|
|
34
|
+
# Logs & Temporary Files
|
|
35
|
+
*.log
|
|
36
|
+
scratch/
|
|
37
|
+
tmp/
|
|
38
|
+
.temp/
|
|
39
|
+
.DS_Store
|
|
40
|
+
.env
|
|
41
|
+
.env.local
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Agent Instructions for `demo-create`
|
|
2
|
+
|
|
3
|
+
## Role & Mission
|
|
4
|
+
You are the Looker Demo Architect Agent. Your mission is to assist users in designing, synthesizing, modeling, and deploying comprehensive data demos on Looker and Embedded Analytics.
|
|
5
|
+
|
|
6
|
+
## Workflow Rules
|
|
7
|
+
1. **Always run `pre-check` first**:
|
|
8
|
+
Execute `demo-create pre-check --fix` (or `uv run demo-create pre-check --fix`) to ensure BigQuery credentials, GCP projects, MCP servers, and intent-based skills are configured.
|
|
9
|
+
|
|
10
|
+
2. **Verify GCP Authentication & Confirm Target Project**:
|
|
11
|
+
- **GCP Re-authentication Prompt**: If the pre-check report or any BigQuery operation indicates that reauthentication is required (`reauth_required: true`, token expiry, or authentication errors), the agent **MUST prompt the user** to reauthenticate by providing the exact shell commands:
|
|
12
|
+
```bash
|
|
13
|
+
gcloud auth login
|
|
14
|
+
gcloud auth application-default login
|
|
15
|
+
```
|
|
16
|
+
Do NOT attempt to bypass or guess invalid credentials.
|
|
17
|
+
- **Project Confirmation**: The agent **MUST prompt the user to confirm/select which Google Cloud Project to use** from the available projects returned in pre-check (or via `gcloud projects list`) BEFORE creating datasets, querying BigQuery, or running workflows.
|
|
18
|
+
|
|
19
|
+
3. **Follow the deterministic decision tree**:
|
|
20
|
+
- Check if dataset exists in BigQuery for the selected project.
|
|
21
|
+
- If dataset exists: Ask user whether to Augment (generate linked tables) or Model LookML Only.
|
|
22
|
+
- If greenfield: Run iterative schema design with micro-sample validation before high-volume generation.
|
|
23
|
+
- Confirm Internal Looker Demo vs External Embedded Portal scope.
|
|
24
|
+
|
|
25
|
+
4. **LookML Quality & Field Documentation Standards**:
|
|
26
|
+
- **Mandatory Labels & Descriptions**: All LookML view files (`.view.lkml`) **MUST include explicit `label:` and `description:` parameters** on every dimension, dimension group, and measure to ensure self-documenting Explores for business users.
|
|
27
|
+
- **Measures & Drill Fields**: Include formatted primary metrics (sum, average, count distinct) with `value_format_name` (e.g. `usd_0`, `percent_2`, `decimal_1`) and drill-down fields.
|
|
28
|
+
|
|
29
|
+
5. **LookML Validation Gate (`lkr-dev-cli`)**:
|
|
30
|
+
- **Validate Before Deploy**: When LookML files are pushed to the Looker dev branch (`dev`), the agent **MUST execute the LookML validator** (via `lkr` CLI / `validate_project`) to catch and self-heal any syntax or join errors before committing and deploying.
|
|
31
|
+
- **Production Deployment**: Only proceed to production deployment (`lkr --dev tools lookml push ... --deploy` or `deploy_to_production`) after the LookML validator passes with 0 errors.
|
|
32
|
+
|
|
33
|
+
6. **Use Intent Skills**:
|
|
34
|
+
- For schema design & synthetic data generation, reference skills in `skills/data-design/` (`data-designer`, `data-designer-architect`).
|
|
35
|
+
- For LookML views, explores, and dashboards, reference skills in `skills/lookml/` (`repo-lookml`, `lookml-model`, `lookml-dashboard`).
|
|
36
|
+
- For frontend embed configuration, reference skills in `skills/embed-portal/` (`setup-embed-demo`, `customize-frontend`).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 lkrdev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: looker-demo-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Deterministic Looker Demo Orchestrator CLI for synthetic data generation, BigQuery upload, LookML modeling, and Embedded Portal scaffolding.
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Requires-Dist: faker>=24.0.0
|
|
8
|
+
Requires-Dist: google-auth>=2.29.0
|
|
9
|
+
Requires-Dist: google-cloud-bigquery>=3.20.0
|
|
10
|
+
Requires-Dist: lkr-dev-cli>=0.0.50
|
|
11
|
+
Requires-Dist: looker-sdk>=24.4.0
|
|
12
|
+
Requires-Dist: numpy>=1.26.0
|
|
13
|
+
Requires-Dist: pandas>=2.2.0
|
|
14
|
+
Requires-Dist: pyarrow>=15.0.0
|
|
15
|
+
Requires-Dist: pydantic>=2.7.0
|
|
16
|
+
Requires-Dist: python-dotenv>=1.0.1
|
|
17
|
+
Requires-Dist: questionary>=2.0.1
|
|
18
|
+
Requires-Dist: rich>=13.7.0
|
|
19
|
+
Requires-Dist: typer>=0.12.0
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# Looker Demo Creator (`demo-create`)
|
|
23
|
+
|
|
24
|
+
> **Automated, deterministic orchestrator for creating end-to-end Looker demos, synthetic BigQuery datasets, LookML semantic models, and Embedded Analytics portals.**
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Overview
|
|
29
|
+
|
|
30
|
+
`demo-create` is a developer and AI agent tool that unifies the end-to-end Looker demo creation lifecycle into a single workflow:
|
|
31
|
+
1. **Pre-flight & Environment Audit (`pre-check`)**: Verifies active GCP/ADC accounts, installs/patches global MCP tools (`data-designer`, `bigquery`, `lkr_codemode`), and organizes agent skills into intent-based subfolders.
|
|
32
|
+
2. **Dataset Decision & Synthesis**: Automatically checks for existing BigQuery datasets, enables data augmentation or green-field relational schema generation, and validates referential integrity.
|
|
33
|
+
3. **BigQuery Loading**: Creates datasets and partitioned/clustered tables in BigQuery.
|
|
34
|
+
4. **LookML Generation & Deployment**: Autogenerates production-ready views, explores, and executive dashboards, provisioning and deploying them directly to the Looker instance using `lkr-dev-cli`.
|
|
35
|
+
5. **Embedded Portal Scaffolding**: Clones and configures a clean, dedicated `looker-embed-demo` workspace for external client demos.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Quickstart & Execution
|
|
40
|
+
|
|
41
|
+
### 1. Run Instantly with `uvx` (No Installation Required)
|
|
42
|
+
|
|
43
|
+
Once published to PyPI or your package index, you can execute the CLI on-demand in an ephemeral, isolated environment without creating a virtual environment or pre-installing dependencies:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Run directly from the package name
|
|
47
|
+
uvx looker-demo-cli pre-check --fix
|
|
48
|
+
|
|
49
|
+
# Or invoke the `demo-create` binary explicitly
|
|
50
|
+
uvx --from looker-demo-cli demo-create pre-check --fix
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### Run with Options & Flags:
|
|
54
|
+
```bash
|
|
55
|
+
# Run pre-flight audit and auto-fix MCP / skills
|
|
56
|
+
uvx looker-demo-cli pre-check --fix
|
|
57
|
+
|
|
58
|
+
# Run end-to-end interactive demo creator
|
|
59
|
+
uvx looker-demo-cli run --project=retail_analytics --scope=internal
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
### 2. Install as a Persistent CLI Tool (`uv tool`)
|
|
65
|
+
|
|
66
|
+
To make `demo-create` / `looker-demo-cli` globally available on your shell's `PATH`:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Install the published package globally in an isolated environment
|
|
70
|
+
uv tool install looker-demo-cli
|
|
71
|
+
|
|
72
|
+
# Now you can run it directly anywhere:
|
|
73
|
+
demo-create pre-check --fix
|
|
74
|
+
# or
|
|
75
|
+
looker-demo-cli pre-check --fix
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
To update to the latest version at any time:
|
|
79
|
+
```bash
|
|
80
|
+
uv tool upgrade looker-demo-cli
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
### 3. Running from Local Source or Git (Development)
|
|
86
|
+
|
|
87
|
+
If you are developing locally or testing before publishing:
|
|
88
|
+
|
|
89
|
+
#### Run directly from local source directory:
|
|
90
|
+
```bash
|
|
91
|
+
# Run from repository root
|
|
92
|
+
uvx --from . demo-create pre-check --fix
|
|
93
|
+
|
|
94
|
+
# Or run from anywhere by pointing to the repository path
|
|
95
|
+
uvx --from /path/to/looker-demo-cli demo-create pre-check --fix
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### Run directly from a Git repository:
|
|
99
|
+
```bash
|
|
100
|
+
uvx --from git+https://github.com/lkrdev/looker-demo-cli.git demo-create pre-check --fix
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
#### Local Editable Installation:
|
|
104
|
+
```bash
|
|
105
|
+
cd ~/looker-demo-cli
|
|
106
|
+
uv venv
|
|
107
|
+
uv pip install -e .
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Commands & Usage
|
|
113
|
+
|
|
114
|
+
### 1. Environment & Skill Audit (`pre-check`)
|
|
115
|
+
```bash
|
|
116
|
+
# Run visual audit of GCP credentials, MCP tools, and intent skills
|
|
117
|
+
demo-create pre-check
|
|
118
|
+
|
|
119
|
+
# Automatically install missing MCP configs and symlink skills into intent subfolders
|
|
120
|
+
demo-create pre-check --fix
|
|
121
|
+
|
|
122
|
+
# Emit raw JSON report for programmatic agent consumption
|
|
123
|
+
demo-create pre-check --json
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 2. End-to-End Demo Creation (`run`)
|
|
127
|
+
```bash
|
|
128
|
+
# Interactive wizard
|
|
129
|
+
demo-create run --project=retail_insights --scope=internal
|
|
130
|
+
|
|
131
|
+
# Non-interactive / Agent Mode
|
|
132
|
+
demo-create run \
|
|
133
|
+
--project=logistics_analytics \
|
|
134
|
+
--scope=external \
|
|
135
|
+
--gcp-project=my-analytics-project \
|
|
136
|
+
--gcp-account=user@example.com \
|
|
137
|
+
--agent-mode
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Intent-Based Skill Organization
|
|
143
|
+
|
|
144
|
+
When you run `demo-create pre-check --fix`, skills are organized into `~/.gemini/config/skills/`:
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
~/.gemini/config/skills/
|
|
148
|
+
├── data-design/
|
|
149
|
+
│ ├── data-designer/
|
|
150
|
+
│ ├── data-designer-architect/
|
|
151
|
+
│ ├── data-designer-engineer/
|
|
152
|
+
│ └── data-designer-evaluator/
|
|
153
|
+
├── lookml/
|
|
154
|
+
│ ├── repo-lookml/
|
|
155
|
+
│ ├── lookml-model/
|
|
156
|
+
│ ├── lookml-explore/
|
|
157
|
+
│ ├── lookml-view/
|
|
158
|
+
│ ├── lookml-dashboard/
|
|
159
|
+
│ └── embed-themes/
|
|
160
|
+
└── embed-portal/
|
|
161
|
+
├── setup-embed-demo/
|
|
162
|
+
├── customize-frontend/
|
|
163
|
+
├── customize-frontend-branding/
|
|
164
|
+
├── customize-frontend-theme/
|
|
165
|
+
└── sso-embed/
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
This guarantees that any Jetski agent in any directory can discover and execute Looker demo workflows.
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Looker Demo Creator (`demo-create`)
|
|
2
|
+
|
|
3
|
+
> **Automated, deterministic orchestrator for creating end-to-end Looker demos, synthetic BigQuery datasets, LookML semantic models, and Embedded Analytics portals.**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
`demo-create` is a developer and AI agent tool that unifies the end-to-end Looker demo creation lifecycle into a single workflow:
|
|
10
|
+
1. **Pre-flight & Environment Audit (`pre-check`)**: Verifies active GCP/ADC accounts, installs/patches global MCP tools (`data-designer`, `bigquery`, `lkr_codemode`), and organizes agent skills into intent-based subfolders.
|
|
11
|
+
2. **Dataset Decision & Synthesis**: Automatically checks for existing BigQuery datasets, enables data augmentation or green-field relational schema generation, and validates referential integrity.
|
|
12
|
+
3. **BigQuery Loading**: Creates datasets and partitioned/clustered tables in BigQuery.
|
|
13
|
+
4. **LookML Generation & Deployment**: Autogenerates production-ready views, explores, and executive dashboards, provisioning and deploying them directly to the Looker instance using `lkr-dev-cli`.
|
|
14
|
+
5. **Embedded Portal Scaffolding**: Clones and configures a clean, dedicated `looker-embed-demo` workspace for external client demos.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Quickstart & Execution
|
|
19
|
+
|
|
20
|
+
### 1. Run Instantly with `uvx` (No Installation Required)
|
|
21
|
+
|
|
22
|
+
Once published to PyPI or your package index, you can execute the CLI on-demand in an ephemeral, isolated environment without creating a virtual environment or pre-installing dependencies:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Run directly from the package name
|
|
26
|
+
uvx looker-demo-cli pre-check --fix
|
|
27
|
+
|
|
28
|
+
# Or invoke the `demo-create` binary explicitly
|
|
29
|
+
uvx --from looker-demo-cli demo-create pre-check --fix
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
#### Run with Options & Flags:
|
|
33
|
+
```bash
|
|
34
|
+
# Run pre-flight audit and auto-fix MCP / skills
|
|
35
|
+
uvx looker-demo-cli pre-check --fix
|
|
36
|
+
|
|
37
|
+
# Run end-to-end interactive demo creator
|
|
38
|
+
uvx looker-demo-cli run --project=retail_analytics --scope=internal
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
### 2. Install as a Persistent CLI Tool (`uv tool`)
|
|
44
|
+
|
|
45
|
+
To make `demo-create` / `looker-demo-cli` globally available on your shell's `PATH`:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Install the published package globally in an isolated environment
|
|
49
|
+
uv tool install looker-demo-cli
|
|
50
|
+
|
|
51
|
+
# Now you can run it directly anywhere:
|
|
52
|
+
demo-create pre-check --fix
|
|
53
|
+
# or
|
|
54
|
+
looker-demo-cli pre-check --fix
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
To update to the latest version at any time:
|
|
58
|
+
```bash
|
|
59
|
+
uv tool upgrade looker-demo-cli
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
### 3. Running from Local Source or Git (Development)
|
|
65
|
+
|
|
66
|
+
If you are developing locally or testing before publishing:
|
|
67
|
+
|
|
68
|
+
#### Run directly from local source directory:
|
|
69
|
+
```bash
|
|
70
|
+
# Run from repository root
|
|
71
|
+
uvx --from . demo-create pre-check --fix
|
|
72
|
+
|
|
73
|
+
# Or run from anywhere by pointing to the repository path
|
|
74
|
+
uvx --from /path/to/looker-demo-cli demo-create pre-check --fix
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
#### Run directly from a Git repository:
|
|
78
|
+
```bash
|
|
79
|
+
uvx --from git+https://github.com/lkrdev/looker-demo-cli.git demo-create pre-check --fix
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### Local Editable Installation:
|
|
83
|
+
```bash
|
|
84
|
+
cd ~/looker-demo-cli
|
|
85
|
+
uv venv
|
|
86
|
+
uv pip install -e .
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Commands & Usage
|
|
92
|
+
|
|
93
|
+
### 1. Environment & Skill Audit (`pre-check`)
|
|
94
|
+
```bash
|
|
95
|
+
# Run visual audit of GCP credentials, MCP tools, and intent skills
|
|
96
|
+
demo-create pre-check
|
|
97
|
+
|
|
98
|
+
# Automatically install missing MCP configs and symlink skills into intent subfolders
|
|
99
|
+
demo-create pre-check --fix
|
|
100
|
+
|
|
101
|
+
# Emit raw JSON report for programmatic agent consumption
|
|
102
|
+
demo-create pre-check --json
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 2. End-to-End Demo Creation (`run`)
|
|
106
|
+
```bash
|
|
107
|
+
# Interactive wizard
|
|
108
|
+
demo-create run --project=retail_insights --scope=internal
|
|
109
|
+
|
|
110
|
+
# Non-interactive / Agent Mode
|
|
111
|
+
demo-create run \
|
|
112
|
+
--project=logistics_analytics \
|
|
113
|
+
--scope=external \
|
|
114
|
+
--gcp-project=my-analytics-project \
|
|
115
|
+
--gcp-account=user@example.com \
|
|
116
|
+
--agent-mode
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Intent-Based Skill Organization
|
|
122
|
+
|
|
123
|
+
When you run `demo-create pre-check --fix`, skills are organized into `~/.gemini/config/skills/`:
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
~/.gemini/config/skills/
|
|
127
|
+
├── data-design/
|
|
128
|
+
│ ├── data-designer/
|
|
129
|
+
│ ├── data-designer-architect/
|
|
130
|
+
│ ├── data-designer-engineer/
|
|
131
|
+
│ └── data-designer-evaluator/
|
|
132
|
+
├── lookml/
|
|
133
|
+
│ ├── repo-lookml/
|
|
134
|
+
│ ├── lookml-model/
|
|
135
|
+
│ ├── lookml-explore/
|
|
136
|
+
│ ├── lookml-view/
|
|
137
|
+
│ ├── lookml-dashboard/
|
|
138
|
+
│ └── embed-themes/
|
|
139
|
+
└── embed-portal/
|
|
140
|
+
├── setup-embed-demo/
|
|
141
|
+
├── customize-frontend/
|
|
142
|
+
├── customize-frontend-branding/
|
|
143
|
+
├── customize-frontend-theme/
|
|
144
|
+
└── sso-embed/
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
This guarantees that any Jetski agent in any directory can discover and execute Looker demo workflows.
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Annotated, Optional
|
|
6
|
+
import typer
|
|
7
|
+
from rich.table import Table
|
|
8
|
+
|
|
9
|
+
from looker_demo_cli.config import (
|
|
10
|
+
DEFAULT_GCP_PROJECT,
|
|
11
|
+
DEFAULT_LOOKER_INSTANCE_URL,
|
|
12
|
+
GEMINI_MCP_CONFIG,
|
|
13
|
+
GEMINI_SKILLS_DIR,
|
|
14
|
+
)
|
|
15
|
+
from looker_demo_cli.precheck.gcp_auth import inspect_gcp_accounts, list_available_gcp_projects
|
|
16
|
+
from looker_demo_cli.precheck.looker_auth import check_looker_auth
|
|
17
|
+
from looker_demo_cli.precheck.mcp_checker import check_mcp_servers, patch_mcp_config
|
|
18
|
+
from looker_demo_cli.precheck.skills_organizer import audit_and_organize_skills
|
|
19
|
+
from looker_demo_cli.utils.console import (
|
|
20
|
+
console,
|
|
21
|
+
print_banner,
|
|
22
|
+
print_error,
|
|
23
|
+
print_info,
|
|
24
|
+
print_step_header,
|
|
25
|
+
print_success,
|
|
26
|
+
print_warning,
|
|
27
|
+
)
|
|
28
|
+
from looker_demo_cli.workflow.runner import FlowRunner
|
|
29
|
+
from looker_demo_cli.workflow.state import FlowState
|
|
30
|
+
|
|
31
|
+
app = typer.Typer(
|
|
32
|
+
name="demo-create",
|
|
33
|
+
help="End-to-end Looker demo creation orchestrator CLI for AI agents and developers.",
|
|
34
|
+
no_args_is_help=True,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@app.command(name="pre-check")
|
|
39
|
+
def pre_check(
|
|
40
|
+
fix: Annotated[bool, typer.Option("--fix", help="Automatically install missing MCP configs and organize global skills")] = False,
|
|
41
|
+
output_json: Annotated[bool, typer.Option("--json", help="Emit raw JSON status report for agent programmatic consumption")] = False,
|
|
42
|
+
gcp_project: Annotated[str, typer.Option("--gcp-project", help="Target Google Cloud Project ID")] = DEFAULT_GCP_PROJECT,
|
|
43
|
+
):
|
|
44
|
+
"""Inspect and configure GCP/ADC accounts, MCP server definitions, and intent-based skill subfolders."""
|
|
45
|
+
if not output_json:
|
|
46
|
+
print_banner("PRE-CHECK: ENVIRONMENT, MCP & SKILL AUDIT", f"Target GCP Project: {gcp_project}")
|
|
47
|
+
|
|
48
|
+
# 1. Inspect GCP & ADC
|
|
49
|
+
gcp_accounts = inspect_gcp_accounts(target_project=gcp_project)
|
|
50
|
+
|
|
51
|
+
# 2. Query available GCP projects
|
|
52
|
+
available_projects = list_available_gcp_projects()
|
|
53
|
+
|
|
54
|
+
# 3. Check MCP Servers
|
|
55
|
+
mcp_statuses = check_mcp_servers()
|
|
56
|
+
if fix:
|
|
57
|
+
patch_mcp_config()
|
|
58
|
+
mcp_statuses = check_mcp_servers()
|
|
59
|
+
|
|
60
|
+
# 4. Organize Skills
|
|
61
|
+
skill_statuses = audit_and_organize_skills(fix=fix)
|
|
62
|
+
|
|
63
|
+
# 5. Check Looker Auth
|
|
64
|
+
looker_status = check_looker_auth()
|
|
65
|
+
|
|
66
|
+
# Determine if re-auth is needed
|
|
67
|
+
reauth_required = any(
|
|
68
|
+
(a.is_active and not a.has_bigquery_access) or ("reauth" in (a.error_message or "").lower())
|
|
69
|
+
for a in gcp_accounts
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
if output_json:
|
|
73
|
+
report = {
|
|
74
|
+
"gcp_accounts": [a.model_dump() for a in gcp_accounts],
|
|
75
|
+
"available_gcp_projects": available_projects,
|
|
76
|
+
"reauth_required": reauth_required,
|
|
77
|
+
"mcp_servers": [m.model_dump() for m in mcp_statuses],
|
|
78
|
+
"skills": [s.model_dump() for s in skill_statuses],
|
|
79
|
+
"looker_auth": looker_status.model_dump(),
|
|
80
|
+
"agent_instructions": {
|
|
81
|
+
"reauth_action": "If reauth_required is true, prompt the user to run 'gcloud auth login' and 'gcloud auth application-default login'.",
|
|
82
|
+
"project_confirmation": "Prompt the user to select or confirm their target GCP project from available_gcp_projects before proceeding.",
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
typer.echo(json.dumps(report, indent=2))
|
|
86
|
+
return
|
|
87
|
+
|
|
88
|
+
# Render Visual Summary
|
|
89
|
+
console.print("\n[bold cyan]1. GCP & ADC Credentials[/bold cyan]")
|
|
90
|
+
t_gcp = Table(show_header=True, header_style="bold blue")
|
|
91
|
+
t_gcp.add_column("Account", style="dim")
|
|
92
|
+
t_gcp.add_column("Active in gcloud")
|
|
93
|
+
t_gcp.add_column("BigQuery Access")
|
|
94
|
+
t_gcp.add_column("Notes")
|
|
95
|
+
|
|
96
|
+
for acc in gcp_accounts:
|
|
97
|
+
bq_label = "[green]YES[/green]" if acc.has_bigquery_access else "[red]NO[/red]"
|
|
98
|
+
active_label = "[green]ACTIVE[/green]" if acc.is_active else "[dim]INACTIVE[/dim]"
|
|
99
|
+
t_gcp.add_row(acc.account_id, active_label, bq_label, acc.error_message or "Valid")
|
|
100
|
+
console.print(t_gcp)
|
|
101
|
+
|
|
102
|
+
if reauth_required:
|
|
103
|
+
console.print("\n[bold red]⚠️ GCP Reauthentication Required[/bold red]")
|
|
104
|
+
console.print("[yellow]Agent & User Instruction:[/yellow] One or more active GCP accounts require reauthentication.")
|
|
105
|
+
console.print("Please prompt the user to run the following in their terminal:")
|
|
106
|
+
console.print(" [bold white]$ gcloud auth login[/bold white]")
|
|
107
|
+
console.print(" [bold white]$ gcloud auth application-default login[/bold white]")
|
|
108
|
+
|
|
109
|
+
console.print("\n[bold cyan]2. Available Google Cloud Projects[/bold cyan]")
|
|
110
|
+
if available_projects:
|
|
111
|
+
t_proj = Table(show_header=True, header_style="bold blue")
|
|
112
|
+
t_proj.add_column("Project ID", style="bold")
|
|
113
|
+
t_proj.add_column("Name")
|
|
114
|
+
t_proj.add_column("Project Number", style="dim")
|
|
115
|
+
for p in available_projects:
|
|
116
|
+
t_proj.add_row(p["project_id"], p["name"], p["project_number"])
|
|
117
|
+
console.print(t_proj)
|
|
118
|
+
print_info("Agent Instruction: Confirm with the user which of the available GCP projects above to use for demo synthesis and BigQuery datasets.")
|
|
119
|
+
else:
|
|
120
|
+
print_warning("No Google Cloud projects found or `gcloud projects list` returned empty.")
|
|
121
|
+
|
|
122
|
+
console.print("\n[bold cyan]3. Global MCP Tool Configurations[/bold cyan]")
|
|
123
|
+
t_mcp = Table(show_header=True, header_style="bold blue")
|
|
124
|
+
t_mcp.add_column("MCP Server")
|
|
125
|
+
t_mcp.add_column("Status")
|
|
126
|
+
t_mcp.add_column("Details")
|
|
127
|
+
|
|
128
|
+
for m in mcp_statuses:
|
|
129
|
+
status_label = "[green]CONFIGURED[/green]" if m.is_configured else "[red]MISSING[/red]"
|
|
130
|
+
details = ", ".join(m.issues) if m.issues else "Ready"
|
|
131
|
+
t_mcp.add_row(m.server_name, status_label, details)
|
|
132
|
+
console.print(t_mcp)
|
|
133
|
+
|
|
134
|
+
console.print("\n[bold cyan]4. Intent-Organized Agent Skills (~/.gemini/config/skills/)[/bold cyan]")
|
|
135
|
+
t_skills = Table(show_header=True, header_style="bold blue")
|
|
136
|
+
t_skills.add_column("Intent Category")
|
|
137
|
+
t_skills.add_column("Skill Name")
|
|
138
|
+
t_skills.add_column("Installed")
|
|
139
|
+
t_skills.add_column("Source Found")
|
|
140
|
+
|
|
141
|
+
for s in skill_statuses:
|
|
142
|
+
inst_label = "[green]YES[/green]" if s.is_installed else "[yellow]NO[/yellow]"
|
|
143
|
+
src_label = "[green]YES[/green]" if s.is_valid else "[red]NOT FOUND[/red]"
|
|
144
|
+
t_skills.add_row(s.category, s.skill_name, inst_label, src_label)
|
|
145
|
+
console.print(t_skills)
|
|
146
|
+
|
|
147
|
+
console.print("\n[bold cyan]5. Looker Instance Authentication[/bold cyan]")
|
|
148
|
+
if looker_status.is_authenticated:
|
|
149
|
+
print_success(f"Connected to {looker_status.instance_url} as {looker_status.user_name} ({looker_status.user_email})")
|
|
150
|
+
if looker_status.has_default_bigquery_conn:
|
|
151
|
+
print_success("Database connection `default_bigquery_connection` is configured.")
|
|
152
|
+
else:
|
|
153
|
+
print_warning("Connection `default_bigquery_connection` not found in available connections.")
|
|
154
|
+
else:
|
|
155
|
+
print_error(f"Failed to connect to Looker: {looker_status.error_message}")
|
|
156
|
+
|
|
157
|
+
if not fix and any(not m.is_configured for m in mcp_statuses):
|
|
158
|
+
print_info("\nTip: Run `demo-create pre-check --fix` to automatically repair missing MCP configs and organize skills.")
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@app.command(name="run")
|
|
162
|
+
def run_flow(
|
|
163
|
+
project_name: Annotated[str, typer.Option("--project", help="Looker project and dataset name")] = "logistics_analytics",
|
|
164
|
+
dataset_name: Annotated[Optional[str], typer.Option("--dataset", help="Target BigQuery dataset ID")] = None,
|
|
165
|
+
scope: Annotated[str, typer.Option("--scope", help="Demo scope: internal or external")] = "internal",
|
|
166
|
+
gcp_project: Annotated[str, typer.Option("--gcp-project", help="Target GCP Project ID")] = DEFAULT_GCP_PROJECT,
|
|
167
|
+
gcp_account: Annotated[Optional[str], typer.Option("--gcp-account", help="Specific authenticated GCP user account")] = None,
|
|
168
|
+
scratch_dir: Annotated[Path, typer.Option("--scratch-dir", help="Local scratch work directory")] = Path.home() / "scratch" / "demo_create",
|
|
169
|
+
agent_mode: Annotated[bool, typer.Option("--agent-mode", help="Non-interactive execution mode for AI agents")] = False,
|
|
170
|
+
):
|
|
171
|
+
"""Execute the full deterministic demo creation workflow."""
|
|
172
|
+
ds_name = dataset_name or project_name
|
|
173
|
+
demo_scope_val = "external_embed" if "ext" in scope.lower() else "internal_looker"
|
|
174
|
+
|
|
175
|
+
state = FlowState(
|
|
176
|
+
gcp_project_id=gcp_project,
|
|
177
|
+
gcp_account=gcp_account,
|
|
178
|
+
looker_project_name=project_name,
|
|
179
|
+
lookml_model_name=project_name,
|
|
180
|
+
bq_dataset_id=ds_name,
|
|
181
|
+
demo_scope=demo_scope_val,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
runner = FlowRunner(
|
|
185
|
+
state=state,
|
|
186
|
+
scratch_dir=scratch_dir,
|
|
187
|
+
target_base_dir=Path.home(),
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
final_state = runner.run()
|
|
191
|
+
if final_state.status == "completed":
|
|
192
|
+
print_success("\nDemo creation finished successfully!")
|
|
193
|
+
if final_state.deployed_dashboard_url:
|
|
194
|
+
print_info(f"Dashboard URL: {final_state.deployed_dashboard_url}")
|
|
195
|
+
if final_state.embed_workspace_dir:
|
|
196
|
+
print_info(f"Embed Workspace: {final_state.embed_workspace_dir}")
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
@app.command(name="skills")
|
|
200
|
+
def list_skills(
|
|
201
|
+
fix: Annotated[bool, typer.Option("--fix", help="Symlink and organize skills into intent subfolders")] = False,
|
|
202
|
+
):
|
|
203
|
+
"""View and manage intent-based global agent skills."""
|
|
204
|
+
statuses = audit_and_organize_skills(fix=fix)
|
|
205
|
+
print_success(f"Organized {len(statuses)} skills across intent categories into {GEMINI_SKILLS_DIR}")
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
if __name__ == "__main__":
|
|
209
|
+
app()
|