Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 0 additions & 1 deletion .browserslistrc

This file was deleted.

5 changes: 4 additions & 1 deletion .env.core.sample
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
RAILS_ENV=development
RAILS_LOG_TO_STDOUT=1
WJR_HOST=localhost:3000
WJR_CORE_URL=http://localhost:3000
WJR_GOOGLE_MAPS_API_KEY=
WJR_FLICKR_API_KEY=
WJR_PASSWORD_SALT=
WJR_SECRET_TOKEN=secret-token
WJR_SECRET_BASE=secret-base
WJR_DEVISE_SECRET_KEY=a3ce9067696ac6eb83a065b0298ec025a97af52d84872e84c9e9e622991fd89f5a2d4b9d20d2e391858ae07240d0c4600c3900a15158e7b90ddae4c20e68d92dm
WJR_DEVISE_SECRET_KEY=generate-with-bin-rails-secret-and-keep-out-of-git
WJR_FACEBOOK_APP_ID=
WJR_FACEBOOK_APP_SECRET=
WJR_GOOGLE_APP_ID=
Expand Down
176 changes: 176 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
name: CI

on:
push:
branches:
- master
pull_request:

env:
IMAGE_NAME: core

jobs:
test:
runs-on: ubuntu-latest

services:
db:
image: mariadb:10.11
env:
MARIADB_ROOT_PASSWORD: root
MARIADB_DATABASE: whyjustrun-test
ports:
- 3306:3306
options: >-
--health-cmd="healthcheck.sh --connect --innodb_initialized"
--health-interval=5s
--health-timeout=5s
--health-retries=10

env:
RAILS_ENV: test
WJR_DATABASE_NAME: whyjustrun
WJR_DATABASE_TEST_NAME: whyjustrun-test
WJR_DATABASE_HOST: 127.0.0.1
WJR_DATABASE_USERNAME: root
WJR_DATABASE_PASSWORD: root
WJR_PASSWORD_SALT: test-only-salt
WJR_SECRET_BASE: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
WJR_SECRET_TOKEN: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
WJR_DEVISE_SECRET_KEY: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
WJR_RECAPTCHA_SITE_KEY: test
WJR_RECAPTCHA_SECRET_KEY: test
WJR_SMTP_ADDRESS: localhost
WJR_SMTP_DOMAIN: example.com
WJR_SMTP_USER_NAME: test
WJR_SMTP_PASSWORD: test
WJR_DATA_FOLDER: /tmp/whyjustrun-data/
WJR_DATA_URL: http://localhost/data/

steps:
- uses: actions/checkout@v4

- name: Install MySQL client headers
run: sudo apt-get update && sudo apt-get install -y default-libmysqlclient-dev imagemagick ghostscript

- uses: ruby/setup-ruby@v1
with:
bundler-cache: true

- name: Prepare test database
run: bundle exec rails db:test:prepare

- name: Run tests
run: bundle exec rails test

system-test:
runs-on: ubuntu-latest

services:
db:
image: mariadb:10.11
env:
MARIADB_ROOT_PASSWORD: root
MARIADB_DATABASE: whyjustrun-test
ports:
- 3306:3306
options: >-
--health-cmd="healthcheck.sh --connect --innodb_initialized"
--health-interval=5s
--health-timeout=5s
--health-retries=10

env:
RAILS_ENV: test
WJR_DATABASE_NAME: whyjustrun
WJR_DATABASE_TEST_NAME: whyjustrun-test
WJR_DATABASE_HOST: 127.0.0.1
WJR_DATABASE_USERNAME: root
WJR_DATABASE_PASSWORD: root
WJR_PASSWORD_SALT: test-only-salt
WJR_SECRET_BASE: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
WJR_SECRET_TOKEN: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
WJR_DEVISE_SECRET_KEY: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
WJR_RECAPTCHA_SITE_KEY: test
WJR_RECAPTCHA_SECRET_KEY: test
WJR_SMTP_ADDRESS: localhost
WJR_SMTP_DOMAIN: example.com
WJR_SMTP_USER_NAME: test
WJR_SMTP_PASSWORD: test
WJR_DATA_FOLDER: /tmp/whyjustrun-data/
WJR_DATA_URL: http://localhost/data/

steps:
- uses: actions/checkout@v4

- name: Install MySQL client headers
run: sudo apt-get update && sudo apt-get install -y default-libmysqlclient-dev imagemagick ghostscript

- uses: ruby/setup-ruby@v1
with:
bundler-cache: true

- name: Prepare test database
run: bundle exec rails db:test:prepare

- name: Run system tests
run: bundle exec rails test:system

- name: Upload failure screenshots and pages
uses: actions/upload-artifact@v4
if: failure()
with:
name: system-test-failures
path: tmp/screenshots/
if-no-files-found: ignore

brakeman:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install MySQL client headers
run: sudo apt-get update && sudo apt-get install -y default-libmysqlclient-dev

- uses: ruby/setup-ruby@v1
with:
bundler-cache: true

- name: Run Brakeman
run: bundle exec brakeman --no-pager

push:
runs-on: ubuntu-latest
needs: [test, system-test, brakeman]
if: github.event_name == 'push'

steps:
- uses: actions/checkout@v4

- name: Build image
run: docker build . --file Dockerfile --tag $IMAGE_NAME

- name: Log into GitHub Container Registry
run: echo "${{ secrets.CR_PAT }}" | docker login https://ghcr.io -u ${{ secrets.CR_USER }} --password-stdin

- name: Push image to GitHub Container Registry
run: |
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME

# Change all uppercase to lowercase
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

# Strip git ref prefix from version
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

# Strip "v" prefix from tag name
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

# Use Docker `latest` tag convention
[ "$VERSION" == "master" ] && VERSION=latest

echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION

docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
docker push $IMAGE_ID:$VERSION
51 changes: 0 additions & 51 deletions .github/workflows/docker-publish.yml

This file was deleted.

3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@

/.env
/.env.core
/public/packs
/public/packs-test
/node_modules
/yarn-error.log
yarn-debug.log*
.yarn-integrity

vendor/
public/assets/
/public/redactor/
1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.3.4
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Project Overview

WhyJustRun Core is a Ruby on Rails application providing authentication, IOF XML APIs, and cross-club pages for [whyjustrun.ca](https://whyjustrun.ca). It works alongside the separate [WhyJustRun Clubsite](https://github.com/WhyJustRun/Clubsite) app.
WhyJustRun Core is a Ruby on Rails application serving [whyjustrun.ca](https://whyjustrun.ca) (authentication, IOF XML APIs, cross-club pages) and every club's website. Club domains are resolved from the Host header into a `Clubsite::` controller namespace (`app/controllers/clubsite/base_controller.rb`); requests on club domains run in the club's timezone and club-scoped data is always accessed through `current_club` associations. The legacy [WhyJustRun Clubsite](https://github.com/WhyJustRun/Clubsite) (CakePHP) is being decommissioned; until cutover it still serves club domains in production against the same database, so cross-app SSO endpoints and permissive CORS must not be removed from master (they are removed on the `rails-cutover` and `post-cutover-cleanup` branches).

## Development Commands

Expand Down Expand Up @@ -44,5 +44,5 @@ Test users (password: "password"): admin@example.com, webmaster@example.com, exe
- **Cross-app sessions**: Shared authentication with the Clubsite app via `CrossAppSession` model
- **Privilege system**: Role-based access with numeric levels (0-100) defined in `config/settings.yml`
- **Cron jobs**: Managed by the `whenever` gem
- **Frontend**: Bootstrap with CoffeeScript, Webpacker, jQuery, Leaflet for maps
- **Frontend**: Bootstrap with CoffeeScript, Sprockets asset pipeline, jQuery, Leaflet for maps
- **Testing**: Minitest with fixtures in `test/fixtures/`
9 changes: 4 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ RUN apk add --no-cache \
build-base \
autoconf \
nodejs \
yarn \
mariadb-dev \
imagemagick \
ghostscript \
chromium \
chromium-chromedriver \
bash # used in crontab generated by whenever

RUN mkdir /application
Expand All @@ -26,12 +29,8 @@ CMD ["rails", "server", "-b", "0.0.0.0"]

FROM dev AS prod

COPY package.json yarn.lock /application/
RUN yarn install --frozen-lockfile

COPY . /application
RUN RAILS_ENV=production \
NODE_OPTIONS=--openssl-legacy-provider \
SECRET_KEY_BASE=placeholder \
WJR_DATABASE_NAME=placeholder \
WJR_DATABASE_TEST_NAME=placeholder \
Expand Down
16 changes: 12 additions & 4 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
source 'http://rubygems.org'

gem 'bundle'

gem 'rails', '~> 7.1'
gem 'mysql2', '~> 0.5.3'

# Use the Puma web server
gem 'puma', '~> 6.4'

# MySQL Session store
gem "activerecord-session_store", "~> 2.1.0"

# Asset pipeline
gem 'sass-rails', '~> 6.0.0'
gem "coffee-script", "~> 2.4.1"
gem "coffee-rails", "~> 5.0.0"
gem "uglifier", "~> 4.2.0"
gem "webpacker", ">= 5.4.4"
gem 'tzinfo-data'

# Authentication
Expand Down Expand Up @@ -56,5 +52,17 @@ gem "exception_notification", "~> 4.5"
# Authorization
gem "pundit", "~> 2.3.2"

# Image thumbnail generation (requires ImageMagick)
gem 'image_processing', '~> 1.13'

# Geo
gem 'haversine', '~> 0.3.2'

group :development, :test do
gem 'brakeman', require: false
end

group :test do
gem 'capybara'
gem 'selenium-webdriver'
end
Loading
Loading