-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JS Extension API #463
JS Extension API #463
Conversation
As mentioned in our chat I think this is a great placeholder and we can fill this with a more widely accepted bridge while working on the bulk of a frontend extension API. Python 3.7 has a new module called
For future compatibility we should base the code the gets the files from specific Redash extensions using the the backport for Python < 3.7. that was released to PyPI as In addition I think the pattern that we should target is that individual Python Redash extensions can ship a
I think copying files from the Python package into the client app directory shouldn't be something we do and maybe we can steal the method pywebpack uses to cross those two worlds. |
41fc6f7
to
de53afe
Compare
@jezdez, I’ve tried your suggestions and there are some things that worked and some didn’t. Here’s a summary: Problem with using
Problem with directly running webpack on the extension packages where they were installed:
Problems with symlinking:
Given the problems above, the latest code I’ve pushed works locally and addresses the following issues:
I also want to point out that Pywebpack also works by copying bundles into the directory where it will be built, so unfortunately I didn’t see any novel ideas that could help us there. Here is the code path to this:
|
ddc55bc
to
de53afe
Compare
5d977f3
to
5133c6b
Compare
@arikfr, as you can see, we're still working through some kinks with how this might work, but I'm cc'ing you early in the process in case you have some insights that we might be missing. Here is a link to where the extension code lives: https://github.com/mozilla/redash-stmo/pull/6/files |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rwc+ ✨
buildscript.py
Outdated
|
||
# Make a directory for extensions and set it as an environment variable | ||
# to be picked up by webpack. | ||
EXTENSIONS_RELATIVE_PATH = "client/app/extensions" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use os.path.join('client', 'app', 'extensions')
instead here for compat reasons and less change for breakage on weird platforms.
buildscript.py
Outdated
# Make a directory for extensions and set it as an environment variable | ||
# to be picked up by webpack. | ||
EXTENSIONS_RELATIVE_PATH = "client/app/extensions" | ||
EXTENSIONS_DIRECTORY = os.path.join(os.getcwd(), EXTENSIONS_RELATIVE_PATH) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Safer is to use os.path.join(os.path.dirname(__file__), EXTENSIONS_RELATIVE_PATH))
in case the buildscript is called from a different working dir.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this still doesn't quite work because os.path.dirname(__file__)
returns /app/bin
where the script lives which is then appended to EXTENSIONS_RELATIVE_PATH
giving /app/bin/client/app/extensions
which isn't what we want either. Perhaps in the Dockerfile
we can do something like ENV ROOT_DIR=/app
and use that environment variable instead in the buildscript. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right, this needs to use the parent dir when we move the file into bin/
:
os.path.join(os.path.dirname(os.path.dirname(__file__)), EXTENSIONS_RELATIVE_PATH))
buildscript.py
Outdated
@@ -0,0 +1,34 @@ | |||
import os |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's move the script to bin/
, rename to just bundle-extensions
, make it executable and add a shebang line as the first line:
#!/usr/bin/env python
That way the script is self-contained and can be called from npm.
buildscript.py
Outdated
|
||
copy_tree(content_folder, destination) | ||
|
||
call("npm run build", shell=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove the call to npm run build
here and instead add a new item to the scripts
section in the package.json
file called prebuild
with the content bin/bundle-extensions
so it's automatically called before the build
script in package.json
.
For the watch
script in package.json we could also add a prewatch
step that calls bin/bundle-extensions
with a --link
option which would create symlinks instead of copies. I think. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few problems I came across here with this:
-
npm run build
is called fromdocker-compose build
when building theDockerfile
and this adds a new/app/client/app/extensions
directory in the container. However thedocker-compose.yml
file then overrides this by mounting the volume.:/app
since locally theextensions
folder is not yet created. This results in theextensions
folder not being visible as expected when runningdocker-compose build
. -
npm run build
won't be callable locally because thebundle-extensions
requiresredash-stmo
to be installed so that it's contents are copied over.
For these two reasons I made this buildscript a separate executable (https://github.com/mozilla/redash/pull/463/files#diff-76ffdf10e3a9d8396a3951f272eaf403R75) that did not run from the Dockerfile
or locally.
Is there perhaps some Docker magic that you know of to get around this?
In terms prewatch
, I'm not quite sure what the purpose of this would be. Could you elaborate a bit? It seemed that once the client/app/extensions
directory exists, changes in it it will already be capturd by watch
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might work if the docker-compose.yml command
field is used to run this buildscript as well as the Dockerfile. I will try that.
Edit: This doesn't quite work still because /app/client/app/extensions
will not be available until docker-compose up
is called which could happen after npm run build
and so the new extensions directory will not be built. We could add npm run build
to the command
in docker-compose.yml
but this will make each call to docker-compose up
very slow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, to summarize our discussion just now. The problem that you hinted at in 1. and 2. is basically the result of an inconsistencies of build environment between when the image is build (and calling npm run build) and when a developer is updating the build from outside the container based on that image.
On top of that docker-compose overlaps the folder that is created inside the image when mounting the working directory over it. As you correctly said, that's why Redash asks developers to run npm build
from the host machine, since that's the only place that has access to the build directory during development.
A strategy to solve that inconsistency between image and development (or: disparity between development and production environment) is:
-
move the folders that are used by both outside the path where docker-compose is mounting the working directory
For ATMO we solved this by creating a new separate directory and installing npm modules there. And then run the build process both when the image is created as well as during development.
-
run all build processes (npm build and bundle-extensions) inside the container for both image creation and development
-
provide helpers such as a script that can be called from the host machine to trigger the container-side build process to help counteract the impact on the development workflow
So I think we only need /opt/npm
for the NPM modules and then provide a docker entrypoint command that provides the ability to run bundle-extensions from the host machine via docker-compose, e.g. what the user would call to build the bundle including the extensions: docker-compose run server bundle
.
circle.yml
Outdated
@@ -7,6 +7,7 @@ machine: | |||
6.9.1 | |||
dependencies: | |||
override: | |||
- python buildscript.py |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No extra need to call this here once we call bin/bundle-extensions
from package.json.
ac95d9a
to
a306cc9
Compare
0f98fbd
to
d92556c
Compare
@jezdez So it turns out that However, I've added a In case it's not clear, the reason I called the npm script Now building looks like this:
|
d92556c
to
46aaefe
Compare
Makefile
Outdated
docker-compose run server tests | ||
|
||
build: bundle | ||
npm run build |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tasks needs to be marked as PHONY to prevent Make from skipping over the steps in case it finds file with the task names, e.g.:
.PHONY: build bundle compose_build create_database test test_db
# ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any chance to add a clean task? That's a common task added to Makefiles and is often super useful to blow away everything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nicely done!
46aaefe
to
46fbb79
Compare
No description provided.