From de933dcebff812805827f419c5466e7440d0c5b8 Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Tue, 24 Oct 2023 01:03:15 -0400 Subject: [PATCH 01/16] Only clone repos necessary for selected services --- command/src/main.rs | 100 +++++++++++++++++++++++++++++++++++++++----- lila-docker | 4 +- 2 files changed, 91 insertions(+), 13 deletions(-) diff --git a/command/src/main.rs b/command/src/main.rs index d59e27ee..2d518356 100644 --- a/command/src/main.rs +++ b/command/src/main.rs @@ -11,37 +11,99 @@ const BANNER: &str = r#" const ENV_PATH: &str = "/.env"; +#[derive(Default, Clone, Eq, PartialEq, Debug)] +struct OptionalService { + compose_profile: Option<&'static str>, + repositories: Option>, +} + fn main() -> std::io::Result<()> { intro(BANNER)?; - let profiles = multiselect( - "Select which optional services to run:\n (Use to toggle, to confirm)", + let services = multiselect( + "Select which optional services to install:\n (Use to toggle, to confirm)", ) .required(false) .item( - "stockfish-play", + OptionalService { + compose_profile: Some("stockfish-play"), + repositories: vec!["lila-fishnet"].into(), + }, "Stockfish (for playing against the computer)", "", ) .item( - "stockfish-analysis", + OptionalService { + compose_profile: Some("stockfish-analysis"), + repositories: None, + }, "Stockfish (for requesting computer analysis of games)", "", ) .item( - "external-engine", + OptionalService { + compose_profile: Some("external-engine"), + repositories: vec!["lila-engine"].into(), + }, "External Engine (for connecting a local chess engine to the analysis board)", "", ) .item( - "search", + OptionalService { + compose_profile: Some("search"), + repositories: vec!["lila-search"].into(), + }, "Search (for searching games, forum posts, etc)", "", ) - .item("gifs", "GIFs (for generating animated GIFs of games)", "") - .item("thumbnails", "Thumbnailer (for resizing images)", "") - .item("api-docs", "API docs", "") - .item("pgn-viewer", "PGN Viewer (Standalone)", "") + .item( + OptionalService { + compose_profile: Some("gifs"), + repositories: vec!["lila-gif"].into(), + }, + "GIFs (for generating animated GIFs of games)", + "", + ) + .item( + OptionalService { + compose_profile: Some("thumbnails"), + repositories: None + }, + "Thumbnailer (for resizing images)", + "", + ) + .item( + OptionalService { + compose_profile: Some("api-docs"), + repositories: vec!["api"].into(), + }, + "API docs", + "", + ) + .item( + OptionalService { + compose_profile: Some("pgn-viewer"), + repositories: vec!["pgn-viewer"].into(), + }, + "PGN Viewer (Standalone)", + "", + ) + .item( + OptionalService { + compose_profile: None, + repositories: vec!["scalachess"].into(), + }, + "Scalachess library", + "", + ) + .item( + OptionalService { + compose_profile: None, + repositories: vec!["berserk"].into(), + }, + "Berserk (Python API client)", + "", + ) .interact()?; let setup_database = @@ -66,8 +128,24 @@ fn main() -> std::io::Result<()> { (String::from(""), String::from("")) }; + let repos = [ + vec!["lila", "lila-ws", "lila-db-seed", "lifat", "chessground"], + services + .iter() + .flat_map(|service| service.repositories.clone()) + .flatten() + .collect::>(), + ] + .concat(); + + let profiles = services + .iter() + .flat_map(|service| service.compose_profile.clone()) + .collect::>(); + let env_contents = format!( - "COMPOSE_PROFILES={}\nSETUP_DB={}\nSU_PASSWORD={}\nPASSWORD={}\n", + "REPOS={}\nCOMPOSE_PROFILES={}\nSETUP_DB={}\nSU_PASSWORD={}\nPASSWORD={}\n", + repos.join(","), profiles.join(","), setup_database, su_password, diff --git a/lila-docker b/lila-docker index 06ecef9d..7f94faea 100755 --- a/lila-docker +++ b/lila-docker @@ -6,8 +6,8 @@ run_setup() { docker compose run --rm -it lila_docker_rs bash -c "cargo run --manifest-path /mnt/Cargo.toml" export $(cat .env | xargs) - echo "Cloning repos..." - repos=(lila lila-ws lila-db-seed lila-engine lila-fishnet lila-gif lila-search lifat scalachess api pgn-viewer chessground berserk) + repos=($(echo $REPOS | tr ',' ' ')) + echo "Cloning repos... ${repos[@]}" for repo in "${repos[@]}"; do [ ! -d repos/$repo ] && git clone --depth 1 https://github.com/lichess-org/$repo.git repos/$repo done From 3613d2fbe2878facf4870a2fe8f4b99fab6793cf Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Tue, 24 Oct 2023 01:09:06 -0400 Subject: [PATCH 02/16] Specify a custom origin name when cloning lichess repos, to avoid confusion when users fork --- lila-docker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lila-docker b/lila-docker index 7f94faea..5575aaa9 100755 --- a/lila-docker +++ b/lila-docker @@ -9,7 +9,7 @@ run_setup() { repos=($(echo $REPOS | tr ',' ' ')) echo "Cloning repos... ${repos[@]}" for repo in "${repos[@]}"; do - [ ! -d repos/$repo ] && git clone --depth 1 https://github.com/lichess-org/$repo.git repos/$repo + [ ! -d repos/$repo ] && git clone --depth 1 --origin lichess-org https://github.com/lichess-org/$repo.git repos/$repo done git -C repos/lila submodule update --init From 7a8a1e232de91980aedd3eec4189c86f2c2aa6ad Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Tue, 24 Oct 2023 17:12:24 -0400 Subject: [PATCH 03/16] use node slim base image --- docker/api-docs.Dockerfile | 2 +- docker/pgn-viewer.Dockerfile | 2 +- docker/ui.Dockerfile | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docker/api-docs.Dockerfile b/docker/api-docs.Dockerfile index b3989def..ae06f41d 100644 --- a/docker/api-docs.Dockerfile +++ b/docker/api-docs.Dockerfile @@ -1,4 +1,4 @@ -FROM node:20.8.1-bookworm +FROM node:20.8.1-bookworm-slim WORKDIR /api/doc diff --git a/docker/pgn-viewer.Dockerfile b/docker/pgn-viewer.Dockerfile index 0578d1c0..0a16d19a 100644 --- a/docker/pgn-viewer.Dockerfile +++ b/docker/pgn-viewer.Dockerfile @@ -1,4 +1,4 @@ -FROM node:20.8.1-bookworm +FROM node:20.8.1-bookworm-slim RUN npm install -g pnpm diff --git a/docker/ui.Dockerfile b/docker/ui.Dockerfile index 594ca2b7..6ffe56ef 100644 --- a/docker/ui.Dockerfile +++ b/docker/ui.Dockerfile @@ -1,6 +1,6 @@ -FROM node:20.8.1-bookworm +FROM node:20.8.1-bookworm-slim + +RUN apt-get update +RUN apt-get install -y git -RUN git config --global --add safe.directory /lila -RUN git config --global --add safe.directory /chessground -RUN git config --global --add safe.directory /pgn-viewer RUN npm install -g pnpm From ce1a22e3ff7465262d2919044fc4e023b011fa87 Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Tue, 24 Oct 2023 17:13:53 -0400 Subject: [PATCH 04/16] install pymongo during build --- docker/python.Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/python.Dockerfile b/docker/python.Dockerfile index af98036f..3d268862 100644 --- a/docker/python.Dockerfile +++ b/docker/python.Dockerfile @@ -2,4 +2,6 @@ FROM eclipse-temurin:21_35-jdk-alpine COPY --from=python:3.12.0-alpine3.18 / / +RUN pip install pymongo + WORKDIR /lila-db-seed From f5a107fc0f9704529a1c63dee932ed0c38da9069 Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Tue, 24 Oct 2023 17:14:10 -0400 Subject: [PATCH 05/16] make chessground an optional service --- README.md | 35 ++++++++++++++--------------------- command/src/main.rs | 12 ++++++++++-- conf/nginx.conf | 4 ---- docker-compose.yml | 14 ++++++++++++-- docker/chessground.Dockerfile | 7 +++++++ lila-docker | 25 +++++++++++-------------- 6 files changed, 54 insertions(+), 43 deletions(-) create mode 100644 docker/chessground.Dockerfile diff --git a/README.md b/README.md index 0ce9d43f..6ba23a30 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,10 @@ The only requirements for running on your local machine are `git` and Docker Des As an alternative to running it on your local machine, you can use Gitpod (a free, online, VS Code-like IDE) for contributing. With a single click, it will launch a workspace and automatically: -- Clone the necessary Lichess repositories -- Install all the dependencies -- Seed your database with test data -- Start your development site +- Clone the necessary Lichess repositories +- Install all the dependencies +- Seed your database with test data +- Start your development site Click here to create a workspace: @@ -56,12 +56,11 @@ To remove the containers: Always available: -| Service | URL | -| ------------------ | ------------------------------------------- | -| Main lila instance | http://localhost:8080/ | -| Chessground demo | http://localhost:8080/chessground/demo.html | -| Mongodb manager | http://localhost:8081/ (admin/pass) | -| Email inbox | http://localhost:8025/ | +| Service | URL | +| ------------------ | ----------------------------------- | +| Main lila instance | http://localhost:8080/ | +| Mongodb manager | http://localhost:8081/ (admin/pass) | +| Email inbox | http://localhost:8025/ | Depending on which optional services you start: @@ -71,7 +70,8 @@ Depending on which optional services you start: | Picfit | http://localhost:3001/healthcheck | | Elasticsearch manager | http://localhost:5601/ | | API docs | http://localhost:8089/ | -| PGN Viewer | http://localhost:8090/ | +| Chessground | http://localhost:8090/demo.html | +| PGN Viewer | http://localhost:8091/ | ## Usage @@ -102,14 +102,7 @@ docker compose run --rm ui bash -c "/lila/bin/trans-dump" ### Code formatting: ```bash -docker compose run --rm ui bash -c "cd /lila && pnpm install && pnpm run format" -docker compose run --rm ui bash -c "cd /chessground && pnpm install && pnpm run format" -docker compose run --rm ui bash -c "cd /pgn-viewer && pnpm install && pnpm run format" - -# sbt scalafmtAll -docker run --rm -v $(pwd)/repos/lila:/lila \ - sbtscala/scala-sbt:eclipse-temurin-jammy-21_35_1.9.7_3.3.1 \ - bash -c "cd /lila && sbt scalafmtAll" +./lila-docker format ``` ### Berserk (Python library): @@ -216,7 +209,7 @@ By default, your local lila instance will use the version of chessground that is docker compose run --rm ui bash -c "/lila/ui/build -w" ``` -Then you can see the updated chessground demo at http://localhost:8080/chessground/demo.html and when you refresh lila, it will use the local copy of chessground. +Then you can see the updated chessground demo at http://localhost:8090/demo.html and when you refresh lila, it will use the local copy of chessground. ### Developing PGN Viewer locally @@ -226,4 +219,4 @@ To re-compile the PGN Viewer after making changes: docker compose run --rm ui bash -c "cd /pgn-viewer && pnpm run sass-dev && pnpm run bundle-dev" ``` -See the changes on the PGN Viewer demo page: http://localhost:8090/ +See the changes on the PGN Viewer demo page: http://localhost:8091/ diff --git a/command/src/main.rs b/command/src/main.rs index 2d518356..b845b2c2 100644 --- a/command/src/main.rs +++ b/command/src/main.rs @@ -21,7 +21,7 @@ fn main() -> std::io::Result<()> { intro(BANNER)?; let services = multiselect( - "Select which optional services to install:\n (Use to toggle, to confirm)", + "Select which optional services to run:\n (Use to toggle, to confirm)", ) .required(false) .item( @@ -80,6 +80,14 @@ fn main() -> std::io::Result<()> { "API docs", "", ) + .item( + OptionalService { + compose_profile: Some("chessground"), + repositories: vec!["chessground"].into(), + }, + "Chessground board UI (Standalone)", + "", + ) .item( OptionalService { compose_profile: Some("pgn-viewer"), @@ -129,7 +137,7 @@ fn main() -> std::io::Result<()> { }; let repos = [ - vec!["lila", "lila-ws", "lila-db-seed", "lifat", "chessground"], + vec!["lila", "lila-ws", "lila-db-seed", "lifat"], services .iter() .flat_map(|service| service.repositories.clone()) diff --git a/conf/nginx.conf b/conf/nginx.conf index 02f22a90..3c617fd9 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -9,10 +9,6 @@ server { alias /lifat; } - location /chessground { - alias /chessground; - } - location / { try_files $uri @$http_upgrade; } diff --git a/docker-compose.yml b/docker-compose.yml index faaec740..3e2c4c76 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -47,7 +47,6 @@ services: - ./conf/nginx.conf:/etc/nginx/conf.d/default.conf - ./repos/lila/public:/lila/public - ./repos/lifat:/lifat - - ./repos/chessground:/chessground - ./nginx:/nginx depends_on: - lila @@ -64,12 +63,23 @@ services: profiles: - api-docs + chessground: + build: + context: docker + dockerfile: chessground.Dockerfile + ports: + - 8090:8080 + volumes: + - ./repos/chessground:/chessground + profiles: + - chessground + pgn_viewer: build: context: docker dockerfile: pgn-viewer.Dockerfile ports: - - 8090:8080 + - 8091:8080 volumes: - ./repos/pgn-viewer:/pgn-viewer profiles: diff --git a/docker/chessground.Dockerfile b/docker/chessground.Dockerfile new file mode 100644 index 00000000..ce1c3447 --- /dev/null +++ b/docker/chessground.Dockerfile @@ -0,0 +1,7 @@ +FROM node:20.8.1-bookworm-slim + +RUN npm install -g pnpm + +WORKDIR /chessground + +ENTRYPOINT pnpm install && pnpm run compile && pnpx http-server -p 8080 diff --git a/lila-docker b/lila-docker index 5575aaa9..b63cf1c7 100755 --- a/lila-docker +++ b/lila-docker @@ -9,22 +9,22 @@ run_setup() { repos=($(echo $REPOS | tr ',' ' ')) echo "Cloning repos... ${repos[@]}" for repo in "${repos[@]}"; do - [ ! -d repos/$repo ] && git clone --depth 1 --origin lichess-org https://github.com/lichess-org/$repo.git repos/$repo + [ ! -d repos/$repo/.git ] && git clone --depth 1 --origin lichess-org https://github.com/lichess-org/$repo repos/$repo done git -C repos/lila submodule update --init run_setup_config - echo "Compiling lila js/css..." - docker compose run --rm ui bash -c "/lila/ui/build" - - echo "Compiling chessground..." - docker compose run --rm ui bash -c "cd /chessground && pnpm install && pnpm run compile" - docker compose build + # separate build specifically for utils profile otherwise its Dockerfile changes won't be detected + docker compose --profile utils build + docker compose up -d + echo "Compiling js/css..." + docker compose run --rm ui bash -c "/lila/ui/build" + if [ "$SETUP_DB" = "true" ]; then setup_database fi @@ -86,7 +86,7 @@ setup_database() { "mongo --host mongodb lichess /lila/bin/mongodb/indexes.js" docker compose run --rm python bash -c \ - "pip install pymongo && python /lila-db-seed/spamdb/spamdb.py --uri=mongodb://mongodb/lichess --password=$PASSWORD --su-password=$SU_PASSWORD --es --es-host=elasticsearch:9200" + "python /lila-db-seed/spamdb/spamdb.py --uri=mongodb://mongodb/lichess --password=$PASSWORD --su-password=$SU_PASSWORD --es --es-host=elasticsearch:9200" docker compose run --rm -v $(pwd)/scripts:/scripts mongodb bash -c \ "mongosh --host mongodb lichess --file /scripts/mongodb/users.js" @@ -94,12 +94,9 @@ setup_database() { run_formatter() { docker compose run --rm ui bash -c "\ - cd /lila && \ - pnpm install && pnpm run format && \ - cd /chessground && \ - pnpm install && pnpm run format && \ - cd /pgn-viewer && \ - pnpm install && pnpm run format" + cd /lila && pnpm install && pnpm run format && \ + (test -f /chessground/package.json && cd /chessground && pnpm install && pnpm run format) || echo 'Skipping chessground' && \ + (test -f /pgn-viewer/package.json && cd /pgn-viewer && pnpm install && pnpm run format) || echo 'Skipping pgn-viewer'" docker run --rm -v $(pwd)/repos/lila:/lila \ sbtscala/scala-sbt:eclipse-temurin-jammy-21_35_1.9.7_3.3.1 \ From 90cbbef75e52543c5c9bf7cd4867f32c3847c0c6 Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Tue, 24 Oct 2023 17:17:58 -0400 Subject: [PATCH 06/16] formatting --- command/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command/src/main.rs b/command/src/main.rs index b845b2c2..201a403d 100644 --- a/command/src/main.rs +++ b/command/src/main.rs @@ -67,7 +67,7 @@ fn main() -> std::io::Result<()> { .item( OptionalService { compose_profile: Some("thumbnails"), - repositories: None + repositories: None, }, "Thumbnailer (for resizing images)", "", From 31691b54d631b6d2fc1afa75c0bf2a23bf06775b Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Tue, 24 Oct 2023 17:25:33 -0400 Subject: [PATCH 07/16] set git safe.directory --- docker/ui.Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docker/ui.Dockerfile b/docker/ui.Dockerfile index 6ffe56ef..85618775 100644 --- a/docker/ui.Dockerfile +++ b/docker/ui.Dockerfile @@ -3,4 +3,8 @@ FROM node:20.8.1-bookworm-slim RUN apt-get update RUN apt-get install -y git +RUN git config --global --add safe.directory /chessground +RUN git config --global --add safe.directory /lila +RUN git config --global --add safe.directory /pgn-viewer + RUN npm install -g pnpm From ca9c0410e3aebaeec74878eedc5a66bd3d2ac224 Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Tue, 24 Oct 2023 17:37:54 -0400 Subject: [PATCH 08/16] add other gitpod ports and assign them labels --- .gitpod.yml | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/.gitpod.yml b/.gitpod.yml index e86bafd4..21c613b6 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -6,19 +6,38 @@ tasks: ports: - port: 8080 name: lichess - description: Your Lichess development site + description: Lichess dev site onOpen: open-preview - port: 8025 name: mailpit - description: For debugging emails + description: Email inbox onOpen: ignore - port: 8081 name: mongo-express - description: "For exploring database schema and contents (u: admin / p: pass)" + description: "Database explorer (u: admin / p: pass)" + onOpen: ignore + - port: 8089 + name: API docs + onOpen: ignore + - port: 8090 + name: chessground + onOpen: ignore + - port: 8091 + name: pgn-viewer + onOpen: ignore + - port: 9666 + name: lila-engine + description: External engine + onOpen: ignore + - port: 6175 + name: lila-gif + onOpen: ignore + - port: 3001 + name: picfit onOpen: ignore - port: 5601 name: kibana - description: For debugging Elasticsearch + description: Elasticsearch manager onOpen: ignore vscode: From 94814f94ac97687c73e9a05917d0916feef4a123 Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Tue, 24 Oct 2023 19:34:21 -0400 Subject: [PATCH 09/16] cleanup optional service prompt --- command/src/main.rs | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/command/src/main.rs b/command/src/main.rs index 201a403d..d6e95ea3 100644 --- a/command/src/main.rs +++ b/command/src/main.rs @@ -21,7 +21,7 @@ fn main() -> std::io::Result<()> { intro(BANNER)?; let services = multiselect( - "Select which optional services to run:\n (Use to toggle, to confirm)", + "Select which optional services to run:\n (Use arrows, to toggle, to continue)\n", ) .required(false) .item( @@ -29,48 +29,48 @@ fn main() -> std::io::Result<()> { compose_profile: Some("stockfish-play"), repositories: vec!["lila-fishnet"].into(), }, - "Stockfish (for playing against the computer)", - "", + "Stockfish Play", + "for playing against the computer", ) .item( OptionalService { compose_profile: Some("stockfish-analysis"), repositories: None, }, - "Stockfish (for requesting computer analysis of games)", - "", + "Stockfish Analysis", + "for requesting computer analysis of games", ) .item( OptionalService { compose_profile: Some("external-engine"), repositories: vec!["lila-engine"].into(), }, - "External Engine (for connecting a local chess engine to the analysis board)", - "", + "External Engine", + "for connecting a local chess engine to the analysis board", ) .item( OptionalService { compose_profile: Some("search"), repositories: vec!["lila-search"].into(), }, - "Search (for searching games, forum posts, etc)", - "", + "Search", + "for searching games, forum posts, etc", ) .item( OptionalService { compose_profile: Some("gifs"), repositories: vec!["lila-gif"].into(), }, - "GIFs (for generating animated GIFs of games)", - "", + "GIFs", + "for generating animated GIFs of games", ) .item( OptionalService { compose_profile: Some("thumbnails"), repositories: None, }, - "Thumbnailer (for resizing images)", - "", + "Thumbnail generator", + "for resizing blog/streamer images", ) .item( OptionalService { @@ -78,39 +78,39 @@ fn main() -> std::io::Result<()> { repositories: vec!["api"].into(), }, "API docs", - "", + "standalone API documentation", ) .item( OptionalService { compose_profile: Some("chessground"), repositories: vec!["chessground"].into(), }, - "Chessground board UI (Standalone)", - "", + "Chessground", + "standalone board UI", ) .item( OptionalService { compose_profile: Some("pgn-viewer"), repositories: vec!["pgn-viewer"].into(), }, - "PGN Viewer (Standalone)", - "", + "PGN Viewer", + "standalone PGN viewer", ) .item( OptionalService { compose_profile: None, repositories: vec!["scalachess"].into(), }, - "Scalachess library", - "", + "Scalachess", + "standalone chess logic library", ) .item( OptionalService { compose_profile: None, repositories: vec!["berserk"].into(), }, - "Berserk (Python API client)", - "", + "Berserk", + "Python API client", ) .interact()?; From 41577aa3b9d0bf55ed0234cbff0c0baeb835e577 Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Tue, 24 Oct 2023 19:43:07 -0400 Subject: [PATCH 10/16] fix cargo clippy warnings --- command/src/main.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/command/src/main.rs b/command/src/main.rs index d6e95ea3..d523edf5 100644 --- a/command/src/main.rs +++ b/command/src/main.rs @@ -1,13 +1,13 @@ use cliclack::{confirm, input, intro, multiselect}; -const BANNER: &str = r#" +const BANNER: &str = r" |\_ _ _ _ /o \ | (_) ___| |__ ___ ___ ___ ___ _ __ __ _ (_. || | | |/ __| '_ \ / _ \/ __/ __| / _ \| '__/ _` | /__\ | | | (__| | | | __/\__ \__ \| (_) | | | (_| | )___( |_|_|\___|_| |_|\___||___/___(_)___/|_| \__, | |___/ -"#; +"; const ENV_PATH: &str = "/.env"; @@ -133,14 +133,14 @@ fn main() -> std::io::Result<()> { .interact()?, ) } else { - (String::from(""), String::from("")) + (String::new(), String::new()) }; let repos = [ vec!["lila", "lila-ws", "lila-db-seed", "lifat"], services .iter() - .flat_map(|service| service.repositories.clone()) + .filter_map(|service| service.repositories.clone()) .flatten() .collect::>(), ] @@ -148,7 +148,7 @@ fn main() -> std::io::Result<()> { let profiles = services .iter() - .flat_map(|service| service.compose_profile.clone()) + .filter_map(|service| service.compose_profile) .collect::>(); let env_contents = format!( @@ -165,7 +165,7 @@ fn main() -> std::io::Result<()> { std::fs::write(ENV_PATH, env_contents)?; } Err(_) => { - println!(".env contents:\n{}", env_contents); + println!(".env contents:\n{env_contents}"); } } From f147dbd77a7f264dcf05b1b2066aa9d912403c3a Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Tue, 24 Oct 2023 20:04:22 -0400 Subject: [PATCH 11/16] cleanup env write --- command/src/main.rs | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/command/src/main.rs b/command/src/main.rs index d523edf5..7828820e 100644 --- a/command/src/main.rs +++ b/command/src/main.rs @@ -151,22 +151,18 @@ fn main() -> std::io::Result<()> { .filter_map(|service| service.compose_profile) .collect::>(); - let env_contents = format!( - "REPOS={}\nCOMPOSE_PROFILES={}\nSETUP_DB={}\nSU_PASSWORD={}\nPASSWORD={}\n", - repos.join(","), - profiles.join(","), - setup_database, - su_password, - password - ); + let env_contents = [ + format!("REPOS={}", repos.join(",")), + format!("COMPOSE_PROFILES={}", profiles.join(",")), + format!("SETUP_DB={setup_database}"), + format!("SU_PASSWORD={su_password}"), + format!("PASSWORD={password}"), + ] + .join("\n"); match std::fs::metadata(ENV_PATH) { - Ok(_) => { - std::fs::write(ENV_PATH, env_contents)?; - } - Err(_) => { - println!(".env contents:\n{env_contents}"); - } + Ok(_) => std::fs::write(ENV_PATH, env_contents)?, + Err(_) => println!(".env contents:\n{env_contents}"), } Ok(()) From 0c620b7c14005b017315357ba3c9f46e44ecd6a7 Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Tue, 24 Oct 2023 20:18:53 -0400 Subject: [PATCH 12/16] move long prompt to its own function --- command/src/main.rs | 116 +++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 55 deletions(-) diff --git a/command/src/main.rs b/command/src/main.rs index 7828820e..5d4fc9b3 100644 --- a/command/src/main.rs +++ b/command/src/main.rs @@ -1,3 +1,5 @@ +use std::io::Error; + use cliclack::{confirm, input, intro, multiselect}; const BANNER: &str = r" @@ -20,7 +22,64 @@ struct OptionalService { fn main() -> std::io::Result<()> { intro(BANNER)?; - let services = multiselect( + let services = prompt_for_optional_services()?; + + let setup_database = + confirm("Do you want to seed the database with test users, games, etc? (Recommended)") + .initial_value(true) + .interact()?; + + let (su_password, password) = if setup_database { + ( + input("Choose a password for admin users (blank for 'password')") + .placeholder("password") + .default_input("password") + .required(false) + .interact()?, + input("Choose a password for regular users (blank for 'password')") + .placeholder("password") + .default_input("password") + .required(false) + .interact()?, + ) + } else { + (String::new(), String::new()) + }; + + let repos = [ + vec!["lila", "lila-ws", "lila-db-seed", "lifat"], + services + .iter() + .filter_map(|service| service.repositories.clone()) + .flatten() + .collect::>(), + ] + .concat(); + + let profiles = services + .iter() + .filter_map(|service| service.compose_profile) + .collect::>(); + + let env_contents = [ + format!("REPOS={}", repos.join(",")), + format!("COMPOSE_PROFILES={}", profiles.join(",")), + format!("SETUP_DB={setup_database}"), + format!("SU_PASSWORD={su_password}"), + format!("PASSWORD={password}"), + ] + .join("\n"); + + match std::fs::metadata(ENV_PATH) { + Ok(_) => std::fs::write(ENV_PATH, env_contents)?, + Err(_) => println!(".env contents:\n{env_contents}"), + } + + Ok(()) +} + +fn prompt_for_optional_services() -> Result, Error> { + multiselect( "Select which optional services to run:\n (Use arrows, to toggle, to continue)\n", ) .required(false) @@ -112,58 +171,5 @@ fn main() -> std::io::Result<()> { "Berserk", "Python API client", ) - .interact()?; - - let setup_database = - confirm("Do you want to seed the database with test users, games, etc? (Recommended)") - .initial_value(true) - .interact()?; - - let (su_password, password) = if setup_database { - ( - input("Choose a password for admin users (blank for 'password')") - .placeholder("password") - .default_input("password") - .required(false) - .interact()?, - input("Choose a password for regular users (blank for 'password')") - .placeholder("password") - .default_input("password") - .required(false) - .interact()?, - ) - } else { - (String::new(), String::new()) - }; - - let repos = [ - vec!["lila", "lila-ws", "lila-db-seed", "lifat"], - services - .iter() - .filter_map(|service| service.repositories.clone()) - .flatten() - .collect::>(), - ] - .concat(); - - let profiles = services - .iter() - .filter_map(|service| service.compose_profile) - .collect::>(); - - let env_contents = [ - format!("REPOS={}", repos.join(",")), - format!("COMPOSE_PROFILES={}", profiles.join(",")), - format!("SETUP_DB={setup_database}"), - format!("SU_PASSWORD={su_password}"), - format!("PASSWORD={password}"), - ] - .join("\n"); - - match std::fs::metadata(ENV_PATH) { - Ok(_) => std::fs::write(ENV_PATH, env_contents)?, - Err(_) => println!(".env contents:\n{env_contents}"), - } - - Ok(()) + .interact() } From 3a67ae435e8a0c1a9ee585303a98631ff45df64e Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Wed, 25 Oct 2023 10:14:17 -0400 Subject: [PATCH 13/16] docs: add playRoutes command --- README.md | 8 ++++++++ command/src/main.rs | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6ba23a30..b3a4f303 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,14 @@ To watch for Typescript/SCSS changes and automatically recompile: docker compose run --rm ui bash -c "/lila/ui/build -w" ``` +## Updating Routes + +If you edit the `conf/routes` file, you'll need to update the route cache. + +```bash +docker compose exec lila bash -c "./lila playRoutes" +``` + ### To add translation keys: After modifying a `translation/source/*.xml` file, run: diff --git a/command/src/main.rs b/command/src/main.rs index 5d4fc9b3..be51e019 100644 --- a/command/src/main.rs +++ b/command/src/main.rs @@ -80,7 +80,7 @@ fn main() -> std::io::Result<()> { fn prompt_for_optional_services() -> Result, Error> { multiselect( - "Select which optional services to run:\n (Use arrows, to toggle, to continue)\n", + "Select which optional services to include:\n (Use arrows, to toggle, to continue)\n", ) .required(false) .item( From fdf4c3b22d7a9a0ec7dd3a558e656ea26588c649 Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Wed, 25 Oct 2023 23:12:28 -0400 Subject: [PATCH 14/16] create placeholder dir for each of the repos --- command/Cargo.lock | 35 ++++++++++++ command/Cargo.toml | 1 + command/src/main.rs | 129 +++++++++++++++++++++++++++++++------------- lila-docker | 10 +++- 4 files changed, 137 insertions(+), 38 deletions(-) diff --git a/command/Cargo.lock b/command/Cargo.lock index 3c60decc..315320b8 100644 --- a/command/Cargo.lock +++ b/command/Cargo.lock @@ -26,6 +26,7 @@ name = "command" version = "0.1.0" dependencies = [ "cliclack", + "strum", ] [[package]] @@ -47,6 +48,12 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "indicatif" version = "0.17.7" @@ -117,12 +124,40 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "smawk" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "syn" version = "2.0.38" diff --git a/command/Cargo.toml b/command/Cargo.toml index 69ea3ace..e7c64d50 100644 --- a/command/Cargo.toml +++ b/command/Cargo.toml @@ -7,3 +7,4 @@ edition = "2021" [dependencies] cliclack = "0.1.6" +strum = { version = "0.25.0", features = ["derive", "strum_macros"] } diff --git a/command/src/main.rs b/command/src/main.rs index be51e019..a5d3cdf4 100644 --- a/command/src/main.rs +++ b/command/src/main.rs @@ -1,6 +1,7 @@ use std::io::Error; use cliclack::{confirm, input, intro, multiselect}; +use strum::{EnumIter, EnumString, IntoEnumIterator}; const BANNER: &str = r" |\_ _ _ _ @@ -15,8 +16,40 @@ const ENV_PATH: &str = "/.env"; #[derive(Default, Clone, Eq, PartialEq, Debug)] struct OptionalService { - compose_profile: Option<&'static str>, - repositories: Option>, + compose_profile: Option, + repositories: Option>, +} + +#[derive(Debug, Clone, PartialEq, EnumString, strum::Display, Eq, EnumIter)] +#[strum(serialize_all = "kebab-case")] +enum ComposeProfile { + StockfishPlay, + StockfishAnalysis, + ExternalEngine, + Search, + Gifs, + Thumbnails, + ApiDocs, + Chessground, + PgnViewer, +} + +#[derive(Debug, Clone, PartialEq, EnumString, strum::Display, Eq, EnumIter)] +#[strum(serialize_all = "kebab-case")] +enum Repository { + Lila, + LilaWs, + LilaDbSeed, + Lifat, + LilaFishnet, + LilaEngine, + LilaSearch, + LilaGif, + Api, + Chessground, + PgnViewer, + Scalachess, + Berserk, } fn main() -> std::io::Result<()> { @@ -46,24 +79,46 @@ fn main() -> std::io::Result<()> { (String::new(), String::new()) }; - let repos = [ - vec!["lila", "lila-ws", "lila-db-seed", "lifat"], - services - .iter() - .filter_map(|service| service.repositories.clone()) - .flatten() - .collect::>(), - ] - .concat(); - - let profiles = services - .iter() - .filter_map(|service| service.compose_profile) - .collect::>(); - let env_contents = [ - format!("REPOS={}", repos.join(",")), - format!("COMPOSE_PROFILES={}", profiles.join(",")), + format!( + "DIRS={}", + Repository::iter() + .map(|repo| repo.to_string()) + .collect::>() + .join(",") + ), + format!( + "REPOS={}", + [ + vec![ + Repository::Lila, + Repository::LilaWs, + Repository::LilaDbSeed, + Repository::Lifat, + ], + services + .iter() + .filter_map(|service| service.repositories.clone()) + .flatten() + .collect::>(), + ] + .concat() + .iter() + .map(std::string::ToString::to_string) + .collect::>() + .join(",") + ), + format!( + "COMPOSE_PROFILES={}", + services + .iter() + .filter_map(|service| service.compose_profile.clone()) + .collect::>() + .iter() + .map(std::string::ToString::to_string) + .collect::>() + .join(",") + ), format!("SETUP_DB={setup_database}"), format!("SU_PASSWORD={su_password}"), format!("PASSWORD={password}"), @@ -85,15 +140,15 @@ fn prompt_for_optional_services() -> Result, Error> { .required(false) .item( OptionalService { - compose_profile: Some("stockfish-play"), - repositories: vec!["lila-fishnet"].into(), + compose_profile: Some(ComposeProfile::StockfishPlay), + repositories: vec![Repository::LilaFishnet].into(), }, "Stockfish Play", "for playing against the computer", ) .item( OptionalService { - compose_profile: Some("stockfish-analysis"), + compose_profile: Some(ComposeProfile::StockfishAnalysis), repositories: None, }, "Stockfish Analysis", @@ -101,31 +156,31 @@ fn prompt_for_optional_services() -> Result, Error> { ) .item( OptionalService { - compose_profile: Some("external-engine"), - repositories: vec!["lila-engine"].into(), + compose_profile: Some(ComposeProfile::ExternalEngine), + repositories: vec![Repository::LilaEngine].into(), }, "External Engine", "for connecting a local chess engine to the analysis board", ) .item( OptionalService { - compose_profile: Some("search"), - repositories: vec!["lila-search"].into(), + compose_profile: Some(ComposeProfile::Search), + repositories: vec![Repository::LilaSearch].into(), }, "Search", "for searching games, forum posts, etc", ) .item( OptionalService { - compose_profile: Some("gifs"), - repositories: vec!["lila-gif"].into(), + compose_profile: Some(ComposeProfile::Gifs), + repositories: vec![Repository::LilaGif].into(), }, "GIFs", "for generating animated GIFs of games", ) .item( OptionalService { - compose_profile: Some("thumbnails"), + compose_profile: Some(ComposeProfile::Thumbnails), repositories: None, }, "Thumbnail generator", @@ -133,24 +188,24 @@ fn prompt_for_optional_services() -> Result, Error> { ) .item( OptionalService { - compose_profile: Some("api-docs"), - repositories: vec!["api"].into(), + compose_profile: Some(ComposeProfile::ApiDocs), + repositories: vec![Repository::Api].into(), }, "API docs", "standalone API documentation", ) .item( OptionalService { - compose_profile: Some("chessground"), - repositories: vec!["chessground"].into(), + compose_profile: Some(ComposeProfile::Chessground), + repositories: vec![Repository::Chessground].into(), }, "Chessground", "standalone board UI", ) .item( OptionalService { - compose_profile: Some("pgn-viewer"), - repositories: vec!["pgn-viewer"].into(), + compose_profile: Some(ComposeProfile::PgnViewer), + repositories: vec![Repository::PgnViewer].into(), }, "PGN Viewer", "standalone PGN viewer", @@ -158,7 +213,7 @@ fn prompt_for_optional_services() -> Result, Error> { .item( OptionalService { compose_profile: None, - repositories: vec!["scalachess"].into(), + repositories: vec![Repository::Scalachess].into(), }, "Scalachess", "standalone chess logic library", @@ -166,7 +221,7 @@ fn prompt_for_optional_services() -> Result, Error> { .item( OptionalService { compose_profile: None, - repositories: vec!["berserk"].into(), + repositories: vec![Repository::Berserk].into(), }, "Berserk", "Python API client", diff --git a/lila-docker b/lila-docker index b63cf1c7..fde4cbaf 100755 --- a/lila-docker +++ b/lila-docker @@ -6,8 +6,16 @@ run_setup() { docker compose run --rm -it lila_docker_rs bash -c "cargo run --manifest-path /mnt/Cargo.toml" export $(cat .env | xargs) + # create a placeholder directory for each of the repos + # otherwise the directories will be created by Docker + # when the volumes are mounted and they may be owned by root + dirs=($(echo $DIRS | tr ',' ' ')) + for dir in "${dirs[@]}"; do + mkdir -p repos/$dir + done + repos=($(echo $REPOS | tr ',' ' ')) - echo "Cloning repos... ${repos[@]}" + echo "Cloning repos ${repos[@]}..." for repo in "${repos[@]}"; do [ ! -d repos/$repo/.git ] && git clone --depth 1 --origin lichess-org https://github.com/lichess-org/$repo repos/$repo done From 4e89def849960145c2db66b41c13704043319008 Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Thu, 26 Oct 2023 07:56:52 -0400 Subject: [PATCH 15/16] create repo placeholder folders in Rust --- command/src/main.rs | 20 +++++++++++--------- docker-compose.yml | 1 + lila-docker | 8 -------- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/command/src/main.rs b/command/src/main.rs index a5d3cdf4..6322058b 100644 --- a/command/src/main.rs +++ b/command/src/main.rs @@ -1,4 +1,4 @@ -use std::io::Error; +use std::{fs, io::Error}; use cliclack::{confirm, input, intro, multiselect}; use strum::{EnumIter, EnumString, IntoEnumIterator}; @@ -80,13 +80,6 @@ fn main() -> std::io::Result<()> { }; let env_contents = [ - format!( - "DIRS={}", - Repository::iter() - .map(|repo| repo.to_string()) - .collect::>() - .join(",") - ), format!( "REPOS={}", [ @@ -126,7 +119,16 @@ fn main() -> std::io::Result<()> { .join("\n"); match std::fs::metadata(ENV_PATH) { - Ok(_) => std::fs::write(ENV_PATH, env_contents)?, + Ok(_) => { + std::fs::write(ENV_PATH, env_contents)?; + + // create a placeholder directory for each of the repos + // otherwise the directories will be created by Docker + // when the volumes are mounted and they may be owned by root + for repo in Repository::iter() { + fs::create_dir_all(format!("/repos/{repo}"))?; + } + } Err(_) => println!(".env contents:\n{env_contents}"), } diff --git a/docker-compose.yml b/docker-compose.yml index 3e2c4c76..3998bd01 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -132,6 +132,7 @@ services: volumes: - .env:/.env - ./command:/mnt + - ./repos:/repos environment: - CARGO_HOME=/mnt/.cargo profiles: diff --git a/lila-docker b/lila-docker index fde4cbaf..419c8afe 100755 --- a/lila-docker +++ b/lila-docker @@ -6,14 +6,6 @@ run_setup() { docker compose run --rm -it lila_docker_rs bash -c "cargo run --manifest-path /mnt/Cargo.toml" export $(cat .env | xargs) - # create a placeholder directory for each of the repos - # otherwise the directories will be created by Docker - # when the volumes are mounted and they may be owned by root - dirs=($(echo $DIRS | tr ',' ' ')) - for dir in "${dirs[@]}"; do - mkdir -p repos/$dir - done - repos=($(echo $REPOS | tr ',' ' ')) echo "Cloning repos ${repos[@]}..." for repo in "${repos[@]}"; do From ff0cb2ee287290555c617173202b4e401ccb223a Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Thu, 26 Oct 2023 08:40:52 -0400 Subject: [PATCH 16/16] Revert "create repo placeholder folders in Rust" This reverts commit 4e89def849960145c2db66b41c13704043319008. --- command/src/main.rs | 20 +++++++++----------- docker-compose.yml | 1 - lila-docker | 8 ++++++++ 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/command/src/main.rs b/command/src/main.rs index 6322058b..a5d3cdf4 100644 --- a/command/src/main.rs +++ b/command/src/main.rs @@ -1,4 +1,4 @@ -use std::{fs, io::Error}; +use std::io::Error; use cliclack::{confirm, input, intro, multiselect}; use strum::{EnumIter, EnumString, IntoEnumIterator}; @@ -80,6 +80,13 @@ fn main() -> std::io::Result<()> { }; let env_contents = [ + format!( + "DIRS={}", + Repository::iter() + .map(|repo| repo.to_string()) + .collect::>() + .join(",") + ), format!( "REPOS={}", [ @@ -119,16 +126,7 @@ fn main() -> std::io::Result<()> { .join("\n"); match std::fs::metadata(ENV_PATH) { - Ok(_) => { - std::fs::write(ENV_PATH, env_contents)?; - - // create a placeholder directory for each of the repos - // otherwise the directories will be created by Docker - // when the volumes are mounted and they may be owned by root - for repo in Repository::iter() { - fs::create_dir_all(format!("/repos/{repo}"))?; - } - } + Ok(_) => std::fs::write(ENV_PATH, env_contents)?, Err(_) => println!(".env contents:\n{env_contents}"), } diff --git a/docker-compose.yml b/docker-compose.yml index 3998bd01..3e2c4c76 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -132,7 +132,6 @@ services: volumes: - .env:/.env - ./command:/mnt - - ./repos:/repos environment: - CARGO_HOME=/mnt/.cargo profiles: diff --git a/lila-docker b/lila-docker index 419c8afe..fde4cbaf 100755 --- a/lila-docker +++ b/lila-docker @@ -6,6 +6,14 @@ run_setup() { docker compose run --rm -it lila_docker_rs bash -c "cargo run --manifest-path /mnt/Cargo.toml" export $(cat .env | xargs) + # create a placeholder directory for each of the repos + # otherwise the directories will be created by Docker + # when the volumes are mounted and they may be owned by root + dirs=($(echo $DIRS | tr ',' ' ')) + for dir in "${dirs[@]}"; do + mkdir -p repos/$dir + done + repos=($(echo $REPOS | tr ',' ' ')) echo "Cloning repos ${repos[@]}..." for repo in "${repos[@]}"; do