def test_temporary_docker_directory_quotes_args(): with tempfile.TemporaryDirectory() as td: os.chdir(td) with open("hello", "w") as fp: fp.write("world") with utils.temporary_docker_directory( files=["hello"], name="t", metadata=None, extra_options="--$HOME", branch=None, template_dir=None, plugins_dir=None, static=[], install=[], spatialite=False, version_note="$PWD", secret="secret", ) as temp_docker: df = os.path.join(temp_docker, "Dockerfile") with open(df) as fp: df_contents = fp.read() assert "'$PWD'" in df_contents assert "'--$HOME'" in df_contents assert "ENV DATASETTE_SECRET 'secret'" in df_contents
def test_temporary_docker_directory_uses_copy_if_hard_link_fails(mock_link): # Copy instead if os.link raises OSError (normally due to different device) mock_link.side_effect = OSError with tempfile.TemporaryDirectory() as td: os.chdir(td) open("hello", "w").write("world") # Default usage of this should use symlink with utils.temporary_docker_directory( files=["hello"], name="t", metadata=None, extra_options=None, branch=None, template_dir=None, plugins_dir=None, static=[], install=[], spatialite=False, version_note=None, secret=None, ) as temp_docker: hello = os.path.join(temp_docker, "hello") assert "world" == open(hello).read() # It should be a copy, not a hard link assert 1 == os.stat(hello).st_nlink
def test_temporary_docker_directory_uses_hard_link(): with tempfile.TemporaryDirectory() as td: os.chdir(td) with open("hello", "w") as fp: fp.write("world") # Default usage of this should use symlink with utils.temporary_docker_directory( files=["hello"], name="t", metadata=None, extra_options=None, branch=None, template_dir=None, plugins_dir=None, static=[], install=[], spatialite=False, version_note=None, secret="secret", ) as temp_docker: hello = os.path.join(temp_docker, "hello") with open(hello) as fp: assert "world" == fp.read() # It should be a hard link assert 2 == os.stat(hello).st_nlink
def test_temporary_docker_directory_uses_hard_link(): with tempfile.TemporaryDirectory() as td: os.chdir(td) open('hello', 'w').write('world') # Default usage of this should use symlink with utils.temporary_docker_directory( files=['hello'], name='t', metadata=None, extra_options=None, branch=None, template_dir=None, static=[], ) as temp_docker: hello = os.path.join(temp_docker, 'hello') assert 'world' == open(hello).read() # It should be a hard link assert 2 == os.stat(hello).st_nlink
def test_temporary_docker_directory_uses_copy_if_hard_link_fails(mock_link): # Copy instead if os.link raises OSError (normally due to different device) mock_link.side_effect = OSError with tempfile.TemporaryDirectory() as td: os.chdir(td) open('hello', 'w').write('world') # Default usage of this should use symlink with utils.temporary_docker_directory( files=['hello'], name='t', metadata=None, extra_options=None, branch=None, template_dir=None, static=[], ) as temp_docker: hello = os.path.join(temp_docker, 'hello') assert 'world' == open(hello).read() # It should be a copy, not a hard link assert 1 == os.stat(hello).st_nlink
def fly( files, metadata, extra_options, branch, template_dir, plugins_dir, static, install, plugin_secret, version_note, secret, title, license, license_url, source, source_url, about, about_url, spatialite, app, ): fail_if_publish_binary_not_installed( "flyctl", "Fly", "https://fly.io/docs/getting-started/installing-flyctl/") extra_metadata = { "title": title, "license": license, "license_url": license_url, "source": source, "source_url": source_url, "about": about, "about_url": about_url, } environment_variables = {} if plugin_secret: extra_metadata["plugins"] = {} for plugin_name, plugin_setting, setting_value in plugin_secret: environment_variable = ("{}_{}".format( plugin_name, plugin_setting).upper().replace("-", "_")) environment_variables[environment_variable] = setting_value extra_metadata["plugins"].setdefault(plugin_name, {})[plugin_setting] = { "$env": environment_variable } with temporary_docker_directory( files, app, metadata, extra_options, branch, template_dir, plugins_dir, static, install, spatialite, version_note, secret, extra_metadata, environment_variables, port=8080, ): apps = existing_apps() if app not in apps: # Attempt to create the app result = run(["flyctl", "apps", "create", "--name", app]) if result.returncode: raise click.ClickException( "That app name is not available") else: open("fly.toml", "w").write(FLY_TOML.format(app=app)) # Now deploy it run(["flyctl", "deploy", "--remote-only"])
def _publish_vercel( files, metadata, extra_options, branch, template_dir, plugins_dir, static, install, plugin_secret, version_note, secret, title, license, license_url, source, source_url, about, about_url, token, project, no_prod, debug, public, generate_dir, settings, ): fail_if_publish_binary_not_installed("vercel", "Vercel", "https://vercel.com/download") extra_metadata = { "title": title, "license": license, "license_url": license_url, "source": source, "source_url": source_url, "about": about, "about_url": about_url, } if generate_dir: generate_dir = str(pathlib.Path(generate_dir).resolve()) with temporary_docker_directory( files, "datasette-now-v2", metadata, extra_options, branch, template_dir, plugins_dir, static, install, False, version_note, secret, extra_metadata, port=8080, ): # We don't actually want the Dockerfile os.remove("Dockerfile") open("now.json", "w").write( json.dumps( { "name": project, "version": 2, "builds": [{ "src": "index.py", "use": "@now/python" }], "routes": [{ "src": "(.*)", "dest": "index.py" }], }, indent=4, )) extras = [] if template_dir: extras.append('template_dir="{}"'.format(template_dir)) if plugins_dir: extras.append('plugins_dir="{}"'.format(plugins_dir)) statics = [item[0] for item in static] open("index.py", "w").write( INDEX_PY.format( database_files=json.dumps( [os.path.split(f)[-1] for f in files]), extras=", {}".format(", ".join(extras)) if extras else "", statics=json.dumps(statics), settings=json.dumps(dict(settings) or {}), )) datasette_install = "datasette" if branch: datasette_install = ( "https://github.com/simonw/datasette/archive/{}.zip".format( branch)) open("requirements.txt", "w").write( "\n".join([datasette_install, "pysqlite3-binary"] + list(install))) 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 Vercel, run the following:") click.echo(" cd {}".format(generate_dir), err=True) click.echo(" vercel --prod".format(generate_dir), err=True) else: # Run the deploy with Vercel cmd = ["vercel", "--confirm", "--no-clipboard"] if debug: cmd.append("--debug") if not no_prod: cmd.append("--prod") if public: cmd.append("--public") if token: cmd.extend(["--token", token]) # Add the secret cmd.extend(["--env", "DATASETTE_SECRET={}".format(secret)]) run(cmd)