8383 type : boolean
8484 default : false
8585 language :
86- description : ' Primary programming language of the project, used for SBOM enrichment (e.g., "ruby", "go", "python")'
86+ description : ' Primary programming language of the project, used for SBOM enrichment (e.g., "ruby", "go", "python", "erlang", "ruby-erlang" )'
8787 required : false
8888 type : string
8989 default : ' ruby'
@@ -234,15 +234,15 @@ jobs:
234234 uses : actions/checkout@v6
235235
236236 - name : Set up Ruby and run bundle install
237- if : inputs.language == 'ruby'
237+ if : inputs.language == 'ruby' || inputs.language == 'ruby-erlang'
238238 uses : ruby/setup-ruby@v1
239239 with :
240240 ruby-version : ' 3.4.2'
241241 bundler-cache : false
242242 working-directory : ${{ inputs.ruby-app-directory != '' && inputs.ruby-app-directory || '.' }}
243243
244244 - name : Configure Bundler for private Ruby gems
245- if : ${{ inputs.run-bundle-install == true && inputs.language == 'ruby' }}
245+ if : ${{ inputs.run-bundle-install == true && ( inputs.language == 'ruby' || inputs.language == 'ruby-erlang') }}
246246 run : |
247247 if [ -z "${{ secrets.PRIVATE_ACCESS_KITCHEN_CHEF_ENTERPRISE }}" ]; then
248248 echo "Skipping: PRIVATE_ACCESS_KITCHEN_CHEF_ENTERPRISE secret not configured or not in scope"
@@ -251,20 +251,28 @@ jobs:
251251 bundle config set --local github.com "x-access-token:${{ secrets.PRIVATE_ACCESS_KITCHEN_CHEF_ENTERPRISE }}"
252252
253253 - name : Set up Erlang/OTP and rebar3
254- if : inputs.language == 'erlang'
254+ if : inputs.language == 'erlang' || inputs.language == 'ruby-erlang'
255255 uses : erlef/setup-beam@v1
256256 with :
257257 otp-version : ' 25.3.2.16'
258258 rebar3-version : ' 3.22.0'
259259
260+ - name : Verify rebar3 installation and add to PATH
261+ if : inputs.language == 'erlang' || inputs.language == 'ruby-erlang'
262+ run : |
263+ echo "Checking for rebar3..."
264+ which rebar3 || echo "rebar3 not found in PATH"
265+ rebar3 version || echo "rebar3 command failed"
266+ echo "PATH: $PATH"
267+
260268 - name : Configure git for private Go modules
261269 if : ${{ inputs.go-private-modules != '' }}
262270 env :
263271 GOPRIVATE : ${{ inputs.go-private-modules }}
264272 run : git config --global url."https://${{ secrets.GH_TOKEN }}@github.com/".insteadOf "https://github.com/"
265273
266274 - name : generate Gemfile.lock if needed for Ruby projects
267- if : ${{ inputs.run-bundle-install == true && inputs.language == 'ruby' }}
275+ if : ${{ inputs.run-bundle-install == true && ( inputs.language == 'ruby' || inputs.language == 'ruby-erlang') }}
268276 continue-on-error : true
269277 working-directory : ${{ inputs.ruby-app-directory != '' && inputs.ruby-app-directory || '.' }}
270278 run : |
@@ -273,7 +281,7 @@ jobs:
273281 fi
274282
275283 - name : attach artifact for Gemfile.lock for debugging
276- if : ${{ inputs.language == 'ruby' }}
284+ if : ${{ inputs.language == 'ruby' || inputs.language == 'ruby-erlang' }}
277285 uses : actions/upload-artifact@v4
278286 continue-on-error : true
279287 with :
@@ -286,6 +294,60 @@ jobs:
286294 with :
287295 go-version : ' stable'
288296
297+ - name : Resolve Erlang/HEX dependencies for BlackDuck scanning
298+ if : inputs.language == 'erlang' || inputs.language == 'ruby-erlang'
299+ continue-on-error : true
300+ run : |
301+ # BlackDuck Detect needs rebar.lock files to accurately detect HEX dependencies.
302+ # Run `rebar3 get-deps` in every directory containing a rebar.config to generate
303+ # the lock files that the HEX detector relies on.
304+ # Also calculate the maximum nesting depth of rebar.config files so the detector
305+ # search depth can be set dynamically — works for any repo layout.
306+ echo "Resolving Erlang/HEX dependencies via rebar3..."
307+ MAX_DEPTH=0
308+ while IFS= read -r cfg; do
309+ dir=$(dirname "$cfg")
310+ echo "Running rebar3 get-deps in: $dir"
311+ (cd "$dir" && rebar3 get-deps) || echo "rebar3 get-deps failed in $dir (continuing)"
312+ # Count directory depth relative to repo root (number of '/' separators after leading ./)
313+ depth=$(echo "$dir" | tr -cd '/' | wc -c)
314+ [ "$depth" -gt "$MAX_DEPTH" ] && MAX_DEPTH="$depth"
315+ done < <(find . -name "rebar.config" -not -path "*/.bridge/*" -not -path "*/node_modules/*" -not -path "*/.git/*")
316+ # Ensure at least depth 1 so the root rebar.config is always found
317+ [ "$MAX_DEPTH" -lt 1 ] && MAX_DEPTH=1
318+ echo "ERLANG_DETECTOR_DEPTH=${MAX_DEPTH}" >> "$GITHUB_ENV"
319+ echo "Erlang detector search depth: ${MAX_DEPTH}"
320+ echo "Erlang dependency resolution complete"
321+
322+ - name : Resolve Ruby dependencies for BlackDuck scanning
323+ if : ${{ inputs.run-bundle-install != true && (inputs.language == 'ruby' || inputs.language == 'ruby-erlang') }}
324+ continue-on-error : true
325+ run : |
326+ # BlackDuck Detect needs Gemfile.lock files to accurately detect RubyGems dependencies.
327+ # Find every Gemfile across the repo (at any depth), run bundle install where a
328+ # Gemfile.lock is missing, and calculate the max nesting depth so the detector
329+ # search depth covers all Gemfile locations — works for any repo layout.
330+ BASE_DIR="${{ inputs.ruby-app-directory != '' && inputs.ruby-app-directory || '.' }}"
331+ echo "Scanning for Gemfiles under: $BASE_DIR"
332+ MAX_DEPTH=0
333+ while IFS= read -r gemfile; do
334+ dir=$(dirname "$gemfile")
335+ depth=$(echo "$dir" | tr -cd '/' | wc -c)
336+ [ "$depth" -gt "$MAX_DEPTH" ] && MAX_DEPTH="$depth"
337+ if [ ! -f "$dir/Gemfile.lock" ]; then
338+ echo "No Gemfile.lock in $dir — running bundle install..."
339+ (cd "$dir" && bundle install --without development test) \
340+ || echo "bundle install failed in $dir (continuing)"
341+ else
342+ echo "Gemfile.lock already exists in $dir — skipping"
343+ fi
344+ done < <(find "$BASE_DIR" -name "Gemfile" -not -name "*.lock" \
345+ -not -path "*/.bridge/*" -not -path "*/node_modules/*" -not -path "*/.git/*")
346+ [ "$MAX_DEPTH" -lt 1 ] && MAX_DEPTH=1
347+ echo "RUBY_DETECTOR_DEPTH=${MAX_DEPTH}" >> "$GITHUB_ENV"
348+ echo "Ruby detector search depth: ${MAX_DEPTH}"
349+ echo "Ruby dependency resolution complete"
350+
289351 - name : Prepare Go workspace for BlackDuck scanning
290352 if : ${{ hashFiles('go.work') != '' }}
291353 run : |
@@ -342,6 +404,23 @@ jobs:
342404 DETECT_ARGS="${DETECT_ARGS} --detect.detector.search.depth=${{ env.GO_WORK_DETECTOR_DEPTH }}"
343405 DETECT_ARGS="${DETECT_ARGS} --detect.accuracy.required=NONE"
344406 fi
407+
408+ # For Erlang, ruby-erlang, and pure Ruby repos, rebar.config/Gemfile files may
409+ # be nested in subdirectories. Default detector search depth is 0 (root only),
410+ # which causes only the Git detector to run. Use the dynamically calculated depth
411+ # (max nesting of rebar.config or Gemfile in this repo) so this works for any layout.
412+ if [[ "${{ inputs.language }}" == "erlang" || "${{ inputs.language }}" == "ruby-erlang" ]]; then
413+ ERLANG_DEPTH="${{ env.ERLANG_DETECTOR_DEPTH }}"
414+ RUBY_DEPTH="${{ env.RUBY_DETECTOR_DEPTH }}"
415+ # Use the greater of the two depths to cover both Ruby and Erlang file trees
416+ MAX_DEPTH=$(( ERLANG_DEPTH > RUBY_DEPTH ? ERLANG_DEPTH : RUBY_DEPTH ))
417+ [ "$MAX_DEPTH" -lt 1 ] && MAX_DEPTH=1
418+ DETECT_ARGS="${DETECT_ARGS} --detect.detector.search.depth=${MAX_DEPTH}"
419+ elif [[ "${{ inputs.language }}" == "ruby" ]]; then
420+ RUBY_DEPTH="${{ env.RUBY_DETECTOR_DEPTH }}"
421+ [ -n "$RUBY_DEPTH" ] && [ "$RUBY_DEPTH" -gt 0 ] && \
422+ DETECT_ARGS="${DETECT_ARGS} --detect.detector.search.depth=${RUBY_DEPTH}"
423+ fi
345424
346425 echo "DETECT_ARGS=${DETECT_ARGS}" >> $GITHUB_ENV
347426 echo "Constructed detect_args: ${DETECT_ARGS}"
0 commit comments