diff --git a/docs/about_decision_docs.md b/docs/about_decision_docs.md new file mode 100644 index 0000000..bc7472d --- /dev/null +++ b/docs/about_decision_docs.md @@ -0,0 +1,24 @@ +# What are Architecture Decision Records (ADRs)? + +Taken from https://adr.github.io/madr/, Architecture +Decision Records are markdown based records of major +architectural decisions that have occurrend in a project. +By including these docs formally within the source code, +you can gain insight into the major decision drivers and +see some potential alternatives that were considered but +ultimately rejected. + +# How to use + +A more thorough walkthrough of using the docs can be found at the website above, but generally speaking the steps are: + +* Make a copy of the madr_template.md file +* Rename copy using the format + `-.md` +* Use as much or as little of the template as needed to + accurate record the driving reasons why a change + was explored, what potential options were considered, + and what the ultimate decision outcome was +* Check in your ADR and request review for further comments + on proposal + \ No newline at end of file diff --git a/docs/decisions/0001-containerization-structure.md b/docs/decisions/0001-containerization-structure.md new file mode 100644 index 0000000..9f39e65 --- /dev/null +++ b/docs/decisions/0001-containerization-structure.md @@ -0,0 +1,127 @@ +# Project Containerization Needs and Design + +## Context and Problem Statement + +While moving towards a more scalable solution for +building, deploying, and hosting Tenant First Aid, we +need a method for deterministic builds, and +deployments that can easily scale by bringing up +identically performing service instances. + +## Decision Drivers + +* Builds for all parts of Tenant First Aid should be easy + to generate requiring as few commands as possible +* Build assets should be in a format that is easy to + consume by cloud services + +## Considered Options Front End +* Static FE assets built through GH actions and deployed + to a GCP Storage Bucket with CDN +* Full front end deployed as a GCP Cloud Run Node.JS app +* Continue deploying full app to a VM + +## Considered Options Back End +* Flask app deployed natively by gcloud api's cloud run + deploy function +* Flask app built agnostically, published to Artifact + Registry directly, served by Cloud Run +* Continue deploying full app to a VM + +## Considered Options Utility Scripts +* Run RAG generation script manually & locally +* Run RAG generation script in GH actions on change +* Deploy RAG generation script as Cloud Function + +## Decision Outcome + +Chosen option: "{title of option 1}", because {justification. e.g., only option, which meets k.o. criterion decision driver | which resolves force {force} | … | comes out best (see below)}. + +<!-- This is an optional element. Feel free to remove. --> +### Consequences + +* Good, because {positive consequence, e.g., improvement of one or more desired qualities, …} +* Bad, because {negative consequence, e.g., compromising one or more desired qualities, …} +* … <!-- numbers of consequences can vary --> + +## Pros and Cons of the Options Front End + +### Static FE assets built through GH actions and deployed to a GCP Storage Bucket with CDN + +If we expose the different parts of our app through GCP +Application Load Balancer, then we will get easy +integration with Cloud CDN (https://cloud.google.com/load-balancing/docs/load-balancing-overview). +The front end doesn't require any server side compute +and so the simplest and likely cheapest method would be +to transpile/build the front end in GH actions and deploy +the public assets generated from the build into a Cloud +Storage bucket. GCP buckets can be enabled for CDN serving +which can reduce the overall retrieval cost of frequently +served assets. + +* Good, because likely the cheapest solution +* Bad, because more GCP infrastructure to track + +### Full front end deployed as a GCP Cloud Run Node.JS app + +Similar to how the app is currently deployed via a Node app, +we can generate and publish a Node.JS based server for +providing the front end app. + +* Good, because this will use similar architecture as BE if + we go with the Cloud Run deploy option for the flask app +* Bad, because this option costs more +* Bad, because there is no actual benefit to hosting a + Node.js server just to serve static assets. + +### Continue deploying full app to a VM + +* Good, because this requires no additional work from current + process +* Bad, because this does not allow for the same level of + scalability as other considered options +* Bad, because this is likely the most expensive option + + +## Pros and Cons of the Options Back End + +### Flask app deployed natively by gcloud api's cloud run deploy function + +GCP's cli has some pretty handy built in functionality for +building and deploying python apps directly to Cloud Run (https://cloud.google.com/run/docs/quickstarts/build-and-deploy/deploy-python-service). +This builds and deploys the app in most likely a pretty +compact format using a GCP native image as its base. +These images do get deployed to an associated Artifact +Registry so it should be available to easily spawn +additional Cloud Run services with the same image +if necessary, such as for a staging/deployment +environment. + +* Good, because this will likely build the smallest image + required for serving the flask app as a Cloud Run + service +* Bad, because this will most likely not generate an image + that is runnable locally + +### Flask app built agnostically, published to Artifact Registry directly, served by Cloud Run + +As opposed to the previous option, this would entail +us or GH actions generating a docker/OCI image using +a lightweight image base such as python:alpine. Alpine +based images are normally as minimal as you can get while +still containing your required runtime. This image should +run the same locally as in the cloud. Once built, the image +would be deployed to an Artifact Registry, and then served +from a Cloud Run instance. + +* Good, because we should get the same behavior of this + image regardless of whether running locally or in the + cloud +* Bad, because it might possibly be a slightly larger image + size than the previous option resulting in a slight cost + increase which should be minimal but worth noting + +### Continue deploying full app to a VM + +* Good, because it's already done! +* Bad, because it's probably the most expensive option diff --git a/docs/decisions/madr_template.md b/docs/decisions/madr_template.md new file mode 100644 index 0000000..d85f861 --- /dev/null +++ b/docs/decisions/madr_template.md @@ -0,0 +1,74 @@ +--- +# These are optional metadata elements. Feel free to remove any of them. +status: "{proposed | rejected | accepted | deprecated | … | superseded by ADR-0123}" +date: {YYYY-MM-DD when the decision was last updated} +decision-makers: {list everyone involved in the decision} +consulted: {list everyone whose opinions are sought (typically subject-matter experts); and with whom there is a two-way communication} +informed: {list everyone who is kept up-to-date on progress; and with whom there is a one-way communication} +--- + +# {short title, representative of solved problem and found solution} + +## Context and Problem Statement + +{Describe the context and problem statement, e.g., in free form using two to three sentences or in the form of an illustrative story. You may want to articulate the problem in form of a question and add links to collaboration boards or issue management systems.} + +<!-- This is an optional element. Feel free to remove. --> +## Decision Drivers + +* {decision driver 1, e.g., a force, facing concern, …} +* {decision driver 2, e.g., a force, facing concern, …} +* … <!-- numbers of drivers can vary --> + +## Considered Options + +* {title of option 1} +* {title of option 2} +* {title of option 3} +* … <!-- numbers of options can vary --> + +## Decision Outcome + +Chosen option: "{title of option 1}", because {justification. e.g., only option, which meets k.o. criterion decision driver | which resolves force {force} | … | comes out best (see below)}. + +<!-- This is an optional element. Feel free to remove. --> +### Consequences + +* Good, because {positive consequence, e.g., improvement of one or more desired qualities, …} +* Bad, because {negative consequence, e.g., compromising one or more desired qualities, …} +* … <!-- numbers of consequences can vary --> + +<!-- This is an optional element. Feel free to remove. --> +### Confirmation + +{Describe how the implementation / compliance of the ADR can/will be confirmed. Is there any automated or manual fitness function? If so, list it and explain how it is applied. Is the chosen design and its implementation in line with the decision? E.g., a design/code review or a test with a library such as ArchUnit can help validate this. Note that although we classify this element as optional, it is included in many ADRs.} + +<!-- This is an optional element. Feel free to remove. --> +## Pros and Cons of the Options + +### {title of option 1} + +<!-- This is an optional element. Feel free to remove. --> +{example | description | pointer to more information | …} + +* Good, because {argument a} +* Good, because {argument b} +<!-- use "neutral" if the given argument weights neither for good nor bad --> +* Neutral, because {argument c} +* Bad, because {argument d} +* … <!-- numbers of pros and cons can vary --> + +### {title of other option} + +{example | description | pointer to more information | …} + +* Good, because {argument a} +* Good, because {argument b} +* Neutral, because {argument c} +* Bad, because {argument d} +* … + +<!-- This is an optional element. Feel free to remove. --> +## More Information + +{You might want to provide additional evidence/confidence for the decision outcome here and/or document the team agreement on the decision and/or define when/how this decision the decision should be realized and if/when it should be re-visited. Links to other decisions and resources might appear here as well.}