diff --git a/.devcontainer/README.md b/.devcontainer/README.md new file mode 100644 index 00000000..43d1c704 --- /dev/null +++ b/.devcontainer/README.md @@ -0,0 +1,46 @@ +# Devcontainer + +This devcontainer is very basic - it just provides a `node` version 18 container, with +enough OS dependencies to work with repo tools and to play nice with VSC. + +The Dockerfile should roughly match that utilized by the GHA workflows. + +## Why? + +With the devcontainer runtime (Linux, node) matching GHA, tools should match and npm +installs should match. npm installs are often binary, and platform-specific; though they +should behave the same, there may be subtle differences. + +Host dependencies can be avoided by installing them into the devcontainer. E.g. the +proper version of node and npm, git, bash, make. This allows development on any platform +which supports Docker and VSC. + +## Quick Start + +1. After starting the devcontainer with VSC, a terminal should open automaitcally. If not, +open one. + + The terminal should open inside the container: + + ```shell + root@europa-ui:/workspace# + ``` + +2. Install dependencies: + + ```shell + npm install + ``` + +3. Run tests: + + ```shell + npm run test . -- --coverage --verbose + ``` + +4. Running devserver: + + ```shell + npm run start + ``` + diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..e81b8583 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,25 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.224.2/containers/docker-existing-docker-compose +// If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml. +{ + "name": "Europa Development Host via Existing Docker Compose (Extend)", + + // Update the 'dockerComposeFile' list if you have more compose files or use different names. + // The .devcontainer/docker-compose.yml file contains any overrides you need/want to make. + "dockerComposeFile": [ + "docker-compose.yml" + ], + + // The 'service' property is the name of the service for the container that VS Code should + // use. Update this value and .devcontainer/docker-compose.yml to the real service name. + "service": "europa-ui", + + // The optional 'workspaceFolder' property is the path VS Code should open by default when + // connected. This is typically a file mount in .devcontainer/docker-compose.yml + "workspaceFolder": "/workspace", + "customizations": { + "vscode": { + + } + } +} \ No newline at end of file diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 00000000..ad35c2aa --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,21 @@ +version: '3.6' +name: kbase-dev +networks: + kbase-dev: + name: kbase-dev +services: + europa-ui: + build: + context: . + dockerfile: ../tools/node/Dockerfile + image: kbase/europa-ui:dev + container_name: europa-ui + hostname: europa-ui + dns: 8.8.8.8 + volumes: + # Update this to wherever you want VS Code to mount the folder of your project + - ..:/workspace:cached + networks: + - kbase-dev + command: /bin/sh -c "while sleep 1000; do :; done" + \ No newline at end of file diff --git a/.env b/.env index 1ad1e2a5..db37e86a 100644 --- a/.env +++ b/.env @@ -2,18 +2,18 @@ # for deploy enviroment configurations, see config.json # Base URL path for the enviroment -PUBLIC_URL = '/dev/' +PUBLIC_URL='/dev/' # Name of enviroment for build -REACT_APP_KBASE_ENV=ci-europa +REACT_APP_KBASE_ENV='ci-europa' # Domain of enviroment for build -REACT_APP_KBASE_DOMAIN=ci-europa.kbase.us +REACT_APP_KBASE_DOMAIN='ci-europa.kbase.us' # The following must be a subdomain of REACT_APP_KBASE_DOMAIN -REACT_APP_KBASE_LEGACY_DOMAIN=legacy.ci-europa.kbase.us +REACT_APP_KBASE_LEGACY_DOMAIN='legacy.ci-europa.kbase.us' # Backup cookie name and domain, empty if unused by enviroment -REACT_APP_KBASE_BACKUP_COOKIE_NAME = 'test_kbase_backup_session' -REACT_APP_KBASE_BACKUP_COOKIE_DOMAIN = 'localhost' +REACT_APP_KBASE_BACKUP_COOKIE_NAME='test_kbase_backup_session' +REACT_APP_KBASE_BACKUP_COOKIE_DOMAIN='localhost' -EXTEND_ESLINT=true -SKIP_PREFLIGHT_CHECK=true +EXTEND_ESLINT='true' +SKIP_PREFLIGHT_CHECK='true' diff --git a/.github/workflows/reusable_build-push.yml b/.github/workflows/reusable_build-push.yml index 1de2d8b4..d68782cd 100644 --- a/.github/workflows/reusable_build-push.yml +++ b/.github/workflows/reusable_build-push.yml @@ -36,7 +36,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v2 with: - node-version: '16' + node-version: '20' - name: Install app run: npm ci diff --git a/dev/.env-ci b/dev/.env-ci new file mode 100644 index 00000000..795fb831 --- /dev/null +++ b/dev/.env-ci @@ -0,0 +1,19 @@ +# Includes env defaults for local development, +# for deploy enviroment configurations, see config.json + +# Base URL path for the enviroment +PUBLIC_URL='/dev/' + +# Name of enviroment for build +REACT_APP_KBASE_ENV='ci' +# Domain of enviroment for build +REACT_APP_KBASE_DOMAIN='ci.kbase.us' +# The following must be a subdomain of REACT_APP_KBASE_DOMAIN +REACT_APP_KBASE_LEGACY_DOMAIN='legacy.ci.kbase.us' + +# Backup cookie name and domain, empty if unused by enviroment +REACT_APP_KBASE_BACKUP_COOKIE_NAME = '' +REACT_APP_KBASE_BACKUP_COOKIE_DOMAIN = '' + +EXTEND_ESLINT='true' +SKIP_PREFLIGHT_CHECK='true' diff --git a/dev/.env-ci-europa b/dev/.env-ci-europa new file mode 100644 index 00000000..b23bcddb --- /dev/null +++ b/dev/.env-ci-europa @@ -0,0 +1,19 @@ +# Includes env defaults for local development, +# for deploy enviroment configurations, see config.json + +# Base URL path for the enviroment +PUBLIC_URL='/dev/' + +# Name of enviroment for build +REACT_APP_KBASE_ENV='ci-europa' +# Domain of enviroment for build +REACT_APP_KBASE_DOMAIN='ci-europa.kbase.us' +# The following must be a subdomain of REACT_APP_KBASE_DOMAIN +REACT_APP_KBASE_LEGACY_DOMAIN='legacy.ci-europa.kbase.us' + +# Backup cookie name and domain, empty if unused by enviroment +REACT_APP_KBASE_BACKUP_COOKIE_NAME='' +REACT_APP_KBASE_BACKUP_COOKIE_DOMAIN='' + +EXTEND_ESLINT='true' +SKIP_PREFLIGHT_CHECK='true' diff --git a/dev/.env-dev b/dev/.env-dev new file mode 100644 index 00000000..db37e86a --- /dev/null +++ b/dev/.env-dev @@ -0,0 +1,19 @@ +# Includes env defaults for local development, +# for deploy enviroment configurations, see config.json + +# Base URL path for the enviroment +PUBLIC_URL='/dev/' + +# Name of enviroment for build +REACT_APP_KBASE_ENV='ci-europa' +# Domain of enviroment for build +REACT_APP_KBASE_DOMAIN='ci-europa.kbase.us' +# The following must be a subdomain of REACT_APP_KBASE_DOMAIN +REACT_APP_KBASE_LEGACY_DOMAIN='legacy.ci-europa.kbase.us' + +# Backup cookie name and domain, empty if unused by enviroment +REACT_APP_KBASE_BACKUP_COOKIE_NAME='test_kbase_backup_session' +REACT_APP_KBASE_BACKUP_COOKIE_DOMAIN='localhost' + +EXTEND_ESLINT='true' +SKIP_PREFLIGHT_CHECK='true' diff --git a/dev/.env-narrative b/dev/.env-narrative new file mode 100644 index 00000000..f7e079a2 --- /dev/null +++ b/dev/.env-narrative @@ -0,0 +1,19 @@ +# Includes env defaults for local development, +# for deploy enviroment configurations, see config.json + +# Base URL path for the enviroment +PUBLIC_URL='/dev/' + +# Name of enviroment for build +REACT_APP_KBASE_ENV='production' +# Domain of enviroment for build +REACT_APP_KBASE_DOMAIN='narrative.kbase.us' +# The following must be a subdomain of REACT_APP_KBASE_DOMAIN +REACT_APP_KBASE_LEGACY_DOMAIN='legacy.narrative.kbase.us' + +# Backup cookie name and domain, empty if unused by enviroment +REACT_APP_KBASE_BACKUP_COOKIE_NAME='kbase_session_backup' +REACT_APP_KBASE_BACKUP_COOKIE_DOMAIN='kbase.us' + +EXTEND_ESLINT='true' +SKIP_PREFLIGHT_CHECK='' diff --git a/dev/.env-narrative-dev b/dev/.env-narrative-dev new file mode 100644 index 00000000..e68f0fee --- /dev/null +++ b/dev/.env-narrative-dev @@ -0,0 +1,19 @@ +# Includes env defaults for local development, +# for deploy enviroment configurations, see config.json + +# Base URL path for the enviroment +PUBLIC_URL='/dev/' + +# Name of enviroment for build +REACT_APP_KBASE_ENV='narrative-dev' +# Domain of enviroment for build +REACT_APP_KBASE_DOMAIN='narrative-dev.kbase.us' +# The following must be a subdomain of REACT_APP_KBASE_DOMAIN +REACT_APP_KBASE_LEGACY_DOMAIN='legacy.narrative-dev.kbase.us' + +# Backup cookie name and domain, empty if unused by enviroment +REACT_APP_KBASE_BACKUP_COOKIE_NAME='' +REACT_APP_KBASE_BACKUP_COOKIE_DOMAIN='' + +EXTEND_ESLINT='true' +SKIP_PREFLIGHT_CHECK='true' diff --git a/dev/.env-next b/dev/.env-next new file mode 100644 index 00000000..eb289293 --- /dev/null +++ b/dev/.env-next @@ -0,0 +1,19 @@ +# Includes env defaults for local development, +# for deploy enviroment configurations, see config.json + +# Base URL path for the enviroment +PUBLIC_URL='/dev/' + +# Name of enviroment for build +REACT_APP_KBASE_ENV='next' +# Domain of enviroment for build +REACT_APP_KBASE_DOMAIN='next.kbase.us' +# The following must be a subdomain of REACT_APP_KBASE_DOMAIN +REACT_APP_KBASE_LEGACY_DOMAIN='legacy.next.kbase.us' + +# Backup cookie name and domain, empty if unused by enviroment +REACT_APP_KBASE_BACKUP_COOKIE_NAME='' +REACT_APP_KBASE_BACKUP_COOKIE_DOMAIN='' + +EXTEND_ESLINT='true' +SKIP_PREFLIGHT_CHECK='true' diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..90a82ff5 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,26 @@ +version: '3.6' +networks: + # For interoperation with kbase-ui and it's proxy. + # This form (with the name property) is required for automatic + # network creation and joining. + kbase-dev: + name: + kbase-dev +services: + europa-ui: + build: + context: . + dockerfile: Dockerfile + image: kbase/europa-ui:server + container_name: europa-ui + hostname: europa-ui + dns: 8.8.8.8 + ports: + - 3000:8080 + networks: + # For interoperation with kbase-ui and it's proxy + - kbase-dev + environment: + - STATIC_ENVIRONMENT + + \ No newline at end of file diff --git a/docs/scripts-with-docker.md b/docs/scripts-with-docker.md new file mode 100644 index 00000000..d1d8dce6 --- /dev/null +++ b/docs/scripts-with-docker.md @@ -0,0 +1,85 @@ +# Scripts with Docker + +Several of the scripts located in the `scripts` directory may be run through +Docker Compose via the top-level `docker-compose.yml`. + +## Setup + +Before using the tool, you'll need to install `npm` packages. First you'll need +to build the `node` image and shell into the container: + +```shell +./tools/node/run npm ci +``` + +## Tests + +The test command line is wrapped in a bash script `scripts/test` and run in the +node container: + +```shell +./tools/node/run ./scripts/test +``` + +To run the tests continually (though this is preferrably done in the +`devcontainer`): + +```shell +WATCH=true ./tools/node/run ./scripts/test +``` + +## Build + +The build command line is wrapped in a bash script `scripts/build` and run in +the node container. The build script is very similar to `build_deploy.sh`, but +separate, as that script is used by the GHA workflows. + +```shell +./tools/node/run ./scripts/build +``` + +or using the existing script `./scripts/build_deploy.sh`: + +```shell +./tools/node/run ./scripts/build_deploy.sh +``` + +## Working in container + +If you desire to work in the container, you may start a `bash` shell: + +```shell +./tools/node/run bash +``` + +You'll be dropped into the `/app` directory, which is the repo directory mounted +into the container. + +Here you may perform maintenacne tasks such as updating `package.json`, or +rebuilding `package-lock.json`. + +However, it is probably a better experience to work in the `devcontainer` to +perform such tasks. + +## Run local server + +The environemt builds above may be run through the nginx server container. The +`scripts/server` script starts the nginx server container with the deploy +environment specified in the environment variable `STATIC_ENVIRONMENT`, which +defaults to `ci-europa`. + +To run the server against CI: + +```shell +STATIC_ENVIRONMENT=ci ./scripts/server +``` + +and for all other environments: + +```shell +STATIC_ENVIRONMENT=ci-europa ./scripts/server +STATIC_ENVIRONMENT=narrative-dev ./scripts/server +STATIC_ENVIRONMENT=next ./scripts/server +STATIC_ENVIRONMENT=appdev ./scripts/server +STATIC_ENVIRONMENT=production ./scripts/server +``` diff --git a/scripts/build b/scripts/build new file mode 100755 index 00000000..dd445d2e --- /dev/null +++ b/scripts/build @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +# Note that Europa calls prod "production", but in all other cases the environment name +# serves as the hostname for the domain as well, so let us be consistent here, and +# handle the exception below. +deploy_envs=( ci ci-europa narrative-dev next appdev narrative ) + +for env in "${deploy_envs[@]}" +do + echo "ENV: ${env}" + + # The prod env is called "production" in Europa, as is the + # deploy directory. The rest are named after the environment + # hostname. + # + # in kbase-ui we've switched to "narrative" as the prod environmane name, + # since that is the hostname, just to avoid this sort of conditional. + # + if [ $env = "narrative" ] + then + dir="production" + backup_cookie_name="kbase_session_backup" + backup_cookie_domain="${env}.kbase.us" + else + dir=$env + backup_cookie_name="" + backup_cookie_domain="" + fi + + export BUILD_PATH="deploy/${dir}" + export REACT_APP_KBASE_ENV="${dir}" + export REACT_APP_KBASE_DOMAIN="${env}.kbase.us" + export REACT_APP_KBASE_LEGACY_DOMAIN="legacy.${env}.kbase.us" + export REACT_APP_KBASE_BACKUP_COOKIE_NAME="${backup_cookie_name}" + export REACT_APP_KBASE_BACKUP_COOKIE_DOMAIN="${backup_cookie_domain}" + export PUBLIC_URL=/ + npm run build +done diff --git a/scripts/server b/scripts/server new file mode 100755 index 00000000..03fc067c --- /dev/null +++ b/scripts/server @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +docker compose up +docker compose rm -f diff --git a/scripts/test b/scripts/test new file mode 100755 index 00000000..82fae565 --- /dev/null +++ b/scripts/test @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +npm run test . -- --coverage --verbose --watchAll="${WATCH:-false}" \ No newline at end of file diff --git a/tools/node/Dockerfile b/tools/node/Dockerfile new file mode 100644 index 00000000..89762321 --- /dev/null +++ b/tools/node/Dockerfile @@ -0,0 +1,8 @@ +FROM node:20.11.1-bookworm + +# Set up +RUN apt-get update && \ + apt-get install -y npm python3 git make bash jq + +# Install fixed npm, then all +RUN npm install --location=global npm@10.5.0 diff --git a/tools/node/docker-compose.yml b/tools/node/docker-compose.yml new file mode 100644 index 00000000..ba2c8e32 --- /dev/null +++ b/tools/node/docker-compose.yml @@ -0,0 +1,20 @@ +version: '3.8' +name: kbase-dev +networks: + kbase-dev: + name: kbase-dev +services: + node-tool: + working_dir: /app + build: + context: ../.. + dockerfile: tools/node/Dockerfile + container_name: node-builder + dns: 8.8.8.8 + networks: + - kbase-dev + environment: + # Add any environment variables supported by scripts + - WATCH + volumes: + - $DIR:/app \ No newline at end of file diff --git a/tools/node/run b/tools/node/run new file mode 100755 index 00000000..5b5c48a2 --- /dev/null +++ b/tools/node/run @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +DIR="${PWD}" docker compose -f tools/node/docker-compose.yml run --rm node-tool "$@" \ No newline at end of file