Skip to content

Commit 69b7468

Browse files
Merge pull request #12 from UCSD-Makerspace/dev
dev
2 parents add5570 + 194ea57 commit 69b7468

108 files changed

Lines changed: 2009 additions & 1649 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ on:
44
push:
55
branches:
66
- main
7+
- dev
78
workflow_dispatch:
89

910
concurrency:
10-
group: production_environment
11+
group: ${{ github.ref_name }}_environment
1112
cancel-in-progress: true
1213

1314
jobs:
@@ -23,6 +24,17 @@ jobs:
2324
id: lowercase
2425
run: echo "owner=$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
2526

27+
- name: Set image name
28+
id: image
29+
run: |
30+
if [ "${{ github.ref_name }}" = "dev" ]; then
31+
echo "name=check-in-dev" >> $GITHUB_OUTPUT
32+
echo "extra_tag=ghcr.io/${{ steps.lowercase.outputs.owner }}/check-in-dev:latest" >> $GITHUB_OUTPUT
33+
else
34+
echo "name=check-in" >> $GITHUB_OUTPUT
35+
echo "extra_tag=ghcr.io/${{ steps.lowercase.outputs.owner }}/check-in:latest" >> $GITHUB_OUTPUT
36+
fi
37+
2638
- name: Set up Docker Buildx
2739
uses: docker/setup-buildx-action@v3
2840

@@ -39,5 +51,5 @@ jobs:
3951
context: .
4052
push: true
4153
tags: |
42-
ghcr.io/${{ steps.lowercase.outputs.owner }}/check-in:${{ github.sha }}
43-
ghcr.io/${{ steps.lowercase.outputs.owner }}/check-in:latest
54+
ghcr.io/${{ steps.lowercase.outputs.owner }}/${{ steps.image.outputs.name }}:${{ github.sha }}
55+
${{ steps.image.outputs.extra_tag }}

Dockerfile

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
FROM python:3.13-slim
1+
FROM python:3.13
22

33
RUN apt-get update && apt-get install -y \
4-
python3-tk \
5-
gcc \
6-
python3-dev \
4+
libqt6widgets6 \
75
&& rm -rf /var/lib/apt/lists/*
86

97
WORKDIR /app

docker-compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
services:
22
check-in:
33
image: ghcr.io/ucsd-makerspace/check-in:latest
4+
pull_policy: always
45
privileged: true
56
network_mode: host
67
environment:
672 KB
Binary file not shown.

install.sh

Lines changed: 0 additions & 8 deletions
This file was deleted.

requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@ pyserial==3.5
22
requests==2.32.5
33
adafruit-circuitpython-pn532
44
RPi.GPIO; sys_platform == 'linux'
5+
pyqt6==6.11.0
6+
qtawesome
7+
pyqt6-sip

run_dev.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash
2+
3+
set -a
4+
source "$(dirname "$0")/.env"
5+
set +a
6+
7+
for arg in "$@"; do
8+
if [ "$arg" = "--dev" ] || [ "$arg" = "-d" ]; then
9+
export DEV_MODE=1
10+
break
11+
fi
12+
done
13+
14+
output_file="log.txt"
15+
16+
echo "" >> "$output_file"
17+
18+
date "+%Y-%m-%d %H:%M:%S" >> "$output_file"
19+
20+
python src/main.py "$@" 2>&1 | tee -a log.txt

src/api/__init__.py

Whitespace-only changes.

src/api/_client.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import logging
2+
import time
3+
4+
import requests
5+
6+
7+
def _req(method, url, **kwargs):
8+
start = time.time()
9+
resp = requests.request(method, url, **kwargs)
10+
ms = (time.time() - start) * 1000
11+
logging.info(f"[CLIENT] {method.upper()} {url} -> {resp.status_code} ({ms:.0f}ms)")
12+
return resp

src/sheets.py renamed to src/api/client.py

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,10 @@
22
import sys
33
import time
44

5-
import requests
6-
75
from config import API_BASE_URL
6+
from api._client import _req
87

98

10-
def _req(method, url, **kwargs):
11-
start = time.time()
12-
resp = requests.request(method, url, **kwargs)
13-
ms = (time.time() - start) * 1000
14-
logging.info(f"[CLIENT] {method.upper()} {url} -> {resp.status_code} ({ms:.0f}ms)")
15-
return resp
16-
179

1810
def check_api_health(retries=3, delay=3):
1911
logging.info(API_BASE_URL)
@@ -31,7 +23,7 @@ def check_api_health(retries=3, delay=3):
3123
sys.exit(1)
3224

3325

34-
class SheetManager:
26+
class ApiClient:
3527
def checkin_by_uuid(self, uuid):
3628
try:
3729
resp = _req("GET", f"{API_BASE_URL}/check-in/uuid/{uuid}", timeout=10)
@@ -58,26 +50,50 @@ def set_traffic_light(self, color):
5850

5951
def get_traffic_light(self):
6052
try:
61-
resp = requests.get(f"{API_BASE_URL}/traffic-light", timeout=5)
53+
resp = _req("GET", f"{API_BASE_URL}/traffic-light", timeout=5)
6254
return resp.json().get("color", "off")
6355
except Exception as e:
6456
logging.error(f"Error getting traffic light: {e}")
6557
return "off"
6658

67-
def create_account(self, first_name, last_name, email, pid, rfid):
59+
def lookup_by_pid(self, pid):
60+
"""Returns dict with first_name/last_name/email/pid, or None if not found."""
61+
try:
62+
resp = _req("GET", f"{API_BASE_URL}/accounts/lookup/pid/{pid}", timeout=10)
63+
if resp.status_code == 404:
64+
return None
65+
resp.raise_for_status()
66+
return resp.json()
67+
except Exception as e:
68+
logging.error(f"Error looking up student by pid {pid}: {e}")
69+
return None
70+
71+
def lookup_by_barcode(self, barcode):
72+
"""Returns dict with first_name/last_name/email/pid, or None if not found."""
73+
try:
74+
resp = _req("GET", f"{API_BASE_URL}/accounts/lookup/barcode/{barcode}", timeout=10)
75+
if resp.status_code == 404:
76+
return None
77+
resp.raise_for_status()
78+
return resp.json()
79+
except Exception as e:
80+
logging.error(f"Error looking up student by barcode: {e}")
81+
return None
82+
83+
def create_account(self, rfid, *, barcode=None, pid=None, first_name=None, last_name=None, email=None):
6884
try:
69-
resp = _req(
70-
"POST",
71-
f"{API_BASE_URL}/accounts",
72-
json={
73-
"first_name": first_name,
74-
"last_name": last_name,
75-
"email": email,
76-
"pid": pid,
77-
"rfid": rfid,
78-
},
79-
timeout=30,
80-
)
85+
payload = {"rfid": rfid}
86+
if barcode:
87+
payload["barcode"] = barcode
88+
if pid:
89+
payload["pid"] = pid
90+
if first_name:
91+
payload["first_name"] = first_name
92+
if last_name:
93+
payload["last_name"] = last_name
94+
if email:
95+
payload["email"] = email
96+
resp = _req("POST", f"{API_BASE_URL}/accounts", json=payload, timeout=30)
8197
resp.raise_for_status()
8298
return resp.json()
8399
except Exception as e:

0 commit comments

Comments
 (0)