Skip to content
Open
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .github/workflows/ci-rocker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: CI - Dockerfile.rocker

on:
pull_request:
paths:
- "Dockerfile.rocker"
- "install_r_packages.R"
- "docker-compose.ci.yml"
- ".github/workflows/ci-rocker.yml"
push:
branches: [develop]
paths:
- "Dockerfile.rocker"
- "install_r_packages.R"
- "docker-compose.ci.yml"
- ".github/workflows/ci-rocker.yml"

jobs:
build-rocker:
name: Build Dockerfile.rocker
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build Dockerfile.rocker
run: |
docker build -t bsyncr-server-rocker \
--build-arg BASE_IMAGE_TAG=4.4.3 \
-f Dockerfile.rocker .

- name: Run smoke test
run: |
docker run -d -p 8080:5000 \
--name bsyncr-rocker \
bsyncr-server-rocker
echo "Waiting for server to start..."
for i in $(seq 1 60); do
if curl -sf http://localhost:8080/health > /dev/null 2>&1; then
echo "Server ready (took ${i}s)"
break
fi
if [ "$i" -eq 60 ]; then
echo "FAIL: Server did not start within 60s"
docker logs bsyncr-rocker | tail -30
exit 1
fi
sleep 1
done
curl -f http://localhost:8080/health
echo ""
echo "Health check passed"

- name: Cleanup
if: always()
run: |
docker stop bsyncr-rocker 2>/dev/null || true
docker rm bsyncr-rocker 2>/dev/null || true
16 changes: 12 additions & 4 deletions Dockerfile.rocker
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
ARG BASE_IMAGE_TAG
ARG ROCKER_REGISTRY

FROM node:22-alpine3.19
FROM node:22-alpine3.19 AS node

# Install necessary dependencies (curl and ca-certificates)
# NLR certs are only reachable from internal networks (CodeBuild VPC);
# on public CI runners this fails gracefully and the build continues without them.
RUN apk add --no-cache curl ca-certificates && \
curl -fsSLk -o /usr/local/share/ca-certificates/nrel_root.crt https://raw.github.nrel.gov/TADA/nrel-certs/v20180329/certs/nrel_root.pem && \
curl -fsSLk -o /usr/local/share/ca-certificates/nrel_xca1.crt https://raw.github.nrel.gov/TADA/nrel-certs/v20180329/certs/nrel_xca1.pem && \
(curl -fsSLk --connect-timeout 5 -o /usr/local/share/ca-certificates/nrel_root.crt https://raw.github.nrel.gov/TADA/nrel-certs/v20180329/certs/nrel_root.pem || true) && \
(curl -fsSLk --connect-timeout 5 -o /usr/local/share/ca-certificates/nrel_xca1.crt https://raw.github.nrel.gov/TADA/nrel-certs/v20180329/certs/nrel_xca1.pem || true) && \
update-ca-certificates

FROM rocker/r-ver:${BASE_IMAGE_TAG:-4.4.3}
FROM ${ROCKER_REGISTRY:+${ROCKER_REGISTRY}/}rocker/r-ver:${BASE_IMAGE_TAG:-4.4.3}

RUN mkdir /usr/src/app

Expand All @@ -17,6 +20,11 @@ COPY --from=node /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificat
COPY --from=node /usr/share/ca-certificates /usr/share/ca-certificates
COPY --from=node /usr/local/share/ca-certificates /usr/local/share/ca-certificates

# Rebuild the CA trust store so R/libcurl trusts the NLR proxy certs
RUN update-ca-certificates
ENV CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt

# Install system dependencies and required tools
RUN apt-get update && \
apt-get upgrade -y && \
Expand Down
48 changes: 48 additions & 0 deletions docker-compose.ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
version: "3.8"
# CI smoke test for Dockerfile.rocker (appfleet ECS build)
# Usage: docker compose -f docker-compose.ci.yml up --build --abort-on-container-exit

services:
bsyncr-server:
build:
context: .
dockerfile: Dockerfile.rocker
args:
BASE_IMAGE_TAG: "4.4.3"
ports:
- "8080:5000"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
interval: 10s
timeout: 5s
retries: 6
start_period: 30s

smoke-test:
image: curlimages/curl:latest
depends_on:
bsyncr-server:
condition: service_healthy
volumes:
- ./tests:/tests
entrypoint: ["/bin/sh", "-c"]
command:
- |
echo "=== Health check ==="
curl -f http://bsyncr-server:5000/health || exit 1
echo ""
echo "=== POST BuildingSync file ==="
curl -X POST "http://bsyncr-server:5000/?model_type=SLR" \
-F "file=@/tests/data/ex_bsync.xml" \
--max-time 120 \
--output /tmp/slr_results.zip
if [ ! -f /tmp/slr_results.zip ]; then
echo "FAIL: slr_results.zip not created"
exit 1
fi
SIZE=$(stat -c%s /tmp/slr_results.zip 2>/dev/null || stat -f%z /tmp/slr_results.zip)
if [ "$SIZE" -le 10240 ]; then
echo "FAIL: slr_results.zip is less than 10kb (got $SIZE bytes)"
exit 1
fi
echo "PASS: slr_results.zip is $SIZE bytes"
13 changes: 11 additions & 2 deletions install_r_packages.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# BuildingSync®, Copyright (c) Alliance for Sustainable Energy, LLC, and other contributors.
# BuildingSync, Copyright (c) Alliance for Sustainable Energy, LLC, and other contributors.
# See also https://github.com/BuildingSync/bsyncr-server/blob/main/LICENSE.txt


# Use HTTPS CRAN mirror
options(repos = c(CRAN = "https://cloud.r-project.org"))

# Install required packages if not already installed
required_packages <- c(
"remotes", "crayon", "dplyr", "tidyr", "crul", "xml2", "testthat", "anytime", "lubridate", "segmented", "xts", "zoo", "ggplot2", "scales", "XML", "rappdirs", "gridExtra", "isdparser", "geonames", "hoardr", "data.table"
Expand All @@ -10,10 +13,16 @@ required_packages <- c(
cat("Checking and installing required packages...\n")
for (pkg in required_packages) {
if (!requireNamespace(pkg, quietly = TRUE)) {
install.packages(pkg, repos = "http://cran.us.r-project.org")
cat(paste0("Installing: ", pkg, "\n"))
install.packages(pkg)
}
}

# Verify remotes installed successfully before proceeding
if (!requireNamespace("remotes", quietly = TRUE)) {
stop("Failed to install 'remotes' package. Check network connectivity and CRAN mirror.")
}

library("remotes")
# RNOAA for weather data
remotes::install_github("ropensci/rnoaa@v1.4.0", upgrade = "never")
Expand Down
Loading