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

Commit e096920

Browse files
committed
Merge branch 'master' of github.com:RunestoneInteractive/RunestoneServer
2 parents 6e49305 + 1cf06b1 commit e096920

File tree

5 files changed

+60
-63
lines changed

5 files changed

+60
-63
lines changed

.github/workflows/python-app.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ jobs:
3535
id: docker-up
3636
run: |
3737
cd RunestoneServer
38-
docker-compose up -d
39-
docker-compose logs --follow &
38+
docker compose up -d
39+
docker compose logs --follow &
4040
# Wait for the container to start and create a basic venv before running docker tools inside it.
4141
sleep 5
4242
# Invoke this directly, since the ``docker-tools`` script isn't installed yet. After this finishes, the docker tools are installed.
43-
docker exec -t runestoneserver_runestone_1 bash -c "\$RUNESTONE_PATH/.venv/bin/python \$RUNESTONE_PATH/docker/docker_tools.py wait"
43+
docker exec -t runestoneserver-runestone-1 bash -c "\$RUNESTONE_PATH/.venv/bin/python \$RUNESTONE_PATH/docker/docker_tools.py wait"
4444
- name: Test
4545
id: pytest
4646
run: |

docker/README.rst

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -206,23 +206,23 @@ For the use case of running the server, you will need to modify these settings t
206206

207207
Pre-start
208208
^^^^^^^^^
209-
Once your environment is ready to go, you can use ``docker-compose`` to bring the containers up. This command will create four containers to run different parts of the application stack (the Runestone server, redis cache, postgres DB, jobe code testing environment).
209+
Once your environment is ready to go, you can use ``docker compose`` to bring the containers up. This command will create four containers to run different parts of the application stack (the Runestone server, redis cache, postgres DB, jobe code testing environment).
210210

211211
For the use case of running the server, execute:
212212

213213
.. code-block:: bash
214214
215-
docker-compose up -d
215+
docker compose up -d
216216
217-
This run the container in the background (detached mode). Use ``docker-compose logs --follow`` to view logging data as the container starts up and runs.
217+
This run the container in the background (detached mode). Use ``docker compose logs --follow`` to view logging data as the container starts up and runs.
218218

219219
**OR**
220220

221221
For the developer use case, execute:
222222

223223
.. code-block:: bash
224224
225-
docker-compose up
225+
docker compose up
226226
227227
This displays logging data from the container in the terminal. To Stop the container, press when ctrl-c.
228228

@@ -254,11 +254,11 @@ No books are installed by default; you must add books using the following proces
254254
255255
rsmanage build --course thinkcspy --clone https://github.com/RunestoneInteractive/thinkcspy.git
256256
257+
After cloning a book, you may need to add it to the database. Most of the standard books are already there, but you can use ``rsmanage addcourse`` to add it if needed.
257258

258259
.. note::
259260

260-
TODO: Edit/improve the docs from this point forward.
261-
261+
PreTeXt authors, see `Publishing to Runestone Academy <https://pretextbook.org/doc/guide/html/sec-publishing-to-runestone-academy.html>`_. The following information applies only *authoring* books using the Runestone.
262262

263263
.. warning::
264264

@@ -268,8 +268,6 @@ No books are installed by default; you must add books using the following proces
268268
If there is a mismatch, you will want to rename the folder you cloned the code into so that it
269269
matches the ``project_name``.
270270

271-
After cloning a book, you may need to add it to the database. Most of the standard books are already there, but you can use ``rsmanage addcourse`` to add it if needed.
272-
273271
.. note::
274272

275273
Most Runestone books set ``master_url`` to ``get_master_url()`` in their ``pavement.py`` file. However, if the book
@@ -349,7 +347,7 @@ trying to load the same records and entering a restart loop because the records
349347

350348
Operation
351349
---------
352-
The containerized application is configured to automatically start as soon as Docker / the Docker Desktop is started. Therefore, on OS X or Windows (when using WSL2): after a reboot or after manually shutting down the Docker Desktop, remember to start the Docker Desktop application.
350+
The containerized application is configured to automatically start as soon as Docker / the Docker Desktop is started. Therefore, on OS X or Windows (when using WSL2): after a reboot or after manually shutting down the Docker Desktop, **remember to start the Docker Desktop application**.
353351

354352

355353
Other Tips & Tricks
@@ -423,12 +421,12 @@ Testing the Entrypoint
423421
**********************************
424422

425423
If you want to test the script, the easiest thing
426-
to do is add a command to the docker-compose to disable it, and then run commands
424+
to do is add a command to the ``docker compose`` to disable it, and then run commands
427425
interactively by shelling into the container.
428426

429427
Bring up the containers and then shell inside. Once inside, you can then issue commands
430428
to test the entry point script - since the other containers were started
431-
with docker-compose everything in them is ready to go.
429+
with ``docker compose`` everything in them is ready to go.
432430

433431
File Permissions
434432
**********************************
@@ -441,23 +439,17 @@ container enough privileges to do your work.
441439
Writing Your Own Book
442440
**********************************
443441

442+
.. note::
443+
444+
PreTeXt authors, see `Publishing to Runestone Academy <https://pretextbook.org/doc/guide/html/sec-publishing-to-runestone-academy.html>`_. The following information applies only *authoring* books using the Runestone.
445+
444446
If you are writing your own book you will want to get that book set up properly in the Runestone
445447
system. You need to do the following:
446448

447449
#. Run the command ``rsmanage addcourse``. Use the project name you configured in ``pavement.py`` as the name of BOTH the course and the basecourse when it asks.
448450

449451
#. Now that your course is registered, rebuild it using the command ``rsmanage build --course <book_name>`` command.
450452

451-
#. If this book is a PreTeXt book you will need to navigate to the directory that contains the ``runestone-manifest.xml`` file and run the command:
452-
453-
.. code-block:: bash
454-
455-
runestone process-manifest --course <yourcourse> --manifest runestone-manifest.xml
456-
457-
.. note::
458-
459-
If you are missing ``runestone-manifest.xml`` then you need to rebuild your PreTeXt
460-
book with ``runestone`` as the publisher. See the PreTeXt docs for how do do this.
461453

462454
Changing dependencies
463455
*********************

docker/docker_tools.py

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
# Local application bootstrap
6868
# ---------------------------
6969
# Everything after this depends on Unix utilities. We can't use ``is_win`` because we don't know if ``ci_utils`` is available.
70-
if sys.platform == "win32":
70+
if sys.platform == "win32x":
7171
sys.exit("ERROR: You must run this program in WSL/VirtualBox/VMWare/etc.")
7272

7373
# See if we're root.
@@ -180,16 +180,6 @@ def pip_user() -> str:
180180
print("Note: this must be an initial install; additional commands missing.")
181181

182182

183-
# Global variables
184-
# ================
185-
# .. note::
186-
#
187-
# Update these regularly!
188-
#
189-
# See the `Docker compose release page <https://github.com/docker/compose/releases>`_ for the latest version.
190-
DOCKER_COMPOSE_VERSION = "2.29.2"
191-
192-
193183
# CLI
194184
# ===
195185
# Create a series of subcommands for this CLI.
@@ -207,15 +197,6 @@ def cli() -> None:
207197

208198
# ``init`` command
209199
# ================
210-
# Check if we're running in WSL or OS X -- don't install Docker if so.
211-
def check_requires_docker_desktop() -> None:
212-
if (is_linux and "WSL" in Path("/proc/version").read_text()) or is_darwin:
213-
sys.exit(
214-
"ERROR: Docker Desktop not detected. You must install and run this\n"
215-
"before proceeding."
216-
)
217-
218-
219200
@cli.command()
220201
@click.option(
221202
"--clone-rs",
@@ -237,9 +218,16 @@ def init(
237218
try:
238219
xqt("docker --version")
239220
except subprocess.CalledProcessError as e:
240-
check_requires_docker_desktop()
221+
print(f"Unable to run docker: {e}")
222+
# Ensure the Docker Desktop is running if we're running in WSL. On Windows, the ``docker`` command doesn't exist when the Docker Desktop isn't running.
223+
if is_linux and "WSL" in Path("/proc/version").read_text():
224+
sys.exit(
225+
"ERROR: Docker Desktop not detected. You must install and run this\n"
226+
"before proceeding."
227+
)
228+
241229
check_install_curl()
242-
print(f"Unable to run docker: {e} Installing Docker...")
230+
print("Installing Docker...")
243231
# Use the `convenience script <https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script>`_.
244232
xqt(
245233
"curl -fsSL https://get.docker.com -o get-docker.sh",
@@ -253,21 +241,24 @@ def init(
253241
if is_darwin:
254242
xqt("sudo dscl . append /Groups/docker GroupMembership $USER")
255243
else:
256-
xqt("sudo usermod -aG docker ${USER}")
244+
xqt("sudo usermod -a -G docker ${USER}")
257245

258246
# The group add doesn't take effect until the user logs out then back in. Work around it for now.
259247
did_group_add = True
260248

261-
# Ensure docker-compose is installed.
249+
# Ensure the Docker Desktop is running if this is OS X. On OS X, the ``docker`` command exists, but can't run the hello, world script. It also serves as a sanity check for the other platforms.
250+
print("Checking that Docker works...")
262251
try:
263-
xqt("docker-compose --version")
252+
xqt("docker run hello-world")
264253
except subprocess.CalledProcessError as e:
265-
check_requires_docker_desktop()
266-
print(f"Unable to run docker-compose: {e} Installing...")
267-
# This is from the `docker-compose install instructions <https://docs.docker.com/compose/install/#install-compose-on-linux-systems>`_.
268-
xqt(
269-
f'sudo curl -L "https://github.com/docker/compose/releases/download/{DOCKER_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose',
270-
"sudo chmod +x /usr/local/bin/docker-compose",
254+
print(f"Unable to execute docker run hello-world: {e}")
255+
sys.exit(
256+
(
257+
"ERROR: Docker Desktop not detected. You must install and run this\n"
258+
"before proceeding."
259+
)
260+
if is_darwin
261+
else "ERROR: Unable to run a basic Docker application."
271262
)
272263

273264
# Make sure git's installed.
@@ -303,6 +294,7 @@ def init(
303294
if is_darwin:
304295
xqt(
305296
"sudo dscl . create /Groups/www-data",
297+
"sudo dscl . create /Groups/www-data gid 799",
306298
"sudo dseditgroup -o edit -a $USER -t user www-data",
307299
"sudo dscl . append /Groups/www-data GroupMembership $USER",
308300
)

docker/docker_tools_misc.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ def _start_servers(dev: bool) -> None:
8888
xqt(
8989
'sudo -u www-data env "PATH=$PATH" "REDIS_URI=$REDIS_URI" '
9090
"poetry run celery --app=scheduled_builder worker --pool=threads "
91-
"--concurrency=3 --loglevel=info &",
91+
"--concurrency=3 --loglevel=info "
92+
# This redirect ensures output ends up in the Docker log even if the servers are restarted. Sending to ``/dev/stdout`` only works at initial startup, but doesn't redirect after the servers are restarted. For more discussion, see `Github <https://github.com/moby/moby/issues/19616#issuecomment-174355979>`_.
93+
"--logfile=/proc/1/fd/1 &",
9294
cwd=f"{env.RUNESTONE_PATH}/modules",
9395
)
9496

@@ -98,16 +100,16 @@ def _start_servers(dev: bool) -> None:
98100
"--error_path /tmp "
99101
"--gconfig $RUNESTONE_PATH/docker/gunicorn_config/fastapi_config.py "
100102
# This much match the address in `./nginx/sites-available/runestone.template`.
101-
"--bind unix:/run/fastapi.sock "
102-
+ ("--reload " if dev else "")
103-
+ "2>&1 > /proc/1/fd/1 &", # This redirect ensures output ends up in the docker log
103+
f"--bind unix:/run/fastapi.sock {'--reload ' if dev else ''}"
104+
# See previous comment on redirecting output to ``/dev/stdout`` even after server restarts.
105+
+ "2>&1 > /proc/1/fd/1 &",
104106
"service nginx start",
105107
"poetry run gunicorn -D --config $RUNESTONE_PATH/docker/gunicorn_config/web2py_config.py &",
106108
cwd=f"{env.RUNESTONE_PATH}/docker/gunicorn_config",
107109
)
108110

109111
# Start the script to collect tickets and store them in the database. Most useful
110-
# for a production environment with several worker containers
112+
# for a production environment with several worker containers.
111113
xqt(
112114
f"cp {env.RUNESTONE_PATH}/scripts/tickets2db.py {env.WEB2PY_PATH}",
113115
"python web2py.py -M -S runestone --run tickets2db.py &",
@@ -137,6 +139,8 @@ def _stop_servers() -> None:
137139
)
138140

139141

142+
# ``restart_servers``
143+
# -------------------
140144
@click.command()
141145
@click.option(
142146
"--dev/--no-dev",
@@ -152,6 +156,8 @@ def restart_servers(dev):
152156
_start_servers()
153157

154158

159+
# ``reloadbks``
160+
# -------------
155161
@click.command()
156162
def reloadbks() -> None:
157163
"""
@@ -162,7 +168,8 @@ def reloadbks() -> None:
162168
pid = pfile.read().strip()
163169

164170
pid = int(pid)
165-
os.kill(pid, 1) # send the HUP signal to bookserver
171+
# send the HUP signal to the BookServer.
172+
os.kill(pid, 1)
166173

167174

168175
# ``test``
@@ -179,12 +186,17 @@ def reloadbks() -> None:
179186
@click.argument("passthrough", nargs=-1, type=click.UNPROCESSED)
180187
def test(bks: bool, rc: bool, rs: bool, passthrough: Tuple) -> None:
181188
"""
182-
Run unit tests.
189+
Run unit tests. All tests are disabled by default; manually select which test to run.
183190
184191
PASSTHROUGH: These arguments are passed directly to the underlying "pytest" command. To pass options to this command, prefix this argument with "--". For example, use "docker_tools.py test -- -k test_just_this" instead of "docker_tools.py test -k test_just_this" (which produces an error).
185192
186193
"""
187194
ensure_in_docker()
195+
if not bks and not rc and not rs:
196+
sys.exit(
197+
"ERROR: No tests selected to run. Pass any combination of --rs, --rs,\n"
198+
"and/or --bks."
199+
)
188200
_stop_servers()
189201
pytest = "$RUNESTONE_PATH/.venv/bin/pytest"
190202
passthrough_args = " ".join(passthrough)
@@ -261,7 +273,7 @@ def ensure_in_docker(
261273
return True
262274
# Get the name of the container running the Runestone servers.
263275
res = subprocess.run(
264-
'docker ps --filter "ancestor=runestone/server" --format "{{.Names}}"',
276+
'docker ps --filter "ancestor=runestone/server" --format "{{.Names}}"',
265277
shell=True,
266278
capture_output=True,
267279
text=True,

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pathlib2 = "^2.0.0"
3636
Paver = ">= 1.2.4"
3737
# This is actually an rsmanage dependency. It's here so that rsmanage can be installed without installing this, which requires Postgres (available only in the container).
3838
pgcli = "^3.0.0"
39+
pretextbook = "^0.7"
3940
psycopg2-binary = "^2.0.0"
4041
pylint = ">= 1.2.1"
4142
python = "^3.8"

0 commit comments

Comments
 (0)