Skip to content

For Developers

Silas Santini edited this page Oct 14, 2026 · 9 revisions

This is a guide for project developers and repository maintainers to set up their environment and start developing.

Local Setup

Step 1: Clone Repo

Clone the repository and change directories into the repository.

	git clone git@github.com:berkeley-cdss/seating.git
	cd seating

Step 2: Set up Virtual Environment

Create and activate a virtual environment.

Windows:

	python3 -m venv venv
	./venv/Scripts/activate

Mac:

	python3 -m venv venv
	source venv/bin/activate

Step 3: Install Dependencies

You should install from both requirements.txt and requirements-dev.txt. Make sure you are in the virtual environment.

    pip install -r requirements.txt
    pip install -r requirements-dev.txt

Step 4: Set up Environment Variables

Create a file named .env and copy into it the contents of .env.sample which includes all needed variables and explanations. Fill in the environment variables that you can. You will need a few API keys and secrets. See the section on external Services for more details.

Step 5: Set up Database

For development, use a local sqlite3 database which does not require configuring any server or connection string. You only need to initialize the database once.

   flask resetdb

Step 6: Spin up the Server

   flask run

Open localhost:5000. You should be able to see the app running locally.

Step 7: Navigate the App

Try clicking into a course offering and create an exam.

Use this demo Google Sheet to import rooms and students, and trying out assigning seatings.

External Services

To use the full functionality of the app, you will need to set up the following external services.

Bare Minimum

This section covers the bare minimum that is needed for functionality of the app.

Authentication: Canvas API

This is for user authentication and data fetching of courses, students, etc.

Contact School LTI team to register your app and client ID and secret.

At Berkeley, the contact email is bcourseshelp AT berkeley DOT edu. Only faculty and staff members should request changes to the keys that are in place for bCourses and test bCourses. Our deployed production app and staging deployment runs on production bCourses. PR previews run on a test instance that closely mirrors production bCourses.

Local development should take place using https://ucberkeleysandbox.instructure.com/. Contact the maintainers of this repository to gain access. Unlike with bCourses/test bCourses, in this sandbox environment we are able to create and edit keys directly. This sandbox environment should not contain real student data.

Google Sheet import functionality: GCP Service Account

This is for Google Sheets API to bulk import rooms and students

Set up a GCP Project and create a service account with the role Project Editor.

There are two ways to provide service account credentials to the app. In any case you will need to download the service account key as a JSON file from GCP Dashboard first, and set GCP_SA_CRED_TYPE to either file or env.

  • Use credentials file
    1. Download the service account key as a JSON file from GCP Dashboard and save it to root directory of the repo as gcp-service-account-credentials.json.
    2. Set the environment variable GCP_SA_CRED_TYPE to file.
    3. Set the environment variable GCP_SA_CRED_FILE to gcp-service-account-credentials.json.
    4. You could of course use a different file path, but make sure you set the environment variable accordingly and never commit the file to version control. The default name of gcp-service-account-credentials.json is already in .gitignore.
  • Use environment variables
    1. Sometimes, using a credentials file is not convenient, like with GitHub Actions and Heroku. You can also encode the content of the downloaded JSON file into a base64 string and supply it via an environment variable.
    2. Download the service account key as a JSON file from GCP Dashboard.
    3. Encode the content of the JSON file into a base64 string. base64 -w 0 path/to/your/service-account-file.json
    4. Set the environment variable GCP_SA_CRED_TYPE to env.
    5. Set the environment variable GCP_SA_CRED_VALUE to the base64 string you just obtained.

Sending emails: An SMTP server

This is for sending emails to students about their seat assignments.

The deployed app sends through the campus SMTP relay using a SPA:

Variable Value
EMAIL_SERVER bcop.berkeley.edu
EMAIL_PORT 587 (STARTTLS)
EMAIL_USERNAME svc-bcop-seamless-learning
EMAIL_SENDER seamless-learning@berkeley.edu (the "From" address)
EMAIL_PASSWORD stored in GCP Secret Manager as seating-email-password

For local development, you can point the EMAIL_* variables at any SMTP server you have access to, e.g. a personal Gmail account or bMail. Be careful about sending real emails to students from a local setup.

Non-essential

The following are related not to functionality but to DevOps.

Heroku (phasing out)

We use Heroku for staging environment. You can use any staging environment. This integration is not intrusive and you do not need to remove anything from the repo if you move away from Heroku.

Right now, we have a Heroku staging environment which uses my personal account (which, should not be the case). If I graduate or if it expires you should get a new one. We should consider shifting to department service account at some point in the future.

We are phasing out the use of Heroku.

Codecov (needs to be updated)

We integrated Codecov for testing coverage report in Github CI. We have already set up the relevant workflow step and put in the Github Repository secret CODECOV_TOKEN, using my personal account (which, should not be the case). If the token expires or if I graduate, make sure to get a new CodeCov account and get a new token. We should consider shifting to department service account at some point in the future.

Sentry (needs to be updated)

We integrated Sentry for server monitoring. We have already integrated it and the only relevant piece of codes are in the root __init__.py. If that DSN expires of if I graduate, make sure to get a new account and new token. We should consider shifting to department service account at some point in the future. We should also apply to Open Source credential for Sentry.

Available CLI Commands

# intialize database
flask initdb
# drop database
flask dropdb
# seed database
flask seeddb
# reset database (drop, init, seed)
flask resetdb
# run linting check
flask lint
# run unit tests
flask unit
# run e2e tests
flask e2e
# run a11y tests
flask a11y
# run all tests (unit, e2e, a11y)
flask test
# run security audit
flask audit

DevOps

Testing

This repo is equipped with some typical testing scaffoldings you might expect to find in a full-stack application:

  • Test runner: pytest
  • Coverage: pytest-cov, which uses coverage.py under the hood
  • HTTP request stubbing: responses
  • Seeding database from fixture files: flask-fixtures
  • Webdriver for UI/e2e tests: selenium

There are a few other aspects worth noting:

  • Canvas OAuth

We don't stub the Canvas OAuth calls with responses. When mock Canvas is on, the app registers its own /dev_login routes as the OAuth2 provider in place of Canvas. /dev_login/ lets you pick a fake user, and /dev_login/oauth2/auth/ and /dev_login/oauth2/token/ act as the authorize and token endpoints. The full OAuth2 flow still runs through Authlib, with user info drawn from server/services/canvas/fake_data/fake_users.json.

  • Canvas API

We call Canvas through the canvasapi library rather than raw HTTP, so we don't stub it with responses either. When mock Canvas is on, server/services/canvas hands back a FakeCanvas client (fake_canvas.py) in place of canvasapi.Canvas. It reads courses, enrollments and users from server/services/canvas/fake_data/.

  • When mock Canvas is on It's on by default in development and always on in testing. It's always off in staging and production. To point a dev server at real Canvas, set MOCK_CANVAS=false. As a safeguard, the app never mocks when FLASK_ENV=production.

  • Email

We provide three ways to test the email feature. For details see here.

CI

We are using GitHub Action for CI.

Deployment

Deployment is currently via Heroku. As of Fall 2026, we are setting up GCP projects for staging and production that become the new hosts of this app.