Skip to content

CI: stop rebuilding rserve on every PR run; pin R deps to a CRAN snapshot - #849

Merged
brianlball merged 2 commits into
developfrom
ci-rserve-snapshot-cache
Jul 16, 2026
Merged

CI: stop rebuilding rserve on every PR run; pin R deps to a CRAN snapshot#849
brianlball merged 2 commits into
developfrom
ci-rserve-snapshot-cache

Conversation

@brianlball

Copy link
Copy Markdown
Contributor

Follow-up to #847's CI work, prompted by the docker-job failure on #845's re-run (2026-07-16 ~19:03Z): the rserve image rebuild died in Rscript install_packages.R on transient cloud.r-project.org download failures plus mid-day CRAN version drift (ggplot2 3.5.1 found, but >= 3.5.2 is required by 'ggrepel'; gtable 0.3.5 loaded, but >= 0.3.6 required). The same rebuild had passed 2.5h earlier — nothing in the PR was at fault.

Why every run rebuilt rserve

BuildKit (default since Docker 23, runners have 28) does not use pulled images as layer cache, so the docker-compose pull before build — the original caching mechanism under the classic builder — stopped helping. Every docker job replayed the full R install (~10 min) against live CRAN.

Changes

  1. PR runs skip the rserve build entirely unless the PR touches docker/R/** (two-commit tree diff against the fetched base tip, so it works on the shallow merge-ref clone; any fetch/diff failure falls back to building everything). The stack uses the pulled nrel/openstudio-rserve:latest, which docker-upload keeps fresh on develop/master pushes. Push runs still build everything since those images get deployed.
  2. cache_from + BUILDKIT_INLINE_CACHE on all built services, so images pushed from develop carry layer-cache metadata and can seed the builds that do still happen.
  3. R installs resolve from a dated Posit Package Manager snapshot (2026-07-15) instead of live CRAN — install_and_verify pinned its named packages but their dependencies floated, which is exactly what broke. The __linux__/jammy path serves prebuilt binaries for the base image (Ubuntu 22.04 + R 4.4): install_packages.R drops from ~480s to ~100s. Bump the snapshot date deliberately to take newer packages.

Testing

  • Local docker build docker/R with the snapshot: completes, 13/13 packages install and pass their load check, R-install layer 102s (was 482s in CI).
  • This PR touches docker/R/**, so its own docker job exercises the "PR changed docker/R → rebuild" path end-to-end, including the snapshot install in CI.
  • docker compose config validates; build args string-quoted for docker-compose 1.29's schema.

🤖 Generated with Claude Code

brianlball and others added 2 commits July 16, 2026 16:56
install_and_verify pins the packages it names, but their dependencies
resolved from live CRAN. A mid-day CRAN publish on 2026-07-16 (ggrepel
requiring ggplot2 >= 3.5.2/gtable >= 0.3.6) broke rserve image rebuilds
that had passed hours earlier, plus transient cloud.r-project.org
download failures. Resolve everything from the 2026-07-15 snapshot: same
inputs every build until the date is bumped deliberately.

The __linux__/jammy path serves prebuilt binaries for the base image
(Ubuntu 22.04 + R 4.4) - install_packages.R drops from ~480s to ~100s -
with the plain source snapshot as fallback. Verified locally: docker
build of docker/R completes, 13/13 packages install and load.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every docker job rebuilt the rserve image from scratch: BuildKit (Docker
28 default) does not use pulled images as layer cache, so the
docker-compose pull that used to make the build a cache no-op under the
classic builder stopped helping. That cost ~10 min per run and exposed
every PR to CRAN availability (see 2026-07-16 failure on #845's run).

- PR runs build only web unless the PR changes docker/R (two-commit tree
  diff against the fetched base tip - works on the shallow merge-ref
  clone; any fetch/diff failure falls back to building everything). The
  pulled nrel/openstudio-rserve:latest, kept fresh by docker-upload on
  develop/master pushes, backs the stack instead
- push runs still build everything (docker-upload deploys those images)
- compose build config gains cache_from + BUILDKIT_INLINE_CACHE so
  images pushed from develop carry layer-cache metadata and can seed
  the builds that do still happen

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@brianlball
brianlball merged commit ba21522 into develop Jul 16, 2026
5 checks passed
@brianlball
brianlball deleted the ci-rserve-snapshot-cache branch July 16, 2026 22:39
brianlball added a commit that referenced this pull request Jul 29, 2026
* Update permissions for rspec_command and enhance README with MVP suitability details

* Enhance external batch execution support:
- Update developer guide to reflect UrbanOpt and custom gemfile support.
- Modify README to clarify MVP suitability and resolved limitations.
- Improve run_chunk.rb to support Windows scripts and enhance logging.
- Update LHS sampling to generate histogram images using pure Ruby.
- Refactor external_batch.rb to handle nil ENV variables gracefully.
- Adjust ingester and packager to support UrbanOpt and gemfile analyses.
- Revise tests to validate packaging for UrbanOpt and gemfile analyses.

* Add Nomad executor implementation for external batch feature

* Add Nomad job submission script for external batch executor

* Add Nomad task wrapper script for external batch processing

Create task_wrapper.sh that serves as the entrypoint for Nomad tasks in the external batch executor. The script:
- Handles package retrieval from shared filesystem or S3
- Sets up execution environment (unsets Bundler vars, configures PATH)
- Executes run_chunk.rb for assigned chunk index
- Handles result storage back to shared filesystem or S3
- Implements proper error handling and logging
- Supports configurable storage types via environment variables
- Matches the interface expected by Nomad job templates

* Add Nomad job template for batch processing

* docs: add Nomad executor section to external_batch/README.md

* Add Nomad executor unit tests for submit_nomad.rb and sync_results.rb. Includes tests for packaging, job submission, parameter handling, and result synchronization. Also adds a full pipeline test for Nomad executor. Ensures existing functionality remains unaffected.

* external_batch/nomad: .env-based config, Ansible provisioning, task_wrapper fixes, doc cleanup

BREAKING: docker-compose.yml no longer has hardcoded IP fallbacks for
OS_SERVER_NOMAD_SSH_HOST or NOMAD_ADDR. Users must set these in .env.

Changes:
- docker-compose.yml: Remove hardcoded 10.60.126.125 from OS_SERVER_NOMAD_SSH_HOST;
  add NOMAD_ADDR env var to web and web-background services
- .gitignore: Add .env (now un-tracked via git rm --cached)
- .env.example: New template with placeholder values and instructions
- Dockerfile: Add rsync package (required for SSH rsync bridge)
- task_wrapper.sh: Use NOMAD_ALLOC_INDEX as fallback for --chunk-index;
  switch work dir to /tmp/nomad/task; use /usr/local/bin/run_chunk.rb;
  downgrade chunk failure to WARNING (non-fatal for individual data points)
- job_array.hcl: raw_exec driver, nomad-client constraint, resources
  2000MHz/4096MB/1000MB with tuning comments
- ansible/: Complete provisioning playbook set (site.yml, 3 playbooks,
  5 roles, create_cluster.py provisioner)
- submit_nomad.rb / sync_results.rb: Update --ssh-host help text to use
  <NOMAD_SERVER_FLOATING_IP> placeholder
- nomad/README.md: Update --ssh-host description, reference OS_SERVER_NOMAD_SSH_HOST
- docs/external_batch_nomad_plan.md: Replace all hardcoded IPs with placeholders

* ansible/README.md: document additive mode, --max, CLI flags, inventory merge

- Quick Start: make auto-inventory path primary, manual copy secondary
- Add additive mode section (auto-detect, skip server, offset indices, merge)
- Add CLI flags reference table
- Update 'what the script generates' to describe merge vs overwrite
- Document --max, --no-auto-inventory, --inventory-output, --prefix flags

* external batch Nomad/Ansible fixes: create_cluster refactor, task wrapper, job templates, .gitignore

Ported from mvp-external-batch-fixes commit 3cc9d73 minus the parts that
conflict with or duplicate develop:
- dropped OpenStudio 3.10.0 / mongo 6.0.7 downgrades (develop stays 3.11.0 / mongo 8)
- dropped bin/openstudio_meta bundler config-set rewrite (broke CI: persistent
  with/without group conflict between test and export install_gems runs)
- dropped DJ/Resque job edits (hand-backports of fixes develop already has via #844/#845)
- dropped empty ansible/tail file and personal .gitignore entries

* Fix CI: rewrite nomad spec to script's real contract, ImageMagick-optional histograms

- external_batch_nomad_spec: was stubbing a nomad CLI via --nomad-cmd, but
  submit_nomad.rb drives the Nomad HTTP API (/v1/jobs/parse -> /v1/jobs) and
  lays out <loc>/analysis_<id>/{package,results}; spec also died in before
  hook on an interpolating heredoc (NameError: output_flag), masking the
  mismatch. Rewritten against the HTTP API with an in-spec stub server.
- nomad/sync_results.rb: NFS branch mirrors via FileUtils instead of rsync
  (absent on Windows dev boxes and slim containers; loop hung without it)
- sampling/lhs.rb: preflight histogram attach non-fatal; paperclip needs
  ImageMagick identify, absent on ubuntu-24.04/macos-15 runners + PAT hosts

(CRAN snapshot pin restore from the original commit is a no-op here: this
branch is based on develop, which already has it via ba21522 / #849.)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Keep tracked .env dev defaults from develop

71c2c39 moved compose config to .env.example + gitignored .env, but
develop ships a tracked .env with dev-default credentials that
docker-compose.yml requires out of the box (REDIS_PASSWORD etc).
Keep both: .env.example documents the knobs, .env keeps a fresh
clone bootable. Removing the tracked .env can be its own PR if wanted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* compose: drop runtime apt-get rsync hack; rsync is in the image now

71c2c39 installed rsync at container start because the published image
lacked it; the same commit added rsync to the Dockerfile, and compose
builds locally, so the runtime install is redundant. chmod of the
optional ssh key moves to the operator (see external_batch/nomad/README).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Address Copilot review on #856

- sampling/lhs.rb: emit valid IHDR chunk (was IHLR + 12-byte pack, every
  histogram PNG invalid); require fileutils/tempfile explicitly
- run_chunk.rb: bundle install once per runner process with completion
  marker keyed on Gemfile digest (was once per datapoint, racy on shared
  dirs); spawn .bat/.cmd via cmd.exe /c and .ps1 argv-style; stop
  rewriting CRLF->LF in Windows scripts
- task_wrapper.sh: per-allocation work dir (NOMAD_TASK_DIR or mktemp,
  was hard-coded /tmp/nomad/task); dotfile/empty-dir-safe cp -a copies
- submit_nomad.rb: validate --job-template/--package-location up front
- external_batch.rb: require tmpdir; guard nil/empty sim_root_path
- compose: mount tracked external_batch/nomad/ssh dir instead of
  gitignored key files (fresh-clone docker compose up worked never)
- ansible: OpenStudio 3.10.0 -> 3.11.0 in examples/defaults per PR intent

Verified: sampling_lhs + external_batch + external_batch_nomad specs
(27 examples, 0 failures, 1 pending); generated PNG decodes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ansible examples: OpenStudio 3.10.0 to match base branch 179

PR retargeted develop -> 179 (OS 3.10). Flip back to 3.11.0 when this
work is promoted to develop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Alex Chapin <achapin@nrel.gov>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant