diff --git a/.gitignore b/.gitignore index fc60914..bdeaa28 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ ci-bundle bundle .DS_Store +.claude +example-local-gtfs/*.zip diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..d4104dd --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,105 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Overview + +This repository contains Docker images for running OneBusAway Application Suite v2, a transit data platform. The system consists of three main components: + +1. **Bundler Service**: Processes GTFS data and creates transit data bundles +2. **OBA App Service**: Runs the OneBusAway API and transit data federation webapps +3. **Database Service**: MySQL (default) or PostgreSQL for storing application data + +## Common Commands + +### Building and Running + +```bash +# Build the app server +docker compose build oba_app + +# Build a bundle with custom GTFS +GTFS_URL=https://example.com/gtfs.zip docker compose up oba_bundler + +# Build with default test data (Unitrans) +docker compose up oba_bundler + +# Run the OBA server +docker compose up oba_app + +# Run validation tests +./bin/validate.sh + +# Clean up +docker compose down -v +``` + +### Testing + +```bash +# Run validation script to test API endpoints +./bin/validate.sh + +# Build and test Docker images locally +docker compose build +docker compose up +``` + +## Architecture + +### Directory Structure + +- `/bundler/`: Docker setup for building transit data bundles from GTFS feeds + - Uses Maven to fetch OneBusAway dependencies + - Includes gtfstidy for cleaning/optimizing GTFS data + - Outputs to `/bundle/` directory + +- `/oba/`: Docker setup for the OneBusAway application server + - Runs on Tomcat 8.5 with Java 11 + - Template-based configuration for database connections + - Supports GTFS-RT feeds + - Includes Prometheus JMX exporter for monitoring + +- `/bundle/`: Shared volume containing processed transit data + - Contains serialized Java objects (.obj files) + - Lucene search indices + - Processed GTFS data + +### Key Technologies + +- **Build System**: Maven-based Java project +- **OneBusAway Version**: v2.6.0 (configurable via OBA_VERSION) +- **Runtime**: Tomcat 8.5.100 with JDK 11 +- **Databases**: MySQL 8.0 or PostgreSQL 16 +- **GTFS Processing**: gtfstidy (Go-based optimizer) +- **Template Engine**: Custom Handlebars renderer (Go) + +### Environment Variables + +Database configuration: +- `JDBC_URL`, `JDBC_DRIVER`, `JDBC_USER`, `JDBC_PASSWORD` + +GTFS configuration: +- `GTFS_URL`: URL to GTFS zip file +- `TZ`: Timezone for the transit agency + +GTFS-RT configuration: +- `TRIP_UPDATES_URL`, `VEHICLE_POSITIONS_URL`, `ALERTS_URL` +- `REFRESH_INTERVAL`: Update frequency in seconds +- `AGENCY_ID`: Transit agency identifier +- `FEED_API_KEY`, `FEED_API_VALUE`: Authentication headers + +### API Endpoints + +When running locally: +- API webapp: http://localhost:8080/ +- Example: http://localhost:8080/api/where/agencies-with-coverage.json?key=TEST +- Transit data federation: http://localhost:8080/onebusaway-transit-data-federation-webapp + +### Docker Images + +Published to Docker Hub: +- `opentransitsoftwarefoundation/onebusaway-bundle-builder` +- `opentransitsoftwarefoundation/onebusaway-api-webapp` + +Multi-architecture support: x86_64, ARM64 \ No newline at end of file diff --git a/README.md b/README.md index cf74735..7e38f41 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,10 @@ You will then have two web apps available: When done using this web server, you can use the shell-standard `^C` to exit out and turn it off. If issues persist across runs, you can try using `docker compose down -v` and then `docker compose up oba_app` to refresh the Docker containers and services. +### Using local GTFS files + +If you have a local GTFS file instead of downloading from a URL, see the [`example-local-gtfs/`](example-local-gtfs/) directory for a complete example that demonstrates how to build bundles using local GTFS files. + ### Inspecting the database The Docker Compose database service should remain up after a call of `docker compose up oba_app`. Otherwise, you can always invoke it using `docker compose up oba_database`. diff --git a/bin/validate.sh b/bin/validate.sh index d05b435..22b36c4 100755 --- a/bin/validate.sh +++ b/bin/validate.sh @@ -9,47 +9,82 @@ else exit 1 fi -output=$(curl -s "http://localhost:8080/api/where/agencies-with-coverage.json?key=test" | jq '.data.list[0].agencyId') +# Get the first agency from agencies-with-coverage +agency_response=$(curl -s "http://localhost:8080/api/where/agencies-with-coverage.json?key=test") +agency_count=$(echo "$agency_response" | jq '.data.list | length') -if [[ ! -z "$output" && "$output" == "\"unitrans\"" ]]; then - echo "agencies-with-coverage.json endpoint works." +if [[ "$agency_count" -gt 0 ]]; then + echo "agencies-with-coverage.json endpoint works (found $agency_count agencies)." + AGENCY_ID=$(echo "$agency_response" | jq -r '.data.list[0].agencyId') + echo "Using agency: $AGENCY_ID" else - echo "Error: agencies-with-coverage.json endpoint is not working: $output" + echo "Error: agencies-with-coverage.json endpoint is not working or no agencies found: $agency_count" exit 1 fi -output=$(curl -s "http://localhost:8080/api/where/routes-for-agency/unitrans.json?key=test" | jq '.data.list | length') -if [[ $output -gt 10 ]]; then - echo "routes-for-agency/unitrans.json endpoint works." +# Get routes for the agency +routes_response=$(curl -s "http://localhost:8080/api/where/routes-for-agency/${AGENCY_ID}.json?key=test") +route_count=$(echo "$routes_response" | jq '.data.list | length') +if [[ "$route_count" -gt 0 ]]; then + echo "routes-for-agency/${AGENCY_ID}.json endpoint works (found $route_count routes)." + ROUTE_ID=$(echo "$routes_response" | jq -r '.data.list[0].id') + echo "Using route: $ROUTE_ID" else - echo "Error: routes-for-agency/unitrans.json is not working: $output" + echo "Error: routes-for-agency/${AGENCY_ID}.json is not working or no routes found: $route_count" exit 1 fi -output=$(curl -s "http://localhost:8080/api/where/stops-for-route/unitrans_C.json?key=test" | jq '.data.entry.routeId') -if [[ ! -z "$output" && "$output" == "\"unitrans_C\"" ]]; then - echo "stops-for-route/unitrans_C.json endpoint works." +# Get stops for the route +stops_response=$(curl -s "http://localhost:8080/api/where/stops-for-route/${ROUTE_ID}.json?key=test") +route_id_check=$(echo "$stops_response" | jq -r '.data.entry.routeId') +if [[ ! -z "$route_id_check" && "$route_id_check" == "$ROUTE_ID" ]]; then + echo "stops-for-route/${ROUTE_ID}.json endpoint works." + STOP_ID=$(echo "$stops_response" | jq -r '.data.entry.stopIds[0]') + echo "Using stop: $STOP_ID" else - echo "Error: stops-for-route/unitrans_C.json endpoint is not working: $output" + echo "Error: stops-for-route/${ROUTE_ID}.json endpoint is not working: $route_id_check" exit 1 fi -output=$(curl -s "http://localhost:8080/api/where/stop/unitrans_22182.json?key=test" | jq '.data.entry.code') -if [[ ! -z "$output" && "$output" == "\"22182\"" ]]; then - echo "stop/unitrans_22182.json endpoint works." +# Get stop details +stop_response=$(curl -s "http://localhost:8080/api/where/stop/${STOP_ID}.json?key=test") +stop_id_check=$(echo "$stop_response" | jq -r '.data.entry.id') +if [[ ! -z "$stop_id_check" && "$stop_id_check" == "$STOP_ID" ]]; then + echo "stop/${STOP_ID}.json endpoint works." + # Extract coordinates for stops-for-location test + STOP_LAT=$(echo "$stop_response" | jq -r '.data.entry.lat') + STOP_LON=$(echo "$stop_response" | jq -r '.data.entry.lon') + echo "Using coordinates: $STOP_LAT, $STOP_LON" else - echo "Error: stop/unitrans_22182.json endpoint is not working: $output" + echo "Error: stop/${STOP_ID}.json endpoint is not working: $stop_id_check" exit 1 fi -output=$(curl -s "http://localhost:8080/api/where/stops-for-location.json?lat=38.555308&lon=-121.735991&key=test" | jq '.data.outOfRange') -if [[ ! -z "$output" && "$output" == "false" ]]; then - echo "stops-for-location/unitrans_false.json endpoint works." +# Test stops-for-location using coordinates from the stop +LOCATION_URL="http://localhost:8080/api/where/stops-for-location.json?lat=${STOP_LAT}&lon=${STOP_LON}&key=test" +location_response=$(curl -s "$LOCATION_URL") +out_of_range=$(echo "$location_response" | jq '.data.outOfRange') +stops_found=$(echo "$location_response" | jq '.data.list | length') +if [[ ! -z "$out_of_range" && "$out_of_range" == "false" && "$stops_found" -gt 0 ]]; then + echo "stops-for-location.json endpoint works (found $stops_found stops)." else - echo "Error: stops-for-location/unitrans_false.json endpoint is not working: $output" + echo "Error: stops-for-location.json endpoint is not working: outOfRange=$out_of_range, stops=$stops_found" + echo "URL: $LOCATION_URL" + echo "Response: $location_response" exit 1 fi -# todo: add support for arrivals-and-departures-for-stop endpoint. -# however, it doesn't seem that the unitrans_22182 stop has arrivals and departures on the weekend, so we'll need -# something else to test with. However, for now, this is still a great step forward. \ No newline at end of file +# Test arrivals-and-departures-for-stop endpoint +arrivals_response=$(curl -s "http://localhost:8080/api/where/arrivals-and-departures-for-stop/${STOP_ID}.json?key=test") +arrivals_stop_id=$(echo "$arrivals_response" | jq -r '.data.entry.stopId') +arrivals_count=$(echo "$arrivals_response" | jq '.data.entry.arrivalsAndDepartures | length // 0') + +if [[ "$arrivals_stop_id" == "$STOP_ID" ]]; then + if [[ "$arrivals_count" -gt 0 ]]; then + echo "arrivals-and-departures-for-stop/${STOP_ID}.json endpoint works (found $arrivals_count arrivals/departures)." + else + echo "arrivals-and-departures-for-stop/${STOP_ID}.json endpoint works but no arrivals/departures at this time." + fi +else + echo "Warning: arrivals-and-departures-for-stop/${STOP_ID}.json endpoint may not be working correctly." +fi \ No newline at end of file diff --git a/bundler/build_bundle.sh b/bundler/build_bundle.sh index 4b8ab7f..0cc77dc 100755 --- a/bundler/build_bundle.sh +++ b/bundler/build_bundle.sh @@ -16,8 +16,14 @@ # limitations under the License. # -if [ -z "$GTFS_URL" ]; then - echo "GTFS_URL is not set" +# Check that either GTFS_URL or GTFS_ZIP_FILENAME is set, but not both +if [ -n "$GTFS_URL" ] && [ -n "$GTFS_ZIP_FILENAME" ]; then + echo "Error: Both GTFS_URL and GTFS_ZIP_FILENAME are set. Please provide only one." + exit 1 +fi + +if [ -z "$GTFS_URL" ] && [ -z "$GTFS_ZIP_FILENAME" ]; then + echo "Error: Neither GTFS_URL nor GTFS_ZIP_FILENAME is set. Please provide one." exit 1 fi @@ -35,17 +41,33 @@ TDF_BUILDER_JAR=${TDF_BUILDER_JAR:-/oba/libs/onebusaway-transit-data-federation- # -D: drop erroneous entries from feed GTFS_TIDY_ARGS=${GTFS_TIDY_ARGS:-OscRCSmeD} -GTFS_ZIP_FILENAME="gtfs_pristine.zip" +# Set default filename if using GTFS_URL +if [ -n "$GTFS_URL" ]; then + GTFS_ZIP_FILENAME="gtfs_pristine.zip" +fi echo "OBA Bundle Builder Starting" -echo "GTFS_URL: $GTFS_URL" +if [ -n "$GTFS_URL" ]; then + echo "GTFS_URL: $GTFS_URL" +else + echo "GTFS_ZIP_FILENAME: $GTFS_ZIP_FILENAME" +fi echo "OBA Version: $OBA_VERSION" echo "GTFS Tidy Args: $GTFS_TIDY_ARGS" echo "TDF_BUILDER_JAR: $TDF_BUILDER_JAR" cd /bundle -wget -O ${GTFS_ZIP_FILENAME} ${GTFS_URL} +# Download GTFS file if URL is provided, otherwise use local file +if [ -n "$GTFS_URL" ]; then + wget -O ${GTFS_ZIP_FILENAME} ${GTFS_URL} +else + # Check if the local file exists + if [ ! -f "$GTFS_ZIP_FILENAME" ]; then + echo "Error: GTFS file not found: $GTFS_ZIP_FILENAME" + exit 1 + fi +fi gtfstidy -${GTFS_TIDY_ARGS} ${GTFS_ZIP_FILENAME} diff --git a/example-local-gtfs/.dockerignore b/example-local-gtfs/.dockerignore new file mode 100644 index 0000000..4a099a9 --- /dev/null +++ b/example-local-gtfs/.dockerignore @@ -0,0 +1,10 @@ +# Ignore everything except GTFS files and Docker-related files +* +!*.zip +!*.gtfs +!Dockerfile +!docker-entrypoint.sh + +# But still ignore these even if they're zip files +!backup*.zip +!old*.zip \ No newline at end of file diff --git a/example-local-gtfs/Dockerfile b/example-local-gtfs/Dockerfile new file mode 100644 index 0000000..5f76bea --- /dev/null +++ b/example-local-gtfs/Dockerfile @@ -0,0 +1,27 @@ +# Example Dockerfile for using local GTFS files with OneBusAway +# This builds on top of the main OBA Docker image + +# First, build the base OBA image if not already built: +# docker build -t oba-base:latest -f ../oba/Dockerfile ../oba + +FROM oba-base:latest + +# Copy your local GTFS file into the container +# We copy to /tmp first because /bundle gets mounted over +COPY *.zip /tmp/ + +# Set the GTFS_ZIP_FILENAME environment variable +# This tells the build_bundle.sh script to use the local file instead of downloading +ENV GTFS_ZIP_FILENAME=gtfs.zip + +# Copy the entrypoint script +COPY docker-entrypoint.sh /docker-entrypoint.sh +RUN chmod +x /docker-entrypoint.sh + +ENTRYPOINT ["/docker-entrypoint.sh"] + +# Optional: Override other environment variables if needed +# ENV TZ=America/Los_Angeles +ENV GTFS_TIDY_ARGS=OscRCSmeD + +# The entrypoint and other configurations are inherited from the base image \ No newline at end of file diff --git a/example-local-gtfs/README.md b/example-local-gtfs/README.md new file mode 100644 index 0000000..ccdc367 --- /dev/null +++ b/example-local-gtfs/README.md @@ -0,0 +1,115 @@ +# Example: Using Local GTFS Files with OneBusAway Docker + +This example demonstrates how to build OneBusAway bundles using local GTFS files instead of downloading them from a URL. + +## Prerequisites + +1. A local GTFS zip file +2. Docker and Docker Compose installed on your system + +## Usage + +### Option 1: Using Docker Compose (Recommended) + +#### Step 1: Copy your GTFS file + +Copy your GTFS zip file to this directory: + +```bash +cp /path/to/your/gtfs.zip ./sta-gtfs-may-2025.zip +``` + +Or update the Dockerfile and docker-compose.yml to use your filename. + +#### Step 2: Run the full stack + +```bash +# build the bundle +docker compose up oba_bundler + +# Then start the app +docker compose up oba_app +``` + +This will: +1. Build a bundle from your local GTFS file +2. Start the database (PostgreSQL or MySQL) +3. Start the OneBusAway API server + +Access the API at: http://localhost:8080/onebusaway-api-webapp/api/where/agencies-with-coverage.json?key=test + +### Option 2: Manual Docker Build + +#### Step 1: Build the base OBA image + +First, build the base OneBusAway image from the parent directory: + +```bash +cd .. +docker build -t oba-base:latest -f oba/Dockerfile . +``` + +#### Step 2: Copy your GTFS file + +Copy your GTFS zip file to this directory and rename it, or update the Dockerfile to use your filename: + +```bash +cp /path/to/your/gtfs.zip ./your-gtfs-file.zip +``` + +#### Step 3: Update the Dockerfile + +Edit the Dockerfile to use your GTFS filename: +- Change `your-gtfs-file.zip` to match your actual filename in both the COPY and ENV lines + +#### Step 4: Build the image with your local GTFS + +```bash +docker build -t oba-local-gtfs:latest . +``` + +#### Step 5: Run the bundle builder + +```bash +docker run --rm -v $(pwd)/../bundle:/bundle oba-local-gtfs:latest +``` + +This will: +- Use your local GTFS file (no download required) +- Run gtfstidy to optimize the GTFS data +- Build the OneBusAway bundle +- Output the bundle to the shared volume + +## Environment Variables + +You can override these environment variables in the Dockerfile or docker-compose.yml: + +- `GTFS_ZIP_FILENAME`: The name of your GTFS file (required when not using GTFS_URL) +- `TZ`: Timezone for the transit agency (default: America/New_York) +- `GTFS_TIDY_ARGS`: Arguments for gtfstidy optimization (default: OscRCSmeD) +- `OBA_VERSION`: OneBusAway version (inherited from base image) + +## Docker Compose Services + +- `oba_database`: MySQL database (optional) +- `oba_database_pg`: PostgreSQL database (default) +- `oba_bundler`: Builds transit data bundle from local GTFS +- `oba_app`: OneBusAway API server + +## How it Works + +1. **Build Time**: Your GTFS zip file is copied into the Docker image at `/tmp/` +2. **Runtime**: The `docker-entrypoint.sh` script: + - Finds your GTFS file in `/tmp/` + - Copies it to `/bundle/gtfs.zip` (after the volume is mounted) + - Executes the main command (build_bundle.sh or supervisord) + +This approach is needed because Docker volume mounts happen after the image is built but before commands run. By copying to `/tmp/` first, we ensure the file isn't hidden by the volume mount. + +## Notes + +- Place any GTFS zip file in this directory - it will be automatically detected +- Make sure not to set GTFS_URL when using GTFS_ZIP_FILENAME +- The bundle output will be in the ../bundle directory +- The docker-compose file uses PostgreSQL by default; comment it out and uncomment MySQL if preferred +- You can override the GTFS filename by setting `GTFS_ZIP_FILENAME` in docker-compose.yml \ No newline at end of file diff --git a/example-local-gtfs/docker-compose.yml b/example-local-gtfs/docker-compose.yml new file mode 100644 index 0000000..2806c07 --- /dev/null +++ b/example-local-gtfs/docker-compose.yml @@ -0,0 +1,67 @@ +services: + oba_database_pg: + image: postgres:16 + container_name: oba_database_pg + environment: + POSTGRES_USER: oba_user + POSTGRES_PASSWORD: oba_password + POSTGRES_DB: oba_database + ports: + - "5432:5432" + volumes: + - type: volume + source: pg-data + target: /var/lib/postgresql/data + restart: always + + # Bundle builder that uses local GTFS file + oba_bundler: + container_name: oba_bundler + build: + context: . + dockerfile: Dockerfile + environment: + # Use local GTFS file instead of downloading + - GTFS_ZIP_FILENAME=gtfs.zip + - TZ=America/Los_Angeles + - GTFS_TIDY_ARGS=OscRCSmeD + volumes: + - type: bind + source: ../bundle + target: /bundle + command: ["/oba/build_bundle.sh"] + + oba_app: + container_name: oba_app + depends_on: + - oba_database_pg + build: + context: ../oba + environment: + - JDBC_URL=jdbc:postgresql://oba_database_pg:5432/oba_database + - JDBC_DRIVER=org.postgresql.Driver + - JDBC_USER=oba_user + - JDBC_PASSWORD=oba_password + - TEST_API_KEY=test # For test only, remove in production + - TZ=America/Los_Angeles + - GTFS_TIDY_ARGS=v + # Note: No GTFS_URL since we're using pre-downloaded GTFS data + volumes: + - type: bind + source: ../bundle + target: /bundle + ports: + # Access the webapp on your host machine at a path like + # http://localhost:8080/onebusaway-api-webapp/api/where/agency/${YOUR_AGENCY}.json?key=TEST + - "8080:8080" + - "1234:1234" # JMX exporter port + +# Uncomment the following section to test with prometheus and the JMX exporter in localhost +# networks: +# monitoring: +# external: true + + +volumes: + mysql-data: + pg-data: \ No newline at end of file diff --git a/example-local-gtfs/docker-entrypoint.sh b/example-local-gtfs/docker-entrypoint.sh new file mode 100644 index 0000000..1e38bf0 --- /dev/null +++ b/example-local-gtfs/docker-entrypoint.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# This entrypoint script handles copying the local GTFS file from the build-time +# location (/tmp) to the runtime location (/bundle) after volumes are mounted. +# +# Why this is needed: +# - At build time, we copy the GTFS zip file to /tmp +# - At runtime, Docker mounts the host's bundle directory to /bundle +# - This mount would hide any files we copied to /bundle during build +# - So we copy the file after the volume is mounted + +# Find the GTFS zip file that was copied during build +GTFS_FILE=$(find /tmp -name "*.zip" -type f | head -1) + +if [ -z "$GTFS_FILE" ]; then + echo "Error: No GTFS zip file found in /tmp" + echo "Make sure your GTFS zip file is in the build context" + exit 1 +fi + +# Copy the file to the bundle directory with the expected name +echo "Found GTFS file: $GTFS_FILE" +echo "Copying to: /bundle/${GTFS_ZIP_FILENAME}" +cp "$GTFS_FILE" "/bundle/${GTFS_ZIP_FILENAME}" + +if [ $? -ne 0 ]; then + echo "Error: Failed to copy GTFS file to /bundle" + exit 1 +fi + +echo "GTFS file copied successfully" + +# Execute the original command (supervisord or build_bundle.sh) +# "$@" expands to all arguments passed to this script +exec "$@" \ No newline at end of file diff --git a/oba/Dockerfile b/oba/Dockerfile index 3071925..bbeef7a 100644 --- a/oba/Dockerfile +++ b/oba/Dockerfile @@ -6,7 +6,7 @@ ARG MYSQL_CONNECTOR_VERSION=8.4.0 # Go Builder # ############## -FROM golang:1.24.1-bookworm AS gobuilder +FROM golang:1.24.4-bookworm AS gobuilder # Install gtfstidy - https://github.com/patrickbr/gtfstidy WORKDIR /src @@ -58,10 +58,14 @@ RUN ./retrieve_maven_artifacts.sh FROM tomcat:8.5.100-jdk11-temurin AS server +ARG GTFS_TIDY_ARGS ENV GTFS_TIDY_ARGS=${GTFS_TIDY_ARGS} ARG OBA_VERSION=2.6.0 +ARG POSTGRESQL_CONNECTOR_VERSION ENV POSTGRESQL_CONNECTOR_VERSION=${POSTGRESQL_CONNECTOR_VERSION} + +ARG MYSQL_CONNECTOR_VERSION ENV MYSQL_CONNECTOR_VERSION=${MYSQL_CONNECTOR_VERSION} ARG OBA_VERSION diff --git a/oba/build_bundle.sh b/oba/build_bundle.sh index 4b8ab7f..0cc77dc 100755 --- a/oba/build_bundle.sh +++ b/oba/build_bundle.sh @@ -16,8 +16,14 @@ # limitations under the License. # -if [ -z "$GTFS_URL" ]; then - echo "GTFS_URL is not set" +# Check that either GTFS_URL or GTFS_ZIP_FILENAME is set, but not both +if [ -n "$GTFS_URL" ] && [ -n "$GTFS_ZIP_FILENAME" ]; then + echo "Error: Both GTFS_URL and GTFS_ZIP_FILENAME are set. Please provide only one." + exit 1 +fi + +if [ -z "$GTFS_URL" ] && [ -z "$GTFS_ZIP_FILENAME" ]; then + echo "Error: Neither GTFS_URL nor GTFS_ZIP_FILENAME is set. Please provide one." exit 1 fi @@ -35,17 +41,33 @@ TDF_BUILDER_JAR=${TDF_BUILDER_JAR:-/oba/libs/onebusaway-transit-data-federation- # -D: drop erroneous entries from feed GTFS_TIDY_ARGS=${GTFS_TIDY_ARGS:-OscRCSmeD} -GTFS_ZIP_FILENAME="gtfs_pristine.zip" +# Set default filename if using GTFS_URL +if [ -n "$GTFS_URL" ]; then + GTFS_ZIP_FILENAME="gtfs_pristine.zip" +fi echo "OBA Bundle Builder Starting" -echo "GTFS_URL: $GTFS_URL" +if [ -n "$GTFS_URL" ]; then + echo "GTFS_URL: $GTFS_URL" +else + echo "GTFS_ZIP_FILENAME: $GTFS_ZIP_FILENAME" +fi echo "OBA Version: $OBA_VERSION" echo "GTFS Tidy Args: $GTFS_TIDY_ARGS" echo "TDF_BUILDER_JAR: $TDF_BUILDER_JAR" cd /bundle -wget -O ${GTFS_ZIP_FILENAME} ${GTFS_URL} +# Download GTFS file if URL is provided, otherwise use local file +if [ -n "$GTFS_URL" ]; then + wget -O ${GTFS_ZIP_FILENAME} ${GTFS_URL} +else + # Check if the local file exists + if [ ! -f "$GTFS_ZIP_FILENAME" ]; then + echo "Error: GTFS file not found: $GTFS_ZIP_FILENAME" + exit 1 + fi +fi gtfstidy -${GTFS_TIDY_ARGS} ${GTFS_ZIP_FILENAME}