Skip to content

Commit

Permalink
feat: full edx-platform setup with tutor dev launch -m ...
Browse files Browse the repository at this point in the history
Before this commit, setting up an edx-platform development environment
took multiple steps:

  tutor dev launch
  tutor dev run --mount=/path/to/edx-platform lms bash
  >> pip install -e .
  >> npm clean-install
  >> openedx-assets build --env=dev

This commit moves the steps under ``run`` into an init task, which
is automatically run by ``launch``. Thus, setup is now one command:

  tutor dev launch --mount=edx-platform

These extra init steps are only applicable when bind-mounting
edx-platform (because bind-mounting the repository overrides
some important artifacts that exist on the image, which must be
re-generated). Thus, the new init tasks exists early if it detects
that it is *not* operating on a bind-mounted repository.

Finally, we try to simplify the Open edX development docs so that
it is clearer how bind-mounting fits into the development process.

Part of: openedx-unsupported/wg-developer-experience#146
Closes: openedx-unsupported/wg-developer-experience#152

This works around (but does not close) these related issues:
* openedx-unsupported/wg-developer-experience#150
* https://github.com/openedx/wg-developer-experience/issues/151
  • Loading branch information
kdmccormick committed Mar 13, 2023
1 parent 4e7c3ee commit 9be70cc
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 48 deletions.
1 change: 1 addition & 0 deletions changelog.d/20230313_110919_kdmc_mounted_init.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- [Improvement] Running ``tutor dev launch --mount=edx-platform`` now performs all necessary setup for a local edx-platform development. This includes running setup.py, installing node modules, and building assets; previously, those steps had to be run explicitly after bind-mounting a local copy of edx-platform (by @kdmccormick).
101 changes: 53 additions & 48 deletions docs/dev.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@ Open edX development

In addition to running Open edX in production, Tutor can be used for local development of Open edX. This means that it is possible to hack on Open edX without setting up a Virtual Machine. Essentially, this replaces the devstack provided by edX.

.. _edx_platform_dev_env:

First-time setup
----------------

First, ensure you have already :ref:`installed Tutor <install>` (for development against the named releases of Open edX) or :ref:`Tutor Nightly <nightly>` (for development against Open edX's master branches).

Then, launch the developer platform setup process::
Then, run one of the following in order to launch the developer platform setup process::

# To use the edx-platform repository that is built into the image:
tutor dev launch

# To bind-mount and run your local clone of edx-platform,
# where './edx-platform' should be replaced with your local edx-platform's path:
tutor dev launch --mount=./edx-platform

This will perform several tasks for you. It will:

* stop any existing locally-running Tutor containers,
Expand All @@ -33,12 +39,30 @@ This will perform several tasks for you. It will:

* run service initialization scripts, such as service user creation and Waffle configuration.

Additionally, if you chose to bind-mount your local clone of edx-platform, it will:

* re-run setup.py,

* clean-reinstall Node modules, and

* regenerate static assets.

Once setup is complete, the platform will be running in the background:

* LMS will be accessible at `http://local.overhang.io:8000 <http://local.overhang.io:8000>`_.
* CMS will be accessible at `http://studio.local.overhang.io:8001 <http://studio.local.overhang.io:8001>`_.
* Plugged-in services should be accessible at their documented URLs.

Now, you can use the ``tutor dev ...`` command-line interface to manage your development environment. Some common commands are described below.

.. note::

Wherever you see ``[-m ./edx-platform]``, either:

* omit it, if you are using the edx-platform repository built into the image, or
* substitute it with ``-m <path/to/your/edx-platform>``.

You can :ref:`read more about bind-mounts below <bind_mounts>`.

Stopping the platform
---------------------
Expand All @@ -47,38 +71,55 @@ To bring down your platform's containers, simply run::

tutor dev stop


Starting the platform back up
-----------------------------

Once you have used ``launch`` once, you can start the platform in the future with the lighter-weight ``start`` command, which brings up containers but does not perform any initialization tasks::
Once you have used ``launch`` once, you can start the platform in the future with the lighter-weight ``start -d`` command, which brings up containers detached (i.e., in the background), but does not perform any initialization tasks::

tutor dev start # Run platform in the same terminal ("attached")
tutor dev start -d # Or, run platform the in the background ("detached")
tutor dev start -d [-m ./edx-platform]

Nonetheless, ``launch`` is idempotent, so it is always safe to run it again in the future without risk to your data. In fact, you may find it useful to use this command as a one-stop-shop for pulling images, running migrations, initializing new plugins you have enabled, and/or executing any new initialization steps that may have been introduced since you set up Tutor::

tutor dev launch --pullimages
tutor dev launch [-m ./edx-platform] --pullimages

Attaching to containers
-----------------------

You can run ``start`` without the ``-d`` flag::

tutor dev start [-m ./edx-platform]

If the platform isn't running, this will start it in your terminal. If the platform is already running in the background, this command will stop it, recreate it, and attach your terminal to it. Later, you can stop the platform with ``Ctrl+c``, or detach (without stopping) using ``Ctrl+z``.

Debugging with breakpoints
--------------------------

To debug a local edx-platform repository, you can add a `python breakpoint <https://docs.python.org/3/library/functions.html#breakpoint>`__ with ``breakpoint()`` anywhere in your code. Then, run ``start`` (without ``-d``) and specify the service through which you want to use the breakpoint, for example::

# Debugging LMS:
tutor dev start [-m ./edx-platform] lms

# Or, debugging CMS:
tutor dev start [-m ./edx-platform] cms

Running arbitrary commands
--------------------------

To run any command inside one of the containers, run ``tutor dev run [OPTIONS] SERVICE [COMMAND] [ARGS]...``. For instance, to open a bash shell in the LMS or CMS containers::

tutor dev run lms bash
tutor dev run cms bash
tutor dev run [-m ./edx-platform] lms bash
tutor dev run [-m ./edx-platform] cms bash

To open a python shell in the LMS or CMS, run::

tutor dev run lms ./manage.py lms shell
tutor dev run cms ./manage.py cms shell
tutor dev run [-m ./edx-platform] lms ./manage.py lms shell
tutor dev run [-m ./edx-platfomr] cms ./manage.py cms shell

You can then import edx-platform and django modules and execute python code.

To collect assets, you can use the ``openedx-assets`` command that ships with Tutor::
To rebuild assets, you can use the ``openedx-assets`` command that ships with Tutor::

tutor dev run lms openedx-assets build --env=dev
tutor dev run [-m ./edx-platform] lms openedx-assets build --env=dev


.. _specialized for developer usage:
Expand Down Expand Up @@ -193,42 +234,6 @@ This override file will be loaded when running any ``tutor dev ..`` command. The
Common tasks
------------

.. _edx_platform_dev_env:

Setting up a development environment for edx-platform
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Following the instructions :ref:`above <bind_mounts>` on how to bind-mount directories from the host above, you may mount your own `edx-platform <https://github.com/openedx/edx-platform/>`__ fork in your containers by running::

tutor dev start -d --mount=/path/to/edx-platform lms

But to achieve that, you will have to make sure that your fork works with Tutor.

First of all, you should make sure that you are working off the latest release tag (unless you are running the Tutor :ref:`nightly <nightly>` branch). See the :ref:`fork edx-platform section <edx_platform_fork>` for more information.

Then, you should run the following commands::

# Run bash in the lms container
tutor dev run --mount=/path/to/edx-platform lms bash

# Compile local python requirements
pip install --requirement requirements/edx/development.txt

# Install nodejs packages in node_modules/
npm clean-install

# Rebuild static assets
openedx-assets build --env=dev

After running all these commands, your edx-platform repository will be ready for local development. To debug a local edx-platform repository, you can then add a `python breakpoint <https://docs.python.org/3/library/functions.html#breakpoint>`__ with ``breakpoint()`` anywhere in your code and run::

tutor dev start --mount=/path/to/edx-platform lms

The default debugger is ``ipdb.set_trace``. ``PYTHONBREAKPOINT`` can be modified by setting an environment variable in the Docker imamge.

If LMS isn't running, this will start it in your terminal. If an LMS container is already running background, this command will stop it, recreate it, and attach your terminal to it. Later, to detach your terminal without stopping the container, just hit ``Ctrl+z``.


XBlock and edx-platform plugin development
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
10 changes: 10 additions & 0 deletions tutor/commands/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from tutor import config as tutor_config
from tutor import env, fmt, hooks
from tutor.hooks import priorities


class DoGroup(click.Group):
Expand Down Expand Up @@ -40,6 +41,15 @@ def _add_core_init_tasks() -> None:
("mysql", env.read_core_template_file("jobs", "init", "mysql.sh"))
)
with hooks.Contexts.APP("lms").enter():
hooks.Filters.CLI_DO_INIT_TASKS.add_item(
(
"lms",
env.read_core_template_file("jobs", "init", "mounted-edx-platform.sh"),
),
# If edx-platform is mounted, then we may need to perform some setup
# before other initialization scripts can be run.
priority=priorities.HIGH,
)
hooks.Filters.CLI_DO_INIT_TASKS.add_item(
("lms", env.read_core_template_file("jobs", "init", "lms.sh"))
)
Expand Down
7 changes: 7 additions & 0 deletions tutor/templates/build/openedx/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,13 @@ RUN openedx-assets themes \
# Create a data directory, which might be used (or not)
RUN mkdir /openedx/data

# If this "canary" file is missing from a container, then that indicates that a
# local edx-platform was bind-mounted into that container, thus overwriting the
# canary. This information is useful during edx-platform initialisation.
RUN echo \
"This copy of edx-platform was built into a Docker image." \
> bindmount-canary

# service variant is "lms" or "cms"
ENV SERVICE_VARIANT lms
ENV DJANGO_SETTINGS_MODULE lms.envs.tutor.production
Expand Down
21 changes: 21 additions & 0 deletions tutor/templates/jobs/init/mounted-edx-platform.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# When a new local copy of edx-platform is bind-mounted, certain build
# artifacts from the openedx image's edx-platform directory are lost.
# We regenerate them here.

if [[ -f /openedx/edx-platform/bindmount-canary ]] ; then
# If this file exists, then edx-platform has not
# been bind mounted. That is: we are running edx-platform
# from the openedx image. Thus, it is safe to skip the k
# regeneration steps below.
exit
fi

# Regenerate Open_edX.egg-info
pip install -e .

# Regenerate node_modules
npm clean-install

# Regenerate static assets.
openedx-assets build --env=dev

0 comments on commit 9be70cc

Please sign in to comment.