From d88fe67c2f94e6bc77d02592e010c51cf228f98d Mon Sep 17 00:00:00 2001 From: Benoit Dherin Date: Tue, 28 May 2024 16:16:31 -0700 Subject: [PATCH 1/3] initial scaffold --- scaffolds/app_engine/.gcloudignore | 19 +++ scaffolds/app_engine/Makefile | 30 ++++ scaffolds/app_engine/README.md | 41 +++++ scaffolds/app_engine/app.yaml | 10 ++ scaffolds/app_engine/app/__init__.py | 0 scaffolds/app_engine/app/server.py | 35 +++++ scaffolds/app_engine/app/static/asl.png | Bin 0 -> 77798 bytes scaffolds/app_engine/app/static/index.html | 30 ++++ scaffolds/app_engine/app/static/main.css | 161 ++++++++++++++++++++ scaffolds/app_engine/app/static/main.js | 51 +++++++ scaffolds/app_engine/requirements.txt | 4 + scaffolds/app_engine/scripts/config.sh | 9 ++ scaffolds/app_engine/scripts/deploy.sh | 6 + scaffolds/app_engine/scripts/run_locally.sh | 11 ++ scaffolds/app_engine/scripts/run_tests.sh | 11 ++ scaffolds/app_engine/setup.py | 14 ++ scaffolds/app_engine/tests/server_test.py | 11 ++ 17 files changed, 443 insertions(+) create mode 100644 scaffolds/app_engine/.gcloudignore create mode 100644 scaffolds/app_engine/Makefile create mode 100644 scaffolds/app_engine/README.md create mode 100644 scaffolds/app_engine/app.yaml create mode 100644 scaffolds/app_engine/app/__init__.py create mode 100644 scaffolds/app_engine/app/server.py create mode 100644 scaffolds/app_engine/app/static/asl.png create mode 100644 scaffolds/app_engine/app/static/index.html create mode 100644 scaffolds/app_engine/app/static/main.css create mode 100644 scaffolds/app_engine/app/static/main.js create mode 100644 scaffolds/app_engine/requirements.txt create mode 100644 scaffolds/app_engine/scripts/config.sh create mode 100755 scaffolds/app_engine/scripts/deploy.sh create mode 100755 scaffolds/app_engine/scripts/run_locally.sh create mode 100755 scaffolds/app_engine/scripts/run_tests.sh create mode 100644 scaffolds/app_engine/setup.py create mode 100644 scaffolds/app_engine/tests/server_test.py diff --git a/scaffolds/app_engine/.gcloudignore b/scaffolds/app_engine/.gcloudignore new file mode 100644 index 00000000..b30f57d9 --- /dev/null +++ b/scaffolds/app_engine/.gcloudignore @@ -0,0 +1,19 @@ +# This file specifies files that are *not* uploaded to Google Cloud +# using gcloud. It follows the same syntax as .gitignore, with the addition of +# "#!include" directives (which insert the entries of the given .gitignore-style +# file at that point). +# +# For more information, run: +# $ gcloud topic gcloudignore +# +.gcloudignore +# If you would like to upload your .git directory, .gitignore file or files +# from your .gitignore file, remove the corresponding line +# below: +.git +.gitignore + +# Python pycache: +__pycache__/ +# Ignored by the build system +/setup.cfg diff --git a/scaffolds/app_engine/Makefile b/scaffolds/app_engine/Makefile new file mode 100644 index 00000000..e35de72e --- /dev/null +++ b/scaffolds/app_engine/Makefile @@ -0,0 +1,30 @@ +all: clean venv + +.PHONY: clean +clean: + @find . -name '*.pyc' -delete + @find . -name '__pycache__' -delete + @find . -name '*egg-info' -type d -exec rm -r {} + + @find . -name '.pytest_cache' -type d -exec rm -r {} + + @rm -rf venv + +.PHONY: venv +venv: + @python3 -m venv venv + @. venv/bin/activate && pip install -U pip && pip install -e . + +.PHONY: auth +auth: + gcloud auth application-default login + +.PHONY: tests +tests: + ./scripts/run_tests.sh + +.PHONY: deploy +deploy: clean + ./scripts/deploy.sh + +.PHONY: run +run: + ./scripts/run_locally.sh diff --git a/scaffolds/app_engine/README.md b/scaffolds/app_engine/README.md new file mode 100644 index 00000000..516be00c --- /dev/null +++ b/scaffolds/app_engine/README.md @@ -0,0 +1,41 @@ +# Developpment Workflow + + +## Local developpment + +The workflow described here works from CloudShell or any node with the gcloud SDK authenticated +,that is, you can do the developpement fully locally on your laptop, which is the preferred +development environment. + +For local development, first install the Google SDK following these instructions(https://cloud.google.com/sdk/docs/install#mac). +Make sure to accept upgrading Python to 3.10 when prompted, then authenticate for local development by running: +```bash +make auth +``` + +Then create and populate the virtual environment: +```bash +make venv +``` + +To run the tests: +```bash +make tests +``` + +Run the answernaut locally with +```bash +make run +``` + +Deploy on AppEngine +```bash +make deploy +``` + +## Developpement workflow + +1. Edit the code +1. Run the tests with `make tests` +1. Test the app local with `make run` +1. Deploy the app on AppEngine with `make deploy` diff --git a/scaffolds/app_engine/app.yaml b/scaffolds/app_engine/app.yaml new file mode 100644 index 00000000..cc7bb2bb --- /dev/null +++ b/scaffolds/app_engine/app.yaml @@ -0,0 +1,10 @@ +runtime: python310 +entrypoint: gunicorn -b :$PORT asl.server:app + +runtime_config: + operating_system: "ubuntu22" + +env_variables: + BUCKET: "dherin-dev" + LOCATION: "us-central1" + PROJECT: "dherin-dev" diff --git a/scaffolds/app_engine/app/__init__.py b/scaffolds/app_engine/app/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/scaffolds/app_engine/app/server.py b/scaffolds/app_engine/app/server.py new file mode 100644 index 00000000..4b836284 --- /dev/null +++ b/scaffolds/app_engine/app/server.py @@ -0,0 +1,35 @@ +""" Flask serving API and small demo UI. +""" +import logging + +from flask import Flask, jsonify, request, send_file + + +app = Flask(__name__) + + +@app.route("/") +def _index(): + """Serve index.html in the static directory""" + return send_file("static/index.html") + + +@app.route("/myapp", methods=["GET"]) +def _answernaut(): + return jsonify({"answer": request.args["query"]}) + + +@app.errorhandler(500) +def _server_error(e): + """Serves a formatted message on-error""" + logging.exception("An error occurred during a request.") + return ( + f"An internal error occurred:
{e}

", + 500, + ) + + +if __name__ == "__main__": + # This is used when running locally. Gunicorn is used to run the + # application on Google App Engine. See entrypoint in app.yaml. + app.run(host="127.0.0.1", port=8080, debug=True) diff --git a/scaffolds/app_engine/app/static/asl.png b/scaffolds/app_engine/app/static/asl.png new file mode 100644 index 0000000000000000000000000000000000000000..02a0b901608ad95f51861b9aebb60a949d7b6196 GIT binary patch literal 77798 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 + + + + + + + + +

+ + + + + + diff --git a/scaffolds/app_engine/app/static/main.css b/scaffolds/app_engine/app/static/main.css new file mode 100644 index 00000000..7efa8f8e --- /dev/null +++ b/scaffolds/app_engine/app/static/main.css @@ -0,0 +1,161 @@ + +*, ::after, ::before { + box-sizing: border-box; + border-width: 0; + border-style: solid; + border-color: #e5e7eb; + font-size: 1rem; + font-family: ui-sans-serif, system-ui, -apple-system, "system-ui", "Segoe UI"; +} + +.body { + padding: 4rem; + justify-content: center; + display: flex; + flex-direction: column; + align-items: center; + width: 100vw; + height: 100vh; +} + +.logo { + margin-bottom: 2.5rem; +} + +.form { + display: flex; + flex-direction: column; + align-items: center; + width: 50%; + margin-bottom: 3rem; +} + +.input { + padding-left: 0.5rem; + padding-right: 0.5rem; + border-width: 1px; + border-radius: 0.5rem; + width: 100%; + height: 2rem; +} + +.ask { + padding-top: 0.25rem; + padding-bottom: 0.25rem; + padding-left: 0.5rem; + padding-right: 0.5rem; + border-width: 1px; + border-color: rgb(191 219 254); + border-radius: 0.5rem; + margin-left: 0.75rem; + margin-top: 2rem; + width: 4rem; + background-color: rgb(219 234 254); +} + +button.ask:hover { + background-color: rgb(3 105 161); +} + +.answer { + display: flex; + padding: 1.25rem; + background-color: rgb(219 234 254); + border-color: rgb(191 219 254); + border-radius: 0.5rem; + width: 50%; + line-height: 1.4rem; + display: none; + overflow-y: auto; +} + +.hide { + display: none !important; +} + +.show { + display: block !important; +} + + +/* Spinner */ + +.lds-spinner { + color: official; + display: inline-block; + position: relative; + width: 80px; + height: 80px; + display: none; +} +.lds-spinner div { + transform-origin: 40px 40px; + animation: lds-spinner 1.2s linear infinite; +} +.lds-spinner div:after { + content: " "; + display: block; + position: absolute; + top: 3px; + left: 37px; + width: 6px; + height: 18px; + border-radius: 20%; + background: rgb(66,132,243); +} +.lds-spinner div:nth-child(1) { + transform: rotate(0deg); + animation-delay: -1.1s; +} +.lds-spinner div:nth-child(2) { + transform: rotate(30deg); + animation-delay: -1s; +} +.lds-spinner div:nth-child(3) { + transform: rotate(60deg); + animation-delay: -0.9s; +} +.lds-spinner div:nth-child(4) { + transform: rotate(90deg); + animation-delay: -0.8s; +} +.lds-spinner div:nth-child(5) { + transform: rotate(120deg); + animation-delay: -0.7s; +} +.lds-spinner div:nth-child(6) { + transform: rotate(150deg); + animation-delay: -0.6s; +} +.lds-spinner div:nth-child(7) { + transform: rotate(180deg); + animation-delay: -0.5s; +} +.lds-spinner div:nth-child(8) { + transform: rotate(210deg); + animation-delay: -0.4s; +} +.lds-spinner div:nth-child(9) { + transform: rotate(240deg); + animation-delay: -0.3s; +} +.lds-spinner div:nth-child(10) { + transform: rotate(270deg); + animation-delay: -0.2s; +} +.lds-spinner div:nth-child(11) { + transform: rotate(300deg); + animation-delay: -0.1s; +} +.lds-spinner div:nth-child(12) { + transform: rotate(330deg); + animation-delay: 0s; +} +@keyframes lds-spinner { + 0% { + opacity: 1; + } + 100% { + opacity: 0; + } +} diff --git a/scaffolds/app_engine/app/static/main.js b/scaffolds/app_engine/app/static/main.js new file mode 100644 index 00000000..7161f879 --- /dev/null +++ b/scaffolds/app_engine/app/static/main.js @@ -0,0 +1,51 @@ +async function queryApi(prompt) { + const endpoint = `/myapp?query=${prompt}` + const response = await fetch(endpoint) + const answer = await response.json() + return answer +} + +function displayAnswer(answer) { + const queryAnswer = document.getElementById("query-answer") + queryAnswer.innerHTML = ` ${answer} ` +} + +function getPrompt() { + const queryInput = document.getElementById("query-input") + return queryInput.value +} + +function getAnswer() { + const spinner = document.getElementById("spinner") + const queryAnswer = document.getElementById("query-answer") + queryAnswer.classList.remove("show") + spinner.classList.add("show") + const prompt = getPrompt() + queryApi(prompt).then( + response => { + spinner.classList.remove("show") + queryAnswer.classList.add("show") + displayAnswer(response.answer) + } + ) + +} + +function init() { + const queryForm = document.getElementById("query-form") + queryForm.addEventListener("submit", e => { + e.preventDefault() + getAnswer() + }) + + const queryInput = document.getElementById("query-input") + queryInput.addEventListener("keyup", e => { + e.preventDefault() + if (e.KeyCode === 13){ + document.getElementById("ask-button").click() + } + }) + + } + +init() diff --git a/scaffolds/app_engine/requirements.txt b/scaffolds/app_engine/requirements.txt new file mode 100644 index 00000000..dfa62aca --- /dev/null +++ b/scaffolds/app_engine/requirements.txt @@ -0,0 +1,4 @@ +Flask==3.0.0 +gunicorn==20.1.0 +pre-commit==3.7.1 +pytest==7.0.1 diff --git a/scaffolds/app_engine/scripts/config.sh b/scaffolds/app_engine/scripts/config.sh new file mode 100644 index 00000000..58dc83a3 --- /dev/null +++ b/scaffolds/app_engine/scripts/config.sh @@ -0,0 +1,9 @@ +PROJECT="dherin-dev" +LOCATION="us-central1" +BUCKET="dherin-dev" + +# Compute various paths from the ROOT_DIR +ROOT_DIR="$(dirname $(cd $(dirname $BASH_SOURCE) && pwd))" +SCRIPTS_DIR="$ROOT_DIR/scripts" +APP_YAML="$ROOT_DIR/app.yaml" +VENV="$ROOT_DIR/venv" diff --git a/scaffolds/app_engine/scripts/deploy.sh b/scaffolds/app_engine/scripts/deploy.sh new file mode 100755 index 00000000..2cbed92d --- /dev/null +++ b/scaffolds/app_engine/scripts/deploy.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +. $(cd $(dirname $BASH_SOURCE) && pwd)/config.sh + +gcloud app deploy $APP_YAML --project=$PROJECT +gcloud app browse --project=$PROJECT diff --git a/scaffolds/app_engine/scripts/run_locally.sh b/scaffolds/app_engine/scripts/run_locally.sh new file mode 100755 index 00000000..fa9bf62c --- /dev/null +++ b/scaffolds/app_engine/scripts/run_locally.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +. $(cd $(dirname $BASH_SOURCE) && pwd)/config.sh + + +export BUCKET=$BUCKET +export LOCATION=$LOCATION +export PROJECT=$PROJECT + +gcloud config set project $PROJECT +. $VENV/bin/activate && python -m app.server diff --git a/scaffolds/app_engine/scripts/run_tests.sh b/scaffolds/app_engine/scripts/run_tests.sh new file mode 100755 index 00000000..eaa0e9ef --- /dev/null +++ b/scaffolds/app_engine/scripts/run_tests.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +. $(cd $(dirname $BASH_SOURCE) && pwd)/config.sh + + +export BUCKET=$BUCKET +export LOCATION=$LOCATION +export PROJECT=$PROJECT + +gcloud config set project $PROJECT +. $VENV/bin/activate && pytest "$ROOT_DIR/tests" diff --git a/scaffolds/app_engine/setup.py b/scaffolds/app_engine/setup.py new file mode 100644 index 00000000..ec61e930 --- /dev/null +++ b/scaffolds/app_engine/setup.py @@ -0,0 +1,14 @@ +""" Setup for pip install -e . +""" +from setuptools import find_packages, setup + +REQS = None +with open("requirements.txt", encoding="utf-8") as fp: + REQS = [req.strip() for req in fp.readlines()] + +setup( + name="app", + version="0.1", + packages=find_packages(), + install_requires=REQS, +) diff --git a/scaffolds/app_engine/tests/server_test.py b/scaffolds/app_engine/tests/server_test.py new file mode 100644 index 00000000..815b19d8 --- /dev/null +++ b/scaffolds/app_engine/tests/server_test.py @@ -0,0 +1,11 @@ +""" Integration tests for server.py +""" +from app import server + + +def test_query(): + server.app.testing = True + client = server.app.test_client() + + r = client.get("/myapp?query=if+I+were+a+unicorn") + assert r.status_code == 200 From 6c3de47452d35d97b095f6fd6ff746dbad5b72a3 Mon Sep 17 00:00:00 2001 From: Benoit Dherin Date: Wed, 29 May 2024 14:36:32 -0700 Subject: [PATCH 2/3] refactor deployment scripts and updated README.md --- scaffolds/app_engine/Makefile | 1 + scaffolds/app_engine/README.md | 34 ++++++++++++++-------- scaffolds/app_engine/app.yaml | 6 ++-- scaffolds/app_engine/scripts/config.sh | 4 +-- scaffolds/app_engine/scripts/create_app.sh | 8 +++++ 5 files changed, 36 insertions(+), 17 deletions(-) create mode 100755 scaffolds/app_engine/scripts/create_app.sh diff --git a/scaffolds/app_engine/Makefile b/scaffolds/app_engine/Makefile index e35de72e..1d08efd5 100644 --- a/scaffolds/app_engine/Makefile +++ b/scaffolds/app_engine/Makefile @@ -23,6 +23,7 @@ tests: .PHONY: deploy deploy: clean + ./scripts/create_app.sh ./scripts/deploy.sh .PHONY: run diff --git a/scaffolds/app_engine/README.md b/scaffolds/app_engine/README.md index 516be00c..0b23fc18 100644 --- a/scaffolds/app_engine/README.md +++ b/scaffolds/app_engine/README.md @@ -1,41 +1,51 @@ -# Developpment Workflow +# Development Workflow +## Local development -## Local developpment +The workflow described here works from CloudShell or any node with the [gcloud CLI](https://cloud.google.com/sdk/docs/install) has been properly installed and authenticated. -The workflow described here works from CloudShell or any node with the gcloud SDK authenticated -,that is, you can do the developpement fully locally on your laptop, which is the preferred -development environment. +This means that you can develop your application fully locally on your laptop for example, as long as you have run `make auth` after installing the [gcloud CLI](https://cloud.google.com/sdk/docs/install) on it. + +The first step is to add your `PROJECT` and `BUCKET` names in the following files: +* `./scripts/config.sh` +* `app.yaml` + +For local development, install then the gcloud CLI following [these instructions](https://cloud.google.com/sdk/docs/install). + +Make sure to accept upgrading Python to 3.10 if prompted, then authenticate for local development by running: -For local development, first install the Google SDK following these instructions(https://cloud.google.com/sdk/docs/install#mac). -Make sure to accept upgrading Python to 3.10 when prompted, then authenticate for local development by running: ```bash make auth ``` -Then create and populate the virtual environment: +The second step is to create and populate the virtual environment with + ```bash make venv ``` +After this step you should find a new folder called `venv` containing the virtual environment. -To run the tests: +At this point you should already be able to run the tests by running ```bash make tests ``` -Run the answernaut locally with +To run the app locally, simply run ```bash make run ``` -Deploy on AppEngine +At last to deploy the application on AppEngine run ```bash make deploy ``` -## Developpement workflow +**Note:** `make clean` will remove all the built artifacts as long as the virtual environment created by `make venv`. This target is invoked by `make deploy` so that the built artifacts are not uploaded to AppEngine. The down-side is that the virtual environment will need to be recreated after each deployment. + +## Development workflow 1. Edit the code 1. Run the tests with `make tests` 1. Test the app local with `make run` 1. Deploy the app on AppEngine with `make deploy` + diff --git a/scaffolds/app_engine/app.yaml b/scaffolds/app_engine/app.yaml index cc7bb2bb..7ae895f5 100644 --- a/scaffolds/app_engine/app.yaml +++ b/scaffolds/app_engine/app.yaml @@ -1,10 +1,10 @@ runtime: python310 -entrypoint: gunicorn -b :$PORT asl.server:app +entrypoint: gunicorn -b :$PORT app.server:app runtime_config: operating_system: "ubuntu22" env_variables: - BUCKET: "dherin-dev" + BUCKET: "" LOCATION: "us-central1" - PROJECT: "dherin-dev" + PROJECT: "" diff --git a/scaffolds/app_engine/scripts/config.sh b/scaffolds/app_engine/scripts/config.sh index 58dc83a3..802bd7d6 100644 --- a/scaffolds/app_engine/scripts/config.sh +++ b/scaffolds/app_engine/scripts/config.sh @@ -1,6 +1,6 @@ -PROJECT="dherin-dev" +PROJECT="" LOCATION="us-central1" -BUCKET="dherin-dev" +BUCKET="" # Compute various paths from the ROOT_DIR ROOT_DIR="$(dirname $(cd $(dirname $BASH_SOURCE) && pwd))" diff --git a/scaffolds/app_engine/scripts/create_app.sh b/scaffolds/app_engine/scripts/create_app.sh new file mode 100755 index 00000000..0e5435ba --- /dev/null +++ b/scaffolds/app_engine/scripts/create_app.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +. $(cd $(dirname $BASH_SOURCE) && pwd)/config.sh + +gcloud app describe --project=$PROJECT 2> /dev/null || { + echo "No App on AppEngine existing. Creating one." + gcloud app create --region=$LOCATION --project=$PROJECT +} From c25ae4a577c7c4ee78cbaddd480de128ea1e68eb Mon Sep 17 00:00:00 2001 From: BenoitDherin Date: Wed, 29 May 2024 22:08:45 +0000 Subject: [PATCH 3/3] precommit --- scaffolds/app_engine/README.md | 11 +++++------ scaffolds/app_engine/app/server.py | 2 +- scaffolds/app_engine/setup.py | 1 + scaffolds/app_engine/tests/server_test.py | 1 + 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/scaffolds/app_engine/README.md b/scaffolds/app_engine/README.md index 0b23fc18..6034b68b 100644 --- a/scaffolds/app_engine/README.md +++ b/scaffolds/app_engine/README.md @@ -1,10 +1,10 @@ -# Development Workflow +# Development Workflow ## Local development -The workflow described here works from CloudShell or any node with the [gcloud CLI](https://cloud.google.com/sdk/docs/install) has been properly installed and authenticated. +The workflow described here works from CloudShell or any node with the [gcloud CLI](https://cloud.google.com/sdk/docs/install) has been properly installed and authenticated. -This means that you can develop your application fully locally on your laptop for example, as long as you have run `make auth` after installing the [gcloud CLI](https://cloud.google.com/sdk/docs/install) on it. +This means that you can develop your application fully locally on your laptop for example, as long as you have run `make auth` after installing the [gcloud CLI](https://cloud.google.com/sdk/docs/install) on it. The first step is to add your `PROJECT` and `BUCKET` names in the following files: * `./scripts/config.sh` @@ -23,14 +23,14 @@ The second step is to create and populate the virtual environment with ```bash make venv ``` -After this step you should find a new folder called `venv` containing the virtual environment. +After this step you should find a new folder called `venv` containing the virtual environment. At this point you should already be able to run the tests by running ```bash make tests ``` -To run the app locally, simply run +To run the app locally, simply run ```bash make run ``` @@ -48,4 +48,3 @@ make deploy 1. Run the tests with `make tests` 1. Test the app local with `make run` 1. Deploy the app on AppEngine with `make deploy` - diff --git a/scaffolds/app_engine/app/server.py b/scaffolds/app_engine/app/server.py index 4b836284..2de65092 100644 --- a/scaffolds/app_engine/app/server.py +++ b/scaffolds/app_engine/app/server.py @@ -1,10 +1,10 @@ """ Flask serving API and small demo UI. """ + import logging from flask import Flask, jsonify, request, send_file - app = Flask(__name__) diff --git a/scaffolds/app_engine/setup.py b/scaffolds/app_engine/setup.py index ec61e930..e731f76f 100644 --- a/scaffolds/app_engine/setup.py +++ b/scaffolds/app_engine/setup.py @@ -1,5 +1,6 @@ """ Setup for pip install -e . """ + from setuptools import find_packages, setup REQS = None diff --git a/scaffolds/app_engine/tests/server_test.py b/scaffolds/app_engine/tests/server_test.py index 815b19d8..3c7f7213 100644 --- a/scaffolds/app_engine/tests/server_test.py +++ b/scaffolds/app_engine/tests/server_test.py @@ -1,5 +1,6 @@ """ Integration tests for server.py """ + from app import server