Skip to content
This repository was archived by the owner on Jun 30, 2024. It is now read-only.

Commit 926b023

Browse files
committed
Fix: auto-edit .env based on the build type.
Links development-only files only in dev mode. Docs: Improve docs on .env.prototype
1 parent fa51e8c commit 926b023

2 files changed

Lines changed: 32 additions & 15 deletions

File tree

docker/.env.prototype

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
RUNESTONE_HOST=localhost
88

99
# Select a configuration for the instructor-facing server (the Runestone server) and the student-facing server (BookServer). Valid values are ``test``, ``development``, and ``production``.
10-
SERVER_CONFIG=development
10+
SERVER_CONFIG=${SERVER_CONFIG}
1111

1212
# For production, change the credentials for the DB to something more secure.
1313
# This should be done prior to first running ``docker/docker_tools.py up``.
@@ -21,9 +21,9 @@ POSTGRES_HOST=db
2121
#
2222
# An admin password is required to log in to the admin interface when using HTTPS.
2323
WEB2PY_ADMIN_PASSWORD=your_password_here
24-
# To generate a new salt value, run ``cd $WEB2PY_PATH; python -c "from gluon.utils import web2py_uuid; print(f'sha512:{web2py_uuid()}')"`` in Docker, then paste the displayed value here. (Adapted from web2py's ``Auth.get_or_create_key`` in ``gluon/tools.py``; see also `web2py authentication <http://web2py.com/books/default/chapter/29/09/access-control#Authentication>`_.)
24+
# You **must** generate a new salt value; the value here IS NOT SECURE. To generate a new salt value, run ``cd $WEB2PY_PATH; python -c "from gluon.utils import web2py_uuid; print(f'sha512:{web2py_uuid()}')"`` in Docker, then paste the displayed value here. (Adapted from web2py's ``Auth.get_or_create_key`` in ``gluon/tools.py``; see also `web2py authentication <http://web2py.com/books/default/chapter/29/09/access-control#Authentication>`_.)
2525
WEB2PY_SALT=sha512:16492eda-ba33-48d4-8748-98d9bbdf8d33
26-
# To generate a new secret, run ``python -c "import secrets; print(secrets.token_urlsafe(16))"``.
26+
# You **must** generate a new secret; the value here IS NOT SECURE. To generate a new secret, run ``python -c "import secrets; print(secrets.token_urlsafe(16))"``.
2727
JWT_SECRET=WT2epQY9p_7HmGVLyRTw5g
2828
# If you support books that students must pay to access, provide Stripe keys.
2929
# STRIPE_PUBLISHABLE_KEY = pk_live_xxx

docker/docker_tools.py

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -533,9 +533,22 @@ def _build_phase_0(
533533
clone_bks = clone_all
534534
clone_rc = clone_all
535535

536-
# Create the ``docker/.env`` if it doesn't already exist. TODO: keep a dict of {file name, checksum} and save as JSON. Use this to detect if a file was hand-edited; if not, we can simply replace it.
537-
if not Path(".env").is_file():
538-
xqt("cp docker/.env.prototype .env")
536+
# Create ``docker/.env`` if it doesn't already exist or wasn't edited.
537+
dot_env = Path(".env")
538+
if not dot_env.is_file() or not subprocess.run(["md5sum", "--check", ".env.md5"]).returncode:
539+
# Edit the prototype file, providing the correct value of ``SERVER_CONFIG``.
540+
dot_env.write_text(
541+
replace_vars(
542+
Path("docker/.env.prototype").read_text(),
543+
dict(
544+
SERVER_CONFIG="development"
545+
if build_config.is_dev()
546+
else "production"
547+
),
548+
)
549+
)
550+
# Save a checksum, so we can auto-update this if no hand edits were made.
551+
xqt("md5sum .env > .env.md5")
539552

540553
# Do the same for ``1.py``.
541554
one_py = Path("models/1.py")
@@ -850,6 +863,7 @@ def _build_phase_1(
850863
# ^^^^^^^^^^^^^^^^^^^
851864
xqt(
852865
"mkdir -p $WEB2PY_PATH/logs",
866+
"mkdir -p $WEB2PY_PATH/errors",
853867
"cp $RUNESTONE_PATH/docker/wsgihandler.py $WEB2PY_PATH/wsgihandler.py",
854868
# Set up nginx (partially -- more in step 3 below).
855869
"rm /etc/nginx/sites-enabled/default",
@@ -867,15 +881,18 @@ def _build_phase_1(
867881
"cp $RUNESTONE_PATH/docker/routes.py $WEB2PY_PATH",
868882
# ``sphinxcontrib.paverutils.run_sphinx`` lacks venv support -- it doesn't use ``sys.executable``, so it doesn't find ``sphinx-build`` in the system path when executing ``/srv/venv/bin/runestone`` directly, instead of activating the venv first (where it does work). As a huge, ugly hack, symlink it to make it available in the system path.
869883
"ln -sf $RUNESTONE_PATH/.venv/bin/sphinx-build /usr/local/bin",
870-
# Deal with a different subdirectory layout inside the container (mandated by web2py) and outside the container by adding these symlinks.
871-
# TODO: should only do this in dev
872-
"ln -sf $BOOK_SERVER_PATH $WEB2PY_PATH/applications/BookServer",
873-
# We can't use ``$BOOK_SERVER_PATH`` here, since we need ``/srv/bookserver-dev`` in lowercase, not CamelCase.
874-
"ln -sf /srv/bookserver-dev $WEB2PY_PATH/applications/bookserver-dev",
875-
"ln -sf /srv/RunestoneComponents $WEB2PY_PATH/applications/RunestoneComponents",
876-
"ln -sf /srv/runestone-dev $WEB2PY_PATH/applications/runestone-dev",
877884
)
878885

886+
if build_config.is_dev():
887+
xqt(
888+
# Deal with a different subdirectory layout inside the container (mandated by web2py) and outside the container by adding these symlinks.
889+
"ln -sf $BOOK_SERVER_PATH $WEB2PY_PATH/applications/BookServer",
890+
# We can't use ``$BOOK_SERVER_PATH`` here, since we need ``/srv/bookserver-dev`` in lowercase, not CamelCase.
891+
"ln -sf /srv/bookserver-dev $WEB2PY_PATH/applications/bookserver-dev",
892+
"ln -sf /srv/RunestoneComponents $WEB2PY_PATH/applications/RunestoneComponents",
893+
"ln -sf /srv/runestone-dev $WEB2PY_PATH/applications/runestone-dev",
894+
)
895+
879896
# Record info about this build. We can't provide ``git`` info, since the repo isn't available (the ``${RUNSTONE_PATH}.git`` directory is hidden, so it's not present at this time). Likewise, volumes aren't mapped, so ``git`` info for the Runestone Components and BookServer isn't available.
880897
Path("/srv/build_info.txt").write_text(
881898
f"Built on {datetime.datetime.now(datetime.timezone.utc)} using arguments {env.DOCKER_BUILD_ARGS}.\n"
@@ -1076,7 +1093,7 @@ def _build_phase_2_core(
10761093

10771094
# Utilities
10781095
# =========
1079-
# A utility to replace all instances of ``${var_name}`` in a string, where the variables are provided in ``vars_``. This is an alternative to the build-in ``str.format()`` which doesn't require escaping all the curly braces.
1096+
# A utility to replace all instances of ``${var_name}`` in a string, where the variables are provided in ``vars_``. This is an alternative to the built-in ``str.format()`` which doesn't require escaping all the curly braces.
10801097
def replace_vars(str_: str, vars_: Dict[str, str]) -> str:
10811098
def repl(matchobj: re.Match):
10821099
var_name = matchobj.group(1)
@@ -1095,7 +1112,7 @@ def repl(matchobj: re.Match):
10951112

10961113
# Run Poetry and associated tools.
10971114
def run_poetry(is_dev: bool):
1098-
no_dev_arg = "" if is_dev else " --no-dev"
1115+
no_dev_arg = "" if is_dev else " --only main"
10991116
xqt(
11001117
# Update dependencies. See `scripts/poetry_fix.py`. This must come before Poetry, since it will check for the existence of the project created by these commands. (Even calling ``poetry config`` will perform this check!)
11011118
f"{sys.executable} -m pip install --user toml",

0 commit comments

Comments
 (0)