From c8077ece8f4767ac2b1e11ba812df3a4c4afafee Mon Sep 17 00:00:00 2001 From: Thomas Breland Date: Sun, 26 Oct 2025 11:52:18 -0400 Subject: [PATCH 1/3] Scale bundler install jobs with CPU count up to 8 The number of jobs should scale with the runner CPU count, up to a point. The bottleneck becomes network / disk I/O at very large numbers, and 8 seems like a reasonable maximum based on my experience at this time. --- bundler.js | 5 ++++- dist/index.js | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/bundler.js b/bundler.js index 8e30223ae..4d96bdd43 100644 --- a/bundler.js +++ b/bundler.js @@ -1,4 +1,5 @@ const fs = require('fs') +const os = require('os') const path = require('path') const core = require('@actions/core') const exec = require('@actions/exec') @@ -193,8 +194,10 @@ export async function bundleInstall(gemfile, lockFile, platform, engine, rubyVer console.log(`Found cache for key: ${cachedKey}`) } + // Number of jobs should scale with runner, up to a point + const jobs = Math.min(os.cpus().length, 8) // Always run 'bundle install' to list the gems - await exec.exec('bundle', ['install', '--jobs', '4']) + await exec.exec('bundle', ['install', '--jobs', jobs]) // @actions/cache only allows to save for non-existing keys if (!common.isExactCacheKeyMatch(key, cachedKey)) { diff --git a/dist/index.js b/dist/index.js index 89aebb79e..3b0e55790 100644 --- a/dist/index.js +++ b/dist/index.js @@ -13,6 +13,7 @@ __nccwpck_require__.r(__webpack_exports__); /* harmony export */ installBundler: () => (/* binding */ installBundler) /* harmony export */ }); const fs = __nccwpck_require__(9896) +const os = __nccwpck_require__(857) const path = __nccwpck_require__(6928) const core = __nccwpck_require__(7484) const exec = __nccwpck_require__(5236) @@ -207,8 +208,10 @@ async function bundleInstall(gemfile, lockFile, platform, engine, rubyVersion, b console.log(`Found cache for key: ${cachedKey}`) } + // Number of jobs should scale with runner, up to a point + const jobs = Math.min(os.cpus().length, 8) // Always run 'bundle install' to list the gems - await exec.exec('bundle', ['install', '--jobs', '4']) + await exec.exec('bundle', ['install', '--jobs', jobs]) // @actions/cache only allows to save for non-existing keys if (!common.isExactCacheKeyMatch(key, cachedKey)) { From 3d186c9056ff685d033df70b364819fc967a8837 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Mon, 27 Oct 2025 12:16:10 +0100 Subject: [PATCH 2/3] Use os.availableParallelism() instead of os.cpus().length * As https://nodejs.org/api/os.html#oscpus says: os.cpus().length should not be used to calculate the amount of parallelism available to an application. Use os.availableParallelism() for this purpose. --- bundler.js | 2 +- dist/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler.js b/bundler.js index 4d96bdd43..b4f344cfb 100644 --- a/bundler.js +++ b/bundler.js @@ -195,7 +195,7 @@ export async function bundleInstall(gemfile, lockFile, platform, engine, rubyVer } // Number of jobs should scale with runner, up to a point - const jobs = Math.min(os.cpus().length, 8) + const jobs = Math.min(os.availableParallelism(), 8) // Always run 'bundle install' to list the gems await exec.exec('bundle', ['install', '--jobs', jobs]) diff --git a/dist/index.js b/dist/index.js index 3b0e55790..934a1cdcc 100644 --- a/dist/index.js +++ b/dist/index.js @@ -209,7 +209,7 @@ async function bundleInstall(gemfile, lockFile, platform, engine, rubyVersion, b } // Number of jobs should scale with runner, up to a point - const jobs = Math.min(os.cpus().length, 8) + const jobs = Math.min(os.availableParallelism(), 8) // Always run 'bundle install' to list the gems await exec.exec('bundle', ['install', '--jobs', jobs]) From b8dc8f0e33357eb8a9b575d9c2a2e4b4eed88617 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Mon, 27 Oct 2025 12:23:48 +0100 Subject: [PATCH 3/3] exec.exec() only accepts strings --- bundler.js | 2 +- dist/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler.js b/bundler.js index b4f344cfb..e0d117931 100644 --- a/bundler.js +++ b/bundler.js @@ -197,7 +197,7 @@ export async function bundleInstall(gemfile, lockFile, platform, engine, rubyVer // Number of jobs should scale with runner, up to a point const jobs = Math.min(os.availableParallelism(), 8) // Always run 'bundle install' to list the gems - await exec.exec('bundle', ['install', '--jobs', jobs]) + await exec.exec('bundle', ['install', '--jobs', `${jobs}`]) // @actions/cache only allows to save for non-existing keys if (!common.isExactCacheKeyMatch(key, cachedKey)) { diff --git a/dist/index.js b/dist/index.js index 934a1cdcc..5ff32c19d 100644 --- a/dist/index.js +++ b/dist/index.js @@ -211,7 +211,7 @@ async function bundleInstall(gemfile, lockFile, platform, engine, rubyVersion, b // Number of jobs should scale with runner, up to a point const jobs = Math.min(os.availableParallelism(), 8) // Always run 'bundle install' to list the gems - await exec.exec('bundle', ['install', '--jobs', jobs]) + await exec.exec('bundle', ['install', '--jobs', `${jobs}`]) // @actions/cache only allows to save for non-existing keys if (!common.isExactCacheKeyMatch(key, cachedKey)) {