Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CT-920][CT-1900] Create Click CLI runner and use it to fix dbt docs … #6723

Merged
merged 8 commits into from
Jan 26, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/unreleased/Under the Hood-20230125-041136.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Under the Hood
body: '[CT-920][CT-1900] Create Click CLI runner and use it to fix dbt docs commands'
time: 2023-01-25T04:11:36.57506-08:00
custom:
Author: aranke
Issue: 5544 6722
23 changes: 20 additions & 3 deletions core/dbt/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from dbt.task.compile import CompileTask
from dbt.task.deps import DepsTask
from dbt.task.run import RunTask
from dbt.task.serve import ServeTask
from dbt.task.test import TestTask
from dbt.task.snapshot import SnapshotTask
from dbt.task.seed import SeedTask
Expand Down Expand Up @@ -170,6 +171,7 @@ def docs(ctx, **kwargs):
@p.models
@p.profile
@p.profiles_dir
@p.project_dir
@p.select
@p.selector
@p.state
Expand All @@ -185,7 +187,11 @@ def docs(ctx, **kwargs):
@requires.manifest
def docs_generate(ctx, **kwargs):
"""Generate the documentation website for your project"""
task = GenerateTask(ctx.obj["flags"], ctx.obj["runtime_config"])
task = GenerateTask(
ctx.obj["flags"],
ctx.obj["runtime_config"],
ctx.obj["manifest"],
)

results = task.run()
success = task.interpret_results(results)
Expand All @@ -203,10 +209,21 @@ def docs_generate(ctx, **kwargs):
@p.target
@p.vars
@requires.preflight
@requires.profile
@requires.project
@requires.runtime_config
@requires.manifest
def docs_serve(ctx, **kwargs):
"""Serve the documentation website for your project"""
click.echo(f"`{inspect.stack()[0][3]}` called\n flags: {ctx.obj['flags']}")
return None, True
task = ServeTask(
ctx.obj["flags"],
ctx.obj["runtime_config"],
ctx.obj["manifest"],
)

results = task.run()
success = task.interpret_results(results)
return results, success


# dbt compile
Expand Down
Binary file modified core/dbt/docs/build/doctrees/environment.pickle
Binary file not shown.
46 changes: 14 additions & 32 deletions core/dbt/task/serve.py
Original file line number Diff line number Diff line change
@@ -1,46 +1,28 @@
import shutil
import os
import shutil
import socketserver
import webbrowser

from dbt.include.global_project import DOCS_INDEX_FILE_PATH
from http.server import SimpleHTTPRequestHandler
from socketserver import TCPServer
from dbt.events.functions import fire_event
from dbt.events.types import ServingDocsPort, ServingDocsAccessInfo, ServingDocsExitInfo, EmptyLine

import click

from dbt.include.global_project import DOCS_INDEX_FILE_PATH
from dbt.task.base import ConfiguredTask


class ServeTask(ConfiguredTask):
def run(self):
os.chdir(self.config.target_path)

port = self.args.port
address = "0.0.0.0"

shutil.copyfile(DOCS_INDEX_FILE_PATH, "index.html")

fire_event(ServingDocsPort(address=address, port=port))
fire_event(ServingDocsAccessInfo(port=port))
fire_event(EmptyLine())
fire_event(EmptyLine())
fire_event(ServingDocsExitInfo())

# mypy doesn't think SimpleHTTPRequestHandler is ok here, but it is
httpd = TCPServer( # type: ignore
(address, port), SimpleHTTPRequestHandler # type: ignore
) # type: ignore

if self.args.open_browser:
try:
webbrowser.open_new_tab(f"http://127.0.0.1:{port}")
except webbrowser.Error:
pass
port = self.args.port

try:
httpd.serve_forever() # blocks
finally:
httpd.shutdown()
httpd.server_close()
if self.args.browser:
webbrowser.open_new_tab(f"http://localhost:{port}")

return None
with socketserver.TCPServer(("", port), SimpleHTTPRequestHandler) as httpd:
click.echo(f"Serving docs at {port}")
click.echo(f"To access from your browser, navigate to: http://localhost:{port}")
click.echo("\n\n")
click.echo("Press Ctrl+C to exit.")
Comment on lines +24 to +27
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change makes sense to me. docs serve is CLI-only functionality; it might make more sense to just click.echo, rather than firing a real event.

If we did want these to keep being "real" events / log messages, we could use the Formatting ("FYI") message type that @peterallenwebb added in #6691. I leave it up to your discretion.

In any case, I think we could also just remove the one-off event types that are no longer being used anywhere else in the codebase: ServingDocsPort, ServingDocsAccessInfo, ServingDocsExitInfo

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll keep these click.echo for now, have removed the one-off event types.

httpd.serve_forever()
2 changes: 2 additions & 0 deletions tests/cli/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dbt_packages
.user.yml
Empty file added tests/cli/__init__.py
Empty file.
5 changes: 5 additions & 0 deletions tests/cli/dbt_project.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: jaffle_shop
profile: jaffle_shop
version: '0.1.0'
config-version: 2
clean-targets: [target, dbt_packages, logs]
aranke marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions tests/cli/models/sample_model.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
select * from {{ ref('sample_seed') }}
13 changes: 13 additions & 0 deletions tests/cli/models/schema.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: 2
models:
- name: sample_model
columns:
- name: sample_num
tests:
- accepted_values:
values: [1, 2]
- not_null
- name: sample_bool
tests:
- not_null
- unique
3 changes: 3 additions & 0 deletions tests/cli/packages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
packages:
- package: dbt-labs/dbt_utils
version: 1.0.0
11 changes: 11 additions & 0 deletions tests/cli/profiles.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
jaffle_shop:
aranke marked this conversation as resolved.
Show resolved Hide resolved
outputs:
dev:
type: postgres
database: postgres
schema: jaffle_shop
host: localhost
user: root
port: 5432
password: password
target: dev
4 changes: 4 additions & 0 deletions tests/cli/seeds/sample_seed.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
sample_num,sample_bool
1,true
2,false
,true
15 changes: 15 additions & 0 deletions tests/cli/snapshots/sample_snapshot.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{% snapshot orders_snapshot %}

{{
config(
target_database='postgres',
target_schema='snapshots',
unique_key='sample_num',
strategy='timestamp',
updated_at='updated_at',
)
}}

select * from {{ ref('sample_model') }}

{% endsnapshot %}
33 changes: 33 additions & 0 deletions tests/cli/test_cli_run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from click.testing import CliRunner

from dbt.cli.main import cli


def test_build():
runner = CliRunner()
clean_result = runner.invoke(cli, ['clean'])
assert 'target' in clean_result.output
assert 'dbt_packages' in clean_result.output
assert 'logs' in clean_result.output

deps_result = runner.invoke(cli, ['deps'])
assert 'dbt-labs/dbt_utils' in deps_result.output
assert '1.0.0' in deps_result.output

ls_result = runner.invoke(cli, ['ls'])
assert '1 seed' in ls_result.output
assert '1 model' in ls_result.output
assert '4 tests' in ls_result.output
assert '1 snapshot' in ls_result.output

build_result = runner.invoke(cli, ['build'])
# 1 seed, 1 model, 2 tests
assert 'PASS=4' in build_result.output
# 2 tests
assert 'ERROR=2' in build_result.output
# 1 snapshot
assert 'SKIP=1' in build_result.output

docs_generate_result = runner.invoke(cli, ['docs', 'generate'])
assert 'Building catalog' in docs_generate_result.output
assert 'Catalog written' in docs_generate_result.output