Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ FROM mcr.microsoft.com/playwright:v1.61.1-noble
ARG LUA_VERSION=5.1.5
ARG LUAROCKS_VERSION=3.11.1
ARG LUALS_VERSION=3.18.2
# Not in requirements.txt on purpose: only needed to run scripts/proxy_lp.py,
# which is a local-development tool rather than a dependency of the repo
ARG MITMPROXY_VERSION=12.2.3

ENV DEBIAN_FRONTEND=noninteractive

Expand Down Expand Up @@ -62,6 +65,7 @@ ENV VIRTUAL_ENV=/opt/venv
ENV PATH=/opt/venv/bin:${PATH}
RUN python3 -m venv "${VIRTUAL_ENV}" \
&& pip install --no-cache-dir --upgrade pip \
&& pip install --no-cache-dir "mitmproxy==${MITMPROXY_VERSION}" \
&& chmod -R a+rwX "${VIRTUAL_ENV}"

# Runs before the features do, which is where the user we run as gets created.
Expand Down
24 changes: 24 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,32 @@
"source": "lua-modules-node-modules",
"target": "${containerWorkspaceFolder}/node_modules",
"type": "volume"
},
// Keeps the mitmproxy CA across rebuilds, so the certificate only has
// to be trusted in the browser once
{
"source": "lua-modules-mitmproxy",
"target": "/home/vscode/.mitmproxy",
"type": "volume"
}
],
// mitmproxy, for serving locally built CSS/JS into the live wiki.
// forwardPorts is the editor side tunnel, appPort is what publishes the port
// for anyone driving the container from the CLI instead. Bound to loopback
// on purpose: publishing on every interface would leave an open forward
// proxy reachable from the local network.
"forwardPorts": [
8080
],
"appPort": [
"127.0.0.1:8080:8080"
],
"portsAttributes": {
"8080": {
"label": "mitmproxy",
"onAutoForward": "silent"
}
},
"containerEnv": {
"PLAYWRIGHT_BROWSERS_PATH": "/ms-playwright"
},
Expand Down
8 changes: 6 additions & 2 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ set -euo pipefail
cd "$(dirname "$0")/.."

echo "==> Installing npm dependencies"
# node_modules is a named volume, which docker creates owned by root
sudo chown "$(id -u):$(id -g)" node_modules
# these are named volumes, which docker creates owned by root
sudo chown "$(id -u):$(id -g)" node_modules ~/.mitmproxy
npm install
Comment on lines +7 to 9

echo "==> Installing python dependencies"
pip install --no-cache-dir -r requirements.txt

echo "==> Building css and js"
# The proxy serves these, and without them it silently passes requests through
npm run build

if [ ! -f .env ]; then
echo "==> Creating .env from .env.example (fill in your bot credentials before deploying)"
# Nobody chose these settings, we generated them, so start in dry-run and
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ Open the repository in VS Code and pick *Dev Containers: Reopen in Container* (r

If you prefer a native setup, follow the platform instructions below instead.

###### Previewing CSS and JS changes on the live wiki

The container also ships [mitmproxy](https://mitmproxy.org/) and the dependencies for `scripts/proxy_lp.py`, which serves your locally built `lua/output/css/main.css` and `lua/output/js/main.js` in place of the ones liquipedia.net would load. See the [wiki page](https://github.com/Liquipedia/Lua-Modules/wiki/Local-Development-Setup-for-CSS-and-JS) for the full background; inside the container the setup is:

1. Run `npm run build`, so there is something to serve. The container does this on first start, but the proxy has nothing to substitute until it has run, and it will tell you so rather than quietly serving you the real files.
2. Start the proxy with `python scripts/proxy_lp.py` from the repository root, or via the *Launch proxy* task in `.vscode/tasks.json`. It listens on port 8080, published to `127.0.0.1:8080` on your host.
3. Point your browser at that proxy. A switcher extension such as Proxy SwitchyOmega (HTTP, `127.0.0.1`, port `8080`) makes it easy to toggle on and off; a system-wide proxy setting works too.
4. With the proxy enabled, open <http://mitm.it> and install the certificate for your browser, so it will trust the intercepted HTTPS responses. The CA is kept in a volume, so this is only needed once, not after every rebuild.
5. Edit `.scss` or `.js`, run `npm run build` again, then hard refresh the wiki page (Ctrl+Shift+R / Cmd+Shift+R).

Turn the proxy off in your browser when you are done — while it is enabled, every request goes through the container.

##### Windows

Recommended to use [WSL](https://learn.microsoft.com/en-us/windows/wsl/install). Then follow the Unix instructions.
Expand Down
41 changes: 23 additions & 18 deletions scripts/proxy_lp.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,31 @@ def request(self, flow: http.HTTPFlow) -> None:
self.__serve_local_js_resource(flow)

def __serve_local_css_resource(self, flow: http.HTTPFlow):
with open("lua/output/css/main.css", "rb") as f:
flow.response = http.Response.make(
HTTPStatus.OK,
f.read(),
{"Content-Type": "text/css; charset=utf-8"},
)
flow.response.headers["Via"] = (
f"{flow.response.http_version} LiquipediaMapper"
)
self.__serve_local_file(
flow, "lua/output/css/main.css", "text/css; charset=utf-8"
)

def __serve_local_js_resource(self, flow: http.HTTPFlow):
with open("lua/output/js/main.js", "rb") as f:
flow.response = http.Response.make(
HTTPStatus.OK,
f.read(),
{"Content-Type": "text/javascript; charset=utf-8"},
)
flow.response.headers["Via"] = (
f"{flow.response.http_version} LiquipediaMapper"
)
self.__serve_local_file(
flow, "lua/output/js/main.js", "text/javascript; charset=utf-8"
)

def __serve_local_file(self, flow: http.HTTPFlow, path: str, content_type: str):
try:
with open(path, "rb") as f:
body = f.read()
except OSError as error:
# Leaving this unsaid means the request goes upstream, the page looks
# untouched and nothing explains why
print(f"LiquipediaMapper: {error}. Run npm run build first.")
return

flow.response = http.Response.make(
HTTPStatus.OK,
body,
{"Content-Type": content_type},
)
flow.response.headers["Via"] = f"{flow.response.http_version} LiquipediaMapper"


async def main():
Expand Down
Loading