Skip to content

feat(build-node): multi-package / multi-asset-path support via inputs - #44

Open
maikschneider wants to merge 2 commits into
mainfrom
feature-build-node-multi-package
Open

feat(build-node): multi-package / multi-asset-path support via inputs#44
maikschneider wants to merge 2 commits into
mainfrom
feature-build-node-multi-package

Conversation

@maikschneider

@maikschneider maikschneider commented Jul 6, 2026

Copy link
Copy Markdown
Member

Why

The current build-node.yml only handles a single package.json with a single node_modules cache and an empty artifacts:paths. Projects with multiple package.json files (e.g. TYPO3 monorepos with several site packages / extensions) have to override the whole build-node job in their .gitlab-ci.yml — install script, artifact paths, image and cache — every time. It also lacks flexibility for multiple asset paths.

What

Rework build-node.yml using spec:inputs so everything is configurable from the include, no job override needed:

Input Default Purpose
image (required) Node image — pin + Renovate-manage in the project (not in the template)
stage build Pipeline stage
package_dirs . Space-separated dirs, each with a package.json; installs + builds each in order
install_command npm ci --unsafe-perm --prefer-offline Install command per dir
build_command npm run build Build command per dir
artifact_paths [] Compiled asset dirs saved as artifacts
artifacts_expire_in 1 day Artifact retention
cache_paths [node_modules/, .npm/] Cached paths (globs ok, e.g. packages/*/node_modules/)
cache_key_files [package-lock.json] Cache key files
cache_key_prefix node Cache key prefix

Defaults preserve the classic single-package behaviour.

Image + Renovate

The image is not pinned in the template — it's a required input, pinned per project so Renovate keeps the digest current. Renovate's gitlabci manager doesn't read include.inputs, so pin it via an inline annotation + a regex customManager in the shared Renovate preset:

include:
  - remote: '.../build-node.yml'
    inputs:
      # renovate: datasource=docker depName=node
      image: "node:22-slim@sha256:..."
"customManagers": [
  {
    "customType": "regex",
    "managerFilePatterns": ["/\\.gitlab-ci\\.yml$/"],
    "matchStrings": ["# renovate: datasource=(?<datasource>\\S+) depName=(?<depName>\\S+)\\s+\\S+:\\s*[\"']?(?<currentValue>[^\"'@\\s]+)(?:@(?<currentDigest>sha256:[a-f0-9]+))?"],
    "datasourceTemplate": "{{{datasource}}}",
    "depNameTemplate": "{{{depName}}}"
  }
]

Example (DWI Symphonia, 3 packages)

include:
  - remote: '.../build-node.yml'
    inputs:
      # renovate: datasource=docker depName=node
      image: "node:22-slim@sha256:..."
      package_dirs: "packages/xima-sitepackage packages/xima-sitepackage-genr packages/xima-api-client"
      artifact_paths:
        - packages/xima-sitepackage/Resources/Public
        - packages/xima-sitepackage-genr/Resources/Public
        - packages/xima-api-client/Resources/Public/Css/dist
        - packages/xima-api-client/Resources/Public/JavaScript/dist
      cache_paths:
        - packages/*/node_modules/
        - .npm/

Breaking changes

  • image is now a required input (previously the image was set in each project's job override / inherited). Consumers must pass image: when bumping to the version containing this change.
  • Job body is now driven by inputs; projects that fully overrode build-node can drop most of the override.

Summary by CodeRabbit

  • New Features

    • Added a reusable Node.js build template with configurable image, stage, build steps, artifacts, and cache settings.
    • Supports building multiple package directories in one job, including separate install and build commands per directory.
  • Chores

    • Improved cache key handling for more flexible and reliable pipeline reuse.
    • Added stricter script behavior to reduce silent build failures.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@maikschneider, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 34 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 64e42fba-7824-470c-bc99-0a4d3cbeccaf

📥 Commits

Reviewing files that changed from the base of the PR and between d9708e9 and 3ca184d.

📒 Files selected for processing (1)
  • build-node.yml

Walkthrough

The build-node.yml GitLab CI job template is refactored from a fixed, single-project job into a reusable, parameterized template driven by spec.inputs. New inputs configure the Docker image, stage, package directories, install/build commands, artifact paths and expiry, and cache paths/keys. The job now loops over one or more package directories to install and build, replacing the prior root-only node_modules cache and fixed artifact/cache configuration. The existing rules block is retained unchanged.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Changes

Cohort / File Change Summary
build-node.yml Converted to reusable template with spec.inputs; added configurable image, stage, package_dirs, install/build commands, artifact paths/expiry, cache paths/keys; multi-directory build loop with strict shell settings; retained existing rules logic

Sequence Diagram(s)

sequenceDiagram
  participant CI as GitLab CI Pipeline
  participant Job as build-node Job
  participant Dir as Package Directory Loop
  participant Cache as Cache Store
  participant Artifacts as Artifact Store

  CI->>Job: Trigger with spec.inputs (image, package_dirs, commands)
  Job->>Cache: Restore cache (cache_key_prefix, cache_key_files)
  loop for each dir in package_dirs
    Job->>Dir: Run install_command
    Job->>Dir: Run build_command
  end
  Job->>Cache: Save updated cache
  Job->>Artifacts: Collect artifact_paths (expire_in)
  Job-->>CI: Report job result via rules
Loading

Related issues: None specified.
Related PRs: None specified.
Suggested labels: ci, enhancement
Suggested reviewers: None specified.

🐰 A rabbit hops through YAML fields anew,
Where one fixed path once grew, now many run through.
Inputs and loops, caches configured with care,
Directories building in a pipeline pair.
Hopping past node_modules, old and confined—
A template now flexible, parameterized, refined.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the move to an input-driven build-node template with multi-package and multi-artifact support.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature-build-node-multi-package

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Rework build-node.yml with spec:inputs so multi-package projects (e.g. TYPO3
monorepos with several site packages) no longer need to override the whole job.

- package_dirs: space-separated list of dirs; installs + builds each in order
- artifact_paths / cache_paths / cache_key_files: configurable via inputs
- install_command / build_command / stage / artifacts_expire_in configurable
- image passed as required input (pin + Renovate-manage it in the project)

Defaults keep the classic single-package behaviour for existing consumers.
@maikschneider
maikschneider force-pushed the feature-build-node-multi-package branch from d9708e9 to 4415ce9 Compare July 6, 2026 16:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
build-node.yml (1)

65-70: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

NPM_CONFIG_CACHE is hardcoded independent of cache_paths.

NPM_CONFIG_CACHE is fixed to "$CI_PROJECT_DIR/.npm", but the actual cached paths are fully driven by the cache_paths input. If a consumer overrides cache_paths and omits .npm/ (e.g. for a multi-package setup that only lists packages/*/node_modules/), the npm cache silently stops being persisted between runs — no functional breakage, just quietly lost caching benefit. Consider documenting this coupling explicitly (e.g. a comment near cache_paths description) so consumers know to keep .npm/ in their override if they want npm cache reuse.

Also applies to: 84-93

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@build-node.yml` around lines 65 - 70, Document the coupling between
cache_paths and the hardcoded NPM_CONFIG_CACHE in build-node.yml so consumers
know npm cache reuse depends on including .npm/ in overrides. Update the
cache_paths description (and the related cache setup block used later in the
file) to explicitly mention that NPM_CONFIG_CACHE is fixed to
$CI_PROJECT_DIR/.npm, so custom cache_paths should retain .npm/ if they want npm
cache persistence.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@build-node.yml`:
- Around line 49-52: The default install_command still includes the obsolete
--unsafe-perm flag, which can fail with the template’s npm version. Update the
install_command default to remove --unsafe-perm while keeping the rest of the
npm ci flags intact. Use the install_command field in build-node.yml as the
place to change this default.

---

Nitpick comments:
In `@build-node.yml`:
- Around line 65-70: Document the coupling between cache_paths and the hardcoded
NPM_CONFIG_CACHE in build-node.yml so consumers know npm cache reuse depends on
including .npm/ in overrides. Update the cache_paths description (and the
related cache setup block used later in the file) to explicitly mention that
NPM_CONFIG_CACHE is fixed to $CI_PROJECT_DIR/.npm, so custom cache_paths should
retain .npm/ if they want npm cache persistence.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 950a8d5f-9a77-431d-8499-f58ee0574092

📥 Commits

Reviewing files that changed from the base of the PR and between a4bb885 and d9708e9.

📒 Files selected for processing (1)
  • build-node.yml

Comment thread build-node.yml
Comment on lines +49 to +52
install_command:
type: string
default: "npm ci --unsafe-perm --prefer-offline"
description: "Command used to install dependencies inside each package directory."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the workflow/template file and inspect the relevant section.
git ls-files | rg '(^|/)build-node\.yml$|(^|/)build-node\.yaml$|(^|/)README\.md$|(^|/)docs?/.*node|(^|/)node.*(yml|yaml)$' || true

echo '--- build-node.yml excerpt ---'
nl -ba build-node.yml | sed -n '1,140p'

echo '--- search for node/npm version references and install_command usage ---'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \
  'install_command|node:22-slim|npm ci --unsafe-perm|unsafe-perm|node:[0-9]+-slim|npm [0-9]' .

echo '--- show any local docs/examples around node version usage ---'
for f in $(git ls-files | rg 'README\.md$|\.ya?ml$|\.md$' | head -n 20); do
  if rg -n 'node:22-slim|install_command|unsafe-perm|npm ci' "$f" >/dev/null 2>&1; then
    echo "### $f"
    nl -ba "$f" | sed -n '1,220p'
  fi
done

Repository: xima-media/gitlab-templates

Length of output: 261


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- build-node.yml lines 1-140 ---'
sed -n '1,140p' build-node.yml | cat -n

echo '--- README.md lines mentioning node/npm/install_command ---'
rg -n -C 2 'node:22-slim|install_command|unsafe-perm|npm ci|npm [0-9]' README.md build-node.yml

Repository: xima-media/gitlab-templates

Length of output: 6613


🌐 Web query:

npm 10 unsafe-perm invalid npm option npm ci documentation

💡 Result:

The unsafe-perm option is obsolete and no longer supported in npm version 7 and later [1][2][3]. Because you are using npm 10, attempting to use the --unsafe-perm flag—either as a command-line argument or in a configuration file—will trigger an "invalid npm option" error [4][2]. Background and Behavior: - Purpose: In older versions of npm (v6 and earlier), unsafe-perm was used to control whether npm would suppress UID/GID switching when running as root [5][3]. Setting it to true allowed scripts to run with root privileges instead of attempting to switch to the owner of the working directory [3]. - Removal: This configuration was made obsolete in npm v7 (released in 2020) [1][6]. Modern versions of npm automatically handle permissions by running lifecycle scripts with the effective UID and GID of the working directory's owner when npm is executed as root [2][3]. - Documentation: Because it is no longer a valid configuration, it has been removed from official npm documentation [1][2][3]. If you are encountering this error in an automated environment (such as Docker, CI/CD, or build tools), you should remove the --unsafe-perm flag from your install commands or configuration files [2]. If your build process requires specific permissions, you should adjust the file system ownership of the working directory so that the user running the command has the appropriate access, rather than relying on the deprecated unsafe-perm flag [6][2][3].

Citations:


🌐 Web query:

node:22-slim npm version official docker image node 22 includes npm 10

💡 Result:

The official Node.js Docker images, including the node:22-slim variant, bundle the version of npm that is distributed with the specific Node.js release [1][2]. Node.js 22 (the "Jod" LTS release) primarily ships with npm 10 [3][4]. For example, as of recent Node.js 22 releases, npm 10.9.x is typically included [3][5]. While there have been discussions and community requests to upgrade the bundled npm version to npm 11 for Node.js 22, the official Node.js 22 release line has continued to maintain npm 10 [5][6]. To verify the specific version of npm included in a particular image, you can check the bundled version by running the following command in your terminal or Dockerfile: node -e "console.log(require('child_process').execSync('npm --version').toString.trim)" Alternatively, you can check the specific version of the node:22-slim image you are using by running: docker run --rm node:22-slim npm --version Because the npm version is tied to the Node.js distribution, the version of npm included does not change unless the Node.js team updates the bundled npm in a subsequent Node.js 22.x patch release [3][5]. Users requiring a different npm version may update it manually within their container or Dockerfile using the npm install -g npm@ command [5].

Citations:


Drop --unsafe-perm from the default install command
build-node.yml:49-52node:22-slim ships npm 10, and --unsafe-perm is obsolete in npm 7+. This default npm ci --unsafe-perm ... can error on the template’s own example image. Remove the flag from install_command.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@build-node.yml` around lines 49 - 52, The default install_command still
includes the obsolete --unsafe-perm flag, which can fail with the template’s npm
version. Update the install_command default to remove --unsafe-perm while
keeping the rest of the npm ci flags intact. Use the install_command field in
build-node.yml as the place to change this default.

GitLab requires the spec:inputs header to be its own YAML document, ended with
---, otherwise inputs are not recognised and passing any input fails with
'Given inputs not defined in the spec section'.
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