From e376a4ee1fb86ae53c052147c8c75b2b10a60ef6 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Wed, 8 Apr 2020 19:54:47 -0700 Subject: [PATCH] --generate-dir option, closes #18 --- README.md | 2 ++ datasette_publish_now/__init__.py | 35 ++++++++++++++++++++++++------- tests/test_publish_now.py | 29 +++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7a4052e..3bd5626 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ The `--project` argument is required - it specifies the project name that should * `--debug` enables the Now CLI debug output * `--token` allows you to pass a Now authentication token, rather than needing to first run `now login` to configure the tool * `--public` runs `now --public` to publish the application source code at `/_src` - e.g. https://datasette-public.now.sh/_src +* `--generate-dir` - by default this tool generates a new Now app in a temporary directory, deploys it and then deletes the directory. Use `--generate-dir=my-app` to output the generated application files to a new directory of your choice instead. You can then deploy it by running `now` in that directory. ### Full help @@ -70,5 +71,6 @@ Options: --no-prod Don't deploy directly to production --debug Enable Now CLI debug output --public Publish source with Now CLI --public + --generate-dir DIRECTORY Output generated application files here --help Show this message and exit. ``` diff --git a/datasette_publish_now/__init__.py b/datasette_publish_now/__init__.py index 28153b1..9f3fc7b 100644 --- a/datasette_publish_now/__init__.py +++ b/datasette_publish_now/__init__.py @@ -9,6 +9,7 @@ import json import os import re +import shutil INDEX_PY = """ from datasette.app import Datasette @@ -58,6 +59,11 @@ def publish_subcommand(publish): @click.option( "--public", is_flag=True, help="Publish source with Now CLI --public", ) + @click.option( + "--generate-dir", + type=click.Path(dir_okay=True, file_okay=False), + help="Output generated application files here", + ) def now2( files, metadata, @@ -81,6 +87,7 @@ def now2( no_prod, debug, public, + generate_dir, ): fail_if_publish_binary_not_installed( "now", "Zeit Now", "https://zeit.co/download" @@ -143,11 +150,23 @@ def now2( open("requirements.txt", "w").write( "\n".join([datasette_install] + list(install)) ) - cmd = ["now", "--confirm", "--no-clipboard"] - if debug: - cmd.append("--debug") - if not no_prod: - cmd.append("--prod") - if public: - cmd.append("--public") - run(cmd) + if generate_dir: + # Copy these to the specified directory + shutil.copytree(".", generate_dir) + click.echo( + "Your generated application files have been written to:", err=True + ) + click.echo(" {}\n".format(generate_dir), err=True) + click.echo("To deploy using Zeit Now, run the following:") + click.echo(" cd {}".format(generate_dir), err=True) + click.echo(" now --prod".format(generate_dir), err=True) + else: + # Run the deploy with now + cmd = ["now", "--confirm", "--no-clipboard"] + if debug: + cmd.append("--debug") + if not no_prod: + cmd.append("--prod") + if public: + cmd.append("--public") + run(cmd) diff --git a/tests/test_publish_now.py b/tests/test_publish_now.py index 202c3a1..27d40f4 100644 --- a/tests/test_publish_now.py +++ b/tests/test_publish_now.py @@ -1,6 +1,7 @@ from click.testing import CliRunner from datasette import cli from unittest import mock +import os import pathlib import re import subprocess @@ -64,6 +65,34 @@ def test_publish_now_public(mock_run, mock_which): ) +@mock.patch("shutil.which") +@mock.patch("datasette_publish_now.run") +def test_publish_now_generate(mock_run, mock_which, tmpdir): + mock_which.return_value = True + mock_run.return_value = mock.Mock(0) + runner = CliRunner() + with runner.isolated_filesystem(): + open("test.db", "w").write("data") + result = runner.invoke( + cli.cli, + [ + "publish", + "now2", + "test.db", + "--project", + "foo", + "--public", + "--generate-dir", + tmpdir / "out", + ], + ) + assert result.exit_code == 0 + assert not mock_run.called + # Test that the correct files were generated + filenames = set(os.listdir(tmpdir / "out")) + assert {"requirements.txt", "index.py", "now.json", "test.db"} == filenames + + def test_help_in_readme(request): # Ensure the --help output embedded in the README is up-to-date readme_path = pathlib.Path(__file__).parent.parent / "README.md"