Skip to content

Commit

Permalink
Merge branch 'gql' into crowd-sourced-data
Browse files Browse the repository at this point in the history
  • Loading branch information
maxmwang committed Dec 24, 2024
2 parents 5df1d58 + c56db12 commit ec041e2
Show file tree
Hide file tree
Showing 38 changed files with 2,354 additions and 3 deletions.
91 changes: 91 additions & 0 deletions .github/workflows/cd-deploy-docs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Deploy Docs (Production)

concurrency: documentation

on:
push:
branches: [master, gql]

jobs:
detect-changes:
name: Detect Documentation Changes
runs-on: ubuntu-latest
outputs:
changed: ${{ steps.changed.outputs.any_changed }}

steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 2

- name: Detect Changed Files
uses: tj-actions/changed-files@v45
id: changed
with:
files: |
docs/**
build-push:
name: Build and Push Docs Image
needs: [detect-changes]
runs-on: ubuntu-latest
if: needs.detect-changes.outputs.changed == 'true'

steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build and push
uses: docker/build-push-action@v6
with:
context: docs
target: docs-prod
tags: ${{ secrets.DOCKER_USERNAME }}/bt-docs:prod
cache-from: type=registry,ref=${{ secrets.DOCKER_USERNAME }}/bt-docs:prod-cache
cache-to: type=registry,ref=${{ secrets.DOCKER_USERNAME }}/bt-docs:prod-cache,mode=max
platforms: linux/amd64
push: true

deploy:
name: SSH and Deploy
needs: [build-push]
runs-on: ubuntu-latest
environment: documentation

steps:
- name: SSH and Helm Install
uses: appleboy/[email protected]
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
set -e # Exit immediately if a command fails
# Check if helm chart exists
helm status bt-prod-docs &>/dev/null && status=true || status=false
# Upgrade helm chart, or install if not exists
helm upgrade bt-prod-docs oci://registry-1.docker.io/octoberkeleytime/bt-docs \
--install \
--version=1.0.0 \
--namespace=bt \
--set host=docs.stanfurdtime.com
# Restart deployment if helm chart existed
if [ $status = true ]; then
kubectl rollout restart deployment bt-prod-docs-docs
fi
# Check container status
kubectl rollout status --timeout=180s deployment bt-prod-docs-docs
14 changes: 11 additions & 3 deletions apps/frontend/src/app/Catalog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useCallback, useMemo, useState } from "react";

import classNames from "classnames";
import { Xmark } from "iconoir-react";
import moment from "moment";
import { useLocation, useNavigate, useParams } from "react-router-dom";

import { IconButton } from "@repo/theme";
Expand Down Expand Up @@ -47,14 +48,21 @@ export default function Catalog() {
const term = useMemo(() => {
if (!terms) return null;

const currentTerm = terms?.find(
// Default to the current term
const currentTerm = terms.find(
(term) => term.temporalPosition === TemporalPosition.Current
);

// Default to the current term
// Fall back to the next term when the current term has ended
const nextTerm = terms
.filter((term) => term.startDate)
.toSorted((a, b) => moment(a.startDate).diff(moment(b.startDate)))
.find((term) => term.temporalPosition === TemporalPosition.Future);

return (
terms?.find((term) => term.year === year && term.semester === semester) ??
currentTerm
currentTerm ??
nextTerm
);
}, [terms, year, semester]);

Expand Down
1 change: 1 addition & 0 deletions docs/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.excalidraw
1 change: 1 addition & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
book
26 changes: 26 additions & 0 deletions docs/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# dev
FROM rust:1.83 AS docs-dev
WORKDIR /docs

RUN ["cargo", "install", "mdbook", "--vers", "^0.4", "--locked"]
RUN ["cargo", "install", "mdbook-alerts"]

COPY . .
VOLUME ["/docs"]
EXPOSE 3000
ENTRYPOINT ["mdbook", "serve", "--hostname=0.0.0.0", "--port=3000"]

# prod
FROM rust:1.83 AS docs-builder
WORKDIR /docs

RUN ["cargo", "install", "mdbook", "--no-default-features", "--features", "search", "--vers", "^0.4", "--locked"]
RUN ["cargo", "install", "mdbook-alerts"]

COPY . .
RUN ["mdbook", "build"]

FROM nginx:alpine AS docs-prod
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=docs-builder /docs/book /var/www/html
EXPOSE 80
13 changes: 13 additions & 0 deletions docs/book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[book]
title = "Berkeleytime Documentation"
authors = ["Berkeleytime Developers"]
description = "The Berkeleytime documentation for developers"
language = "en"
multilingual = false
src = "src"

[output.html]
git-repository-url = "https://github.com/asuc-octo/berkeleytime/tree/gql/docs"
edit-url-template = "https://github.com/asuc-octo/berkeleytime/tree/gql/docs/{path}"

[preprocessor.alerts]
12 changes: 12 additions & 0 deletions docs/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
server {
root /var/www/html;

listen 80;
server_name localhost;

location / {
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
expires off;
sendfile off;
}
}
72 changes: 72 additions & 0 deletions docs/src/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Introduction

> [!WARNING]
> The Berkeleytime Documentation is currently under construction.
Welcome to the Berkeleytime Docs! This is the primary documentation source for developers.

## Getting Started

### Developing and Building Locally

There are two options: with and without containerization (ie. Docker).

#### With Containerization (Recommended)

Using Docker allows us to build the docs without downloading dependencies on our host machine, greatly simplifying the build process.

```sh
# ./berkeleytime
# Ensure you are on the latest commit
git pull

# Build the container
docker build --target docs-dev --tag="docs:dev" ./docs

# Run the container
docker run --publish 3000:3000 --volume ./docs:/docs "docs:dev"
```

The docs should be available at `http://localhost:3000/`. To change the port to port `XXXX`, modify the last command:
```sh
# Run the container and publish the docs to http://localhost:XXXX/
docker run --publish XXXX:3000 --volume ./docs:/docs "docs:dev"
```

#### Without Containerization

To build and view the docs locally, `mdBook` must be installed by following the guide [here](https://rust-lang.github.io/mdBook/guide/installation.html#build-from-source-using-rust). It is necessary to install Rust locally as there is a dependency that is installed with `cargo`. Thus, it is highly recommended to [build mdbook from Rust](https://rust-lang.github.io/mdBook/guide/installation.html#build-from-source-using-rust).

```sh
# Install mdbook-alerts dependency with cargo
cargo install mdbook-alerts

# ./berkeleytime
# Ensure you are on the latest commit
git pull

# Navigate into the docs directory
cd docs

# Build the book and serve at http://localhost:3000/
mdbook serve --port=3000 --open
```

Changes in the markdown files will be shown live.

### Creating Books with Markdown and mdBook

As these docs are primarily written with markdown, feel free to check [this quick guide](https://www.markdownguide.org/basic-syntax/) on markdown's syntax.

To add new pages to the docs, check out the [`mdBook` guide](https://rust-lang.github.io/mdBook/guide/creating.html). Below is a step-by-step guide on creating a new page:

1. Create a new `.md` file in the `src` directory. For example, if you want your new page to be in the Infrastructure section, you should put the new file in `src/infrastructure`.

2. Add this file to `SUMMARY.md`. The indentation indicates which section your file will go under. For example:

```md
- [Infrastructure](./infrastructure/README.md)
- [My New File's Title](./infrastructure/my-new-file.md)
```

3. Add content to your file and see the results!
38 changes: 38 additions & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Summary

[Introduction](README.md)

---

# Getting Started

- [Local Development](./getting-started/local-development.md)
- [Deployment with CI/CD](./getting-started/deployment-with-cicd.md)

---

# Core Documentation

- [Backend](./core/backend/README.md)

- [Datapuller](./core/datapuller/README.md)

- [Frontend](./core/frontend/README.md)

- [Infrastructure](./core/infrastructure/README.md)
- [Onboarding](./core/infrastructure/onboarding.md)
- [Architecture](./core/infrastructure/architecture.md)
- [Kubernetes & Helm](./core/infrastructure/kubernetes-helm.md)
- [CI/CD](./core/infrastructure/cicd.md)

---

# Fall 2024 Pods

- [Crowd Sourced Data](./fa24/crowd-sourced-data/README.md)

- [Decals](./fa24/decals/README.md)

- [GradTrak](./fa24/gradtrak/README.md)

- [Semantic Search](./fa24/semantic-search/README.md)
3 changes: 3 additions & 0 deletions docs/src/core/backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Backend

TODO
3 changes: 3 additions & 0 deletions docs/src/core/datapuller/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Datapuller

TODO
3 changes: 3 additions & 0 deletions docs/src/core/frontend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Frontend

TODO
18 changes: 18 additions & 0 deletions docs/src/core/infrastructure/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Infrastructure

> [!WARNING]
> The infrastructure section is currently under construction.
Welcome to the infrastructure section.

> [!NOTE]
> Infrastructure concepts tend to be more complex than application concepts. Don't be discouraged if a large amount of content in the infrastructure section is confusing!
## What is Infrastructure?

![application-infrastructure-layers](./assets/app-infra-layer.svg)

Software infrastructure refers to the services and tools that create an underlying layer of abstractions that the application is developed on. Compared to the application layer, infrastructure is significantly more broad in its responsibilities, although these responsibilities are more common in software development.

> [!IMPORTANT]
> We aim to use a **small** set of **existing** infrastructure solutions with large communities. This philosophy reduces the [cognitive load](https://thevaluable.dev/cognitive-load-theory-software-developer/) on each developer and simplifies the onboarding process, both of which are valuable for creating long-lasting software in a team where developers are typically cycled out after only ~4 years.
35 changes: 35 additions & 0 deletions docs/src/core/infrastructure/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Architecture

Berkeleytime uses a fairly simple microservices architecture—we decouple only a few application components into separate services. Below is a high-level diagram of the current architecture (switch to a light viewing mode to see arrows).
<p align="center">
<img
src="./assets/architecture-diagram.svg"
alt="berkeleytime architecture design"
width="75%" />
</p>

Note that, other than the application services developed by us, all other services are well-known and have large communities. These services have many tutorials, guides, and issues already created online, streamlining the setup and debugging processes.

## An HTTP Request's Life

To better understand the roles of each component in the Berkeleytime architecture, we describe the lifecycle of an HTTP request from a user's action.

1. An HTTP request starts from a user's browser. For example, when a user visits `https://berkeleytime.com`, a `GET` request is sent to `hozer-51`.[^1]

2. Once the request reaches `hozer-51`, it is first encountered by `hozer-51`'s Kubernetes cluster load balancer, a [MetalLB](https://metallb.io/) instance, which balances external traffic into the cluster across nodes.[^2]

3. Next, the request reaches the [reverse proxy](https://www.cloudflare.com/learning/cdn/glossary/reverse-proxy/), an [nginx](https://nginx.org/) instance, which forwards HTTP requests to either the [backend](../backend) or [frontend](../frontend/) service based on the URL of the request.
- Requests with URLs matching `https://berkeleytime.com/api/*` are forwarded to the backend service.
- All other requests are forwarded to the frontend service.

4. The request is processed by one of the services.
- The backend service may interact with the MongoDB database or the Redis cache while processing the request.[^3]

5. Finally, an HTTP response is sent back through the system to the user's machine.


[^1]: More specifically, the user's machine first requests a DNS record of `berkeleytime.com` from a DNS server, which should return `hozer-51`'s IP address. After the user's machine knows the `hozer-51` IP address, the `GET` request is sent.

[^2]: Currently, we only have one node: `hozer-51`.

[^3]: Requests sent from the backend to the database or cache are *not* necessarily HTTP requests.
Loading

0 comments on commit ec041e2

Please sign in to comment.