Skip to content

Commit fc94e04

Browse files
James McHughclaude
andcommitted
Initial commit: train workout tracker
iPhone-only mobile barbell tracker with auto-progression. Go + HTMX + sqlc + SQLite + Google OIDC. Includes systemd unit, deploy script, and Caddy-fronted server-setup.sh for Linode deployment. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 parents  commit fc94e04

53 files changed

Lines changed: 6862 additions & 0 deletions

Some content is hidden

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

.env.example

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Server
2+
PORT=8080
3+
PROD=False
4+
APP_TIMEZONE=Australia/Sydney
5+
6+
# Google OAuth (https://console.cloud.google.com/apis/credentials)
7+
GOOGLE_CLIENT_ID=your_client_id_here
8+
GOOGLE_CLIENT_SECRET=your_client_secret_here
9+
OAUTH_REDIRECT_URL=http://localhost:8080/auth/google/callback
10+
11+
# Random 32 bytes hex - generate with: openssl rand -hex 32
12+
SESSION_KEY=replace_with_64_random_hex_chars
13+
14+
# Optional: shortcut to bypass Google OAuth in local dev. If set,
15+
# /auth/login auto-creates this user and signs them in. NEVER set in prod.
16+
DEV_USER_EMAIL=

.gitattributes

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Force LF line endings on all text files. Shell scripts and systemd units
2+
# bound for the Linux server must not carry CRLF when edited on Windows.
3+
* text=auto eol=lf
4+
*.bat text eol=crlf

.github/workflows/deploy.yml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Test and Deploy
2+
3+
on:
4+
push:
5+
branches: [master]
6+
pull_request:
7+
branches: [master]
8+
9+
jobs:
10+
test:
11+
name: Test
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v6
15+
16+
- name: Set up Go
17+
uses: actions/setup-go@v6
18+
with:
19+
go-version-file: go.mod
20+
21+
- name: Download dependencies
22+
run: go mod download
23+
24+
- name: Build
25+
run: go build ./...
26+
27+
- name: Run tests
28+
run: go test -v ./...
29+
30+
deploy:
31+
name: Deploy to Production
32+
needs: test
33+
runs-on: ubuntu-latest
34+
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
35+
36+
steps:
37+
- uses: actions/checkout@v6
38+
39+
- name: Set up Go
40+
uses: actions/setup-go@v6
41+
with:
42+
go-version-file: go.mod
43+
44+
- name: Download dependencies
45+
run: go mod download
46+
47+
- name: Build Linux binary
48+
run: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o train .
49+
50+
- name: Copy files to server
51+
uses: appleboy/scp-action@v0.1.7
52+
with:
53+
host: ${{ secrets.DEPLOY_HOST }}
54+
username: ${{ secrets.DEPLOY_USER }}
55+
key: ${{ secrets.DEPLOY_SSH_KEY }}
56+
port: ${{ secrets.DEPLOY_PORT || '22' }}
57+
source: "train,templates/,static/,scripts/deploy-train"
58+
target: "/tmp/train-deploy"
59+
overwrite: true
60+
61+
- name: Stop service before deploy
62+
continue-on-error: true
63+
uses: appleboy/ssh-action@v1.0.3
64+
with:
65+
host: ${{ secrets.DEPLOY_HOST }}
66+
username: ${{ secrets.DEPLOY_USER }}
67+
key: ${{ secrets.DEPLOY_SSH_KEY }}
68+
port: ${{ secrets.DEPLOY_PORT || '22' }}
69+
script: sudo systemctl stop train
70+
71+
- name: Install and restart service
72+
uses: appleboy/ssh-action@v1.0.3
73+
with:
74+
host: ${{ secrets.DEPLOY_HOST }}
75+
username: ${{ secrets.DEPLOY_USER }}
76+
key: ${{ secrets.DEPLOY_SSH_KEY }}
77+
port: ${{ secrets.DEPLOY_PORT || '22' }}
78+
script: sudo /usr/local/bin/deploy-train /tmp/train-deploy

.gitignore

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Binaries
2+
train
3+
*.exe
4+
*.test
5+
6+
# Local environment
7+
.env
8+
.env.local
9+
10+
# Local files
11+
.local/
12+
13+
# Local database
14+
*.db
15+
*.db-journal
16+
*.db-wal
17+
*.db-shm
18+
*.db.bak
19+
20+
# IDE/editor
21+
.vscode/
22+
.idea/
23+
24+
# OS
25+
.DS_Store
26+
Thumbs.db
27+
28+
# Build artifacts
29+
dist/
30+
build/
31+
32+
# Local-only one-shot tools
33+
scripts/import_stronglifts/

README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Train
2+
3+
iPhone-only mobile barbell workout tracker with auto-progression. Hosted at
4+
[train.mchugh.au](https://train.mchugh.au).
5+
6+
## Stack
7+
8+
- Go (stdlib `net/http` + `html/template`)
9+
- HTMX (vendored at `static/htmx.min.js`)
10+
- sqlc + SQLite (`modernc.org/sqlite`, pure Go, `CGO_ENABLED=0`)
11+
- Google OAuth (`coreos/go-oidc` + `golang.org/x/oauth2`)
12+
- systemd on Linode Debian, deployed via GitHub Actions
13+
14+
## Local dev
15+
16+
1. `cp .env.example .env`
17+
2. Set `SESSION_KEY` to 64 random hex chars (`openssl rand -hex 32`).
18+
3. Set `DEV_USER_EMAIL=james67@gmail.com` to bypass Google OAuth.
19+
4. `build.bat` (Windows) — builds and runs on http://localhost:8080.
20+
5. Use Chrome DevTools iPhone emulation (Cmd+Opt+I → toggle device).
21+
22+
## DB
23+
24+
`db/schema.sql` is the source of truth (run on every startup with
25+
`CREATE TABLE IF NOT EXISTS`). After editing `db/queries.sql`, run:
26+
27+
```
28+
sqlc generate
29+
```
30+
31+
The generated files (`db/db.go`, `db/models.go`, `db/queries.sql.go`) are
32+
committed. Hand-written code (`db/migrate.go`, `db/seed.go`) lives in the
33+
same package.
34+
35+
## Deploy
36+
37+
```
38+
git push origin master
39+
```
40+
41+
GitHub Actions builds a static Linux binary and SCPs it + assets to the
42+
server, where `/usr/local/bin/deploy-train` (run via `sudo`) restarts the
43+
systemd unit.
44+
45+
First-time server setup: see `scripts/server-setup.sh`.

0 commit comments

Comments
 (0)