--version-note for datasette, datasette publish and datasette package

This is a relatively obscure new command-line argument that helps solve the
problem of showing accurate version information in deployed instances of
Datasette even if they were deployed directly from source code.

You can pass --version-note to datasette publish and package and it will then
in turn be passed to datasette when it starts:

    datasette --version-note=hello fixtures.db

Now if you visit /-/versions.json you will see this:

    {
        "datasette": {
            "note": "hello",
            "version": "0+unknown"
        },
        "python": {
            "full": "3.6.5 (default, Jun  6 2018, 19:19:24) \n[GCC 6.3.0 20170516]",
            "version": "3.6.5"
        },
        ...
    }

I plan to use this in some Travis CI configuration, refs #313
This commit is contained in:
Simon Willison 2018-06-17 13:14:55 -07:00
commit db1e6bc182
No known key found for this signature in database
GPG key ID: 17E2DEA2588B7F52
5 changed files with 24 additions and 3 deletions

View file

@ -181,6 +181,7 @@ This will create a docker image containing both the datasette application and th
files files
--install TEXT Additional packages (e.g. plugins) to install --install TEXT Additional packages (e.g. plugins) to install
--spatialite Enable SpatialLite extension --spatialite Enable SpatialLite extension
--version-note TEXT Additional note to show on /-/versions
--title TEXT Title for metadata --title TEXT Title for metadata
--license TEXT License label for metadata --license TEXT License label for metadata
--license_url TEXT License URL for metadata --license_url TEXT License URL for metadata
@ -209,6 +210,7 @@ If you have docker installed you can use `datasette package` to create a new Doc
files files
--install TEXT Additional packages (e.g. plugins) to install --install TEXT Additional packages (e.g. plugins) to install
--spatialite Enable SpatialLite extension --spatialite Enable SpatialLite extension
--version-note TEXT Additional note to show on /-/versions
--title TEXT Title for metadata --title TEXT Title for metadata
--license TEXT License label for metadata --license TEXT License label for metadata
--license_url TEXT License URL for metadata --license_url TEXT License URL for metadata

View file

@ -119,6 +119,7 @@ class Datasette:
plugins_dir=None, plugins_dir=None,
static_mounts=None, static_mounts=None,
config=None, config=None,
version_note=None,
): ):
self.files = files self.files = files
self.cache_headers = cache_headers self.cache_headers = cache_headers
@ -131,6 +132,7 @@ class Datasette:
self.plugins_dir = plugins_dir self.plugins_dir = plugins_dir
self.static_mounts = static_mounts or [] self.static_mounts = static_mounts or []
self.config = dict(DEFAULT_CONFIG, **(config or {})) self.config = dict(DEFAULT_CONFIG, **(config or {}))
self.version_note = version_note
self.executor = futures.ThreadPoolExecutor( self.executor = futures.ThreadPoolExecutor(
max_workers=self.config["num_sql_threads"] max_workers=self.config["num_sql_threads"]
) )
@ -298,12 +300,14 @@ class Datasette:
fts_versions.append(fts) fts_versions.append(fts)
except sqlite3.OperationalError: except sqlite3.OperationalError:
continue continue
datasette_version = {"version": __version__}
if self.version_note:
datasette_version["note"] = self.version_note
return { return {
"python": { "python": {
"version": ".".join(map(str, sys.version_info[:3])), "full": sys.version "version": ".".join(map(str, sys.version_info[:3])), "full": sys.version
}, },
"datasette": {"version": __version__}, "datasette": datasette_version,
"sqlite": { "sqlite": {
"version": sqlite_version, "version": sqlite_version,
"fts_versions": fts_versions, "fts_versions": fts_versions,

View file

@ -136,6 +136,7 @@ def inspect(files, inspect_file, sqlite_extensions):
@click.option( @click.option(
"--spatialite", is_flag=True, help="Enable SpatialLite extension" "--spatialite", is_flag=True, help="Enable SpatialLite extension"
) )
@click.option("--version-note", help="Additional note to show on /-/versions")
@click.option("--title", help="Title for metadata") @click.option("--title", help="Title for metadata")
@click.option("--license", help="License label for metadata") @click.option("--license", help="License label for metadata")
@click.option("--license_url", help="License URL for metadata") @click.option("--license_url", help="License URL for metadata")
@ -155,6 +156,7 @@ def publish(
static, static,
install, install,
spatialite, spatialite,
version_note,
**extra_metadata **extra_metadata
): ):
""" """
@ -200,6 +202,7 @@ def publish(
static, static,
install, install,
spatialite, spatialite,
version_note,
extra_metadata, extra_metadata,
): ):
args = [] args = []
@ -373,6 +376,7 @@ def skeleton(files, metadata, sqlite_extensions):
@click.option( @click.option(
"--spatialite", is_flag=True, help="Enable SpatialLite extension" "--spatialite", is_flag=True, help="Enable SpatialLite extension"
) )
@click.option("--version-note", help="Additional note to show on /-/versions")
@click.option("--title", help="Title for metadata") @click.option("--title", help="Title for metadata")
@click.option("--license", help="License label for metadata") @click.option("--license", help="License label for metadata")
@click.option("--license_url", help="License URL for metadata") @click.option("--license_url", help="License URL for metadata")
@ -389,6 +393,7 @@ def package(
static, static,
install, install,
spatialite, spatialite,
version_note,
**extra_metadata **extra_metadata
): ):
"Package specified SQLite files into a new datasette Docker container" "Package specified SQLite files into a new datasette Docker container"
@ -412,6 +417,7 @@ def package(
static, static,
install, install,
spatialite, spatialite,
version_note,
extra_metadata, extra_metadata,
): ):
args = ["docker", "build"] args = ["docker", "build"]
@ -478,6 +484,7 @@ def package(
help="Set config option using configname:value datasette.readthedocs.io/en/latest/config.html", help="Set config option using configname:value datasette.readthedocs.io/en/latest/config.html",
multiple=True, multiple=True,
) )
@click.option("--version-note", help="Additional note to show on /-/versions")
@click.option( @click.option(
"--help-config", "--help-config",
is_flag=True, is_flag=True,
@ -497,6 +504,7 @@ def serve(
plugins_dir, plugins_dir,
static, static,
config, config,
version_note,
help_config, help_config,
): ):
"""Serve up specified SQLite database files with a web UI""" """Serve up specified SQLite database files with a web UI"""
@ -538,6 +546,7 @@ def serve(
plugins_dir=plugins_dir, plugins_dir=plugins_dir,
static_mounts=static, static_mounts=static,
config=dict(config), config=dict(config),
version_note=version_note,
) )
# Force initial hashing/table counting # Force initial hashing/table counting
ds.inspect() ds.inspect()

View file

@ -241,7 +241,7 @@ def escape_sqlite(s):
return '[{}]'.format(s) return '[{}]'.format(s)
def make_dockerfile(files, metadata_file, extra_options, branch, template_dir, plugins_dir, static, install, spatialite): def make_dockerfile(files, metadata_file, extra_options, branch, template_dir, plugins_dir, static, install, spatialite, version_note):
cmd = ['"datasette"', '"serve"', '"--host"', '"0.0.0.0"'] cmd = ['"datasette"', '"serve"', '"--host"', '"0.0.0.0"']
cmd.append('"' + '", "'.join(files) + '"') cmd.append('"' + '", "'.join(files) + '"')
cmd.extend(['"--cors"', '"--port"', '"8001"', '"--inspect-file"', '"inspect-data.json"']) cmd.extend(['"--cors"', '"--port"', '"8001"', '"--inspect-file"', '"inspect-data.json"'])
@ -251,6 +251,8 @@ def make_dockerfile(files, metadata_file, extra_options, branch, template_dir, p
cmd.extend(['"--template-dir"', '"templates/"']) cmd.extend(['"--template-dir"', '"templates/"'])
if plugins_dir: if plugins_dir:
cmd.extend(['"--plugins-dir"', '"plugins/"']) cmd.extend(['"--plugins-dir"', '"plugins/"'])
if version_note:
cmd.extend(['"--version-note"', '"{}"'.format(version_note)])
if static: if static:
for mount_point, _ in static: for mount_point, _ in static:
cmd.extend(['"--static"', '"{}:{}"'.format(mount_point, mount_point)]) cmd.extend(['"--static"', '"{}:{}"'.format(mount_point, mount_point)])
@ -293,6 +295,7 @@ def temporary_docker_directory(
static, static,
install, install,
spatialite, spatialite,
version_note,
extra_metadata=None extra_metadata=None
): ):
extra_metadata = extra_metadata or {} extra_metadata = extra_metadata or {}
@ -324,6 +327,7 @@ def temporary_docker_directory(
static, static,
install, install,
spatialite, spatialite,
version_note,
) )
os.chdir(datasette_dir) os.chdir(datasette_dir)
if metadata_content: if metadata_content:

View file

@ -252,6 +252,7 @@ def test_temporary_docker_directory_uses_hard_link():
static=[], static=[],
install=[], install=[],
spatialite=False, spatialite=False,
version_note=None,
) as temp_docker: ) as temp_docker:
hello = os.path.join(temp_docker, 'hello') hello = os.path.join(temp_docker, 'hello')
assert 'world' == open(hello).read() assert 'world' == open(hello).read()
@ -278,6 +279,7 @@ def test_temporary_docker_directory_uses_copy_if_hard_link_fails(mock_link):
static=[], static=[],
install=[], install=[],
spatialite=False, spatialite=False,
version_note=None,
) as temp_docker: ) as temp_docker:
hello = os.path.join(temp_docker, 'hello') hello = os.path.join(temp_docker, 'hello')
assert 'world' == open(hello).read() assert 'world' == open(hello).read()